commit da6d257e305958e323625d71acfdfa4ded8c0d5f Author: cxf <2417125293@qq.com> Date: Sun Feb 1 15:09:30 2026 +0800 init:furuiwang diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..14cb465c --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +*.iml +.gradle +/local.properties +/.idea/caches +/.idea/libraries +/.idea/modules.xml +/.idea/workspace.xml +/.idea/navEditor.xml +/.idea/assetWizardSettings.xml +.DS_Store +/build +/captures +.externalNativeBuild +.cxx +local.properties + + +# 新增:DJI SDK 子模块的 build 目录(关键!) +android-sdk-v5-uxsdk/build/ +android-sdk-v5-uxsdk/.gradle/ +android-sdk-v5-mission/build/ +*/build/ # 捕获所有子模块的 build \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 00000000..26d33521 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 00000000..dbb864bb --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +ApronV5 \ No newline at end of file diff --git a/.idea/AndroidProjectSystem.xml b/.idea/AndroidProjectSystem.xml new file mode 100644 index 00000000..4a53bee8 --- /dev/null +++ b/.idea/AndroidProjectSystem.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 00000000..b589d56e --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/deploymentTargetSelector.xml b/.idea/deploymentTargetSelector.xml new file mode 100644 index 00000000..b268ef36 --- /dev/null +++ b/.idea/deploymentTargetSelector.xml @@ -0,0 +1,10 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 00000000..7c7654d8 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,20 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/jarRepositories.xml b/.idea/jarRepositories.xml new file mode 100644 index 00000000..ae666d42 --- /dev/null +++ b/.idea/jarRepositories.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/kotlinc.xml b/.idea/kotlinc.xml new file mode 100644 index 00000000..0e65ceac --- /dev/null +++ b/.idea/kotlinc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/migrations.xml b/.idea/migrations.xml new file mode 100644 index 00000000..f8051a6f --- /dev/null +++ b/.idea/migrations.xml @@ -0,0 +1,10 @@ + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 00000000..481db9dd --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 00000000..16660f1d --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,17 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 00000000..83067447 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/OpenCV/build.gradle b/OpenCV/build.gradle new file mode 100644 index 00000000..448158c4 --- /dev/null +++ b/OpenCV/build.gradle @@ -0,0 +1,17 @@ +apply plugin: 'com.android.library' + +android { + compileSdkVersion 29 + buildToolsVersion "29.0.2" + + defaultConfig { + + } + + buildTypes { + release { + minifyEnabled false + proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt' + } + } +} diff --git a/OpenCV/src/main/AndroidManifest.xml b/OpenCV/src/main/AndroidManifest.xml new file mode 100644 index 00000000..ccf8ab8f --- /dev/null +++ b/OpenCV/src/main/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + diff --git a/OpenCV/src/main/aidl/org/opencv/engine/OpenCVEngineInterface.aidl b/OpenCV/src/main/aidl/org/opencv/engine/OpenCVEngineInterface.aidl new file mode 100644 index 00000000..21fe5f71 --- /dev/null +++ b/OpenCV/src/main/aidl/org/opencv/engine/OpenCVEngineInterface.aidl @@ -0,0 +1,33 @@ +package org.opencv.engine; + +/** +* Class provides a Java interface for OpenCV Engine Service. It's synchronous with native OpenCVEngine class. +*/ +interface OpenCVEngineInterface +{ + /** + * @return Returns service version. + */ + int getEngineVersion(); + + /** + * Finds an installed OpenCV library. + * @param OpenCV version. + * @return Returns path to OpenCV native libs or an empty string if OpenCV can not be found. + */ + String getLibPathByVersion(String version); + + /** + * Tries to install defined version of OpenCV from Google Play Market. + * @param OpenCV version. + * @return Returns true if installation was successful or OpenCV package has been already installed. + */ + boolean installVersion(String version); + + /** + * Returns list of libraries in loading order, separated by semicolon. + * @param OpenCV version. + * @return Returns names of OpenCV libraries, separated by semicolon. + */ + String getLibraryList(String version); +} diff --git a/OpenCV/src/main/java/org/opencv/android/AsyncServiceHelper.java b/OpenCV/src/main/java/org/opencv/android/AsyncServiceHelper.java new file mode 100644 index 00000000..a718ca3c --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/android/AsyncServiceHelper.java @@ -0,0 +1,391 @@ +package org.opencv.android; + +import java.io.File; +import java.util.StringTokenizer; + +import org.opencv.core.Core; +import org.opencv.engine.OpenCVEngineInterface; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.net.Uri; +import android.os.IBinder; +import android.os.RemoteException; +import android.util.Log; + +class AsyncServiceHelper +{ + public static boolean initOpenCV(String Version, final Context AppContext, + final LoaderCallbackInterface Callback) + { + AsyncServiceHelper helper = new AsyncServiceHelper(Version, AppContext, Callback); + Intent intent = new Intent("org.opencv.engine.BIND"); + intent.setPackage("org.opencv.engine"); + if (AppContext.bindService(intent, helper.mServiceConnection, Context.BIND_AUTO_CREATE)) + { + return true; + } + else + { + AppContext.unbindService(helper.mServiceConnection); + InstallService(AppContext, Callback); + return false; + } + } + + protected AsyncServiceHelper(String Version, Context AppContext, LoaderCallbackInterface Callback) + { + mOpenCVersion = Version; + mUserAppCallback = Callback; + mAppContext = AppContext; + } + + protected static final String TAG = "OpenCVManager/Helper"; + protected static final int MINIMUM_ENGINE_VERSION = 2; + protected OpenCVEngineInterface mEngineService; + protected LoaderCallbackInterface mUserAppCallback; + protected String mOpenCVersion; + protected Context mAppContext; + protected static boolean mServiceInstallationProgress = false; + protected static boolean mLibraryInstallationProgress = false; + + protected static boolean InstallServiceQuiet(Context context) + { + boolean result = true; + try + { + Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(OPEN_CV_SERVICE_URL)); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + context.startActivity(intent); + } + catch(Exception e) + { + result = false; + } + + return result; + } + + protected static void InstallService(final Context AppContext, final LoaderCallbackInterface Callback) + { + if (!mServiceInstallationProgress) + { + Log.d(TAG, "Request new service installation"); + InstallCallbackInterface InstallQuery = new InstallCallbackInterface() { + private LoaderCallbackInterface mUserAppCallback = Callback; + public String getPackageName() + { + return "OpenCV Manager"; + } + public void install() { + Log.d(TAG, "Trying to install OpenCV Manager via Google Play"); + + boolean result = InstallServiceQuiet(AppContext); + if (result) + { + mServiceInstallationProgress = true; + Log.d(TAG, "Package installation started"); + } + else + { + Log.d(TAG, "OpenCV package was not installed!"); + int Status = LoaderCallbackInterface.MARKET_ERROR; + Log.d(TAG, "Init finished with status " + Status); + Log.d(TAG, "Unbind from service"); + Log.d(TAG, "Calling using callback"); + mUserAppCallback.onManagerConnected(Status); + } + } + + public void cancel() + { + Log.d(TAG, "OpenCV library installation was canceled"); + int Status = LoaderCallbackInterface.INSTALL_CANCELED; + Log.d(TAG, "Init finished with status " + Status); + Log.d(TAG, "Calling using callback"); + mUserAppCallback.onManagerConnected(Status); + } + + public void wait_install() + { + Log.e(TAG, "Installation was not started! Nothing to wait!"); + } + }; + + Callback.onPackageInstall(InstallCallbackInterface.NEW_INSTALLATION, InstallQuery); + } + else + { + Log.d(TAG, "Waiting current installation process"); + InstallCallbackInterface WaitQuery = new InstallCallbackInterface() { + private LoaderCallbackInterface mUserAppCallback = Callback; + public String getPackageName() + { + return "OpenCV Manager"; + } + public void install() + { + Log.e(TAG, "Nothing to install we just wait current installation"); + } + public void cancel() + { + Log.d(TAG, "Waiting for OpenCV canceled by user"); + mServiceInstallationProgress = false; + int Status = LoaderCallbackInterface.INSTALL_CANCELED; + Log.d(TAG, "Init finished with status " + Status); + Log.d(TAG, "Calling using callback"); + mUserAppCallback.onManagerConnected(Status); + } + public void wait_install() + { + InstallServiceQuiet(AppContext); + } + }; + + Callback.onPackageInstall(InstallCallbackInterface.INSTALLATION_PROGRESS, WaitQuery); + } + } + + /** + * URL of OpenCV Manager page on Google Play Market. + */ + protected static final String OPEN_CV_SERVICE_URL = "market://details?id=org.opencv.engine"; + + protected ServiceConnection mServiceConnection = new ServiceConnection() + { + public void onServiceConnected(ComponentName className, IBinder service) + { + Log.d(TAG, "Service connection created"); + mEngineService = OpenCVEngineInterface.Stub.asInterface(service); + if (null == mEngineService) + { + Log.d(TAG, "OpenCV Manager Service connection fails. May be service was not installed?"); + InstallService(mAppContext, mUserAppCallback); + } + else + { + mServiceInstallationProgress = false; + try + { + if (mEngineService.getEngineVersion() < MINIMUM_ENGINE_VERSION) + { + Log.d(TAG, "Init finished with status " + LoaderCallbackInterface.INCOMPATIBLE_MANAGER_VERSION); + Log.d(TAG, "Unbind from service"); + mAppContext.unbindService(mServiceConnection); + Log.d(TAG, "Calling using callback"); + mUserAppCallback.onManagerConnected(LoaderCallbackInterface.INCOMPATIBLE_MANAGER_VERSION); + return; + } + + Log.d(TAG, "Trying to get library path"); + String path = mEngineService.getLibPathByVersion(mOpenCVersion); + if ((null == path) || (path.length() == 0)) + { + if (!mLibraryInstallationProgress) + { + InstallCallbackInterface InstallQuery = new InstallCallbackInterface() { + public String getPackageName() + { + return "OpenCV library"; + } + public void install() { + Log.d(TAG, "Trying to install OpenCV lib via Google Play"); + try + { + if (mEngineService.installVersion(mOpenCVersion)) + { + mLibraryInstallationProgress = true; + Log.d(TAG, "Package installation started"); + Log.d(TAG, "Unbind from service"); + mAppContext.unbindService(mServiceConnection); + } + else + { + Log.d(TAG, "OpenCV package was not installed!"); + Log.d(TAG, "Init finished with status " + LoaderCallbackInterface.MARKET_ERROR); + Log.d(TAG, "Unbind from service"); + mAppContext.unbindService(mServiceConnection); + Log.d(TAG, "Calling using callback"); + mUserAppCallback.onManagerConnected(LoaderCallbackInterface.MARKET_ERROR); + } + } catch (RemoteException e) { + e.printStackTrace();; + Log.d(TAG, "Init finished with status " + LoaderCallbackInterface.INIT_FAILED); + Log.d(TAG, "Unbind from service"); + mAppContext.unbindService(mServiceConnection); + Log.d(TAG, "Calling using callback"); + mUserAppCallback.onManagerConnected(LoaderCallbackInterface.INIT_FAILED); + } + } + public void cancel() { + Log.d(TAG, "OpenCV library installation was canceled"); + Log.d(TAG, "Init finished with status " + LoaderCallbackInterface.INSTALL_CANCELED); + Log.d(TAG, "Unbind from service"); + mAppContext.unbindService(mServiceConnection); + Log.d(TAG, "Calling using callback"); + mUserAppCallback.onManagerConnected(LoaderCallbackInterface.INSTALL_CANCELED); + } + public void wait_install() { + Log.e(TAG, "Installation was not started! Nothing to wait!"); + } + }; + + mUserAppCallback.onPackageInstall(InstallCallbackInterface.NEW_INSTALLATION, InstallQuery); + } + else + { + InstallCallbackInterface WaitQuery = new InstallCallbackInterface() { + public String getPackageName() + { + return "OpenCV library"; + } + + public void install() { + Log.e(TAG, "Nothing to install we just wait current installation"); + } + public void cancel() + { + Log.d(TAG, "OpenCV library installation was canceled"); + mLibraryInstallationProgress = false; + Log.d(TAG, "Init finished with status " + LoaderCallbackInterface.INSTALL_CANCELED); + Log.d(TAG, "Unbind from service"); + mAppContext.unbindService(mServiceConnection); + Log.d(TAG, "Calling using callback"); + mUserAppCallback.onManagerConnected(LoaderCallbackInterface.INSTALL_CANCELED); + } + public void wait_install() { + Log.d(TAG, "Waiting for current installation"); + try + { + if (!mEngineService.installVersion(mOpenCVersion)) + { + Log.d(TAG, "OpenCV package was not installed!"); + Log.d(TAG, "Init finished with status " + LoaderCallbackInterface.MARKET_ERROR); + Log.d(TAG, "Calling using callback"); + mUserAppCallback.onManagerConnected(LoaderCallbackInterface.MARKET_ERROR); + } + else + { + Log.d(TAG, "Wating for package installation"); + } + + Log.d(TAG, "Unbind from service"); + mAppContext.unbindService(mServiceConnection); + + } catch (RemoteException e) { + e.printStackTrace(); + Log.d(TAG, "Init finished with status " + LoaderCallbackInterface.INIT_FAILED); + Log.d(TAG, "Unbind from service"); + mAppContext.unbindService(mServiceConnection); + Log.d(TAG, "Calling using callback"); + mUserAppCallback.onManagerConnected(LoaderCallbackInterface.INIT_FAILED); + } + } + }; + + mUserAppCallback.onPackageInstall(InstallCallbackInterface.INSTALLATION_PROGRESS, WaitQuery); + } + return; + } + else + { + Log.d(TAG, "Trying to get library list"); + mLibraryInstallationProgress = false; + String libs = mEngineService.getLibraryList(mOpenCVersion); + Log.d(TAG, "Library list: \"" + libs + "\""); + Log.d(TAG, "First attempt to load libs"); + int status; + if (initOpenCVLibs(path, libs)) + { + Log.d(TAG, "First attempt to load libs is OK"); + String eol = System.getProperty("line.separator"); + for (String str : Core.getBuildInformation().split(eol)) + Log.i(TAG, str); + + status = LoaderCallbackInterface.SUCCESS; + } + else + { + Log.d(TAG, "First attempt to load libs fails"); + status = LoaderCallbackInterface.INIT_FAILED; + } + + Log.d(TAG, "Init finished with status " + status); + Log.d(TAG, "Unbind from service"); + mAppContext.unbindService(mServiceConnection); + Log.d(TAG, "Calling using callback"); + mUserAppCallback.onManagerConnected(status); + } + } + catch (RemoteException e) + { + e.printStackTrace(); + Log.d(TAG, "Init finished with status " + LoaderCallbackInterface.INIT_FAILED); + Log.d(TAG, "Unbind from service"); + mAppContext.unbindService(mServiceConnection); + Log.d(TAG, "Calling using callback"); + mUserAppCallback.onManagerConnected(LoaderCallbackInterface.INIT_FAILED); + } + } + } + + public void onServiceDisconnected(ComponentName className) + { + mEngineService = null; + } + }; + + private boolean loadLibrary(String AbsPath) + { + boolean result = true; + + Log.d(TAG, "Trying to load library " + AbsPath); + try + { + System.load(AbsPath); + Log.d(TAG, "OpenCV libs init was ok!"); + } + catch(UnsatisfiedLinkError e) + { + Log.d(TAG, "Cannot load library \"" + AbsPath + "\""); + e.printStackTrace(); + result = false; + } + + return result; + } + + private boolean initOpenCVLibs(String Path, String Libs) + { + Log.d(TAG, "Trying to init OpenCV libs"); + if ((null != Path) && (Path.length() != 0)) + { + boolean result = true; + if ((null != Libs) && (Libs.length() != 0)) + { + Log.d(TAG, "Trying to load libs by dependency list"); + StringTokenizer splitter = new StringTokenizer(Libs, ";"); + while(splitter.hasMoreTokens()) + { + String AbsLibraryPath = Path + File.separator + splitter.nextToken(); + result &= loadLibrary(AbsLibraryPath); + } + } + else + { + // If the dependencies list is not defined or empty. + String AbsLibraryPath = Path + File.separator + "libopencv_java4.so"; + result = loadLibrary(AbsLibraryPath); + } + + return result; + } + else + { + Log.d(TAG, "Library path \"" + Path + "\" is empty"); + return false; + } + } +} diff --git a/OpenCV/src/main/java/org/opencv/android/BaseLoaderCallback.java b/OpenCV/src/main/java/org/opencv/android/BaseLoaderCallback.java new file mode 100644 index 00000000..8ece6625 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/android/BaseLoaderCallback.java @@ -0,0 +1,141 @@ +package org.opencv.android; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.DialogInterface.OnClickListener; +import android.util.Log; + +/** + * Basic implementation of LoaderCallbackInterface. + */ +public abstract class BaseLoaderCallback implements LoaderCallbackInterface { + + public BaseLoaderCallback(Context AppContext) { + mAppContext = AppContext; + } + + public void onManagerConnected(int status) + { + switch (status) + { + /** OpenCV initialization was successful. **/ + case LoaderCallbackInterface.SUCCESS: + { + /** Application must override this method to handle successful library initialization. **/ + } break; + /** OpenCV loader can not start Google Play Market. **/ + case LoaderCallbackInterface.MARKET_ERROR: + { + Log.e(TAG, "Package installation failed!"); + AlertDialog MarketErrorMessage = new AlertDialog.Builder(mAppContext).create(); + MarketErrorMessage.setTitle("OpenCV Manager"); + MarketErrorMessage.setMessage("Package installation failed!"); + MarketErrorMessage.setCancelable(false); // This blocks the 'BACK' button + MarketErrorMessage.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + finish(); + } + }); + MarketErrorMessage.show(); + } break; + /** Package installation has been canceled. **/ + case LoaderCallbackInterface.INSTALL_CANCELED: + { + Log.d(TAG, "OpenCV library installation was canceled by user"); + finish(); + } break; + /** Application is incompatible with this version of OpenCV Manager. Possibly, a service update is required. **/ + case LoaderCallbackInterface.INCOMPATIBLE_MANAGER_VERSION: + { + Log.d(TAG, "OpenCV Manager Service is uncompatible with this app!"); + AlertDialog IncomatibilityMessage = new AlertDialog.Builder(mAppContext).create(); + IncomatibilityMessage.setTitle("OpenCV Manager"); + IncomatibilityMessage.setMessage("OpenCV Manager service is incompatible with this app. Try to update it via Google Play."); + IncomatibilityMessage.setCancelable(false); // This blocks the 'BACK' button + IncomatibilityMessage.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + finish(); + } + }); + IncomatibilityMessage.show(); + } break; + /** Other status, i.e. INIT_FAILED. **/ + default: + { + Log.e(TAG, "OpenCV loading failed!"); + AlertDialog InitFailedDialog = new AlertDialog.Builder(mAppContext).create(); + InitFailedDialog.setTitle("OpenCV error"); + InitFailedDialog.setMessage("OpenCV was not initialised correctly. Application will be shut down"); + InitFailedDialog.setCancelable(false); // This blocks the 'BACK' button + InitFailedDialog.setButton(AlertDialog.BUTTON_POSITIVE, "OK", new OnClickListener() { + + public void onClick(DialogInterface dialog, int which) { + finish(); + } + }); + + InitFailedDialog.show(); + } break; + } + } + + public void onPackageInstall(final int operation, final InstallCallbackInterface callback) + { + switch (operation) + { + case InstallCallbackInterface.NEW_INSTALLATION: + { + AlertDialog InstallMessage = new AlertDialog.Builder(mAppContext).create(); + InstallMessage.setTitle("Package not found"); + InstallMessage.setMessage(callback.getPackageName() + " package was not found! Try to install it?"); + InstallMessage.setCancelable(false); // This blocks the 'BACK' button + InstallMessage.setButton(AlertDialog.BUTTON_POSITIVE, "Yes", new OnClickListener() + { + public void onClick(DialogInterface dialog, int which) + { + callback.install(); + } + }); + + InstallMessage.setButton(AlertDialog.BUTTON_NEGATIVE, "No", new OnClickListener() { + + public void onClick(DialogInterface dialog, int which) + { + callback.cancel(); + } + }); + + InstallMessage.show(); + } break; + case InstallCallbackInterface.INSTALLATION_PROGRESS: + { + AlertDialog WaitMessage = new AlertDialog.Builder(mAppContext).create(); + WaitMessage.setTitle("OpenCV is not ready"); + WaitMessage.setMessage("Installation is in progress. Wait or exit?"); + WaitMessage.setCancelable(false); // This blocks the 'BACK' button + WaitMessage.setButton(AlertDialog.BUTTON_POSITIVE, "Wait", new OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + callback.wait_install(); + } + }); + WaitMessage.setButton(AlertDialog.BUTTON_NEGATIVE, "Exit", new OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + callback.cancel(); + } + }); + + WaitMessage.show(); + } break; + } + } + + void finish() + { + ((Activity) mAppContext).finish(); + } + + protected Context mAppContext; + private final static String TAG = "OCV/BaseLoaderCallback"; +} diff --git a/OpenCV/src/main/java/org/opencv/android/Camera2Renderer.java b/OpenCV/src/main/java/org/opencv/android/Camera2Renderer.java new file mode 100644 index 00000000..40821405 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/android/Camera2Renderer.java @@ -0,0 +1,302 @@ +package org.opencv.android; + +import java.util.Arrays; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.SurfaceTexture; +import android.hardware.camera2.CameraAccessException; +import android.hardware.camera2.CameraCaptureSession; +import android.hardware.camera2.CameraCharacteristics; +import android.hardware.camera2.CameraDevice; +import android.hardware.camera2.CameraManager; +import android.hardware.camera2.CaptureRequest; +import android.hardware.camera2.params.StreamConfigurationMap; +import android.os.Handler; +import android.os.HandlerThread; +import android.util.Log; +import android.util.Size; +import android.view.Surface; + +@TargetApi(21) +public class Camera2Renderer extends CameraGLRendererBase { + + protected final String LOGTAG = "Camera2Renderer"; + private CameraDevice mCameraDevice; + private CameraCaptureSession mCaptureSession; + private CaptureRequest.Builder mPreviewRequestBuilder; + private String mCameraID; + private Size mPreviewSize = new Size(-1, -1); + + private HandlerThread mBackgroundThread; + private Handler mBackgroundHandler; + private Semaphore mCameraOpenCloseLock = new Semaphore(1); + + Camera2Renderer(CameraGLSurfaceView view) { + super(view); + } + + @Override + protected void doStart() { + Log.d(LOGTAG, "doStart"); + startBackgroundThread(); + super.doStart(); + } + + + @Override + protected void doStop() { + Log.d(LOGTAG, "doStop"); + super.doStop(); + stopBackgroundThread(); + } + + boolean cacPreviewSize(final int width, final int height) { + Log.i(LOGTAG, "cacPreviewSize: "+width+"x"+height); + if(mCameraID == null) { + Log.e(LOGTAG, "Camera isn't initialized!"); + return false; + } + CameraManager manager = (CameraManager) mView.getContext() + .getSystemService(Context.CAMERA_SERVICE); + try { + CameraCharacteristics characteristics = manager + .getCameraCharacteristics(mCameraID); + StreamConfigurationMap map = characteristics + .get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); + int bestWidth = 0, bestHeight = 0; + float aspect = (float)width / height; + for (Size psize : map.getOutputSizes(SurfaceTexture.class)) { + int w = psize.getWidth(), h = psize.getHeight(); + Log.d(LOGTAG, "trying size: "+w+"x"+h); + if ( width >= w && height >= h && + bestWidth <= w && bestHeight <= h && + Math.abs(aspect - (float)w/h) < 0.2 ) { + bestWidth = w; + bestHeight = h; + } + } + Log.i(LOGTAG, "best size: "+bestWidth+"x"+bestHeight); + if( bestWidth == 0 || bestHeight == 0 || + mPreviewSize.getWidth() == bestWidth && + mPreviewSize.getHeight() == bestHeight ) + return false; + else { + mPreviewSize = new Size(bestWidth, bestHeight); + return true; + } + } catch (CameraAccessException e) { + Log.e(LOGTAG, "cacPreviewSize - Camera Access Exception"); + } catch (IllegalArgumentException e) { + Log.e(LOGTAG, "cacPreviewSize - Illegal Argument Exception"); + } catch (SecurityException e) { + Log.e(LOGTAG, "cacPreviewSize - Security Exception"); + } + return false; + } + + @Override + protected void openCamera(int id) { + Log.i(LOGTAG, "openCamera"); + CameraManager manager = (CameraManager) mView.getContext().getSystemService(Context.CAMERA_SERVICE); + try { + String camList[] = manager.getCameraIdList(); + if(camList.length == 0) { + Log.e(LOGTAG, "Error: camera isn't detected."); + return; + } + if(id == CameraBridgeViewBase.CAMERA_ID_ANY) { + mCameraID = camList[0]; + } else { + for (String cameraID : camList) { + CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraID); + if( id == CameraBridgeViewBase.CAMERA_ID_BACK && + characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK || + id == CameraBridgeViewBase.CAMERA_ID_FRONT && + characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) { + mCameraID = cameraID; + break; + } + } + } + if(mCameraID != null) { + if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) { + throw new RuntimeException( + "Time out waiting to lock camera opening."); + } + Log.i(LOGTAG, "Opening camera: " + mCameraID); + manager.openCamera(mCameraID, mStateCallback, mBackgroundHandler); + } + } catch (CameraAccessException e) { + Log.e(LOGTAG, "OpenCamera - Camera Access Exception"); + } catch (IllegalArgumentException e) { + Log.e(LOGTAG, "OpenCamera - Illegal Argument Exception"); + } catch (SecurityException e) { + Log.e(LOGTAG, "OpenCamera - Security Exception"); + } catch (InterruptedException e) { + Log.e(LOGTAG, "OpenCamera - Interrupted Exception"); + } + } + + @Override + protected void closeCamera() { + Log.i(LOGTAG, "closeCamera"); + try { + mCameraOpenCloseLock.acquire(); + if (null != mCaptureSession) { + mCaptureSession.close(); + mCaptureSession = null; + } + if (null != mCameraDevice) { + mCameraDevice.close(); + mCameraDevice = null; + } + } catch (InterruptedException e) { + throw new RuntimeException("Interrupted while trying to lock camera closing.", e); + } finally { + mCameraOpenCloseLock.release(); + } + } + + private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() { + + @Override + public void onOpened(CameraDevice cameraDevice) { + mCameraDevice = cameraDevice; + mCameraOpenCloseLock.release(); + createCameraPreviewSession(); + } + + @Override + public void onDisconnected(CameraDevice cameraDevice) { + cameraDevice.close(); + mCameraDevice = null; + mCameraOpenCloseLock.release(); + } + + @Override + public void onError(CameraDevice cameraDevice, int error) { + cameraDevice.close(); + mCameraDevice = null; + mCameraOpenCloseLock.release(); + } + + }; + + private void createCameraPreviewSession() { + int w=mPreviewSize.getWidth(), h=mPreviewSize.getHeight(); + Log.i(LOGTAG, "createCameraPreviewSession("+w+"x"+h+")"); + if(w<0 || h<0) + return; + try { + mCameraOpenCloseLock.acquire(); + if (null == mCameraDevice) { + mCameraOpenCloseLock.release(); + Log.e(LOGTAG, "createCameraPreviewSession: camera isn't opened"); + return; + } + if (null != mCaptureSession) { + mCameraOpenCloseLock.release(); + Log.e(LOGTAG, "createCameraPreviewSession: mCaptureSession is already started"); + return; + } + if(null == mSTexture) { + mCameraOpenCloseLock.release(); + Log.e(LOGTAG, "createCameraPreviewSession: preview SurfaceTexture is null"); + return; + } + mSTexture.setDefaultBufferSize(w, h); + + Surface surface = new Surface(mSTexture); + + mPreviewRequestBuilder = mCameraDevice + .createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); + mPreviewRequestBuilder.addTarget(surface); + + mCameraDevice.createCaptureSession(Arrays.asList(surface), + new CameraCaptureSession.StateCallback() { + @Override + public void onConfigured( CameraCaptureSession cameraCaptureSession) { + mCaptureSession = cameraCaptureSession; + try { + mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); + mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); + + mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), null, mBackgroundHandler); + Log.i(LOGTAG, "CameraPreviewSession has been started"); + } catch (CameraAccessException e) { + Log.e(LOGTAG, "createCaptureSession failed"); + } + mCameraOpenCloseLock.release(); + } + + @Override + public void onConfigureFailed( + CameraCaptureSession cameraCaptureSession) { + Log.e(LOGTAG, "createCameraPreviewSession failed"); + mCameraOpenCloseLock.release(); + } + }, mBackgroundHandler); + } catch (CameraAccessException e) { + Log.e(LOGTAG, "createCameraPreviewSession"); + } catch (InterruptedException e) { + throw new RuntimeException( + "Interrupted while createCameraPreviewSession", e); + } + finally { + //mCameraOpenCloseLock.release(); + } + } + + private void startBackgroundThread() { + Log.i(LOGTAG, "startBackgroundThread"); + stopBackgroundThread(); + mBackgroundThread = new HandlerThread("CameraBackground"); + mBackgroundThread.start(); + mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); + } + + private void stopBackgroundThread() { + Log.i(LOGTAG, "stopBackgroundThread"); + if(mBackgroundThread == null) + return; + mBackgroundThread.quitSafely(); + try { + mBackgroundThread.join(); + mBackgroundThread = null; + mBackgroundHandler = null; + } catch (InterruptedException e) { + Log.e(LOGTAG, "stopBackgroundThread"); + } + } + + @Override + protected void setCameraPreviewSize(int width, int height) { + Log.i(LOGTAG, "setCameraPreviewSize("+width+"x"+height+")"); + if(mMaxCameraWidth > 0 && mMaxCameraWidth < width) width = mMaxCameraWidth; + if(mMaxCameraHeight > 0 && mMaxCameraHeight < height) height = mMaxCameraHeight; + try { + mCameraOpenCloseLock.acquire(); + + boolean needReconfig = cacPreviewSize(width, height); + mCameraWidth = mPreviewSize.getWidth(); + mCameraHeight = mPreviewSize.getHeight(); + + if( !needReconfig ) { + mCameraOpenCloseLock.release(); + return; + } + if (null != mCaptureSession) { + Log.d(LOGTAG, "closing existing previewSession"); + mCaptureSession.close(); + mCaptureSession = null; + } + mCameraOpenCloseLock.release(); + createCameraPreviewSession(); + } catch (InterruptedException e) { + mCameraOpenCloseLock.release(); + throw new RuntimeException("Interrupted while setCameraPreviewSize.", e); + } + } +} diff --git a/OpenCV/src/main/java/org/opencv/android/CameraBridgeViewBase.java b/OpenCV/src/main/java/org/opencv/android/CameraBridgeViewBase.java new file mode 100644 index 00000000..54871057 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/android/CameraBridgeViewBase.java @@ -0,0 +1,495 @@ +package org.opencv.android; + +import java.util.List; + +import org.opencv.BuildConfig; +import org.opencv.R; +import org.opencv.core.Mat; +import org.opencv.core.Size; + +import android.app.Activity; +import android.app.AlertDialog; +import android.content.Context; +import android.content.DialogInterface; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.util.AttributeSet; +import android.util.Log; +import android.view.SurfaceHolder; +import android.view.SurfaceView; + +/** + * This is a basic class, implementing the interaction with Camera and OpenCV library. + * The main responsibility of it - is to control when camera can be enabled, process the frame, + * call external listener to make any adjustments to the frame and then draw the resulting + * frame to the screen. + * The clients shall implement CvCameraViewListener. + */ +public abstract class CameraBridgeViewBase extends SurfaceView implements SurfaceHolder.Callback { + + private static final String TAG = "CameraBridge"; + private static final int MAX_UNSPECIFIED = -1; + private static final int STOPPED = 0; + private static final int STARTED = 1; + + private int mState = STOPPED; + private Bitmap mCacheBitmap; + private CvCameraViewListener2 mListener; + private boolean mSurfaceExist; + private final Object mSyncObject = new Object(); + + protected int mFrameWidth; + protected int mFrameHeight; + protected int mMaxHeight; + protected int mMaxWidth; + protected float mScale = 0; + protected int mPreviewFormat = RGBA; + protected int mCameraIndex = CAMERA_ID_ANY; + protected boolean mEnabled; + protected FpsMeter mFpsMeter = null; + + public static final int CAMERA_ID_ANY = -1; + public static final int CAMERA_ID_BACK = 99; + public static final int CAMERA_ID_FRONT = 98; + public static final int RGBA = 1; + public static final int GRAY = 2; + + public CameraBridgeViewBase(Context context, int cameraId) { + super(context); + mCameraIndex = cameraId; + getHolder().addCallback(this); + mMaxWidth = MAX_UNSPECIFIED; + mMaxHeight = MAX_UNSPECIFIED; + } + + public CameraBridgeViewBase(Context context, AttributeSet attrs) { + super(context, attrs); + + int count = attrs.getAttributeCount(); + Log.d(TAG, "Attr count: " + Integer.valueOf(count)); + + TypedArray styledAttrs = getContext().obtainStyledAttributes(attrs, R.styleable.CameraBridgeViewBase); + if (styledAttrs.getBoolean(R.styleable.CameraBridgeViewBase_show_fps, false)) + enableFpsMeter(); + + mCameraIndex = styledAttrs.getInt(R.styleable.CameraBridgeViewBase_camera_id, -1); + + getHolder().addCallback(this); + mMaxWidth = MAX_UNSPECIFIED; + mMaxHeight = MAX_UNSPECIFIED; + styledAttrs.recycle(); + } + + /** + * Sets the camera index + * @param cameraIndex new camera index + */ + public void setCameraIndex(int cameraIndex) { + this.mCameraIndex = cameraIndex; + } + + public interface CvCameraViewListener { + /** + * This method is invoked when camera preview has started. After this method is invoked + * the frames will start to be delivered to client via the onCameraFrame() callback. + * @param width - the width of the frames that will be delivered + * @param height - the height of the frames that will be delivered + */ + public void onCameraViewStarted(int width, int height); + + /** + * This method is invoked when camera preview has been stopped for some reason. + * No frames will be delivered via onCameraFrame() callback after this method is called. + */ + public void onCameraViewStopped(); + + /** + * This method is invoked when delivery of the frame needs to be done. + * The returned values - is a modified frame which needs to be displayed on the screen. + * TODO: pass the parameters specifying the format of the frame (BPP, YUV or RGB and etc) + */ + public Mat onCameraFrame(Mat inputFrame); + } + + public interface CvCameraViewListener2 { + /** + * This method is invoked when camera preview has started. After this method is invoked + * the frames will start to be delivered to client via the onCameraFrame() callback. + * @param width - the width of the frames that will be delivered + * @param height - the height of the frames that will be delivered + */ + public void onCameraViewStarted(int width, int height); + + /** + * This method is invoked when camera preview has been stopped for some reason. + * No frames will be delivered via onCameraFrame() callback after this method is called. + */ + public void onCameraViewStopped(); + + /** + * This method is invoked when delivery of the frame needs to be done. + * The returned values - is a modified frame which needs to be displayed on the screen. + * TODO: pass the parameters specifying the format of the frame (BPP, YUV or RGB and etc) + */ + public Mat onCameraFrame(CvCameraViewFrame inputFrame); + }; + + protected class CvCameraViewListenerAdapter implements CvCameraViewListener2 { + public CvCameraViewListenerAdapter(CvCameraViewListener oldStypeListener) { + mOldStyleListener = oldStypeListener; + } + + public void onCameraViewStarted(int width, int height) { + mOldStyleListener.onCameraViewStarted(width, height); + } + + public void onCameraViewStopped() { + mOldStyleListener.onCameraViewStopped(); + } + + public Mat onCameraFrame(CvCameraViewFrame inputFrame) { + Mat result = null; + switch (mPreviewFormat) { + case RGBA: + result = mOldStyleListener.onCameraFrame(inputFrame.rgba()); + break; + case GRAY: + result = mOldStyleListener.onCameraFrame(inputFrame.gray()); + break; + default: + Log.e(TAG, "Invalid frame format! Only RGBA and Gray Scale are supported!"); + }; + + return result; + } + + public void setFrameFormat(int format) { + mPreviewFormat = format; + } + + private int mPreviewFormat = RGBA; + private CvCameraViewListener mOldStyleListener; + }; + + /** + * This class interface is abstract representation of single frame from camera for onCameraFrame callback + * Attention: Do not use objects, that represents this interface out of onCameraFrame callback! + */ + public interface CvCameraViewFrame { + + /** + * This method returns RGBA Mat with frame + */ + public Mat rgba(); + + /** + * This method returns single channel gray scale Mat with frame + */ + public Mat gray(); + }; + + public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { + Log.d(TAG, "call surfaceChanged event"); + synchronized(mSyncObject) { + if (!mSurfaceExist) { + mSurfaceExist = true; + checkCurrentState(); + } else { + /** Surface changed. We need to stop camera and restart with new parameters */ + /* Pretend that old surface has been destroyed */ + mSurfaceExist = false; + checkCurrentState(); + /* Now use new surface. Say we have it now */ + mSurfaceExist = true; + checkCurrentState(); + } + } + } + + public void surfaceCreated(SurfaceHolder holder) { + /* Do nothing. Wait until surfaceChanged delivered */ + } + + public void surfaceDestroyed(SurfaceHolder holder) { + synchronized(mSyncObject) { + mSurfaceExist = false; + checkCurrentState(); + } + } + + /** + * This method is provided for clients, so they can enable the camera connection. + * The actual onCameraViewStarted callback will be delivered only after both this method is called and surface is available + */ + public void enableView() { + synchronized(mSyncObject) { + mEnabled = true; + checkCurrentState(); + } + } + + /** + * This method is provided for clients, so they can disable camera connection and stop + * the delivery of frames even though the surface view itself is not destroyed and still stays on the scren + */ + public void disableView() { + synchronized(mSyncObject) { + mEnabled = false; + checkCurrentState(); + } + } + + /** + * This method enables label with fps value on the screen + */ + public void enableFpsMeter() { + if (mFpsMeter == null) { + mFpsMeter = new FpsMeter(); + mFpsMeter.setResolution(mFrameWidth, mFrameHeight); + } + } + + public void disableFpsMeter() { + mFpsMeter = null; + } + + /** + * + * @param listener + */ + + public void setCvCameraViewListener(CvCameraViewListener2 listener) { + mListener = listener; + } + + public void setCvCameraViewListener(CvCameraViewListener listener) { + CvCameraViewListenerAdapter adapter = new CvCameraViewListenerAdapter(listener); + adapter.setFrameFormat(mPreviewFormat); + mListener = adapter; + } + + /** + * This method sets the maximum size that camera frame is allowed to be. When selecting + * size - the biggest size which less or equal the size set will be selected. + * As an example - we set setMaxFrameSize(200,200) and we have 176x152 and 320x240 sizes. The + * preview frame will be selected with 176x152 size. + * This method is useful when need to restrict the size of preview frame for some reason (for example for video recording) + * @param maxWidth - the maximum width allowed for camera frame. + * @param maxHeight - the maximum height allowed for camera frame + */ + public void setMaxFrameSize(int maxWidth, int maxHeight) { + mMaxWidth = maxWidth; + mMaxHeight = maxHeight; + } + + public void SetCaptureFormat(int format) + { + mPreviewFormat = format; + if (mListener instanceof CvCameraViewListenerAdapter) { + CvCameraViewListenerAdapter adapter = (CvCameraViewListenerAdapter) mListener; + adapter.setFrameFormat(mPreviewFormat); + } + } + + /** + * Called when mSyncObject lock is held + */ + private void checkCurrentState() { + Log.d(TAG, "call checkCurrentState"); + int targetState; + + if (mEnabled && mSurfaceExist && getVisibility() == VISIBLE) { + targetState = STARTED; + } else { + targetState = STOPPED; + } + + if (targetState != mState) { + /* The state change detected. Need to exit the current state and enter target state */ + processExitState(mState); + mState = targetState; + processEnterState(mState); + } + } + + private void processEnterState(int state) { + Log.d(TAG, "call processEnterState: " + state); + switch(state) { + case STARTED: + onEnterStartedState(); + if (mListener != null) { + mListener.onCameraViewStarted(mFrameWidth, mFrameHeight); + } + break; + case STOPPED: + onEnterStoppedState(); + if (mListener != null) { + mListener.onCameraViewStopped(); + } + break; + }; + } + + private void processExitState(int state) { + Log.d(TAG, "call processExitState: " + state); + switch(state) { + case STARTED: + onExitStartedState(); + break; + case STOPPED: + onExitStoppedState(); + break; + }; + } + + private void onEnterStoppedState() { + /* nothing to do */ + } + + private void onExitStoppedState() { + /* nothing to do */ + } + + // NOTE: The order of bitmap constructor and camera connection is important for android 4.1.x + // Bitmap must be constructed before surface + private void onEnterStartedState() { + Log.d(TAG, "call onEnterStartedState"); + /* Connect camera */ + if (!connectCamera(getWidth(), getHeight())) { + AlertDialog ad = new AlertDialog.Builder(getContext()).create(); + ad.setCancelable(false); // This blocks the 'BACK' button + ad.setMessage("It seems that you device does not support camera (or it is locked). Application will be closed."); + ad.setButton(DialogInterface.BUTTON_NEUTRAL, "OK", new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + ((Activity) getContext()).finish(); + } + }); + ad.show(); + + } + } + + private void onExitStartedState() { + disconnectCamera(); + if (mCacheBitmap != null) { + mCacheBitmap.recycle(); + } + } + + /** + * This method shall be called by the subclasses when they have valid + * object and want it to be delivered to external client (via callback) and + * then displayed on the screen. + * @param frame - the current frame to be delivered + */ + protected void deliverAndDrawFrame(CvCameraViewFrame frame) { + Mat modified; + + if (mListener != null) { + modified = mListener.onCameraFrame(frame); + } else { + modified = frame.rgba(); + } + + boolean bmpValid = true; + if (modified != null) { + try { + Utils.matToBitmap(modified, mCacheBitmap); + } catch(Exception e) { + Log.e(TAG, "Mat type: " + modified); + Log.e(TAG, "Bitmap type: " + mCacheBitmap.getWidth() + "*" + mCacheBitmap.getHeight()); + Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage()); + bmpValid = false; + } + } + + if (bmpValid && mCacheBitmap != null) { + Canvas canvas = getHolder().lockCanvas(); + if (canvas != null) { + canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR); + if (BuildConfig.DEBUG) + Log.d(TAG, "mStretch value: " + mScale); + + if (mScale != 0) { + canvas.drawBitmap(mCacheBitmap, new Rect(0,0,mCacheBitmap.getWidth(), mCacheBitmap.getHeight()), + new Rect((int)((canvas.getWidth() - mScale*mCacheBitmap.getWidth()) / 2), + (int)((canvas.getHeight() - mScale*mCacheBitmap.getHeight()) / 2), + (int)((canvas.getWidth() - mScale*mCacheBitmap.getWidth()) / 2 + mScale*mCacheBitmap.getWidth()), + (int)((canvas.getHeight() - mScale*mCacheBitmap.getHeight()) / 2 + mScale*mCacheBitmap.getHeight())), null); + } else { + canvas.drawBitmap(mCacheBitmap, new Rect(0,0,mCacheBitmap.getWidth(), mCacheBitmap.getHeight()), + new Rect((canvas.getWidth() - mCacheBitmap.getWidth()) / 2, + (canvas.getHeight() - mCacheBitmap.getHeight()) / 2, + (canvas.getWidth() - mCacheBitmap.getWidth()) / 2 + mCacheBitmap.getWidth(), + (canvas.getHeight() - mCacheBitmap.getHeight()) / 2 + mCacheBitmap.getHeight()), null); + } + + if (mFpsMeter != null) { + mFpsMeter.measure(); + mFpsMeter.draw(canvas, 20, 30); + } + getHolder().unlockCanvasAndPost(canvas); + } + } + } + + /** + * This method is invoked shall perform concrete operation to initialize the camera. + * CONTRACT: as a result of this method variables mFrameWidth and mFrameHeight MUST be + * initialized with the size of the Camera frames that will be delivered to external processor. + * @param width - the width of this SurfaceView + * @param height - the height of this SurfaceView + */ + protected abstract boolean connectCamera(int width, int height); + + /** + * Disconnects and release the particular camera object being connected to this surface view. + * Called when syncObject lock is held + */ + protected abstract void disconnectCamera(); + + // NOTE: On Android 4.1.x the function must be called before SurfaceTexture constructor! + protected void AllocateCache() + { + mCacheBitmap = Bitmap.createBitmap(mFrameWidth, mFrameHeight, Bitmap.Config.ARGB_8888); + } + + public interface ListItemAccessor { + public int getWidth(Object obj); + public int getHeight(Object obj); + }; + + /** + * This helper method can be called by subclasses to select camera preview size. + * It goes over the list of the supported preview sizes and selects the maximum one which + * fits both values set via setMaxFrameSize() and surface frame allocated for this view + * @param supportedSizes + * @param surfaceWidth + * @param surfaceHeight + * @return optimal frame size + */ + protected Size calculateCameraFrameSize(List supportedSizes, ListItemAccessor accessor, int surfaceWidth, int surfaceHeight) { + int calcWidth = 0; + int calcHeight = 0; + + int maxAllowedWidth = (mMaxWidth != MAX_UNSPECIFIED && mMaxWidth < surfaceWidth)? mMaxWidth : surfaceWidth; + int maxAllowedHeight = (mMaxHeight != MAX_UNSPECIFIED && mMaxHeight < surfaceHeight)? mMaxHeight : surfaceHeight; + + for (Object size : supportedSizes) { + int width = accessor.getWidth(size); + int height = accessor.getHeight(size); + + if (width <= maxAllowedWidth && height <= maxAllowedHeight) { + if (width >= calcWidth && height >= calcHeight) { + calcWidth = (int) width; + calcHeight = (int) height; + } + } + } + + return new Size(calcWidth, calcHeight); + } +} diff --git a/OpenCV/src/main/java/org/opencv/android/CameraGLRendererBase.java b/OpenCV/src/main/java/org/opencv/android/CameraGLRendererBase.java new file mode 100644 index 00000000..60c37c30 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/android/CameraGLRendererBase.java @@ -0,0 +1,440 @@ +package org.opencv.android; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.nio.FloatBuffer; + +import javax.microedition.khronos.egl.EGLConfig; +import javax.microedition.khronos.opengles.GL10; + +import org.opencv.android.CameraGLSurfaceView.CameraTextureListener; + +import android.annotation.TargetApi; +import android.graphics.SurfaceTexture; +import android.opengl.GLES11Ext; +import android.opengl.GLES20; +import android.opengl.GLSurfaceView; +import android.util.Log; +import android.view.View; + +@TargetApi(15) +public abstract class CameraGLRendererBase implements GLSurfaceView.Renderer, SurfaceTexture.OnFrameAvailableListener { + + protected final String LOGTAG = "CameraGLRendererBase"; + + // shaders + private final String vss = "" + + "attribute vec2 vPosition;\n" + + "attribute vec2 vTexCoord;\n" + "varying vec2 texCoord;\n" + + "void main() {\n" + " texCoord = vTexCoord;\n" + + " gl_Position = vec4 ( vPosition.x, vPosition.y, 0.0, 1.0 );\n" + + "}"; + + private final String fssOES = "" + + "#extension GL_OES_EGL_image_external : require\n" + + "precision mediump float;\n" + + "uniform samplerExternalOES sTexture;\n" + + "varying vec2 texCoord;\n" + + "void main() {\n" + + " gl_FragColor = texture2D(sTexture,texCoord);\n" + "}"; + + private final String fss2D = "" + + "precision mediump float;\n" + + "uniform sampler2D sTexture;\n" + + "varying vec2 texCoord;\n" + + "void main() {\n" + + " gl_FragColor = texture2D(sTexture,texCoord);\n" + "}"; + + // coord-s + private final float vertices[] = { + -1, -1, + -1, 1, + 1, -1, + 1, 1 }; + private final float texCoordOES[] = { + 0, 1, + 0, 0, + 1, 1, + 1, 0 }; + private final float texCoord2D[] = { + 0, 0, + 0, 1, + 1, 0, + 1, 1 }; + + private int[] texCamera = {0}, texFBO = {0}, texDraw = {0}; + private int[] FBO = {0}; + private int progOES = -1, prog2D = -1; + private int vPosOES, vTCOES, vPos2D, vTC2D; + + private FloatBuffer vert, texOES, tex2D; + + protected int mCameraWidth = -1, mCameraHeight = -1; + protected int mFBOWidth = -1, mFBOHeight = -1; + protected int mMaxCameraWidth = -1, mMaxCameraHeight = -1; + protected int mCameraIndex = CameraBridgeViewBase.CAMERA_ID_ANY; + + protected SurfaceTexture mSTexture; + + protected boolean mHaveSurface = false; + protected boolean mHaveFBO = false; + protected boolean mUpdateST = false; + protected boolean mEnabled = true; + protected boolean mIsStarted = false; + + protected CameraGLSurfaceView mView; + + protected abstract void openCamera(int id); + protected abstract void closeCamera(); + protected abstract void setCameraPreviewSize(int width, int height); // updates mCameraWidth & mCameraHeight + + public CameraGLRendererBase(CameraGLSurfaceView view) { + mView = view; + int bytes = vertices.length * Float.SIZE / Byte.SIZE; + vert = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer(); + texOES = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer(); + tex2D = ByteBuffer.allocateDirect(bytes).order(ByteOrder.nativeOrder()).asFloatBuffer(); + vert.put(vertices).position(0); + texOES.put(texCoordOES).position(0); + tex2D.put(texCoord2D).position(0); + } + + @Override + public synchronized void onFrameAvailable(SurfaceTexture surfaceTexture) { + //Log.i(LOGTAG, "onFrameAvailable"); + mUpdateST = true; + mView.requestRender(); + } + + @Override + public void onDrawFrame(GL10 gl) { + //Log.i(LOGTAG, "onDrawFrame start"); + + if (!mHaveFBO) + return; + + synchronized(this) { + if (mUpdateST) { + mSTexture.updateTexImage(); + mUpdateST = false; + } + + GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); + + CameraTextureListener texListener = mView.getCameraTextureListener(); + if(texListener != null) { + //Log.d(LOGTAG, "haveUserCallback"); + // texCamera(OES) -> texFBO + drawTex(texCamera[0], true, FBO[0]); + + // call user code (texFBO -> texDraw) + boolean modified = texListener.onCameraTexture(texFBO[0], texDraw[0], mCameraWidth, mCameraHeight); + + if(modified) { + // texDraw -> screen + drawTex(texDraw[0], false, 0); + } else { + // texFBO -> screen + drawTex(texFBO[0], false, 0); + } + } else { + Log.d(LOGTAG, "texCamera(OES) -> screen"); + // texCamera(OES) -> screen + drawTex(texCamera[0], true, 0); + } + //Log.i(LOGTAG, "onDrawFrame end"); + } + } + + @Override + public void onSurfaceChanged(GL10 gl, int surfaceWidth, int surfaceHeight) { + Log.i(LOGTAG, "onSurfaceChanged("+surfaceWidth+"x"+surfaceHeight+")"); + mHaveSurface = true; + updateState(); + setPreviewSize(surfaceWidth, surfaceHeight); + } + + @Override + public void onSurfaceCreated(GL10 gl, EGLConfig config) { + Log.i(LOGTAG, "onSurfaceCreated"); + initShaders(); + } + + private void initShaders() { + String strGLVersion = GLES20.glGetString(GLES20.GL_VERSION); + if (strGLVersion != null) + Log.i(LOGTAG, "OpenGL ES version: " + strGLVersion); + + GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f); + + progOES = loadShader(vss, fssOES); + vPosOES = GLES20.glGetAttribLocation(progOES, "vPosition"); + vTCOES = GLES20.glGetAttribLocation(progOES, "vTexCoord"); + GLES20.glEnableVertexAttribArray(vPosOES); + GLES20.glEnableVertexAttribArray(vTCOES); + + prog2D = loadShader(vss, fss2D); + vPos2D = GLES20.glGetAttribLocation(prog2D, "vPosition"); + vTC2D = GLES20.glGetAttribLocation(prog2D, "vTexCoord"); + GLES20.glEnableVertexAttribArray(vPos2D); + GLES20.glEnableVertexAttribArray(vTC2D); + } + + private void initSurfaceTexture() { + Log.d(LOGTAG, "initSurfaceTexture"); + deleteSurfaceTexture(); + initTexOES(texCamera); + mSTexture = new SurfaceTexture(texCamera[0]); + mSTexture.setOnFrameAvailableListener(this); + } + + private void deleteSurfaceTexture() { + Log.d(LOGTAG, "deleteSurfaceTexture"); + if(mSTexture != null) { + mSTexture.release(); + mSTexture = null; + deleteTex(texCamera); + } + } + + private void initTexOES(int[] tex) { + if(tex.length == 1) { + GLES20.glGenTextures(1, tex, 0); + GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex[0]); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); + GLES20.glTexParameteri(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); + } + } + + private static void deleteTex(int[] tex) { + if(tex.length == 1) { + GLES20.glDeleteTextures(1, tex, 0); + } + } + + private static int loadShader(String vss, String fss) { + Log.d("CameraGLRendererBase", "loadShader"); + int vshader = GLES20.glCreateShader(GLES20.GL_VERTEX_SHADER); + GLES20.glShaderSource(vshader, vss); + GLES20.glCompileShader(vshader); + int[] status = new int[1]; + GLES20.glGetShaderiv(vshader, GLES20.GL_COMPILE_STATUS, status, 0); + if (status[0] == 0) { + Log.e("CameraGLRendererBase", "Could not compile vertex shader: "+GLES20.glGetShaderInfoLog(vshader)); + GLES20.glDeleteShader(vshader); + vshader = 0; + return 0; + } + + int fshader = GLES20.glCreateShader(GLES20.GL_FRAGMENT_SHADER); + GLES20.glShaderSource(fshader, fss); + GLES20.glCompileShader(fshader); + GLES20.glGetShaderiv(fshader, GLES20.GL_COMPILE_STATUS, status, 0); + if (status[0] == 0) { + Log.e("CameraGLRendererBase", "Could not compile fragment shader:"+GLES20.glGetShaderInfoLog(fshader)); + GLES20.glDeleteShader(vshader); + GLES20.glDeleteShader(fshader); + fshader = 0; + return 0; + } + + int program = GLES20.glCreateProgram(); + GLES20.glAttachShader(program, vshader); + GLES20.glAttachShader(program, fshader); + GLES20.glLinkProgram(program); + GLES20.glDeleteShader(vshader); + GLES20.glDeleteShader(fshader); + GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, status, 0); + if (status[0] == 0) { + Log.e("CameraGLRendererBase", "Could not link shader program: "+GLES20.glGetProgramInfoLog(program)); + program = 0; + return 0; + } + GLES20.glValidateProgram(program); + GLES20.glGetProgramiv(program, GLES20.GL_VALIDATE_STATUS, status, 0); + if (status[0] == 0) + { + Log.e("CameraGLRendererBase", "Shader program validation error: "+GLES20.glGetProgramInfoLog(program)); + GLES20.glDeleteProgram(program); + program = 0; + return 0; + } + + Log.d("CameraGLRendererBase", "Shader program is built OK"); + + return program; + } + + private void deleteFBO() + { + Log.d(LOGTAG, "deleteFBO("+mFBOWidth+"x"+mFBOHeight+")"); + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0); + GLES20.glDeleteFramebuffers(1, FBO, 0); + + deleteTex(texFBO); + deleteTex(texDraw); + mFBOWidth = mFBOHeight = 0; + } + + private void initFBO(int width, int height) + { + Log.d(LOGTAG, "initFBO("+width+"x"+height+")"); + + deleteFBO(); + + GLES20.glGenTextures(1, texDraw, 0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texDraw[0]); + GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); + + GLES20.glGenTextures(1, texFBO, 0); + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texFBO[0]); + GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0, GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST); + GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST); + + //int hFBO; + GLES20.glGenFramebuffers(1, FBO, 0); + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, FBO[0]); + GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, texFBO[0], 0); + Log.d(LOGTAG, "initFBO error status: " + GLES20.glGetError()); + + int FBOstatus = GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER); + if (FBOstatus != GLES20.GL_FRAMEBUFFER_COMPLETE) + Log.e(LOGTAG, "initFBO failed, status: " + FBOstatus); + + mFBOWidth = width; + mFBOHeight = height; + } + + // draw texture to FBO or to screen if fbo == 0 + private void drawTex(int tex, boolean isOES, int fbo) + { + GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbo); + + if(fbo == 0) + GLES20.glViewport(0, 0, mView.getWidth(), mView.getHeight()); + else + GLES20.glViewport(0, 0, mFBOWidth, mFBOHeight); + + GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT); + + if(isOES) { + GLES20.glUseProgram(progOES); + GLES20.glVertexAttribPointer(vPosOES, 2, GLES20.GL_FLOAT, false, 4*2, vert); + GLES20.glVertexAttribPointer(vTCOES, 2, GLES20.GL_FLOAT, false, 4*2, texOES); + } else { + GLES20.glUseProgram(prog2D); + GLES20.glVertexAttribPointer(vPos2D, 2, GLES20.GL_FLOAT, false, 4*2, vert); + GLES20.glVertexAttribPointer(vTC2D, 2, GLES20.GL_FLOAT, false, 4*2, tex2D); + } + + GLES20.glActiveTexture(GLES20.GL_TEXTURE0); + + if(isOES) { + GLES20.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, tex); + GLES20.glUniform1i(GLES20.glGetUniformLocation(progOES, "sTexture"), 0); + } else { + GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, tex); + GLES20.glUniform1i(GLES20.glGetUniformLocation(prog2D, "sTexture"), 0); + } + + GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4); + GLES20.glFlush(); + } + + public synchronized void enableView() { + Log.d(LOGTAG, "enableView"); + mEnabled = true; + updateState(); + } + + public synchronized void disableView() { + Log.d(LOGTAG, "disableView"); + mEnabled = false; + updateState(); + } + + protected void updateState() { + Log.d(LOGTAG, "updateState"); + Log.d(LOGTAG, "mEnabled="+mEnabled+", mHaveSurface="+mHaveSurface); + boolean willStart = mEnabled && mHaveSurface && mView.getVisibility() == View.VISIBLE; + if (willStart != mIsStarted) { + if(willStart) doStart(); + else doStop(); + } else { + Log.d(LOGTAG, "keeping State unchanged"); + } + Log.d(LOGTAG, "updateState end"); + } + + protected synchronized void doStart() { + Log.d(LOGTAG, "doStart"); + initSurfaceTexture(); + openCamera(mCameraIndex); + mIsStarted = true; + if(mCameraWidth>0 && mCameraHeight>0) + setPreviewSize(mCameraWidth, mCameraHeight); // start preview and call listener.onCameraViewStarted() + } + + + protected void doStop() { + Log.d(LOGTAG, "doStop"); + synchronized(this) { + mUpdateST = false; + mIsStarted = false; + mHaveFBO = false; + closeCamera(); + deleteSurfaceTexture(); + } + CameraTextureListener listener = mView.getCameraTextureListener(); + if(listener != null) listener.onCameraViewStopped(); + + } + + protected void setPreviewSize(int width, int height) { + synchronized(this) { + mHaveFBO = false; + mCameraWidth = width; + mCameraHeight = height; + setCameraPreviewSize(width, height); // can change mCameraWidth & mCameraHeight + initFBO(mCameraWidth, mCameraHeight); + mHaveFBO = true; + } + + CameraTextureListener listener = mView.getCameraTextureListener(); + if(listener != null) listener.onCameraViewStarted(mCameraWidth, mCameraHeight); + } + + public void setCameraIndex(int cameraIndex) { + disableView(); + mCameraIndex = cameraIndex; + enableView(); + } + + public void setMaxCameraPreviewSize(int maxWidth, int maxHeight) { + disableView(); + mMaxCameraWidth = maxWidth; + mMaxCameraHeight = maxHeight; + enableView(); + } + + public void onResume() { + Log.i(LOGTAG, "onResume"); + } + + public void onPause() { + Log.i(LOGTAG, "onPause"); + mHaveSurface = false; + updateState(); + mCameraWidth = mCameraHeight = -1; + } + +} diff --git a/OpenCV/src/main/java/org/opencv/android/CameraGLSurfaceView.java b/OpenCV/src/main/java/org/opencv/android/CameraGLSurfaceView.java new file mode 100644 index 00000000..05f950b4 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/android/CameraGLSurfaceView.java @@ -0,0 +1,119 @@ +package org.opencv.android; + +import org.opencv.R; + +import android.content.Context; +import android.content.res.TypedArray; +import android.opengl.GLSurfaceView; +import android.util.AttributeSet; +import android.util.Log; +import android.view.SurfaceHolder; + +public class CameraGLSurfaceView extends GLSurfaceView { + + private static final String LOGTAG = "CameraGLSurfaceView"; + + public interface CameraTextureListener { + /** + * This method is invoked when camera preview has started. After this method is invoked + * the frames will start to be delivered to client via the onCameraFrame() callback. + * @param width - the width of the frames that will be delivered + * @param height - the height of the frames that will be delivered + */ + public void onCameraViewStarted(int width, int height); + + /** + * This method is invoked when camera preview has been stopped for some reason. + * No frames will be delivered via onCameraFrame() callback after this method is called. + */ + public void onCameraViewStopped(); + + /** + * This method is invoked when a new preview frame from Camera is ready. + * @param texIn - the OpenGL texture ID that contains frame in RGBA format + * @param texOut - the OpenGL texture ID that can be used to store modified frame image t display + * @param width - the width of the frame + * @param height - the height of the frame + * @return `true` if `texOut` should be displayed, `false` - to show `texIn` + */ + public boolean onCameraTexture(int texIn, int texOut, int width, int height); + }; + + private CameraTextureListener mTexListener; + private CameraGLRendererBase mRenderer; + + public CameraGLSurfaceView(Context context, AttributeSet attrs) { + super(context, attrs); + + TypedArray styledAttrs = getContext().obtainStyledAttributes(attrs, R.styleable.CameraBridgeViewBase); + int cameraIndex = styledAttrs.getInt(R.styleable.CameraBridgeViewBase_camera_id, -1); + styledAttrs.recycle(); + + if(android.os.Build.VERSION.SDK_INT >= 21) + mRenderer = new Camera2Renderer(this); + else + mRenderer = new CameraRenderer(this); + + setCameraIndex(cameraIndex); + + setEGLContextClientVersion(2); + setRenderer(mRenderer); + setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY); + } + + public void setCameraTextureListener(CameraTextureListener texListener) + { + mTexListener = texListener; + } + + public CameraTextureListener getCameraTextureListener() + { + return mTexListener; + } + + public void setCameraIndex(int cameraIndex) { + mRenderer.setCameraIndex(cameraIndex); + } + + public void setMaxCameraPreviewSize(int maxWidth, int maxHeight) { + mRenderer.setMaxCameraPreviewSize(maxWidth, maxHeight); + } + + @Override + public void surfaceCreated(SurfaceHolder holder) { + super.surfaceCreated(holder); + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + mRenderer.mHaveSurface = false; + super.surfaceDestroyed(holder); + } + + @Override + public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { + super.surfaceChanged(holder, format, w, h); + } + + @Override + public void onResume() { + Log.i(LOGTAG, "onResume"); + super.onResume(); + mRenderer.onResume(); + } + + @Override + public void onPause() { + Log.i(LOGTAG, "onPause"); + mRenderer.onPause(); + super.onPause(); + } + + public void enableView() { + mRenderer.enableView(); + } + + public void disableView() { + mRenderer.disableView(); + } +} diff --git a/OpenCV/src/main/java/org/opencv/android/CameraRenderer.java b/OpenCV/src/main/java/org/opencv/android/CameraRenderer.java new file mode 100644 index 00000000..2d668ffa --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/android/CameraRenderer.java @@ -0,0 +1,166 @@ +package org.opencv.android; + +import java.io.IOException; +import java.util.List; + +import android.annotation.TargetApi; +import android.hardware.Camera; +import android.hardware.Camera.Size; +import android.os.Build; +import android.util.Log; + +@TargetApi(15) +@SuppressWarnings("deprecation") +public class CameraRenderer extends CameraGLRendererBase { + + public static final String LOGTAG = "CameraRenderer"; + + private Camera mCamera; + private boolean mPreviewStarted = false; + + CameraRenderer(CameraGLSurfaceView view) { + super(view); + } + + @Override + protected synchronized void closeCamera() { + Log.i(LOGTAG, "closeCamera"); + if(mCamera != null) { + mCamera.stopPreview(); + mPreviewStarted = false; + mCamera.release(); + mCamera = null; + } + } + + @Override + protected synchronized void openCamera(int id) { + Log.i(LOGTAG, "openCamera"); + closeCamera(); + if (id == CameraBridgeViewBase.CAMERA_ID_ANY) { + Log.d(LOGTAG, "Trying to open camera with old open()"); + try { + mCamera = Camera.open(); + } + catch (Exception e){ + Log.e(LOGTAG, "Camera is not available (in use or does not exist): " + e.getLocalizedMessage()); + } + + if(mCamera == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { + boolean connected = false; + for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) { + Log.d(LOGTAG, "Trying to open camera with new open(" + camIdx + ")"); + try { + mCamera = Camera.open(camIdx); + connected = true; + } catch (RuntimeException e) { + Log.e(LOGTAG, "Camera #" + camIdx + "failed to open: " + e.getLocalizedMessage()); + } + if (connected) break; + } + } + } else { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { + int localCameraIndex = mCameraIndex; + if (mCameraIndex == CameraBridgeViewBase.CAMERA_ID_BACK) { + Log.i(LOGTAG, "Trying to open BACK camera"); + Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); + for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) { + Camera.getCameraInfo( camIdx, cameraInfo ); + if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { + localCameraIndex = camIdx; + break; + } + } + } else if (mCameraIndex == CameraBridgeViewBase.CAMERA_ID_FRONT) { + Log.i(LOGTAG, "Trying to open FRONT camera"); + Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); + for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) { + Camera.getCameraInfo( camIdx, cameraInfo ); + if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { + localCameraIndex = camIdx; + break; + } + } + } + if (localCameraIndex == CameraBridgeViewBase.CAMERA_ID_BACK) { + Log.e(LOGTAG, "Back camera not found!"); + } else if (localCameraIndex == CameraBridgeViewBase.CAMERA_ID_FRONT) { + Log.e(LOGTAG, "Front camera not found!"); + } else { + Log.d(LOGTAG, "Trying to open camera with new open(" + localCameraIndex + ")"); + try { + mCamera = Camera.open(localCameraIndex); + } catch (RuntimeException e) { + Log.e(LOGTAG, "Camera #" + localCameraIndex + "failed to open: " + e.getLocalizedMessage()); + } + } + } + } + if(mCamera == null) { + Log.e(LOGTAG, "Error: can't open camera"); + return; + } + Camera.Parameters params = mCamera.getParameters(); + List FocusModes = params.getSupportedFocusModes(); + if (FocusModes != null && FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) + { + params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); + } + mCamera.setParameters(params); + + try { + mCamera.setPreviewTexture(mSTexture); + } catch (IOException ioe) { + Log.e(LOGTAG, "setPreviewTexture() failed: " + ioe.getMessage()); + } + } + + @Override + public synchronized void setCameraPreviewSize(int width, int height) { + Log.i(LOGTAG, "setCameraPreviewSize: "+width+"x"+height); + if(mCamera == null) { + Log.e(LOGTAG, "Camera isn't initialized!"); + return; + } + + if(mMaxCameraWidth > 0 && mMaxCameraWidth < width) width = mMaxCameraWidth; + if(mMaxCameraHeight > 0 && mMaxCameraHeight < height) height = mMaxCameraHeight; + + Camera.Parameters param = mCamera.getParameters(); + List psize = param.getSupportedPreviewSizes(); + int bestWidth = 0, bestHeight = 0; + if (psize.size() > 0) { + float aspect = (float)width / height; + for (Size size : psize) { + int w = size.width, h = size.height; + Log.d(LOGTAG, "checking camera preview size: "+w+"x"+h); + if ( w <= width && h <= height && + w >= bestWidth && h >= bestHeight && + Math.abs(aspect - (float)w/h) < 0.2 ) { + bestWidth = w; + bestHeight = h; + } + } + if(bestWidth <= 0 || bestHeight <= 0) { + bestWidth = psize.get(0).width; + bestHeight = psize.get(0).height; + Log.e(LOGTAG, "Error: best size was not selected, using "+bestWidth+" x "+bestHeight); + } else { + Log.i(LOGTAG, "Selected best size: "+bestWidth+" x "+bestHeight); + } + + if(mPreviewStarted) { + mCamera.stopPreview(); + mPreviewStarted = false; + } + mCameraWidth = bestWidth; + mCameraHeight = bestHeight; + param.setPreviewSize(bestWidth, bestHeight); + } + param.set("orientation", "landscape"); + mCamera.setParameters(param); + mCamera.startPreview(); + mPreviewStarted = true; + } +} \ No newline at end of file diff --git a/OpenCV/src/main/java/org/opencv/android/FpsMeter.java b/OpenCV/src/main/java/org/opencv/android/FpsMeter.java new file mode 100644 index 00000000..d22c68e4 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/android/FpsMeter.java @@ -0,0 +1,66 @@ +package org.opencv.android; + +import java.text.DecimalFormat; + +import org.opencv.core.Core; + +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.util.Log; + +public class FpsMeter { + private static final String TAG = "FpsMeter"; + private static final int STEP = 20; + private static final DecimalFormat FPS_FORMAT = new DecimalFormat("0.00"); + + private int mFramesCounter; + private double mFrequency; + private long mprevFrameTime; + private String mStrfps; + Paint mPaint; + boolean mIsInitialized = false; + int mWidth = 0; + int mHeight = 0; + + public void init() { + mFramesCounter = 0; + mFrequency = Core.getTickFrequency(); + mprevFrameTime = Core.getTickCount(); + mStrfps = ""; + + mPaint = new Paint(); + mPaint.setColor(Color.BLUE); + mPaint.setTextSize(20); + } + + public void measure() { + if (!mIsInitialized) { + init(); + mIsInitialized = true; + } else { + mFramesCounter++; + if (mFramesCounter % STEP == 0) { + long time = Core.getTickCount(); + double fps = STEP * mFrequency / (time - mprevFrameTime); + mprevFrameTime = time; + if (mWidth != 0 && mHeight != 0) + mStrfps = FPS_FORMAT.format(fps) + " FPS@" + Integer.valueOf(mWidth) + "x" + Integer.valueOf(mHeight); + else + mStrfps = FPS_FORMAT.format(fps) + " FPS"; + Log.i(TAG, mStrfps); + } + } + } + + public void setResolution(int width, int height) { + mWidth = width; + mHeight = height; + } + + public void draw(Canvas canvas, float offsetx, float offsety) { + Log.d(TAG, mStrfps); + canvas.drawText(mStrfps, offsetx, offsety, mPaint); + } + +} diff --git a/OpenCV/src/main/java/org/opencv/android/InstallCallbackInterface.java b/OpenCV/src/main/java/org/opencv/android/InstallCallbackInterface.java new file mode 100644 index 00000000..f68027a7 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/android/InstallCallbackInterface.java @@ -0,0 +1,34 @@ +package org.opencv.android; + +/** + * Installation callback interface. + */ +public interface InstallCallbackInterface +{ + /** + * New package installation is required. + */ + static final int NEW_INSTALLATION = 0; + /** + * Current package installation is in progress. + */ + static final int INSTALLATION_PROGRESS = 1; + + /** + * Target package name. + * @return Return target package name. + */ + public String getPackageName(); + /** + * Installation is approved. + */ + public void install(); + /** + * Installation is canceled. + */ + public void cancel(); + /** + * Wait for package installation. + */ + public void wait_install(); +}; diff --git a/OpenCV/src/main/java/org/opencv/android/JavaCamera2View.java b/OpenCV/src/main/java/org/opencv/android/JavaCamera2View.java new file mode 100644 index 00000000..c22eaa90 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/android/JavaCamera2View.java @@ -0,0 +1,421 @@ +package org.opencv.android; + +import java.nio.ByteBuffer; +import java.util.Arrays; + +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.ImageFormat; +import android.hardware.camera2.CameraAccessException; +import android.hardware.camera2.CameraCaptureSession; +import android.hardware.camera2.CameraCharacteristics; +import android.hardware.camera2.CameraDevice; +import android.hardware.camera2.CameraManager; +import android.hardware.camera2.CaptureRequest; +import android.hardware.camera2.params.StreamConfigurationMap; +import android.media.Image; +import android.media.ImageReader; +import android.os.Handler; +import android.os.HandlerThread; +import android.util.AttributeSet; +import android.util.Log; +import android.view.Surface; +import android.view.ViewGroup.LayoutParams; + +import org.opencv.core.CvType; +import org.opencv.core.Mat; +import org.opencv.imgproc.Imgproc; + +/** + * This class is an implementation of the Bridge View between OpenCV and Java Camera. + * This class relays on the functionality available in base class and only implements + * required functions: + * connectCamera - opens Java camera and sets the PreviewCallback to be delivered. + * disconnectCamera - closes the camera and stops preview. + * When frame is delivered via callback from Camera - it processed via OpenCV to be + * converted to RGBA32 and then passed to the external callback for modifications if required. + */ + +@TargetApi(21) +public class JavaCamera2View extends CameraBridgeViewBase { + + private static final String LOGTAG = "JavaCamera2View"; + + private ImageReader mImageReader; + private int mPreviewFormat = ImageFormat.YUV_420_888; + + private CameraDevice mCameraDevice; + private CameraCaptureSession mCaptureSession; + private CaptureRequest.Builder mPreviewRequestBuilder; + private String mCameraID; + private android.util.Size mPreviewSize = new android.util.Size(-1, -1); + + private HandlerThread mBackgroundThread; + private Handler mBackgroundHandler; + + public JavaCamera2View(Context context, int cameraId) { + super(context, cameraId); + } + + public JavaCamera2View(Context context, AttributeSet attrs) { + super(context, attrs); + } + + private void startBackgroundThread() { + Log.i(LOGTAG, "startBackgroundThread"); + stopBackgroundThread(); + mBackgroundThread = new HandlerThread("OpenCVCameraBackground"); + mBackgroundThread.start(); + mBackgroundHandler = new Handler(mBackgroundThread.getLooper()); + } + + private void stopBackgroundThread() { + Log.i(LOGTAG, "stopBackgroundThread"); + if (mBackgroundThread == null) + return; + mBackgroundThread.quitSafely(); + try { + mBackgroundThread.join(); + mBackgroundThread = null; + mBackgroundHandler = null; + } catch (InterruptedException e) { + Log.e(LOGTAG, "stopBackgroundThread", e); + } + } + + protected boolean initializeCamera() { + Log.i(LOGTAG, "initializeCamera"); + CameraManager manager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE); + try { + String camList[] = manager.getCameraIdList(); + if (camList.length == 0) { + Log.e(LOGTAG, "Error: camera isn't detected."); + return false; + } + if (mCameraIndex == CameraBridgeViewBase.CAMERA_ID_ANY) { + mCameraID = camList[0]; + } else { + for (String cameraID : camList) { + CameraCharacteristics characteristics = manager.getCameraCharacteristics(cameraID); + if ((mCameraIndex == CameraBridgeViewBase.CAMERA_ID_BACK && + characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK) || + (mCameraIndex == CameraBridgeViewBase.CAMERA_ID_FRONT && + characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_FRONT) + ) { + mCameraID = cameraID; + break; + } + } + } + if (mCameraID != null) { + Log.i(LOGTAG, "Opening camera: " + mCameraID); + manager.openCamera(mCameraID, mStateCallback, mBackgroundHandler); + } else { // make JavaCamera2View behaves in the same way as JavaCameraView + Log.i(LOGTAG, "Trying to open camera with the value (" + mCameraIndex + ")"); + if (mCameraIndex < camList.length) { + mCameraID = camList[mCameraIndex]; + manager.openCamera(mCameraID, mStateCallback, mBackgroundHandler); + } else { + // CAMERA_DISCONNECTED is used when the camera id is no longer valid + throw new CameraAccessException(CameraAccessException.CAMERA_DISCONNECTED); + } + } + return true; + } catch (CameraAccessException e) { + Log.e(LOGTAG, "OpenCamera - Camera Access Exception", e); + } catch (IllegalArgumentException e) { + Log.e(LOGTAG, "OpenCamera - Illegal Argument Exception", e); + } catch (SecurityException e) { + Log.e(LOGTAG, "OpenCamera - Security Exception", e); + } + return false; + } + + private final CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() { + + @Override + public void onOpened(CameraDevice cameraDevice) { + mCameraDevice = cameraDevice; + createCameraPreviewSession(); + } + + @Override + public void onDisconnected(CameraDevice cameraDevice) { + cameraDevice.close(); + mCameraDevice = null; + } + + @Override + public void onError(CameraDevice cameraDevice, int error) { + cameraDevice.close(); + mCameraDevice = null; + } + + }; + + private void createCameraPreviewSession() { + final int w = mPreviewSize.getWidth(), h = mPreviewSize.getHeight(); + Log.i(LOGTAG, "createCameraPreviewSession(" + w + "x" + h + ")"); + if (w < 0 || h < 0) + return; + try { + if (null == mCameraDevice) { + Log.e(LOGTAG, "createCameraPreviewSession: camera isn't opened"); + return; + } + if (null != mCaptureSession) { + Log.e(LOGTAG, "createCameraPreviewSession: mCaptureSession is already started"); + return; + } + + mImageReader = ImageReader.newInstance(w, h, mPreviewFormat, 2); + mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() { + @Override + public void onImageAvailable(ImageReader reader) { + Image image = reader.acquireLatestImage(); + if (image == null) + return; + + // sanity checks - 3 planes + Image.Plane[] planes = image.getPlanes(); + assert (planes.length == 3); + assert (image.getFormat() == mPreviewFormat); + + JavaCamera2Frame tempFrame = new JavaCamera2Frame(image); + deliverAndDrawFrame(tempFrame); + tempFrame.release(); + image.close(); + } + }, mBackgroundHandler); + Surface surface = mImageReader.getSurface(); + + mPreviewRequestBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW); + mPreviewRequestBuilder.addTarget(surface); + + mCameraDevice.createCaptureSession(Arrays.asList(surface), + new CameraCaptureSession.StateCallback() { + @Override + public void onConfigured(CameraCaptureSession cameraCaptureSession) { + Log.i(LOGTAG, "createCaptureSession::onConfigured"); + if (null == mCameraDevice) { + return; // camera is already closed + } + mCaptureSession = cameraCaptureSession; + try { + mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, + CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE); + mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, + CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH); + + mCaptureSession.setRepeatingRequest(mPreviewRequestBuilder.build(), null, mBackgroundHandler); + Log.i(LOGTAG, "CameraPreviewSession has been started"); + } catch (Exception e) { + Log.e(LOGTAG, "createCaptureSession failed", e); + } + } + + @Override + public void onConfigureFailed(CameraCaptureSession cameraCaptureSession) { + Log.e(LOGTAG, "createCameraPreviewSession failed"); + } + }, + null + ); + } catch (CameraAccessException e) { + Log.e(LOGTAG, "createCameraPreviewSession", e); + } + } + + @Override + protected void disconnectCamera() { + Log.i(LOGTAG, "closeCamera"); + try { + CameraDevice c = mCameraDevice; + mCameraDevice = null; + if (null != mCaptureSession) { + mCaptureSession.close(); + mCaptureSession = null; + } + if (null != c) { + c.close(); + } + if (null != mImageReader) { + mImageReader.close(); + mImageReader = null; + } + } finally { + stopBackgroundThread(); + } + } + + boolean calcPreviewSize(final int width, final int height) { + Log.i(LOGTAG, "calcPreviewSize: " + width + "x" + height); + if (mCameraID == null) { + Log.e(LOGTAG, "Camera isn't initialized!"); + return false; + } + CameraManager manager = (CameraManager) getContext().getSystemService(Context.CAMERA_SERVICE); + try { + CameraCharacteristics characteristics = manager.getCameraCharacteristics(mCameraID); + StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP); + int bestWidth = 0, bestHeight = 0; + float aspect = (float) width / height; + android.util.Size[] sizes = map.getOutputSizes(ImageReader.class); + bestWidth = sizes[0].getWidth(); + bestHeight = sizes[0].getHeight(); + for (android.util.Size sz : sizes) { + int w = sz.getWidth(), h = sz.getHeight(); + Log.d(LOGTAG, "trying size: " + w + "x" + h); + if (width >= w && height >= h && bestWidth <= w && bestHeight <= h + && Math.abs(aspect - (float) w / h) < 0.2) { + bestWidth = w; + bestHeight = h; + } + } + Log.i(LOGTAG, "best size: " + bestWidth + "x" + bestHeight); + assert(!(bestWidth == 0 || bestHeight == 0)); + if (mPreviewSize.getWidth() == bestWidth && mPreviewSize.getHeight() == bestHeight) + return false; + else { + mPreviewSize = new android.util.Size(bestWidth, bestHeight); + return true; + } + } catch (CameraAccessException e) { + Log.e(LOGTAG, "calcPreviewSize - Camera Access Exception", e); + } catch (IllegalArgumentException e) { + Log.e(LOGTAG, "calcPreviewSize - Illegal Argument Exception", e); + } catch (SecurityException e) { + Log.e(LOGTAG, "calcPreviewSize - Security Exception", e); + } + return false; + } + + @Override + protected boolean connectCamera(int width, int height) { + Log.i(LOGTAG, "setCameraPreviewSize(" + width + "x" + height + ")"); + startBackgroundThread(); + initializeCamera(); + try { + boolean needReconfig = calcPreviewSize(width, height); + mFrameWidth = mPreviewSize.getWidth(); + mFrameHeight = mPreviewSize.getHeight(); + + if ((getLayoutParams().width == LayoutParams.MATCH_PARENT) && (getLayoutParams().height == LayoutParams.MATCH_PARENT)) + mScale = Math.min(((float)height)/mFrameHeight, ((float)width)/mFrameWidth); + else + mScale = 0; + + AllocateCache(); + + if (needReconfig) { + if (null != mCaptureSession) { + Log.d(LOGTAG, "closing existing previewSession"); + mCaptureSession.close(); + mCaptureSession = null; + } + createCameraPreviewSession(); + } + } catch (RuntimeException e) { + throw new RuntimeException("Interrupted while setCameraPreviewSize.", e); + } + return true; + } + + private class JavaCamera2Frame implements CvCameraViewFrame { + @Override + public Mat gray() { + Image.Plane[] planes = mImage.getPlanes(); + int w = mImage.getWidth(); + int h = mImage.getHeight(); + ByteBuffer y_plane = planes[0].getBuffer(); + mGray = new Mat(h, w, CvType.CV_8UC1, y_plane); + return mGray; + } + + @Override + public Mat rgba() { + Image.Plane[] planes = mImage.getPlanes(); + int w = mImage.getWidth(); + int h = mImage.getHeight(); + int chromaPixelStride = planes[1].getPixelStride(); + + + if (chromaPixelStride == 2) { // Chroma channels are interleaved + assert(planes[0].getPixelStride() == 1); + assert(planes[2].getPixelStride() == 2); + ByteBuffer y_plane = planes[0].getBuffer(); + ByteBuffer uv_plane1 = planes[1].getBuffer(); + ByteBuffer uv_plane2 = planes[2].getBuffer(); + Mat y_mat = new Mat(h, w, CvType.CV_8UC1, y_plane); + Mat uv_mat1 = new Mat(h / 2, w / 2, CvType.CV_8UC2, uv_plane1); + Mat uv_mat2 = new Mat(h / 2, w / 2, CvType.CV_8UC2, uv_plane2); + long addr_diff = uv_mat2.dataAddr() - uv_mat1.dataAddr(); + if (addr_diff > 0) { + assert(addr_diff == 1); + Imgproc.cvtColorTwoPlane(y_mat, uv_mat1, mRgba, Imgproc.COLOR_YUV2RGBA_NV12); + } else { + assert(addr_diff == -1); + Imgproc.cvtColorTwoPlane(y_mat, uv_mat2, mRgba, Imgproc.COLOR_YUV2RGBA_NV21); + } + return mRgba; + } else { // Chroma channels are not interleaved + byte[] yuv_bytes = new byte[w*(h+h/2)]; + ByteBuffer y_plane = planes[0].getBuffer(); + ByteBuffer u_plane = planes[1].getBuffer(); + ByteBuffer v_plane = planes[2].getBuffer(); + + y_plane.get(yuv_bytes, 0, w*h); + + int chromaRowStride = planes[1].getRowStride(); + int chromaRowPadding = chromaRowStride - w/2; + + int offset = w*h; + if (chromaRowPadding == 0){ + // When the row stride of the chroma channels equals their width, we can copy + // the entire channels in one go + u_plane.get(yuv_bytes, offset, w*h/4); + offset += w*h/4; + v_plane.get(yuv_bytes, offset, w*h/4); + } else { + // When not equal, we need to copy the channels row by row + for (int i = 0; i < h/2; i++){ + u_plane.get(yuv_bytes, offset, w/2); + offset += w/2; + if (i < h/2-1){ + u_plane.position(u_plane.position() + chromaRowPadding); + } + } + for (int i = 0; i < h/2; i++){ + v_plane.get(yuv_bytes, offset, w/2); + offset += w/2; + if (i < h/2-1){ + v_plane.position(v_plane.position() + chromaRowPadding); + } + } + } + + Mat yuv_mat = new Mat(h+h/2, w, CvType.CV_8UC1); + yuv_mat.put(0, 0, yuv_bytes); + Imgproc.cvtColor(yuv_mat, mRgba, Imgproc.COLOR_YUV2RGBA_I420, 4); + return mRgba; + } + } + + + public JavaCamera2Frame(Image image) { + super(); + mImage = image; + mRgba = new Mat(); + mGray = new Mat(); + } + + public void release() { + mRgba.release(); + mGray.release(); + } + + private Image mImage; + private Mat mRgba; + private Mat mGray; + }; +} diff --git a/OpenCV/src/main/java/org/opencv/android/JavaCameraView.java b/OpenCV/src/main/java/org/opencv/android/JavaCameraView.java new file mode 100644 index 00000000..a7c72e43 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/android/JavaCameraView.java @@ -0,0 +1,379 @@ +package org.opencv.android; + +import java.util.List; + +import android.content.Context; +import android.graphics.ImageFormat; +import android.graphics.SurfaceTexture; +import android.hardware.Camera; +import android.hardware.Camera.PreviewCallback; +import android.os.Build; +import android.util.AttributeSet; +import android.util.Log; +import android.view.ViewGroup.LayoutParams; + +import org.opencv.BuildConfig; +import org.opencv.core.CvType; +import org.opencv.core.Mat; +import org.opencv.core.Size; +import org.opencv.imgproc.Imgproc; + +/** + * This class is an implementation of the Bridge View between OpenCV and Java Camera. + * This class relays on the functionality available in base class and only implements + * required functions: + * connectCamera - opens Java camera and sets the PreviewCallback to be delivered. + * disconnectCamera - closes the camera and stops preview. + * When frame is delivered via callback from Camera - it processed via OpenCV to be + * converted to RGBA32 and then passed to the external callback for modifications if required. + */ +public class JavaCameraView extends CameraBridgeViewBase implements PreviewCallback { + + private static final int MAGIC_TEXTURE_ID = 10; + private static final String TAG = "JavaCameraView"; + + private byte mBuffer[]; + private Mat[] mFrameChain; + private int mChainIdx = 0; + private Thread mThread; + private boolean mStopThread; + + protected Camera mCamera; + protected JavaCameraFrame[] mCameraFrame; + private SurfaceTexture mSurfaceTexture; + private int mPreviewFormat = ImageFormat.NV21; + + public static class JavaCameraSizeAccessor implements ListItemAccessor { + + @Override + public int getWidth(Object obj) { + Camera.Size size = (Camera.Size) obj; + return size.width; + } + + @Override + public int getHeight(Object obj) { + Camera.Size size = (Camera.Size) obj; + return size.height; + } + } + + public JavaCameraView(Context context, int cameraId) { + super(context, cameraId); + } + + public JavaCameraView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + protected boolean initializeCamera(int width, int height) { + Log.d(TAG, "Initialize java camera"); + boolean result = true; + synchronized (this) { + mCamera = null; + + if (mCameraIndex == CAMERA_ID_ANY) { + Log.d(TAG, "Trying to open camera with old open()"); + try { + mCamera = Camera.open(); + } + catch (Exception e){ + Log.e(TAG, "Camera is not available (in use or does not exist): " + e.getLocalizedMessage()); + } + + if(mCamera == null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { + boolean connected = false; + for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) { + Log.d(TAG, "Trying to open camera with new open(" + Integer.valueOf(camIdx) + ")"); + try { + mCamera = Camera.open(camIdx); + connected = true; + } catch (RuntimeException e) { + Log.e(TAG, "Camera #" + camIdx + "failed to open: " + e.getLocalizedMessage()); + } + if (connected) break; + } + } + } else { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) { + int localCameraIndex = mCameraIndex; + if (mCameraIndex == CAMERA_ID_BACK) { + Log.i(TAG, "Trying to open back camera"); + Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); + for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) { + Camera.getCameraInfo( camIdx, cameraInfo ); + if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) { + localCameraIndex = camIdx; + break; + } + } + } else if (mCameraIndex == CAMERA_ID_FRONT) { + Log.i(TAG, "Trying to open front camera"); + Camera.CameraInfo cameraInfo = new Camera.CameraInfo(); + for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) { + Camera.getCameraInfo( camIdx, cameraInfo ); + if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) { + localCameraIndex = camIdx; + break; + } + } + } + if (localCameraIndex == CAMERA_ID_BACK) { + Log.e(TAG, "Back camera not found!"); + } else if (localCameraIndex == CAMERA_ID_FRONT) { + Log.e(TAG, "Front camera not found!"); + } else { + Log.d(TAG, "Trying to open camera with new open(" + Integer.valueOf(localCameraIndex) + ")"); + try { + mCamera = Camera.open(localCameraIndex); + } catch (RuntimeException e) { + Log.e(TAG, "Camera #" + localCameraIndex + "failed to open: " + e.getLocalizedMessage()); + } + } + } + } + + if (mCamera == null) + return false; + + /* Now set camera parameters */ + try { + Camera.Parameters params = mCamera.getParameters(); + Log.d(TAG, "getSupportedPreviewSizes()"); + List sizes = params.getSupportedPreviewSizes(); + + if (sizes != null) { + /* Select the size that fits surface considering maximum size allowed */ + Size frameSize = calculateCameraFrameSize(sizes, new JavaCameraSizeAccessor(), width, height); + + /* Image format NV21 causes issues in the Android emulators */ + if (Build.FINGERPRINT.startsWith("generic") + || Build.FINGERPRINT.startsWith("unknown") + || Build.MODEL.contains("google_sdk") + || Build.MODEL.contains("Emulator") + || Build.MODEL.contains("Android SDK built for x86") + || Build.MANUFACTURER.contains("Genymotion") + || (Build.BRAND.startsWith("generic") && Build.DEVICE.startsWith("generic")) + || "google_sdk".equals(Build.PRODUCT)) + params.setPreviewFormat(ImageFormat.YV12); // "generic" or "android" = android emulator + else + params.setPreviewFormat(ImageFormat.NV21); + + mPreviewFormat = params.getPreviewFormat(); + + Log.d(TAG, "Set preview size to " + Integer.valueOf((int)frameSize.width) + "x" + Integer.valueOf((int)frameSize.height)); + params.setPreviewSize((int)frameSize.width, (int)frameSize.height); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH && !android.os.Build.MODEL.equals("GT-I9100")) + params.setRecordingHint(true); + + List FocusModes = params.getSupportedFocusModes(); + if (FocusModes != null && FocusModes.contains(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO)) + { + params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO); + } + + mCamera.setParameters(params); + params = mCamera.getParameters(); + + mFrameWidth = params.getPreviewSize().width; + mFrameHeight = params.getPreviewSize().height; + + if ((getLayoutParams().width == LayoutParams.MATCH_PARENT) && (getLayoutParams().height == LayoutParams.MATCH_PARENT)) + mScale = Math.min(((float)height)/mFrameHeight, ((float)width)/mFrameWidth); + else + mScale = 0; + + if (mFpsMeter != null) { + mFpsMeter.setResolution(mFrameWidth, mFrameHeight); + } + + int size = mFrameWidth * mFrameHeight; + size = size * ImageFormat.getBitsPerPixel(params.getPreviewFormat()) / 8; + mBuffer = new byte[size]; + + mCamera.addCallbackBuffer(mBuffer); + mCamera.setPreviewCallbackWithBuffer(this); + + mFrameChain = new Mat[2]; + mFrameChain[0] = new Mat(mFrameHeight + (mFrameHeight/2), mFrameWidth, CvType.CV_8UC1); + mFrameChain[1] = new Mat(mFrameHeight + (mFrameHeight/2), mFrameWidth, CvType.CV_8UC1); + + AllocateCache(); + + mCameraFrame = new JavaCameraFrame[2]; + mCameraFrame[0] = new JavaCameraFrame(mFrameChain[0], mFrameWidth, mFrameHeight); + mCameraFrame[1] = new JavaCameraFrame(mFrameChain[1], mFrameWidth, mFrameHeight); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { + mSurfaceTexture = new SurfaceTexture(MAGIC_TEXTURE_ID); + mCamera.setPreviewTexture(mSurfaceTexture); + } else + mCamera.setPreviewDisplay(null); + + /* Finally we are ready to start the preview */ + Log.d(TAG, "startPreview"); + mCamera.startPreview(); + } + else + result = false; + } catch (Exception e) { + result = false; + e.printStackTrace(); + } + } + + return result; + } + + protected void releaseCamera() { + synchronized (this) { + if (mCamera != null) { + mCamera.stopPreview(); + mCamera.setPreviewCallback(null); + + mCamera.release(); + } + mCamera = null; + if (mFrameChain != null) { + mFrameChain[0].release(); + mFrameChain[1].release(); + } + if (mCameraFrame != null) { + mCameraFrame[0].release(); + mCameraFrame[1].release(); + } + } + } + + private boolean mCameraFrameReady = false; + + @Override + protected boolean connectCamera(int width, int height) { + + /* 1. We need to instantiate camera + * 2. We need to start thread which will be getting frames + */ + /* First step - initialize camera connection */ + Log.d(TAG, "Connecting to camera"); + if (!initializeCamera(width, height)) + return false; + + mCameraFrameReady = false; + + /* now we can start update thread */ + Log.d(TAG, "Starting processing thread"); + mStopThread = false; + mThread = new Thread(new CameraWorker()); + mThread.start(); + + return true; + } + + @Override + protected void disconnectCamera() { + /* 1. We need to stop thread which updating the frames + * 2. Stop camera and release it + */ + Log.d(TAG, "Disconnecting from camera"); + try { + mStopThread = true; + Log.d(TAG, "Notify thread"); + synchronized (this) { + this.notify(); + } + Log.d(TAG, "Waiting for thread"); + if (mThread != null) + mThread.join(); + } catch (InterruptedException e) { + e.printStackTrace(); + } finally { + mThread = null; + } + + /* Now release camera */ + releaseCamera(); + + mCameraFrameReady = false; + } + + @Override + public void onPreviewFrame(byte[] frame, Camera arg1) { + if (BuildConfig.DEBUG) + Log.d(TAG, "Preview Frame received. Frame size: " + frame.length); + synchronized (this) { + mFrameChain[mChainIdx].put(0, 0, frame); + mCameraFrameReady = true; + this.notify(); + } + if (mCamera != null) + mCamera.addCallbackBuffer(mBuffer); + } + + private class JavaCameraFrame implements CvCameraViewFrame { + @Override + public Mat gray() { + return mYuvFrameData.submat(0, mHeight, 0, mWidth); + } + + @Override + public Mat rgba() { + if (mPreviewFormat == ImageFormat.NV21) + Imgproc.cvtColor(mYuvFrameData, mRgba, Imgproc.COLOR_YUV2RGBA_NV21, 4); + else if (mPreviewFormat == ImageFormat.YV12) + Imgproc.cvtColor(mYuvFrameData, mRgba, Imgproc.COLOR_YUV2RGB_I420, 4); // COLOR_YUV2RGBA_YV12 produces inverted colors + else + throw new IllegalArgumentException("Preview Format can be NV21 or YV12"); + + return mRgba; + } + + public JavaCameraFrame(Mat Yuv420sp, int width, int height) { + super(); + mWidth = width; + mHeight = height; + mYuvFrameData = Yuv420sp; + mRgba = new Mat(); + } + + public void release() { + mRgba.release(); + } + + private Mat mYuvFrameData; + private Mat mRgba; + private int mWidth; + private int mHeight; + }; + + private class CameraWorker implements Runnable { + + @Override + public void run() { + do { + boolean hasFrame = false; + synchronized (JavaCameraView.this) { + try { + while (!mCameraFrameReady && !mStopThread) { + JavaCameraView.this.wait(); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + if (mCameraFrameReady) + { + mChainIdx = 1 - mChainIdx; + mCameraFrameReady = false; + hasFrame = true; + } + } + + if (!mStopThread && hasFrame) { + if (!mFrameChain[1 - mChainIdx].empty()) + deliverAndDrawFrame(mCameraFrame[1 - mChainIdx]); + } + } while (!mStopThread); + Log.d(TAG, "Finish processing thread"); + } + } +} diff --git a/OpenCV/src/main/java/org/opencv/android/LoaderCallbackInterface.java b/OpenCV/src/main/java/org/opencv/android/LoaderCallbackInterface.java new file mode 100644 index 00000000..a941e837 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/android/LoaderCallbackInterface.java @@ -0,0 +1,40 @@ +package org.opencv.android; + +/** + * Interface for callback object in case of asynchronous initialization of OpenCV. + */ +public interface LoaderCallbackInterface +{ + /** + * OpenCV initialization finished successfully. + */ + static final int SUCCESS = 0; + /** + * Google Play Market cannot be invoked. + */ + static final int MARKET_ERROR = 2; + /** + * OpenCV library installation has been canceled by the user. + */ + static final int INSTALL_CANCELED = 3; + /** + * This version of OpenCV Manager Service is incompatible with the app. Possibly, a service update is required. + */ + static final int INCOMPATIBLE_MANAGER_VERSION = 4; + /** + * OpenCV library initialization has failed. + */ + static final int INIT_FAILED = 0xff; + + /** + * Callback method, called after OpenCV library initialization. + * @param status status of initialization (see initialization status constants). + */ + public void onManagerConnected(int status); + + /** + * Callback method, called in case the package installation is needed. + * @param callback answer object with approve and cancel methods and the package description. + */ + public void onPackageInstall(final int operation, InstallCallbackInterface callback); +}; diff --git a/OpenCV/src/main/java/org/opencv/android/OpenCVLoader.java b/OpenCV/src/main/java/org/opencv/android/OpenCVLoader.java new file mode 100644 index 00000000..0fd30411 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/android/OpenCVLoader.java @@ -0,0 +1,132 @@ +package org.opencv.android; + +import android.content.Context; + +/** + * Helper class provides common initialization methods for OpenCV library. + */ +public class OpenCVLoader +{ + /** + * OpenCV Library version 2.4.2. + */ + public static final String OPENCV_VERSION_2_4_2 = "2.4.2"; + + /** + * OpenCV Library version 2.4.3. + */ + public static final String OPENCV_VERSION_2_4_3 = "2.4.3"; + + /** + * OpenCV Library version 2.4.4. + */ + public static final String OPENCV_VERSION_2_4_4 = "2.4.4"; + + /** + * OpenCV Library version 2.4.5. + */ + public static final String OPENCV_VERSION_2_4_5 = "2.4.5"; + + /** + * OpenCV Library version 2.4.6. + */ + public static final String OPENCV_VERSION_2_4_6 = "2.4.6"; + + /** + * OpenCV Library version 2.4.7. + */ + public static final String OPENCV_VERSION_2_4_7 = "2.4.7"; + + /** + * OpenCV Library version 2.4.8. + */ + public static final String OPENCV_VERSION_2_4_8 = "2.4.8"; + + /** + * OpenCV Library version 2.4.9. + */ + public static final String OPENCV_VERSION_2_4_9 = "2.4.9"; + + /** + * OpenCV Library version 2.4.10. + */ + public static final String OPENCV_VERSION_2_4_10 = "2.4.10"; + + /** + * OpenCV Library version 2.4.11. + */ + public static final String OPENCV_VERSION_2_4_11 = "2.4.11"; + + /** + * OpenCV Library version 2.4.12. + */ + public static final String OPENCV_VERSION_2_4_12 = "2.4.12"; + + /** + * OpenCV Library version 2.4.13. + */ + public static final String OPENCV_VERSION_2_4_13 = "2.4.13"; + + /** + * OpenCV Library version 3.0.0. + */ + public static final String OPENCV_VERSION_3_0_0 = "3.0.0"; + + /** + * OpenCV Library version 3.1.0. + */ + public static final String OPENCV_VERSION_3_1_0 = "3.1.0"; + + /** + * OpenCV Library version 3.2.0. + */ + public static final String OPENCV_VERSION_3_2_0 = "3.2.0"; + + /** + * OpenCV Library version 3.3.0. + */ + public static final String OPENCV_VERSION_3_3_0 = "3.3.0"; + + /** + * OpenCV Library version 3.4.0. + */ + public static final String OPENCV_VERSION_3_4_0 = "3.4.0"; + + /** + * Current OpenCV Library version + */ + public static final String OPENCV_VERSION = "4.1.0"; + + + /** + * Loads and initializes OpenCV library from current application package. Roughly, it's an analog of system.loadLibrary("opencv_java"). + * @return Returns true is initialization of OpenCV was successful. + */ + public static boolean initDebug() + { + return StaticHelper.initOpenCV(false); + } + + /** + * Loads and initializes OpenCV library from current application package. Roughly, it's an analog of system.loadLibrary("opencv_java"). + * @param InitCuda load and initialize CUDA runtime libraries. + * @return Returns true is initialization of OpenCV was successful. + */ + public static boolean initDebug(boolean InitCuda) + { + return StaticHelper.initOpenCV(InitCuda); + } + + /** + * Loads and initializes OpenCV library using OpenCV Engine service. + * @param Version OpenCV library version. + * @param AppContext application context for connecting to the service. + * @param Callback object, that implements LoaderCallbackInterface for handling the connection status. + * @return Returns true if initialization of OpenCV is successful. + */ + public static boolean initAsync(String Version, Context AppContext, + LoaderCallbackInterface Callback) + { + return AsyncServiceHelper.initOpenCV(Version, AppContext, Callback); + } +} diff --git a/OpenCV/src/main/java/org/opencv/android/StaticHelper.java b/OpenCV/src/main/java/org/opencv/android/StaticHelper.java new file mode 100644 index 00000000..934dd757 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/android/StaticHelper.java @@ -0,0 +1,104 @@ +package org.opencv.android; + +import org.opencv.core.Core; + +import java.util.StringTokenizer; +import android.util.Log; + +class StaticHelper { + + public static boolean initOpenCV(boolean InitCuda) + { + boolean result; + String libs = ""; + + if(InitCuda) + { + loadLibrary("cudart"); + loadLibrary("nppc"); + loadLibrary("nppi"); + loadLibrary("npps"); + loadLibrary("cufft"); + loadLibrary("cublas"); + } + + Log.d(TAG, "Trying to get library list"); + + try + { + System.loadLibrary("opencv_info"); + libs = getLibraryList(); + } + catch(UnsatisfiedLinkError e) + { + Log.e(TAG, "OpenCV error: Cannot load info library for OpenCV"); + } + + Log.d(TAG, "Library list: \"" + libs + "\""); + Log.d(TAG, "First attempt to load libs"); + if (initOpenCVLibs(libs)) + { + Log.d(TAG, "First attempt to load libs is OK"); + String eol = System.getProperty("line.separator"); + for (String str : Core.getBuildInformation().split(eol)) + Log.i(TAG, str); + + result = true; + } + else + { + Log.d(TAG, "First attempt to load libs fails"); + result = false; + } + + return result; + } + + private static boolean loadLibrary(String Name) + { + boolean result = true; + + Log.d(TAG, "Trying to load library " + Name); + try + { + System.loadLibrary(Name); + Log.d(TAG, "Library " + Name + " loaded"); + } + catch(UnsatisfiedLinkError e) + { + Log.d(TAG, "Cannot load library \"" + Name + "\""); + e.printStackTrace(); + result = false; + } + + return result; + } + + private static boolean initOpenCVLibs(String Libs) + { + Log.d(TAG, "Trying to init OpenCV libs"); + + boolean result = true; + + if ((null != Libs) && (Libs.length() != 0)) + { + Log.d(TAG, "Trying to load libs by dependency list"); + StringTokenizer splitter = new StringTokenizer(Libs, ";"); + while(splitter.hasMoreTokens()) + { + result &= loadLibrary(splitter.nextToken()); + } + } + else + { + // If dependencies list is not defined or empty. + result = loadLibrary("opencv_java4"); + } + + return result; + } + + private static final String TAG = "OpenCV/StaticHelper"; + + private static native String getLibraryList(); +} diff --git a/OpenCV/src/main/java/org/opencv/android/Utils.java b/OpenCV/src/main/java/org/opencv/android/Utils.java new file mode 100644 index 00000000..eef4c456 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/android/Utils.java @@ -0,0 +1,139 @@ +package org.opencv.android; + +import android.content.Context; +import android.graphics.Bitmap; + +import org.opencv.core.CvException; +import org.opencv.core.CvType; +import org.opencv.core.Mat; +import org.opencv.imgcodecs.Imgcodecs; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public class Utils { + + public static String exportResource(Context context, int resourceId) { + return exportResource(context, resourceId, "OpenCV_data"); + } + + public static String exportResource(Context context, int resourceId, String dirname) { + String fullname = context.getResources().getString(resourceId); + String resName = fullname.substring(fullname.lastIndexOf("/") + 1); + try { + InputStream is = context.getResources().openRawResource(resourceId); + File resDir = context.getDir(dirname, Context.MODE_PRIVATE); + File resFile = new File(resDir, resName); + + FileOutputStream os = new FileOutputStream(resFile); + + byte[] buffer = new byte[4096]; + int bytesRead; + while ((bytesRead = is.read(buffer)) != -1) { + os.write(buffer, 0, bytesRead); + } + is.close(); + os.close(); + + return resFile.getAbsolutePath(); + } catch (IOException e) { + e.printStackTrace(); + throw new CvException("Failed to export resource " + resName + + ". Exception thrown: " + e); + } + } + + public static Mat loadResource(Context context, int resourceId) throws IOException + { + return loadResource(context, resourceId, -1); + } + + public static Mat loadResource(Context context, int resourceId, int flags) throws IOException + { + InputStream is = context.getResources().openRawResource(resourceId); + ByteArrayOutputStream os = new ByteArrayOutputStream(is.available()); + + byte[] buffer = new byte[4096]; + int bytesRead; + while ((bytesRead = is.read(buffer)) != -1) { + os.write(buffer, 0, bytesRead); + } + is.close(); + + Mat encoded = new Mat(1, os.size(), CvType.CV_8U); + encoded.put(0, 0, os.toByteArray()); + os.close(); + + Mat decoded = Imgcodecs.imdecode(encoded, flags); + encoded.release(); + + return decoded; + } + + /** + * Converts Android Bitmap to OpenCV Mat. + *

+ * This function converts an Android Bitmap image to the OpenCV Mat. + *
'ARGB_8888' and 'RGB_565' input Bitmap formats are supported. + *
The output Mat is always created of the same size as the input Bitmap and of the 'CV_8UC4' type, + * it keeps the image in RGBA format. + *
This function throws an exception if the conversion fails. + * @param bmp is a valid input Bitmap object of the type 'ARGB_8888' or 'RGB_565'. + * @param mat is a valid output Mat object, it will be reallocated if needed, so it may be empty. + * @param unPremultiplyAlpha is a flag, that determines, whether the bitmap needs to be converted from alpha premultiplied format (like Android keeps 'ARGB_8888' ones) to regular one; this flag is ignored for 'RGB_565' bitmaps. + */ + public static void bitmapToMat(Bitmap bmp, Mat mat, boolean unPremultiplyAlpha) { + if (bmp == null) + throw new IllegalArgumentException("bmp == null"); + if (mat == null) + throw new IllegalArgumentException("mat == null"); + nBitmapToMat2(bmp, mat.nativeObj, unPremultiplyAlpha); + } + + /** + * Short form of the bitmapToMat(bmp, mat, unPremultiplyAlpha=false). + * @param bmp is a valid input Bitmap object of the type 'ARGB_8888' or 'RGB_565'. + * @param mat is a valid output Mat object, it will be reallocated if needed, so Mat may be empty. + */ + public static void bitmapToMat(Bitmap bmp, Mat mat) { + bitmapToMat(bmp, mat, false); + } + + + /** + * Converts OpenCV Mat to Android Bitmap. + *

+ *
This function converts an image in the OpenCV Mat representation to the Android Bitmap. + *
The input Mat object has to be of the types 'CV_8UC1' (gray-scale), 'CV_8UC3' (RGB) or 'CV_8UC4' (RGBA). + *
The output Bitmap object has to be of the same size as the input Mat and of the types 'ARGB_8888' or 'RGB_565'. + *
This function throws an exception if the conversion fails. + * + * @param mat is a valid input Mat object of types 'CV_8UC1', 'CV_8UC3' or 'CV_8UC4'. + * @param bmp is a valid Bitmap object of the same size as the Mat and of type 'ARGB_8888' or 'RGB_565'. + * @param premultiplyAlpha is a flag, that determines, whether the Mat needs to be converted to alpha premultiplied format (like Android keeps 'ARGB_8888' bitmaps); the flag is ignored for 'RGB_565' bitmaps. + */ + public static void matToBitmap(Mat mat, Bitmap bmp, boolean premultiplyAlpha) { + if (mat == null) + throw new IllegalArgumentException("mat == null"); + if (bmp == null) + throw new IllegalArgumentException("bmp == null"); + nMatToBitmap2(mat.nativeObj, bmp, premultiplyAlpha); + } + + /** + * Short form of the matToBitmap(mat, bmp, premultiplyAlpha=false) + * @param mat is a valid input Mat object of the types 'CV_8UC1', 'CV_8UC3' or 'CV_8UC4'. + * @param bmp is a valid Bitmap object of the same size as the Mat and of type 'ARGB_8888' or 'RGB_565'. + */ + public static void matToBitmap(Mat mat, Bitmap bmp) { + matToBitmap(mat, bmp, false); + } + + + private static native void nBitmapToMat2(Bitmap b, long m_addr, boolean unPremultiplyAlpha); + + private static native void nMatToBitmap2(long m_addr, Bitmap b, boolean premultiplyAlpha); +} diff --git a/OpenCV/src/main/java/org/opencv/aruco/Aruco.java b/OpenCV/src/main/java/org/opencv/aruco/Aruco.java new file mode 100644 index 00000000..79cb2b73 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/aruco/Aruco.java @@ -0,0 +1,955 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.aruco; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.aruco.Board; +import org.opencv.aruco.CharucoBoard; +import org.opencv.aruco.DetectorParameters; +import org.opencv.aruco.Dictionary; +import org.opencv.core.Mat; +import org.opencv.core.Scalar; +import org.opencv.core.Size; +import org.opencv.core.TermCriteria; +import org.opencv.utils.Converters; + +// C++: class Aruco +//javadoc: Aruco + +public class Aruco { + + // C++: enum CornerRefineMethod + public static final int + CORNER_REFINE_NONE = 0, + CORNER_REFINE_SUBPIX = 1, + CORNER_REFINE_CONTOUR = 2, + CORNER_REFINE_APRILTAG = 3; + + + // C++: enum PREDEFINED_DICTIONARY_NAME + public static final int + DICT_4X4_50 = 0, + DICT_4X4_100 = 0+1, + DICT_4X4_250 = 0+2, + DICT_4X4_1000 = 0+3, + DICT_5X5_50 = 0+4, + DICT_5X5_100 = 0+5, + DICT_5X5_250 = 0+6, + DICT_5X5_1000 = 0+7, + DICT_6X6_50 = 0+8, + DICT_6X6_100 = 0+9, + DICT_6X6_250 = 0+10, + DICT_6X6_1000 = 0+11, + DICT_7X7_50 = 0+12, + DICT_7X7_100 = 0+13, + DICT_7X7_250 = 0+14, + DICT_7X7_1000 = 0+15, + DICT_ARUCO_ORIGINAL = 0+16, + DICT_APRILTAG_16h5 = 0+17, + DICT_APRILTAG_25h9 = 0+18, + DICT_APRILTAG_36h10 = 0+19, + DICT_APRILTAG_36h11 = 0+20; + + // + // C++: Ptr_Dictionary cv::aruco::generateCustomDictionary(int nMarkers, int markerSize, Ptr_Dictionary baseDictionary, int randomSeed = 0) + // + + //javadoc: custom_dictionary_from(nMarkers, markerSize, baseDictionary, randomSeed) + public static Dictionary custom_dictionary_from(int nMarkers, int markerSize, Dictionary baseDictionary, int randomSeed) + { + + Dictionary retVal = Dictionary.__fromPtr__(custom_dictionary_from_0(nMarkers, markerSize, baseDictionary.getNativeObjAddr(), randomSeed)); + + return retVal; + } + + //javadoc: custom_dictionary_from(nMarkers, markerSize, baseDictionary) + public static Dictionary custom_dictionary_from(int nMarkers, int markerSize, Dictionary baseDictionary) + { + + Dictionary retVal = Dictionary.__fromPtr__(custom_dictionary_from_1(nMarkers, markerSize, baseDictionary.getNativeObjAddr())); + + return retVal; + } + + + // + // C++: Ptr_Dictionary cv::aruco::generateCustomDictionary(int nMarkers, int markerSize, int randomSeed = 0) + // + + //javadoc: custom_dictionary(nMarkers, markerSize, randomSeed) + public static Dictionary custom_dictionary(int nMarkers, int markerSize, int randomSeed) + { + + Dictionary retVal = Dictionary.__fromPtr__(custom_dictionary_0(nMarkers, markerSize, randomSeed)); + + return retVal; + } + + //javadoc: custom_dictionary(nMarkers, markerSize) + public static Dictionary custom_dictionary(int nMarkers, int markerSize) + { + + Dictionary retVal = Dictionary.__fromPtr__(custom_dictionary_1(nMarkers, markerSize)); + + return retVal; + } + + + // + // C++: Ptr_Dictionary cv::aruco::getPredefinedDictionary(int dict) + // + + //javadoc: getPredefinedDictionary(dict) + public static Dictionary getPredefinedDictionary(int dict) + { + + Dictionary retVal = Dictionary.__fromPtr__(getPredefinedDictionary_0(dict)); + + return retVal; + } + + + // + // C++: bool cv::aruco::estimatePoseCharucoBoard(Mat charucoCorners, Mat charucoIds, Ptr_CharucoBoard board, Mat cameraMatrix, Mat distCoeffs, Mat& rvec, Mat& tvec, bool useExtrinsicGuess = false) + // + + //javadoc: estimatePoseCharucoBoard(charucoCorners, charucoIds, board, cameraMatrix, distCoeffs, rvec, tvec, useExtrinsicGuess) + public static boolean estimatePoseCharucoBoard(Mat charucoCorners, Mat charucoIds, CharucoBoard board, Mat cameraMatrix, Mat distCoeffs, Mat rvec, Mat tvec, boolean useExtrinsicGuess) + { + + boolean retVal = estimatePoseCharucoBoard_0(charucoCorners.nativeObj, charucoIds.nativeObj, board.getNativeObjAddr(), cameraMatrix.nativeObj, distCoeffs.nativeObj, rvec.nativeObj, tvec.nativeObj, useExtrinsicGuess); + + return retVal; + } + + //javadoc: estimatePoseCharucoBoard(charucoCorners, charucoIds, board, cameraMatrix, distCoeffs, rvec, tvec) + public static boolean estimatePoseCharucoBoard(Mat charucoCorners, Mat charucoIds, CharucoBoard board, Mat cameraMatrix, Mat distCoeffs, Mat rvec, Mat tvec) + { + + boolean retVal = estimatePoseCharucoBoard_1(charucoCorners.nativeObj, charucoIds.nativeObj, board.getNativeObjAddr(), cameraMatrix.nativeObj, distCoeffs.nativeObj, rvec.nativeObj, tvec.nativeObj); + + return retVal; + } + + + // + // C++: double cv::aruco::calibrateCameraAruco(vector_Mat corners, Mat ids, Mat counter, Ptr_Board board, Size imageSize, Mat& cameraMatrix, Mat& distCoeffs, vector_Mat& rvecs, vector_Mat& tvecs, Mat& stdDeviationsIntrinsics, Mat& stdDeviationsExtrinsics, Mat& perViewErrors, int flags = 0, TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)) + // + + //javadoc: calibrateCameraArucoExtended(corners, ids, counter, board, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, stdDeviationsIntrinsics, stdDeviationsExtrinsics, perViewErrors, flags, criteria) + public static double calibrateCameraArucoExtended(List corners, Mat ids, Mat counter, Board board, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, Mat stdDeviationsIntrinsics, Mat stdDeviationsExtrinsics, Mat perViewErrors, int flags, TermCriteria criteria) + { + Mat corners_mat = Converters.vector_Mat_to_Mat(corners); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraArucoExtended_0(corners_mat.nativeObj, ids.nativeObj, counter.nativeObj, board.getNativeObjAddr(), imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, stdDeviationsIntrinsics.nativeObj, stdDeviationsExtrinsics.nativeObj, perViewErrors.nativeObj, flags, criteria.type, criteria.maxCount, criteria.epsilon); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCameraArucoExtended(corners, ids, counter, board, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, stdDeviationsIntrinsics, stdDeviationsExtrinsics, perViewErrors, flags) + public static double calibrateCameraArucoExtended(List corners, Mat ids, Mat counter, Board board, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, Mat stdDeviationsIntrinsics, Mat stdDeviationsExtrinsics, Mat perViewErrors, int flags) + { + Mat corners_mat = Converters.vector_Mat_to_Mat(corners); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraArucoExtended_1(corners_mat.nativeObj, ids.nativeObj, counter.nativeObj, board.getNativeObjAddr(), imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, stdDeviationsIntrinsics.nativeObj, stdDeviationsExtrinsics.nativeObj, perViewErrors.nativeObj, flags); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCameraArucoExtended(corners, ids, counter, board, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, stdDeviationsIntrinsics, stdDeviationsExtrinsics, perViewErrors) + public static double calibrateCameraArucoExtended(List corners, Mat ids, Mat counter, Board board, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, Mat stdDeviationsIntrinsics, Mat stdDeviationsExtrinsics, Mat perViewErrors) + { + Mat corners_mat = Converters.vector_Mat_to_Mat(corners); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraArucoExtended_2(corners_mat.nativeObj, ids.nativeObj, counter.nativeObj, board.getNativeObjAddr(), imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, stdDeviationsIntrinsics.nativeObj, stdDeviationsExtrinsics.nativeObj, perViewErrors.nativeObj); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + + // + // C++: double cv::aruco::calibrateCameraAruco(vector_Mat corners, Mat ids, Mat counter, Ptr_Board board, Size imageSize, Mat& cameraMatrix, Mat& distCoeffs, vector_Mat& rvecs = vector_Mat(), vector_Mat& tvecs = vector_Mat(), int flags = 0, TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)) + // + + //javadoc: calibrateCameraAruco(corners, ids, counter, board, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, flags, criteria) + public static double calibrateCameraAruco(List corners, Mat ids, Mat counter, Board board, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, int flags, TermCriteria criteria) + { + Mat corners_mat = Converters.vector_Mat_to_Mat(corners); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraAruco_0(corners_mat.nativeObj, ids.nativeObj, counter.nativeObj, board.getNativeObjAddr(), imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, flags, criteria.type, criteria.maxCount, criteria.epsilon); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCameraAruco(corners, ids, counter, board, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, flags) + public static double calibrateCameraAruco(List corners, Mat ids, Mat counter, Board board, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, int flags) + { + Mat corners_mat = Converters.vector_Mat_to_Mat(corners); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraAruco_1(corners_mat.nativeObj, ids.nativeObj, counter.nativeObj, board.getNativeObjAddr(), imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, flags); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCameraAruco(corners, ids, counter, board, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs) + public static double calibrateCameraAruco(List corners, Mat ids, Mat counter, Board board, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs) + { + Mat corners_mat = Converters.vector_Mat_to_Mat(corners); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraAruco_2(corners_mat.nativeObj, ids.nativeObj, counter.nativeObj, board.getNativeObjAddr(), imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCameraAruco(corners, ids, counter, board, imageSize, cameraMatrix, distCoeffs, rvecs) + public static double calibrateCameraAruco(List corners, Mat ids, Mat counter, Board board, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs) + { + Mat corners_mat = Converters.vector_Mat_to_Mat(corners); + Mat rvecs_mat = new Mat(); + double retVal = calibrateCameraAruco_3(corners_mat.nativeObj, ids.nativeObj, counter.nativeObj, board.getNativeObjAddr(), imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCameraAruco(corners, ids, counter, board, imageSize, cameraMatrix, distCoeffs) + public static double calibrateCameraAruco(List corners, Mat ids, Mat counter, Board board, Size imageSize, Mat cameraMatrix, Mat distCoeffs) + { + Mat corners_mat = Converters.vector_Mat_to_Mat(corners); + double retVal = calibrateCameraAruco_4(corners_mat.nativeObj, ids.nativeObj, counter.nativeObj, board.getNativeObjAddr(), imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj); + + return retVal; + } + + + // + // C++: double cv::aruco::calibrateCameraCharuco(vector_Mat charucoCorners, vector_Mat charucoIds, Ptr_CharucoBoard board, Size imageSize, Mat& cameraMatrix, Mat& distCoeffs, vector_Mat& rvecs, vector_Mat& tvecs, Mat& stdDeviationsIntrinsics, Mat& stdDeviationsExtrinsics, Mat& perViewErrors, int flags = 0, TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)) + // + + //javadoc: calibrateCameraCharucoExtended(charucoCorners, charucoIds, board, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, stdDeviationsIntrinsics, stdDeviationsExtrinsics, perViewErrors, flags, criteria) + public static double calibrateCameraCharucoExtended(List charucoCorners, List charucoIds, CharucoBoard board, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, Mat stdDeviationsIntrinsics, Mat stdDeviationsExtrinsics, Mat perViewErrors, int flags, TermCriteria criteria) + { + Mat charucoCorners_mat = Converters.vector_Mat_to_Mat(charucoCorners); + Mat charucoIds_mat = Converters.vector_Mat_to_Mat(charucoIds); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraCharucoExtended_0(charucoCorners_mat.nativeObj, charucoIds_mat.nativeObj, board.getNativeObjAddr(), imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, stdDeviationsIntrinsics.nativeObj, stdDeviationsExtrinsics.nativeObj, perViewErrors.nativeObj, flags, criteria.type, criteria.maxCount, criteria.epsilon); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCameraCharucoExtended(charucoCorners, charucoIds, board, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, stdDeviationsIntrinsics, stdDeviationsExtrinsics, perViewErrors, flags) + public static double calibrateCameraCharucoExtended(List charucoCorners, List charucoIds, CharucoBoard board, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, Mat stdDeviationsIntrinsics, Mat stdDeviationsExtrinsics, Mat perViewErrors, int flags) + { + Mat charucoCorners_mat = Converters.vector_Mat_to_Mat(charucoCorners); + Mat charucoIds_mat = Converters.vector_Mat_to_Mat(charucoIds); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraCharucoExtended_1(charucoCorners_mat.nativeObj, charucoIds_mat.nativeObj, board.getNativeObjAddr(), imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, stdDeviationsIntrinsics.nativeObj, stdDeviationsExtrinsics.nativeObj, perViewErrors.nativeObj, flags); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCameraCharucoExtended(charucoCorners, charucoIds, board, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, stdDeviationsIntrinsics, stdDeviationsExtrinsics, perViewErrors) + public static double calibrateCameraCharucoExtended(List charucoCorners, List charucoIds, CharucoBoard board, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, Mat stdDeviationsIntrinsics, Mat stdDeviationsExtrinsics, Mat perViewErrors) + { + Mat charucoCorners_mat = Converters.vector_Mat_to_Mat(charucoCorners); + Mat charucoIds_mat = Converters.vector_Mat_to_Mat(charucoIds); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraCharucoExtended_2(charucoCorners_mat.nativeObj, charucoIds_mat.nativeObj, board.getNativeObjAddr(), imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, stdDeviationsIntrinsics.nativeObj, stdDeviationsExtrinsics.nativeObj, perViewErrors.nativeObj); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + + // + // C++: double cv::aruco::calibrateCameraCharuco(vector_Mat charucoCorners, vector_Mat charucoIds, Ptr_CharucoBoard board, Size imageSize, Mat& cameraMatrix, Mat& distCoeffs, vector_Mat& rvecs = vector_Mat(), vector_Mat& tvecs = vector_Mat(), int flags = 0, TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)) + // + + //javadoc: calibrateCameraCharuco(charucoCorners, charucoIds, board, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, flags, criteria) + public static double calibrateCameraCharuco(List charucoCorners, List charucoIds, CharucoBoard board, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, int flags, TermCriteria criteria) + { + Mat charucoCorners_mat = Converters.vector_Mat_to_Mat(charucoCorners); + Mat charucoIds_mat = Converters.vector_Mat_to_Mat(charucoIds); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraCharuco_0(charucoCorners_mat.nativeObj, charucoIds_mat.nativeObj, board.getNativeObjAddr(), imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, flags, criteria.type, criteria.maxCount, criteria.epsilon); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCameraCharuco(charucoCorners, charucoIds, board, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, flags) + public static double calibrateCameraCharuco(List charucoCorners, List charucoIds, CharucoBoard board, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, int flags) + { + Mat charucoCorners_mat = Converters.vector_Mat_to_Mat(charucoCorners); + Mat charucoIds_mat = Converters.vector_Mat_to_Mat(charucoIds); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraCharuco_1(charucoCorners_mat.nativeObj, charucoIds_mat.nativeObj, board.getNativeObjAddr(), imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, flags); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCameraCharuco(charucoCorners, charucoIds, board, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs) + public static double calibrateCameraCharuco(List charucoCorners, List charucoIds, CharucoBoard board, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs) + { + Mat charucoCorners_mat = Converters.vector_Mat_to_Mat(charucoCorners); + Mat charucoIds_mat = Converters.vector_Mat_to_Mat(charucoIds); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraCharuco_2(charucoCorners_mat.nativeObj, charucoIds_mat.nativeObj, board.getNativeObjAddr(), imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCameraCharuco(charucoCorners, charucoIds, board, imageSize, cameraMatrix, distCoeffs, rvecs) + public static double calibrateCameraCharuco(List charucoCorners, List charucoIds, CharucoBoard board, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs) + { + Mat charucoCorners_mat = Converters.vector_Mat_to_Mat(charucoCorners); + Mat charucoIds_mat = Converters.vector_Mat_to_Mat(charucoIds); + Mat rvecs_mat = new Mat(); + double retVal = calibrateCameraCharuco_3(charucoCorners_mat.nativeObj, charucoIds_mat.nativeObj, board.getNativeObjAddr(), imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCameraCharuco(charucoCorners, charucoIds, board, imageSize, cameraMatrix, distCoeffs) + public static double calibrateCameraCharuco(List charucoCorners, List charucoIds, CharucoBoard board, Size imageSize, Mat cameraMatrix, Mat distCoeffs) + { + Mat charucoCorners_mat = Converters.vector_Mat_to_Mat(charucoCorners); + Mat charucoIds_mat = Converters.vector_Mat_to_Mat(charucoIds); + double retVal = calibrateCameraCharuco_4(charucoCorners_mat.nativeObj, charucoIds_mat.nativeObj, board.getNativeObjAddr(), imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj); + + return retVal; + } + + + // + // C++: int cv::aruco::estimatePoseBoard(vector_Mat corners, Mat ids, Ptr_Board board, Mat cameraMatrix, Mat distCoeffs, Mat& rvec, Mat& tvec, bool useExtrinsicGuess = false) + // + + //javadoc: estimatePoseBoard(corners, ids, board, cameraMatrix, distCoeffs, rvec, tvec, useExtrinsicGuess) + public static int estimatePoseBoard(List corners, Mat ids, Board board, Mat cameraMatrix, Mat distCoeffs, Mat rvec, Mat tvec, boolean useExtrinsicGuess) + { + Mat corners_mat = Converters.vector_Mat_to_Mat(corners); + int retVal = estimatePoseBoard_0(corners_mat.nativeObj, ids.nativeObj, board.getNativeObjAddr(), cameraMatrix.nativeObj, distCoeffs.nativeObj, rvec.nativeObj, tvec.nativeObj, useExtrinsicGuess); + + return retVal; + } + + //javadoc: estimatePoseBoard(corners, ids, board, cameraMatrix, distCoeffs, rvec, tvec) + public static int estimatePoseBoard(List corners, Mat ids, Board board, Mat cameraMatrix, Mat distCoeffs, Mat rvec, Mat tvec) + { + Mat corners_mat = Converters.vector_Mat_to_Mat(corners); + int retVal = estimatePoseBoard_1(corners_mat.nativeObj, ids.nativeObj, board.getNativeObjAddr(), cameraMatrix.nativeObj, distCoeffs.nativeObj, rvec.nativeObj, tvec.nativeObj); + return retVal; + } + + + // + // C++: int cv::aruco::interpolateCornersCharuco(vector_Mat markerCorners, Mat markerIds, Mat image, Ptr_CharucoBoard board, Mat& charucoCorners, Mat& charucoIds, Mat cameraMatrix = Mat(), Mat distCoeffs = Mat(), int minMarkers = 2) + // + + //javadoc: interpolateCornersCharuco(markerCorners, markerIds, image, board, charucoCorners, charucoIds, cameraMatrix, distCoeffs, minMarkers) + public static int interpolateCornersCharuco(List markerCorners, Mat markerIds, Mat image, CharucoBoard board, Mat charucoCorners, Mat charucoIds, Mat cameraMatrix, Mat distCoeffs, int minMarkers) + { + Mat markerCorners_mat = Converters.vector_Mat_to_Mat(markerCorners); + int retVal = interpolateCornersCharuco_0(markerCorners_mat.nativeObj, markerIds.nativeObj, image.nativeObj, board.getNativeObjAddr(), charucoCorners.nativeObj, charucoIds.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, minMarkers); + + return retVal; + } + + //javadoc: interpolateCornersCharuco(markerCorners, markerIds, image, board, charucoCorners, charucoIds, cameraMatrix, distCoeffs) + public static int interpolateCornersCharuco(List markerCorners, Mat markerIds, Mat image, CharucoBoard board, Mat charucoCorners, Mat charucoIds, Mat cameraMatrix, Mat distCoeffs) + { + Mat markerCorners_mat = Converters.vector_Mat_to_Mat(markerCorners); + int retVal = interpolateCornersCharuco_1(markerCorners_mat.nativeObj, markerIds.nativeObj, image.nativeObj, board.getNativeObjAddr(), charucoCorners.nativeObj, charucoIds.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj); + + return retVal; + } + + //javadoc: interpolateCornersCharuco(markerCorners, markerIds, image, board, charucoCorners, charucoIds, cameraMatrix) + public static int interpolateCornersCharuco(List markerCorners, Mat markerIds, Mat image, CharucoBoard board, Mat charucoCorners, Mat charucoIds, Mat cameraMatrix) + { + Mat markerCorners_mat = Converters.vector_Mat_to_Mat(markerCorners); + int retVal = interpolateCornersCharuco_2(markerCorners_mat.nativeObj, markerIds.nativeObj, image.nativeObj, board.getNativeObjAddr(), charucoCorners.nativeObj, charucoIds.nativeObj, cameraMatrix.nativeObj); + return retVal; + } + + //javadoc: interpolateCornersCharuco(markerCorners, markerIds, image, board, charucoCorners, charucoIds) + public static int interpolateCornersCharuco(List markerCorners, Mat markerIds, Mat image, CharucoBoard board, Mat charucoCorners, Mat charucoIds) + { + Mat markerCorners_mat = Converters.vector_Mat_to_Mat(markerCorners); + int retVal = interpolateCornersCharuco_3(markerCorners_mat.nativeObj, markerIds.nativeObj, image.nativeObj, board.getNativeObjAddr(), charucoCorners.nativeObj, charucoIds.nativeObj); + return retVal; + } + + + // + // C++: void cv::aruco::detectCharucoDiamond(Mat image, vector_Mat markerCorners, Mat markerIds, float squareMarkerLengthRate, vector_Mat& diamondCorners, Mat& diamondIds, Mat cameraMatrix = Mat(), Mat distCoeffs = Mat()) + // + + //javadoc: detectCharucoDiamond(image, markerCorners, markerIds, squareMarkerLengthRate, diamondCorners, diamondIds, cameraMatrix, distCoeffs) + public static void detectCharucoDiamond(Mat image, List markerCorners, Mat markerIds, float squareMarkerLengthRate, List diamondCorners, Mat diamondIds, Mat cameraMatrix, Mat distCoeffs) + { + Mat markerCorners_mat = Converters.vector_Mat_to_Mat(markerCorners); + Mat diamondCorners_mat = new Mat(); + detectCharucoDiamond_0(image.nativeObj, markerCorners_mat.nativeObj, markerIds.nativeObj, squareMarkerLengthRate, diamondCorners_mat.nativeObj, diamondIds.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj); + Converters.Mat_to_vector_Mat(diamondCorners_mat, diamondCorners); + diamondCorners_mat.release(); + return; + } + + //javadoc: detectCharucoDiamond(image, markerCorners, markerIds, squareMarkerLengthRate, diamondCorners, diamondIds, cameraMatrix) + public static void detectCharucoDiamond(Mat image, List markerCorners, Mat markerIds, float squareMarkerLengthRate, List diamondCorners, Mat diamondIds, Mat cameraMatrix) + { + Mat markerCorners_mat = Converters.vector_Mat_to_Mat(markerCorners); + Mat diamondCorners_mat = new Mat(); + detectCharucoDiamond_1(image.nativeObj, markerCorners_mat.nativeObj, markerIds.nativeObj, squareMarkerLengthRate, diamondCorners_mat.nativeObj, diamondIds.nativeObj, cameraMatrix.nativeObj); + Converters.Mat_to_vector_Mat(diamondCorners_mat, diamondCorners); + diamondCorners_mat.release(); + return; + } + + //javadoc: detectCharucoDiamond(image, markerCorners, markerIds, squareMarkerLengthRate, diamondCorners, diamondIds) + public static void detectCharucoDiamond(Mat image, List markerCorners, Mat markerIds, float squareMarkerLengthRate, List diamondCorners, Mat diamondIds) + { + Mat markerCorners_mat = Converters.vector_Mat_to_Mat(markerCorners); + Mat diamondCorners_mat = new Mat(); + detectCharucoDiamond_2(image.nativeObj, markerCorners_mat.nativeObj, markerIds.nativeObj, squareMarkerLengthRate, diamondCorners_mat.nativeObj, diamondIds.nativeObj); + Converters.Mat_to_vector_Mat(diamondCorners_mat, diamondCorners); + diamondCorners_mat.release(); + return; + } + + + // + // C++: void cv::aruco::detectMarkers(Mat image, Ptr_Dictionary dictionary, vector_Mat& corners, Mat& ids, Ptr_DetectorParameters parameters = DetectorParameters::create(), vector_Mat& rejectedImgPoints = vector_Mat(), Mat cameraMatrix = Mat(), Mat distCoeff = Mat()) + // + + //javadoc: detectMarkers(image, dictionary, corners, ids, parameters, rejectedImgPoints, cameraMatrix, distCoeff) + public static void detectMarkers(Mat image, Dictionary dictionary, List corners, Mat ids, DetectorParameters parameters, List rejectedImgPoints, Mat cameraMatrix, Mat distCoeff) + { + Mat corners_mat = new Mat(); + Mat rejectedImgPoints_mat = new Mat(); + detectMarkers_0(image.nativeObj, dictionary.getNativeObjAddr(), corners_mat.nativeObj, ids.nativeObj, parameters.getNativeObjAddr(), rejectedImgPoints_mat.nativeObj, cameraMatrix.nativeObj, distCoeff.nativeObj); + Converters.Mat_to_vector_Mat(corners_mat, corners); + corners_mat.release(); + Converters.Mat_to_vector_Mat(rejectedImgPoints_mat, rejectedImgPoints); + rejectedImgPoints_mat.release(); + return; + } + + //javadoc: detectMarkers(image, dictionary, corners, ids, parameters, rejectedImgPoints, cameraMatrix) + public static void detectMarkers(Mat image, Dictionary dictionary, List corners, Mat ids, DetectorParameters parameters, List rejectedImgPoints, Mat cameraMatrix) + { + Mat corners_mat = new Mat(); + Mat rejectedImgPoints_mat = new Mat(); + detectMarkers_1(image.nativeObj, dictionary.getNativeObjAddr(), corners_mat.nativeObj, ids.nativeObj, parameters.getNativeObjAddr(), rejectedImgPoints_mat.nativeObj, cameraMatrix.nativeObj); + Converters.Mat_to_vector_Mat(corners_mat, corners); + corners_mat.release(); + Converters.Mat_to_vector_Mat(rejectedImgPoints_mat, rejectedImgPoints); + rejectedImgPoints_mat.release(); + return; + } + + //javadoc: detectMarkers(image, dictionary, corners, ids, parameters, rejectedImgPoints) + public static void detectMarkers(Mat image, Dictionary dictionary, List corners, Mat ids, DetectorParameters parameters, List rejectedImgPoints) + { + Mat corners_mat = new Mat(); + Mat rejectedImgPoints_mat = new Mat(); + detectMarkers_2(image.nativeObj, dictionary.getNativeObjAddr(), corners_mat.nativeObj, ids.nativeObj, parameters.getNativeObjAddr(), rejectedImgPoints_mat.nativeObj); + Converters.Mat_to_vector_Mat(corners_mat, corners); + corners_mat.release(); + Converters.Mat_to_vector_Mat(rejectedImgPoints_mat, rejectedImgPoints); + rejectedImgPoints_mat.release(); + return; + } + + //javadoc: detectMarkers(image, dictionary, corners, ids, parameters) + public static void detectMarkers(Mat image, Dictionary dictionary, List corners, Mat ids, DetectorParameters parameters) + { + Mat corners_mat = new Mat(); + detectMarkers_3(image.nativeObj, dictionary.getNativeObjAddr(), corners_mat.nativeObj, ids.nativeObj, parameters.getNativeObjAddr()); + Converters.Mat_to_vector_Mat(corners_mat, corners); + corners_mat.release(); + return; + } + + //javadoc: detectMarkers(image, dictionary, corners, ids) + public static void detectMarkers(Mat image, Dictionary dictionary, List corners, Mat ids) + { + Mat corners_mat = new Mat(); + detectMarkers_4(image.nativeObj, dictionary.getNativeObjAddr(), corners_mat.nativeObj, ids.nativeObj); + Converters.Mat_to_vector_Mat(corners_mat, corners); + corners_mat.release(); + return; + } + + + // + // C++: void cv::aruco::drawAxis(Mat& image, Mat cameraMatrix, Mat distCoeffs, Mat rvec, Mat tvec, float length) + // + + //javadoc: drawAxis(image, cameraMatrix, distCoeffs, rvec, tvec, length) + @Deprecated + public static void drawAxis(Mat image, Mat cameraMatrix, Mat distCoeffs, Mat rvec, Mat tvec, float length) + { + + drawAxis_0(image.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvec.nativeObj, tvec.nativeObj, length); + + return; + } + + + // + // C++: void cv::aruco::drawDetectedCornersCharuco(Mat& image, Mat charucoCorners, Mat charucoIds = Mat(), Scalar cornerColor = Scalar(255, 0, 0)) + // + + //javadoc: drawDetectedCornersCharuco(image, charucoCorners, charucoIds, cornerColor) + public static void drawDetectedCornersCharuco(Mat image, Mat charucoCorners, Mat charucoIds, Scalar cornerColor) + { + + drawDetectedCornersCharuco_0(image.nativeObj, charucoCorners.nativeObj, charucoIds.nativeObj, cornerColor.val[0], cornerColor.val[1], cornerColor.val[2], cornerColor.val[3]); + + return; + } + + //javadoc: drawDetectedCornersCharuco(image, charucoCorners, charucoIds) + public static void drawDetectedCornersCharuco(Mat image, Mat charucoCorners, Mat charucoIds) + { + + drawDetectedCornersCharuco_1(image.nativeObj, charucoCorners.nativeObj, charucoIds.nativeObj); + + return; + } + + //javadoc: drawDetectedCornersCharuco(image, charucoCorners) + public static void drawDetectedCornersCharuco(Mat image, Mat charucoCorners) + { + drawDetectedCornersCharuco_2(image.nativeObj, charucoCorners.nativeObj); + + return; + } + + + // + // C++: void cv::aruco::drawDetectedDiamonds(Mat& image, vector_Mat diamondCorners, Mat diamondIds = Mat(), Scalar borderColor = Scalar(0, 0, 255)) + // + + //javadoc: drawDetectedDiamonds(image, diamondCorners, diamondIds, borderColor) + public static void drawDetectedDiamonds(Mat image, List diamondCorners, Mat diamondIds, Scalar borderColor) + { + Mat diamondCorners_mat = Converters.vector_Mat_to_Mat(diamondCorners); + drawDetectedDiamonds_0(image.nativeObj, diamondCorners_mat.nativeObj, diamondIds.nativeObj, borderColor.val[0], borderColor.val[1], borderColor.val[2], borderColor.val[3]); + + return; + } + + //javadoc: drawDetectedDiamonds(image, diamondCorners, diamondIds) + public static void drawDetectedDiamonds(Mat image, List diamondCorners, Mat diamondIds) + { + Mat diamondCorners_mat = Converters.vector_Mat_to_Mat(diamondCorners); + drawDetectedDiamonds_1(image.nativeObj, diamondCorners_mat.nativeObj, diamondIds.nativeObj); + + return; + } + + //javadoc: drawDetectedDiamonds(image, diamondCorners) + public static void drawDetectedDiamonds(Mat image, List diamondCorners) + { + Mat diamondCorners_mat = Converters.vector_Mat_to_Mat(diamondCorners); + drawDetectedDiamonds_2(image.nativeObj, diamondCorners_mat.nativeObj); + + return; + } + + + // + // C++: void cv::aruco::drawDetectedMarkers(Mat& image, vector_Mat corners, Mat ids = Mat(), Scalar borderColor = Scalar(0, 255, 0)) + // + + //javadoc: drawDetectedMarkers(image, corners, ids, borderColor) + public static void drawDetectedMarkers(Mat image, List corners, Mat ids, Scalar borderColor) + { + Mat corners_mat = Converters.vector_Mat_to_Mat(corners); + drawDetectedMarkers_0(image.nativeObj, corners_mat.nativeObj, ids.nativeObj, borderColor.val[0], borderColor.val[1], borderColor.val[2], borderColor.val[3]); + + return; + } + + //javadoc: drawDetectedMarkers(image, corners, ids) + public static void drawDetectedMarkers(Mat image, List corners, Mat ids) + { + Mat corners_mat = Converters.vector_Mat_to_Mat(corners); + drawDetectedMarkers_1(image.nativeObj, corners_mat.nativeObj, ids.nativeObj); + + return; + } + + //javadoc: drawDetectedMarkers(image, corners) + public static void drawDetectedMarkers(Mat image, List corners) + { + Mat corners_mat = Converters.vector_Mat_to_Mat(corners); + drawDetectedMarkers_2(image.nativeObj, corners_mat.nativeObj); + + return; + } + + + // + // C++: void cv::aruco::drawMarker(Ptr_Dictionary dictionary, int id, int sidePixels, Mat& img, int borderBits = 1) + // + + //javadoc: drawMarker(dictionary, id, sidePixels, img, borderBits) + public static void drawMarker(Dictionary dictionary, int id, int sidePixels, Mat img, int borderBits) + { + + drawMarker_0(dictionary.getNativeObjAddr(), id, sidePixels, img.nativeObj, borderBits); + + return; + } + + //javadoc: drawMarker(dictionary, id, sidePixels, img) + public static void drawMarker(Dictionary dictionary, int id, int sidePixels, Mat img) + { + + drawMarker_1(dictionary.getNativeObjAddr(), id, sidePixels, img.nativeObj); + + return; + } + + + // + // C++: void cv::aruco::drawPlanarBoard(Ptr_Board board, Size outSize, Mat& img, int marginSize = 0, int borderBits = 1) + // + + //javadoc: drawPlanarBoard(board, outSize, img, marginSize, borderBits) + public static void drawPlanarBoard(Board board, Size outSize, Mat img, int marginSize, int borderBits) + { + + drawPlanarBoard_0(board.getNativeObjAddr(), outSize.width, outSize.height, img.nativeObj, marginSize, borderBits); + + return; + } + + //javadoc: drawPlanarBoard(board, outSize, img, marginSize) + public static void drawPlanarBoard(Board board, Size outSize, Mat img, int marginSize) + { + + drawPlanarBoard_1(board.getNativeObjAddr(), outSize.width, outSize.height, img.nativeObj, marginSize); + + return; + } + + //javadoc: drawPlanarBoard(board, outSize, img) + public static void drawPlanarBoard(Board board, Size outSize, Mat img) + { + + drawPlanarBoard_2(board.getNativeObjAddr(), outSize.width, outSize.height, img.nativeObj); + + return; + } + + + // + // C++: void cv::aruco::estimatePoseSingleMarkers(vector_Mat corners, float markerLength, Mat cameraMatrix, Mat distCoeffs, Mat& rvecs, Mat& tvecs, Mat& _objPoints = Mat()) + // + + //javadoc: estimatePoseSingleMarkers(corners, markerLength, cameraMatrix, distCoeffs, rvecs, tvecs, _objPoints) + public static void estimatePoseSingleMarkers(List corners, float markerLength, Mat cameraMatrix, Mat distCoeffs, Mat rvecs, Mat tvecs, Mat _objPoints) + { + Mat corners_mat = Converters.vector_Mat_to_Mat(corners); + estimatePoseSingleMarkers_0(corners_mat.nativeObj, markerLength, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs.nativeObj, tvecs.nativeObj, _objPoints.nativeObj); + + return; + } + + //javadoc: estimatePoseSingleMarkers(corners, markerLength, cameraMatrix, distCoeffs, rvecs, tvecs) + public static void estimatePoseSingleMarkers(List corners, float markerLength, Mat cameraMatrix, Mat distCoeffs, Mat rvecs, Mat tvecs) + { + Mat corners_mat = Converters.vector_Mat_to_Mat(corners); + estimatePoseSingleMarkers_1(corners_mat.nativeObj, markerLength, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs.nativeObj, tvecs.nativeObj); + + return; + } + + + // + // C++: void cv::aruco::getBoardObjectAndImagePoints(Ptr_Board board, vector_Mat detectedCorners, Mat detectedIds, Mat& objPoints, Mat& imgPoints) + // + + //javadoc: getBoardObjectAndImagePoints(board, detectedCorners, detectedIds, objPoints, imgPoints) + public static void getBoardObjectAndImagePoints(Board board, List detectedCorners, Mat detectedIds, Mat objPoints, Mat imgPoints) + { + Mat detectedCorners_mat = Converters.vector_Mat_to_Mat(detectedCorners); + getBoardObjectAndImagePoints_0(board.getNativeObjAddr(), detectedCorners_mat.nativeObj, detectedIds.nativeObj, objPoints.nativeObj, imgPoints.nativeObj); + + return; + } + + + // + // C++: void cv::aruco::refineDetectedMarkers(Mat image, Ptr_Board board, vector_Mat& detectedCorners, Mat& detectedIds, vector_Mat& rejectedCorners, Mat cameraMatrix = Mat(), Mat distCoeffs = Mat(), float minRepDistance = 10.f, float errorCorrectionRate = 3.f, bool checkAllOrders = true, Mat& recoveredIdxs = Mat(), Ptr_DetectorParameters parameters = DetectorParameters::create()) + // + + //javadoc: refineDetectedMarkers(image, board, detectedCorners, detectedIds, rejectedCorners, cameraMatrix, distCoeffs, minRepDistance, errorCorrectionRate, checkAllOrders, recoveredIdxs, parameters) + public static void refineDetectedMarkers(Mat image, Board board, List detectedCorners, Mat detectedIds, List rejectedCorners, Mat cameraMatrix, Mat distCoeffs, float minRepDistance, float errorCorrectionRate, boolean checkAllOrders, Mat recoveredIdxs, DetectorParameters parameters) + { + Mat detectedCorners_mat = Converters.vector_Mat_to_Mat(detectedCorners); + Mat rejectedCorners_mat = Converters.vector_Mat_to_Mat(rejectedCorners); + refineDetectedMarkers_0(image.nativeObj, board.getNativeObjAddr(), detectedCorners_mat.nativeObj, detectedIds.nativeObj, rejectedCorners_mat.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, minRepDistance, errorCorrectionRate, checkAllOrders, recoveredIdxs.nativeObj, parameters.getNativeObjAddr()); + Converters.Mat_to_vector_Mat(detectedCorners_mat, detectedCorners); + detectedCorners_mat.release(); + Converters.Mat_to_vector_Mat(rejectedCorners_mat, rejectedCorners); + rejectedCorners_mat.release(); + return; + } + + //javadoc: refineDetectedMarkers(image, board, detectedCorners, detectedIds, rejectedCorners, cameraMatrix, distCoeffs, minRepDistance, errorCorrectionRate, checkAllOrders, recoveredIdxs) + public static void refineDetectedMarkers(Mat image, Board board, List detectedCorners, Mat detectedIds, List rejectedCorners, Mat cameraMatrix, Mat distCoeffs, float minRepDistance, float errorCorrectionRate, boolean checkAllOrders, Mat recoveredIdxs) + { + Mat detectedCorners_mat = Converters.vector_Mat_to_Mat(detectedCorners); + Mat rejectedCorners_mat = Converters.vector_Mat_to_Mat(rejectedCorners); + refineDetectedMarkers_1(image.nativeObj, board.getNativeObjAddr(), detectedCorners_mat.nativeObj, detectedIds.nativeObj, rejectedCorners_mat.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, minRepDistance, errorCorrectionRate, checkAllOrders, recoveredIdxs.nativeObj); + Converters.Mat_to_vector_Mat(detectedCorners_mat, detectedCorners); + detectedCorners_mat.release(); + Converters.Mat_to_vector_Mat(rejectedCorners_mat, rejectedCorners); + rejectedCorners_mat.release(); + return; + } + + //javadoc: refineDetectedMarkers(image, board, detectedCorners, detectedIds, rejectedCorners, cameraMatrix, distCoeffs, minRepDistance, errorCorrectionRate, checkAllOrders) + public static void refineDetectedMarkers(Mat image, Board board, List detectedCorners, Mat detectedIds, List rejectedCorners, Mat cameraMatrix, Mat distCoeffs, float minRepDistance, float errorCorrectionRate, boolean checkAllOrders) + { + Mat detectedCorners_mat = Converters.vector_Mat_to_Mat(detectedCorners); + Mat rejectedCorners_mat = Converters.vector_Mat_to_Mat(rejectedCorners); + refineDetectedMarkers_2(image.nativeObj, board.getNativeObjAddr(), detectedCorners_mat.nativeObj, detectedIds.nativeObj, rejectedCorners_mat.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, minRepDistance, errorCorrectionRate, checkAllOrders); + Converters.Mat_to_vector_Mat(detectedCorners_mat, detectedCorners); + detectedCorners_mat.release(); + Converters.Mat_to_vector_Mat(rejectedCorners_mat, rejectedCorners); + rejectedCorners_mat.release(); + return; + } + + //javadoc: refineDetectedMarkers(image, board, detectedCorners, detectedIds, rejectedCorners, cameraMatrix, distCoeffs, minRepDistance, errorCorrectionRate) + public static void refineDetectedMarkers(Mat image, Board board, List detectedCorners, Mat detectedIds, List rejectedCorners, Mat cameraMatrix, Mat distCoeffs, float minRepDistance, float errorCorrectionRate) + { + Mat detectedCorners_mat = Converters.vector_Mat_to_Mat(detectedCorners); + Mat rejectedCorners_mat = Converters.vector_Mat_to_Mat(rejectedCorners); + refineDetectedMarkers_3(image.nativeObj, board.getNativeObjAddr(), detectedCorners_mat.nativeObj, detectedIds.nativeObj, rejectedCorners_mat.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, minRepDistance, errorCorrectionRate); + Converters.Mat_to_vector_Mat(detectedCorners_mat, detectedCorners); + detectedCorners_mat.release(); + Converters.Mat_to_vector_Mat(rejectedCorners_mat, rejectedCorners); + rejectedCorners_mat.release(); + return; + } + + //javadoc: refineDetectedMarkers(image, board, detectedCorners, detectedIds, rejectedCorners, cameraMatrix, distCoeffs, minRepDistance) + public static void refineDetectedMarkers(Mat image, Board board, List detectedCorners, Mat detectedIds, List rejectedCorners, Mat cameraMatrix, Mat distCoeffs, float minRepDistance) + { + Mat detectedCorners_mat = Converters.vector_Mat_to_Mat(detectedCorners); + Mat rejectedCorners_mat = Converters.vector_Mat_to_Mat(rejectedCorners); + refineDetectedMarkers_4(image.nativeObj, board.getNativeObjAddr(), detectedCorners_mat.nativeObj, detectedIds.nativeObj, rejectedCorners_mat.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, minRepDistance); + Converters.Mat_to_vector_Mat(detectedCorners_mat, detectedCorners); + detectedCorners_mat.release(); + Converters.Mat_to_vector_Mat(rejectedCorners_mat, rejectedCorners); + rejectedCorners_mat.release(); + return; + } + + //javadoc: refineDetectedMarkers(image, board, detectedCorners, detectedIds, rejectedCorners, cameraMatrix, distCoeffs) + public static void refineDetectedMarkers(Mat image, Board board, List detectedCorners, Mat detectedIds, List rejectedCorners, Mat cameraMatrix, Mat distCoeffs) + { + Mat detectedCorners_mat = Converters.vector_Mat_to_Mat(detectedCorners); + Mat rejectedCorners_mat = Converters.vector_Mat_to_Mat(rejectedCorners); + refineDetectedMarkers_5(image.nativeObj, board.getNativeObjAddr(), detectedCorners_mat.nativeObj, detectedIds.nativeObj, rejectedCorners_mat.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj); + Converters.Mat_to_vector_Mat(detectedCorners_mat, detectedCorners); + detectedCorners_mat.release(); + Converters.Mat_to_vector_Mat(rejectedCorners_mat, rejectedCorners); + rejectedCorners_mat.release(); + return; + } + + //javadoc: refineDetectedMarkers(image, board, detectedCorners, detectedIds, rejectedCorners, cameraMatrix) + public static void refineDetectedMarkers(Mat image, Board board, List detectedCorners, Mat detectedIds, List rejectedCorners, Mat cameraMatrix) + { + Mat detectedCorners_mat = Converters.vector_Mat_to_Mat(detectedCorners); + Mat rejectedCorners_mat = Converters.vector_Mat_to_Mat(rejectedCorners); + refineDetectedMarkers_6(image.nativeObj, board.getNativeObjAddr(), detectedCorners_mat.nativeObj, detectedIds.nativeObj, rejectedCorners_mat.nativeObj, cameraMatrix.nativeObj); + Converters.Mat_to_vector_Mat(detectedCorners_mat, detectedCorners); + detectedCorners_mat.release(); + Converters.Mat_to_vector_Mat(rejectedCorners_mat, rejectedCorners); + rejectedCorners_mat.release(); + return; + } + + //javadoc: refineDetectedMarkers(image, board, detectedCorners, detectedIds, rejectedCorners) + public static void refineDetectedMarkers(Mat image, Board board, List detectedCorners, Mat detectedIds, List rejectedCorners) + { + Mat detectedCorners_mat = Converters.vector_Mat_to_Mat(detectedCorners); + Mat rejectedCorners_mat = Converters.vector_Mat_to_Mat(rejectedCorners); + refineDetectedMarkers_7(image.nativeObj, board.getNativeObjAddr(), detectedCorners_mat.nativeObj, detectedIds.nativeObj, rejectedCorners_mat.nativeObj); + Converters.Mat_to_vector_Mat(detectedCorners_mat, detectedCorners); + detectedCorners_mat.release(); + Converters.Mat_to_vector_Mat(rejectedCorners_mat, rejectedCorners); + rejectedCorners_mat.release(); + return; + } + + + + + // C++: Ptr_Dictionary cv::aruco::generateCustomDictionary(int nMarkers, int markerSize, Ptr_Dictionary baseDictionary, int randomSeed = 0) + private static native long custom_dictionary_from_0(int nMarkers, int markerSize, long baseDictionary_nativeObj, int randomSeed); + private static native long custom_dictionary_from_1(int nMarkers, int markerSize, long baseDictionary_nativeObj); + + // C++: Ptr_Dictionary cv::aruco::generateCustomDictionary(int nMarkers, int markerSize, int randomSeed = 0) + private static native long custom_dictionary_0(int nMarkers, int markerSize, int randomSeed); + private static native long custom_dictionary_1(int nMarkers, int markerSize); + + // C++: Ptr_Dictionary cv::aruco::getPredefinedDictionary(int dict) + private static native long getPredefinedDictionary_0(int dict); + + // C++: bool cv::aruco::estimatePoseCharucoBoard(Mat charucoCorners, Mat charucoIds, Ptr_CharucoBoard board, Mat cameraMatrix, Mat distCoeffs, Mat& rvec, Mat& tvec, bool useExtrinsicGuess = false) + private static native boolean estimatePoseCharucoBoard_0(long charucoCorners_nativeObj, long charucoIds_nativeObj, long board_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvec_nativeObj, long tvec_nativeObj, boolean useExtrinsicGuess); + private static native boolean estimatePoseCharucoBoard_1(long charucoCorners_nativeObj, long charucoIds_nativeObj, long board_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvec_nativeObj, long tvec_nativeObj); + + // C++: double cv::aruco::calibrateCameraAruco(vector_Mat corners, Mat ids, Mat counter, Ptr_Board board, Size imageSize, Mat& cameraMatrix, Mat& distCoeffs, vector_Mat& rvecs, vector_Mat& tvecs, Mat& stdDeviationsIntrinsics, Mat& stdDeviationsExtrinsics, Mat& perViewErrors, int flags = 0, TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)) + private static native double calibrateCameraArucoExtended_0(long corners_mat_nativeObj, long ids_nativeObj, long counter_nativeObj, long board_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, long stdDeviationsIntrinsics_nativeObj, long stdDeviationsExtrinsics_nativeObj, long perViewErrors_nativeObj, int flags, int criteria_type, int criteria_maxCount, double criteria_epsilon); + private static native double calibrateCameraArucoExtended_1(long corners_mat_nativeObj, long ids_nativeObj, long counter_nativeObj, long board_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, long stdDeviationsIntrinsics_nativeObj, long stdDeviationsExtrinsics_nativeObj, long perViewErrors_nativeObj, int flags); + private static native double calibrateCameraArucoExtended_2(long corners_mat_nativeObj, long ids_nativeObj, long counter_nativeObj, long board_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, long stdDeviationsIntrinsics_nativeObj, long stdDeviationsExtrinsics_nativeObj, long perViewErrors_nativeObj); + + // C++: double cv::aruco::calibrateCameraAruco(vector_Mat corners, Mat ids, Mat counter, Ptr_Board board, Size imageSize, Mat& cameraMatrix, Mat& distCoeffs, vector_Mat& rvecs = vector_Mat(), vector_Mat& tvecs = vector_Mat(), int flags = 0, TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)) + private static native double calibrateCameraAruco_0(long corners_mat_nativeObj, long ids_nativeObj, long counter_nativeObj, long board_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, int flags, int criteria_type, int criteria_maxCount, double criteria_epsilon); + private static native double calibrateCameraAruco_1(long corners_mat_nativeObj, long ids_nativeObj, long counter_nativeObj, long board_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, int flags); + private static native double calibrateCameraAruco_2(long corners_mat_nativeObj, long ids_nativeObj, long counter_nativeObj, long board_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj); + private static native double calibrateCameraAruco_3(long corners_mat_nativeObj, long ids_nativeObj, long counter_nativeObj, long board_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj); + private static native double calibrateCameraAruco_4(long corners_mat_nativeObj, long ids_nativeObj, long counter_nativeObj, long board_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj); + + // C++: double cv::aruco::calibrateCameraCharuco(vector_Mat charucoCorners, vector_Mat charucoIds, Ptr_CharucoBoard board, Size imageSize, Mat& cameraMatrix, Mat& distCoeffs, vector_Mat& rvecs, vector_Mat& tvecs, Mat& stdDeviationsIntrinsics, Mat& stdDeviationsExtrinsics, Mat& perViewErrors, int flags = 0, TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)) + private static native double calibrateCameraCharucoExtended_0(long charucoCorners_mat_nativeObj, long charucoIds_mat_nativeObj, long board_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, long stdDeviationsIntrinsics_nativeObj, long stdDeviationsExtrinsics_nativeObj, long perViewErrors_nativeObj, int flags, int criteria_type, int criteria_maxCount, double criteria_epsilon); + private static native double calibrateCameraCharucoExtended_1(long charucoCorners_mat_nativeObj, long charucoIds_mat_nativeObj, long board_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, long stdDeviationsIntrinsics_nativeObj, long stdDeviationsExtrinsics_nativeObj, long perViewErrors_nativeObj, int flags); + private static native double calibrateCameraCharucoExtended_2(long charucoCorners_mat_nativeObj, long charucoIds_mat_nativeObj, long board_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, long stdDeviationsIntrinsics_nativeObj, long stdDeviationsExtrinsics_nativeObj, long perViewErrors_nativeObj); + + // C++: double cv::aruco::calibrateCameraCharuco(vector_Mat charucoCorners, vector_Mat charucoIds, Ptr_CharucoBoard board, Size imageSize, Mat& cameraMatrix, Mat& distCoeffs, vector_Mat& rvecs = vector_Mat(), vector_Mat& tvecs = vector_Mat(), int flags = 0, TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)) + private static native double calibrateCameraCharuco_0(long charucoCorners_mat_nativeObj, long charucoIds_mat_nativeObj, long board_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, int flags, int criteria_type, int criteria_maxCount, double criteria_epsilon); + private static native double calibrateCameraCharuco_1(long charucoCorners_mat_nativeObj, long charucoIds_mat_nativeObj, long board_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, int flags); + private static native double calibrateCameraCharuco_2(long charucoCorners_mat_nativeObj, long charucoIds_mat_nativeObj, long board_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj); + private static native double calibrateCameraCharuco_3(long charucoCorners_mat_nativeObj, long charucoIds_mat_nativeObj, long board_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj); + private static native double calibrateCameraCharuco_4(long charucoCorners_mat_nativeObj, long charucoIds_mat_nativeObj, long board_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj); + + // C++: int cv::aruco::estimatePoseBoard(vector_Mat corners, Mat ids, Ptr_Board board, Mat cameraMatrix, Mat distCoeffs, Mat& rvec, Mat& tvec, bool useExtrinsicGuess = false) + private static native int estimatePoseBoard_0(long corners_mat_nativeObj, long ids_nativeObj, long board_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvec_nativeObj, long tvec_nativeObj, boolean useExtrinsicGuess); + private static native int estimatePoseBoard_1(long corners_mat_nativeObj, long ids_nativeObj, long board_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvec_nativeObj, long tvec_nativeObj); + + // C++: int cv::aruco::interpolateCornersCharuco(vector_Mat markerCorners, Mat markerIds, Mat image, Ptr_CharucoBoard board, Mat& charucoCorners, Mat& charucoIds, Mat cameraMatrix = Mat(), Mat distCoeffs = Mat(), int minMarkers = 2) + private static native int interpolateCornersCharuco_0(long markerCorners_mat_nativeObj, long markerIds_nativeObj, long image_nativeObj, long board_nativeObj, long charucoCorners_nativeObj, long charucoIds_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, int minMarkers); + private static native int interpolateCornersCharuco_1(long markerCorners_mat_nativeObj, long markerIds_nativeObj, long image_nativeObj, long board_nativeObj, long charucoCorners_nativeObj, long charucoIds_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj); + private static native int interpolateCornersCharuco_2(long markerCorners_mat_nativeObj, long markerIds_nativeObj, long image_nativeObj, long board_nativeObj, long charucoCorners_nativeObj, long charucoIds_nativeObj, long cameraMatrix_nativeObj); + private static native int interpolateCornersCharuco_3(long markerCorners_mat_nativeObj, long markerIds_nativeObj, long image_nativeObj, long board_nativeObj, long charucoCorners_nativeObj, long charucoIds_nativeObj); + + // C++: void cv::aruco::detectCharucoDiamond(Mat image, vector_Mat markerCorners, Mat markerIds, float squareMarkerLengthRate, vector_Mat& diamondCorners, Mat& diamondIds, Mat cameraMatrix = Mat(), Mat distCoeffs = Mat()) + private static native void detectCharucoDiamond_0(long image_nativeObj, long markerCorners_mat_nativeObj, long markerIds_nativeObj, float squareMarkerLengthRate, long diamondCorners_mat_nativeObj, long diamondIds_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj); + private static native void detectCharucoDiamond_1(long image_nativeObj, long markerCorners_mat_nativeObj, long markerIds_nativeObj, float squareMarkerLengthRate, long diamondCorners_mat_nativeObj, long diamondIds_nativeObj, long cameraMatrix_nativeObj); + private static native void detectCharucoDiamond_2(long image_nativeObj, long markerCorners_mat_nativeObj, long markerIds_nativeObj, float squareMarkerLengthRate, long diamondCorners_mat_nativeObj, long diamondIds_nativeObj); + + // C++: void cv::aruco::detectMarkers(Mat image, Ptr_Dictionary dictionary, vector_Mat& corners, Mat& ids, Ptr_DetectorParameters parameters = DetectorParameters::create(), vector_Mat& rejectedImgPoints = vector_Mat(), Mat cameraMatrix = Mat(), Mat distCoeff = Mat()) + private static native void detectMarkers_0(long image_nativeObj, long dictionary_nativeObj, long corners_mat_nativeObj, long ids_nativeObj, long parameters_nativeObj, long rejectedImgPoints_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeff_nativeObj); + private static native void detectMarkers_1(long image_nativeObj, long dictionary_nativeObj, long corners_mat_nativeObj, long ids_nativeObj, long parameters_nativeObj, long rejectedImgPoints_mat_nativeObj, long cameraMatrix_nativeObj); + private static native void detectMarkers_2(long image_nativeObj, long dictionary_nativeObj, long corners_mat_nativeObj, long ids_nativeObj, long parameters_nativeObj, long rejectedImgPoints_mat_nativeObj); + private static native void detectMarkers_3(long image_nativeObj, long dictionary_nativeObj, long corners_mat_nativeObj, long ids_nativeObj, long parameters_nativeObj); + private static native void detectMarkers_4(long image_nativeObj, long dictionary_nativeObj, long corners_mat_nativeObj, long ids_nativeObj); + + // C++: void cv::aruco::drawAxis(Mat& image, Mat cameraMatrix, Mat distCoeffs, Mat rvec, Mat tvec, float length) + private static native void drawAxis_0(long image_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvec_nativeObj, long tvec_nativeObj, float length); + + // C++: void cv::aruco::drawDetectedCornersCharuco(Mat& image, Mat charucoCorners, Mat charucoIds = Mat(), Scalar cornerColor = Scalar(255, 0, 0)) + private static native void drawDetectedCornersCharuco_0(long image_nativeObj, long charucoCorners_nativeObj, long charucoIds_nativeObj, double cornerColor_val0, double cornerColor_val1, double cornerColor_val2, double cornerColor_val3); + private static native void drawDetectedCornersCharuco_1(long image_nativeObj, long charucoCorners_nativeObj, long charucoIds_nativeObj); + private static native void drawDetectedCornersCharuco_2(long image_nativeObj, long charucoCorners_nativeObj); + + // C++: void cv::aruco::drawDetectedDiamonds(Mat& image, vector_Mat diamondCorners, Mat diamondIds = Mat(), Scalar borderColor = Scalar(0, 0, 255)) + private static native void drawDetectedDiamonds_0(long image_nativeObj, long diamondCorners_mat_nativeObj, long diamondIds_nativeObj, double borderColor_val0, double borderColor_val1, double borderColor_val2, double borderColor_val3); + private static native void drawDetectedDiamonds_1(long image_nativeObj, long diamondCorners_mat_nativeObj, long diamondIds_nativeObj); + private static native void drawDetectedDiamonds_2(long image_nativeObj, long diamondCorners_mat_nativeObj); + + // C++: void cv::aruco::drawDetectedMarkers(Mat& image, vector_Mat corners, Mat ids = Mat(), Scalar borderColor = Scalar(0, 255, 0)) + private static native void drawDetectedMarkers_0(long image_nativeObj, long corners_mat_nativeObj, long ids_nativeObj, double borderColor_val0, double borderColor_val1, double borderColor_val2, double borderColor_val3); + private static native void drawDetectedMarkers_1(long image_nativeObj, long corners_mat_nativeObj, long ids_nativeObj); + private static native void drawDetectedMarkers_2(long image_nativeObj, long corners_mat_nativeObj); + + // C++: void cv::aruco::drawMarker(Ptr_Dictionary dictionary, int id, int sidePixels, Mat& img, int borderBits = 1) + private static native void drawMarker_0(long dictionary_nativeObj, int id, int sidePixels, long img_nativeObj, int borderBits); + private static native void drawMarker_1(long dictionary_nativeObj, int id, int sidePixels, long img_nativeObj); + + // C++: void cv::aruco::drawPlanarBoard(Ptr_Board board, Size outSize, Mat& img, int marginSize = 0, int borderBits = 1) + private static native void drawPlanarBoard_0(long board_nativeObj, double outSize_width, double outSize_height, long img_nativeObj, int marginSize, int borderBits); + private static native void drawPlanarBoard_1(long board_nativeObj, double outSize_width, double outSize_height, long img_nativeObj, int marginSize); + private static native void drawPlanarBoard_2(long board_nativeObj, double outSize_width, double outSize_height, long img_nativeObj); + + // C++: void cv::aruco::estimatePoseSingleMarkers(vector_Mat corners, float markerLength, Mat cameraMatrix, Mat distCoeffs, Mat& rvecs, Mat& tvecs, Mat& _objPoints = Mat()) + private static native void estimatePoseSingleMarkers_0(long corners_mat_nativeObj, float markerLength, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_nativeObj, long tvecs_nativeObj, long _objPoints_nativeObj); + private static native void estimatePoseSingleMarkers_1(long corners_mat_nativeObj, float markerLength, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_nativeObj, long tvecs_nativeObj); + + // C++: void cv::aruco::getBoardObjectAndImagePoints(Ptr_Board board, vector_Mat detectedCorners, Mat detectedIds, Mat& objPoints, Mat& imgPoints) + private static native void getBoardObjectAndImagePoints_0(long board_nativeObj, long detectedCorners_mat_nativeObj, long detectedIds_nativeObj, long objPoints_nativeObj, long imgPoints_nativeObj); + + // C++: void cv::aruco::refineDetectedMarkers(Mat image, Ptr_Board board, vector_Mat& detectedCorners, Mat& detectedIds, vector_Mat& rejectedCorners, Mat cameraMatrix = Mat(), Mat distCoeffs = Mat(), float minRepDistance = 10.f, float errorCorrectionRate = 3.f, bool checkAllOrders = true, Mat& recoveredIdxs = Mat(), Ptr_DetectorParameters parameters = DetectorParameters::create()) + private static native void refineDetectedMarkers_0(long image_nativeObj, long board_nativeObj, long detectedCorners_mat_nativeObj, long detectedIds_nativeObj, long rejectedCorners_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, float minRepDistance, float errorCorrectionRate, boolean checkAllOrders, long recoveredIdxs_nativeObj, long parameters_nativeObj); + private static native void refineDetectedMarkers_1(long image_nativeObj, long board_nativeObj, long detectedCorners_mat_nativeObj, long detectedIds_nativeObj, long rejectedCorners_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, float minRepDistance, float errorCorrectionRate, boolean checkAllOrders, long recoveredIdxs_nativeObj); + private static native void refineDetectedMarkers_2(long image_nativeObj, long board_nativeObj, long detectedCorners_mat_nativeObj, long detectedIds_nativeObj, long rejectedCorners_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, float minRepDistance, float errorCorrectionRate, boolean checkAllOrders); + private static native void refineDetectedMarkers_3(long image_nativeObj, long board_nativeObj, long detectedCorners_mat_nativeObj, long detectedIds_nativeObj, long rejectedCorners_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, float minRepDistance, float errorCorrectionRate); + private static native void refineDetectedMarkers_4(long image_nativeObj, long board_nativeObj, long detectedCorners_mat_nativeObj, long detectedIds_nativeObj, long rejectedCorners_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, float minRepDistance); + private static native void refineDetectedMarkers_5(long image_nativeObj, long board_nativeObj, long detectedCorners_mat_nativeObj, long detectedIds_nativeObj, long rejectedCorners_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj); + private static native void refineDetectedMarkers_6(long image_nativeObj, long board_nativeObj, long detectedCorners_mat_nativeObj, long detectedIds_nativeObj, long rejectedCorners_mat_nativeObj, long cameraMatrix_nativeObj); + private static native void refineDetectedMarkers_7(long image_nativeObj, long board_nativeObj, long detectedCorners_mat_nativeObj, long detectedIds_nativeObj, long rejectedCorners_mat_nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/aruco/Board.java b/OpenCV/src/main/java/org/opencv/aruco/Board.java new file mode 100644 index 00000000..e2d73fe2 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/aruco/Board.java @@ -0,0 +1,106 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.aruco; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.aruco.Board; +import org.opencv.aruco.Dictionary; +import org.opencv.core.Mat; +import org.opencv.core.MatOfInt; +import org.opencv.core.MatOfPoint3f; +import org.opencv.utils.Converters; + +// C++: class Board +//javadoc: Board + +public class Board { + + protected final long nativeObj; + protected Board(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static Board __fromPtr__(long addr) { return new Board(addr); } + + // + // C++: static Ptr_Board cv::aruco::Board::create(vector_Mat objPoints, Ptr_Dictionary dictionary, Mat ids) + // + + //javadoc: Board::create(objPoints, dictionary, ids) + public static Board create(List objPoints, Dictionary dictionary, Mat ids) + { + Mat objPoints_mat = Converters.vector_Mat_to_Mat(objPoints); + Board retVal = Board.__fromPtr__(create_0(objPoints_mat.nativeObj, dictionary.getNativeObjAddr(), ids.nativeObj)); + + return retVal; + } + + + // + // C++: vector_vector_Point3f Board::objPoints + // + + //javadoc: Board::get_objPoints() + public List get_objPoints() + { + List retVal = new ArrayList(); + Mat retValMat = new Mat(get_objPoints_0(nativeObj)); + Converters.Mat_to_vector_vector_Point3f(retValMat, retVal); + return retVal; + } + + + // + // C++: Ptr_Dictionary Board::dictionary + // + + //javadoc: Board::get_dictionary() + public Dictionary get_dictionary() + { + + Dictionary retVal = Dictionary.__fromPtr__(get_dictionary_0(nativeObj)); + + return retVal; + } + + + // + // C++: vector_int Board::ids + // + + //javadoc: Board::get_ids() + public MatOfInt get_ids() + { + + MatOfInt retVal = MatOfInt.fromNativeAddr(get_ids_0(nativeObj)); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_Board cv::aruco::Board::create(vector_Mat objPoints, Ptr_Dictionary dictionary, Mat ids) + private static native long create_0(long objPoints_mat_nativeObj, long dictionary_nativeObj, long ids_nativeObj); + + // C++: vector_vector_Point3f Board::objPoints + private static native long get_objPoints_0(long nativeObj); + + // C++: Ptr_Dictionary Board::dictionary + private static native long get_dictionary_0(long nativeObj); + + // C++: vector_int Board::ids + private static native long get_ids_0(long nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/aruco/CharucoBoard.java b/OpenCV/src/main/java/org/opencv/aruco/CharucoBoard.java new file mode 100644 index 00000000..7eb6d14c --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/aruco/CharucoBoard.java @@ -0,0 +1,172 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.aruco; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.aruco.Board; +import org.opencv.aruco.CharucoBoard; +import org.opencv.aruco.Dictionary; +import org.opencv.core.Mat; +import org.opencv.core.MatOfPoint3f; +import org.opencv.core.Size; +import org.opencv.utils.Converters; + +// C++: class CharucoBoard +//javadoc: CharucoBoard + +public class CharucoBoard extends Board { + + protected CharucoBoard(long addr) { super(addr); } + + // internal usage only + public static CharucoBoard __fromPtr__(long addr) { return new CharucoBoard(addr); } + + // + // C++: static Ptr_CharucoBoard cv::aruco::CharucoBoard::create(int squaresX, int squaresY, float squareLength, float markerLength, Ptr_Dictionary dictionary) + // + + //javadoc: CharucoBoard::create(squaresX, squaresY, squareLength, markerLength, dictionary) + public static CharucoBoard create(int squaresX, int squaresY, float squareLength, float markerLength, Dictionary dictionary) + { + + CharucoBoard retVal = CharucoBoard.__fromPtr__(create_0(squaresX, squaresY, squareLength, markerLength, dictionary.getNativeObjAddr())); + + return retVal; + } + + + // + // C++: Size cv::aruco::CharucoBoard::getChessboardSize() + // + + //javadoc: CharucoBoard::getChessboardSize() + public Size getChessboardSize() + { + + Size retVal = new Size(getChessboardSize_0(nativeObj)); + + return retVal; + } + + + // + // C++: float cv::aruco::CharucoBoard::getMarkerLength() + // + + //javadoc: CharucoBoard::getMarkerLength() + public float getMarkerLength() + { + + float retVal = getMarkerLength_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::aruco::CharucoBoard::getSquareLength() + // + + //javadoc: CharucoBoard::getSquareLength() + public float getSquareLength() + { + + float retVal = getSquareLength_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::aruco::CharucoBoard::draw(Size outSize, Mat& img, int marginSize = 0, int borderBits = 1) + // + + //javadoc: CharucoBoard::draw(outSize, img, marginSize, borderBits) + public void draw(Size outSize, Mat img, int marginSize, int borderBits) + { + + draw_0(nativeObj, outSize.width, outSize.height, img.nativeObj, marginSize, borderBits); + + return; + } + + //javadoc: CharucoBoard::draw(outSize, img, marginSize) + public void draw(Size outSize, Mat img, int marginSize) + { + + draw_1(nativeObj, outSize.width, outSize.height, img.nativeObj, marginSize); + + return; + } + + //javadoc: CharucoBoard::draw(outSize, img) + public void draw(Size outSize, Mat img) + { + + draw_2(nativeObj, outSize.width, outSize.height, img.nativeObj); + + return; + } + + + // + // C++: vector_Point3f CharucoBoard::chessboardCorners + // + + //javadoc: CharucoBoard::get_chessboardCorners() + public MatOfPoint3f get_chessboardCorners() + { + + MatOfPoint3f retVal = MatOfPoint3f.fromNativeAddr(get_chessboardCorners_0(nativeObj)); + + return retVal; + } + + + // + // C++: vector_vector_int CharucoBoard::nearestMarkerIdx + // + + // Return type 'vector_vector_int' is not supported, skipping the function + + + // + // C++: vector_vector_int CharucoBoard::nearestMarkerCorners + // + + // Return type 'vector_vector_int' is not supported, skipping the function + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_CharucoBoard cv::aruco::CharucoBoard::create(int squaresX, int squaresY, float squareLength, float markerLength, Ptr_Dictionary dictionary) + private static native long create_0(int squaresX, int squaresY, float squareLength, float markerLength, long dictionary_nativeObj); + + // C++: Size cv::aruco::CharucoBoard::getChessboardSize() + private static native double[] getChessboardSize_0(long nativeObj); + + // C++: float cv::aruco::CharucoBoard::getMarkerLength() + private static native float getMarkerLength_0(long nativeObj); + + // C++: float cv::aruco::CharucoBoard::getSquareLength() + private static native float getSquareLength_0(long nativeObj); + + // C++: void cv::aruco::CharucoBoard::draw(Size outSize, Mat& img, int marginSize = 0, int borderBits = 1) + private static native void draw_0(long nativeObj, double outSize_width, double outSize_height, long img_nativeObj, int marginSize, int borderBits); + private static native void draw_1(long nativeObj, double outSize_width, double outSize_height, long img_nativeObj, int marginSize); + private static native void draw_2(long nativeObj, double outSize_width, double outSize_height, long img_nativeObj); + + // C++: vector_Point3f CharucoBoard::chessboardCorners + private static native long get_chessboardCorners_0(long nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/aruco/DetectorParameters.java b/OpenCV/src/main/java/org/opencv/aruco/DetectorParameters.java new file mode 100644 index 00000000..d63b5e20 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/aruco/DetectorParameters.java @@ -0,0 +1,1000 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.aruco; + +import org.opencv.aruco.DetectorParameters; + +// C++: class DetectorParameters +//javadoc: DetectorParameters + +public class DetectorParameters { + + protected final long nativeObj; + protected DetectorParameters(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static DetectorParameters __fromPtr__(long addr) { return new DetectorParameters(addr); } + + // + // C++: static Ptr_DetectorParameters cv::aruco::DetectorParameters::create() + // + + //javadoc: DetectorParameters::create() + public static DetectorParameters create() + { + + DetectorParameters retVal = DetectorParameters.__fromPtr__(create_0()); + + return retVal; + } + + + // + // C++: int DetectorParameters::adaptiveThreshWinSizeMin + // + + //javadoc: DetectorParameters::get_adaptiveThreshWinSizeMin() + public int get_adaptiveThreshWinSizeMin() + { + + int retVal = get_adaptiveThreshWinSizeMin_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::adaptiveThreshWinSizeMin + // + + //javadoc: DetectorParameters::set_adaptiveThreshWinSizeMin(adaptiveThreshWinSizeMin) + public void set_adaptiveThreshWinSizeMin(int adaptiveThreshWinSizeMin) + { + + set_adaptiveThreshWinSizeMin_0(nativeObj, adaptiveThreshWinSizeMin); + + return; + } + + + // + // C++: int DetectorParameters::adaptiveThreshWinSizeMax + // + + //javadoc: DetectorParameters::get_adaptiveThreshWinSizeMax() + public int get_adaptiveThreshWinSizeMax() + { + + int retVal = get_adaptiveThreshWinSizeMax_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::adaptiveThreshWinSizeMax + // + + //javadoc: DetectorParameters::set_adaptiveThreshWinSizeMax(adaptiveThreshWinSizeMax) + public void set_adaptiveThreshWinSizeMax(int adaptiveThreshWinSizeMax) + { + + set_adaptiveThreshWinSizeMax_0(nativeObj, adaptiveThreshWinSizeMax); + + return; + } + + + // + // C++: int DetectorParameters::adaptiveThreshWinSizeStep + // + + //javadoc: DetectorParameters::get_adaptiveThreshWinSizeStep() + public int get_adaptiveThreshWinSizeStep() + { + + int retVal = get_adaptiveThreshWinSizeStep_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::adaptiveThreshWinSizeStep + // + + //javadoc: DetectorParameters::set_adaptiveThreshWinSizeStep(adaptiveThreshWinSizeStep) + public void set_adaptiveThreshWinSizeStep(int adaptiveThreshWinSizeStep) + { + + set_adaptiveThreshWinSizeStep_0(nativeObj, adaptiveThreshWinSizeStep); + + return; + } + + + // + // C++: double DetectorParameters::adaptiveThreshConstant + // + + //javadoc: DetectorParameters::get_adaptiveThreshConstant() + public double get_adaptiveThreshConstant() + { + + double retVal = get_adaptiveThreshConstant_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::adaptiveThreshConstant + // + + //javadoc: DetectorParameters::set_adaptiveThreshConstant(adaptiveThreshConstant) + public void set_adaptiveThreshConstant(double adaptiveThreshConstant) + { + + set_adaptiveThreshConstant_0(nativeObj, adaptiveThreshConstant); + + return; + } + + + // + // C++: double DetectorParameters::minMarkerPerimeterRate + // + + //javadoc: DetectorParameters::get_minMarkerPerimeterRate() + public double get_minMarkerPerimeterRate() + { + + double retVal = get_minMarkerPerimeterRate_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::minMarkerPerimeterRate + // + + //javadoc: DetectorParameters::set_minMarkerPerimeterRate(minMarkerPerimeterRate) + public void set_minMarkerPerimeterRate(double minMarkerPerimeterRate) + { + + set_minMarkerPerimeterRate_0(nativeObj, minMarkerPerimeterRate); + + return; + } + + + // + // C++: double DetectorParameters::maxMarkerPerimeterRate + // + + //javadoc: DetectorParameters::get_maxMarkerPerimeterRate() + public double get_maxMarkerPerimeterRate() + { + + double retVal = get_maxMarkerPerimeterRate_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::maxMarkerPerimeterRate + // + + //javadoc: DetectorParameters::set_maxMarkerPerimeterRate(maxMarkerPerimeterRate) + public void set_maxMarkerPerimeterRate(double maxMarkerPerimeterRate) + { + + set_maxMarkerPerimeterRate_0(nativeObj, maxMarkerPerimeterRate); + + return; + } + + + // + // C++: double DetectorParameters::polygonalApproxAccuracyRate + // + + //javadoc: DetectorParameters::get_polygonalApproxAccuracyRate() + public double get_polygonalApproxAccuracyRate() + { + + double retVal = get_polygonalApproxAccuracyRate_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::polygonalApproxAccuracyRate + // + + //javadoc: DetectorParameters::set_polygonalApproxAccuracyRate(polygonalApproxAccuracyRate) + public void set_polygonalApproxAccuracyRate(double polygonalApproxAccuracyRate) + { + + set_polygonalApproxAccuracyRate_0(nativeObj, polygonalApproxAccuracyRate); + + return; + } + + + // + // C++: double DetectorParameters::minCornerDistanceRate + // + + //javadoc: DetectorParameters::get_minCornerDistanceRate() + public double get_minCornerDistanceRate() + { + + double retVal = get_minCornerDistanceRate_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::minCornerDistanceRate + // + + //javadoc: DetectorParameters::set_minCornerDistanceRate(minCornerDistanceRate) + public void set_minCornerDistanceRate(double minCornerDistanceRate) + { + + set_minCornerDistanceRate_0(nativeObj, minCornerDistanceRate); + + return; + } + + + // + // C++: int DetectorParameters::minDistanceToBorder + // + + //javadoc: DetectorParameters::get_minDistanceToBorder() + public int get_minDistanceToBorder() + { + + int retVal = get_minDistanceToBorder_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::minDistanceToBorder + // + + //javadoc: DetectorParameters::set_minDistanceToBorder(minDistanceToBorder) + public void set_minDistanceToBorder(int minDistanceToBorder) + { + + set_minDistanceToBorder_0(nativeObj, minDistanceToBorder); + + return; + } + + + // + // C++: double DetectorParameters::minMarkerDistanceRate + // + + //javadoc: DetectorParameters::get_minMarkerDistanceRate() + public double get_minMarkerDistanceRate() + { + + double retVal = get_minMarkerDistanceRate_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::minMarkerDistanceRate + // + + //javadoc: DetectorParameters::set_minMarkerDistanceRate(minMarkerDistanceRate) + public void set_minMarkerDistanceRate(double minMarkerDistanceRate) + { + + set_minMarkerDistanceRate_0(nativeObj, minMarkerDistanceRate); + + return; + } + + + // + // C++: int DetectorParameters::cornerRefinementMethod + // + + //javadoc: DetectorParameters::get_cornerRefinementMethod() + public int get_cornerRefinementMethod() + { + + int retVal = get_cornerRefinementMethod_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::cornerRefinementMethod + // + + //javadoc: DetectorParameters::set_cornerRefinementMethod(cornerRefinementMethod) + public void set_cornerRefinementMethod(int cornerRefinementMethod) + { + + set_cornerRefinementMethod_0(nativeObj, cornerRefinementMethod); + + return; + } + + + // + // C++: int DetectorParameters::cornerRefinementWinSize + // + + //javadoc: DetectorParameters::get_cornerRefinementWinSize() + public int get_cornerRefinementWinSize() + { + + int retVal = get_cornerRefinementWinSize_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::cornerRefinementWinSize + // + + //javadoc: DetectorParameters::set_cornerRefinementWinSize(cornerRefinementWinSize) + public void set_cornerRefinementWinSize(int cornerRefinementWinSize) + { + + set_cornerRefinementWinSize_0(nativeObj, cornerRefinementWinSize); + + return; + } + + + // + // C++: int DetectorParameters::cornerRefinementMaxIterations + // + + //javadoc: DetectorParameters::get_cornerRefinementMaxIterations() + public int get_cornerRefinementMaxIterations() + { + + int retVal = get_cornerRefinementMaxIterations_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::cornerRefinementMaxIterations + // + + //javadoc: DetectorParameters::set_cornerRefinementMaxIterations(cornerRefinementMaxIterations) + public void set_cornerRefinementMaxIterations(int cornerRefinementMaxIterations) + { + + set_cornerRefinementMaxIterations_0(nativeObj, cornerRefinementMaxIterations); + + return; + } + + + // + // C++: double DetectorParameters::cornerRefinementMinAccuracy + // + + //javadoc: DetectorParameters::get_cornerRefinementMinAccuracy() + public double get_cornerRefinementMinAccuracy() + { + + double retVal = get_cornerRefinementMinAccuracy_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::cornerRefinementMinAccuracy + // + + //javadoc: DetectorParameters::set_cornerRefinementMinAccuracy(cornerRefinementMinAccuracy) + public void set_cornerRefinementMinAccuracy(double cornerRefinementMinAccuracy) + { + + set_cornerRefinementMinAccuracy_0(nativeObj, cornerRefinementMinAccuracy); + + return; + } + + + // + // C++: int DetectorParameters::markerBorderBits + // + + //javadoc: DetectorParameters::get_markerBorderBits() + public int get_markerBorderBits() + { + + int retVal = get_markerBorderBits_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::markerBorderBits + // + + //javadoc: DetectorParameters::set_markerBorderBits(markerBorderBits) + public void set_markerBorderBits(int markerBorderBits) + { + + set_markerBorderBits_0(nativeObj, markerBorderBits); + + return; + } + + + // + // C++: int DetectorParameters::perspectiveRemovePixelPerCell + // + + //javadoc: DetectorParameters::get_perspectiveRemovePixelPerCell() + public int get_perspectiveRemovePixelPerCell() + { + + int retVal = get_perspectiveRemovePixelPerCell_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::perspectiveRemovePixelPerCell + // + + //javadoc: DetectorParameters::set_perspectiveRemovePixelPerCell(perspectiveRemovePixelPerCell) + public void set_perspectiveRemovePixelPerCell(int perspectiveRemovePixelPerCell) + { + + set_perspectiveRemovePixelPerCell_0(nativeObj, perspectiveRemovePixelPerCell); + + return; + } + + + // + // C++: double DetectorParameters::perspectiveRemoveIgnoredMarginPerCell + // + + //javadoc: DetectorParameters::get_perspectiveRemoveIgnoredMarginPerCell() + public double get_perspectiveRemoveIgnoredMarginPerCell() + { + + double retVal = get_perspectiveRemoveIgnoredMarginPerCell_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::perspectiveRemoveIgnoredMarginPerCell + // + + //javadoc: DetectorParameters::set_perspectiveRemoveIgnoredMarginPerCell(perspectiveRemoveIgnoredMarginPerCell) + public void set_perspectiveRemoveIgnoredMarginPerCell(double perspectiveRemoveIgnoredMarginPerCell) + { + + set_perspectiveRemoveIgnoredMarginPerCell_0(nativeObj, perspectiveRemoveIgnoredMarginPerCell); + + return; + } + + + // + // C++: double DetectorParameters::maxErroneousBitsInBorderRate + // + + //javadoc: DetectorParameters::get_maxErroneousBitsInBorderRate() + public double get_maxErroneousBitsInBorderRate() + { + + double retVal = get_maxErroneousBitsInBorderRate_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::maxErroneousBitsInBorderRate + // + + //javadoc: DetectorParameters::set_maxErroneousBitsInBorderRate(maxErroneousBitsInBorderRate) + public void set_maxErroneousBitsInBorderRate(double maxErroneousBitsInBorderRate) + { + + set_maxErroneousBitsInBorderRate_0(nativeObj, maxErroneousBitsInBorderRate); + + return; + } + + + // + // C++: double DetectorParameters::minOtsuStdDev + // + + //javadoc: DetectorParameters::get_minOtsuStdDev() + public double get_minOtsuStdDev() + { + + double retVal = get_minOtsuStdDev_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::minOtsuStdDev + // + + //javadoc: DetectorParameters::set_minOtsuStdDev(minOtsuStdDev) + public void set_minOtsuStdDev(double minOtsuStdDev) + { + + set_minOtsuStdDev_0(nativeObj, minOtsuStdDev); + + return; + } + + + // + // C++: double DetectorParameters::errorCorrectionRate + // + + //javadoc: DetectorParameters::get_errorCorrectionRate() + public double get_errorCorrectionRate() + { + + double retVal = get_errorCorrectionRate_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::errorCorrectionRate + // + + //javadoc: DetectorParameters::set_errorCorrectionRate(errorCorrectionRate) + public void set_errorCorrectionRate(double errorCorrectionRate) + { + + set_errorCorrectionRate_0(nativeObj, errorCorrectionRate); + + return; + } + + + // + // C++: float DetectorParameters::aprilTagQuadDecimate + // + + //javadoc: DetectorParameters::get_aprilTagQuadDecimate() + public float get_aprilTagQuadDecimate() + { + + float retVal = get_aprilTagQuadDecimate_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::aprilTagQuadDecimate + // + + //javadoc: DetectorParameters::set_aprilTagQuadDecimate(aprilTagQuadDecimate) + public void set_aprilTagQuadDecimate(float aprilTagQuadDecimate) + { + + set_aprilTagQuadDecimate_0(nativeObj, aprilTagQuadDecimate); + + return; + } + + + // + // C++: float DetectorParameters::aprilTagQuadSigma + // + + //javadoc: DetectorParameters::get_aprilTagQuadSigma() + public float get_aprilTagQuadSigma() + { + + float retVal = get_aprilTagQuadSigma_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::aprilTagQuadSigma + // + + //javadoc: DetectorParameters::set_aprilTagQuadSigma(aprilTagQuadSigma) + public void set_aprilTagQuadSigma(float aprilTagQuadSigma) + { + + set_aprilTagQuadSigma_0(nativeObj, aprilTagQuadSigma); + + return; + } + + + // + // C++: int DetectorParameters::aprilTagMinClusterPixels + // + + //javadoc: DetectorParameters::get_aprilTagMinClusterPixels() + public int get_aprilTagMinClusterPixels() + { + + int retVal = get_aprilTagMinClusterPixels_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::aprilTagMinClusterPixels + // + + //javadoc: DetectorParameters::set_aprilTagMinClusterPixels(aprilTagMinClusterPixels) + public void set_aprilTagMinClusterPixels(int aprilTagMinClusterPixels) + { + + set_aprilTagMinClusterPixels_0(nativeObj, aprilTagMinClusterPixels); + + return; + } + + + // + // C++: int DetectorParameters::aprilTagMaxNmaxima + // + + //javadoc: DetectorParameters::get_aprilTagMaxNmaxima() + public int get_aprilTagMaxNmaxima() + { + + int retVal = get_aprilTagMaxNmaxima_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::aprilTagMaxNmaxima + // + + //javadoc: DetectorParameters::set_aprilTagMaxNmaxima(aprilTagMaxNmaxima) + public void set_aprilTagMaxNmaxima(int aprilTagMaxNmaxima) + { + + set_aprilTagMaxNmaxima_0(nativeObj, aprilTagMaxNmaxima); + + return; + } + + + // + // C++: float DetectorParameters::aprilTagCriticalRad + // + + //javadoc: DetectorParameters::get_aprilTagCriticalRad() + public float get_aprilTagCriticalRad() + { + + float retVal = get_aprilTagCriticalRad_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::aprilTagCriticalRad + // + + //javadoc: DetectorParameters::set_aprilTagCriticalRad(aprilTagCriticalRad) + public void set_aprilTagCriticalRad(float aprilTagCriticalRad) + { + + set_aprilTagCriticalRad_0(nativeObj, aprilTagCriticalRad); + + return; + } + + + // + // C++: float DetectorParameters::aprilTagMaxLineFitMse + // + + //javadoc: DetectorParameters::get_aprilTagMaxLineFitMse() + public float get_aprilTagMaxLineFitMse() + { + + float retVal = get_aprilTagMaxLineFitMse_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::aprilTagMaxLineFitMse + // + + //javadoc: DetectorParameters::set_aprilTagMaxLineFitMse(aprilTagMaxLineFitMse) + public void set_aprilTagMaxLineFitMse(float aprilTagMaxLineFitMse) + { + + set_aprilTagMaxLineFitMse_0(nativeObj, aprilTagMaxLineFitMse); + + return; + } + + + // + // C++: int DetectorParameters::aprilTagMinWhiteBlackDiff + // + + //javadoc: DetectorParameters::get_aprilTagMinWhiteBlackDiff() + public int get_aprilTagMinWhiteBlackDiff() + { + + int retVal = get_aprilTagMinWhiteBlackDiff_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::aprilTagMinWhiteBlackDiff + // + + //javadoc: DetectorParameters::set_aprilTagMinWhiteBlackDiff(aprilTagMinWhiteBlackDiff) + public void set_aprilTagMinWhiteBlackDiff(int aprilTagMinWhiteBlackDiff) + { + + set_aprilTagMinWhiteBlackDiff_0(nativeObj, aprilTagMinWhiteBlackDiff); + + return; + } + + + // + // C++: int DetectorParameters::aprilTagDeglitch + // + + //javadoc: DetectorParameters::get_aprilTagDeglitch() + public int get_aprilTagDeglitch() + { + + int retVal = get_aprilTagDeglitch_0(nativeObj); + + return retVal; + } + + + // + // C++: void DetectorParameters::aprilTagDeglitch + // + + //javadoc: DetectorParameters::set_aprilTagDeglitch(aprilTagDeglitch) + public void set_aprilTagDeglitch(int aprilTagDeglitch) + { + + set_aprilTagDeglitch_0(nativeObj, aprilTagDeglitch); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_DetectorParameters cv::aruco::DetectorParameters::create() + private static native long create_0(); + + // C++: int DetectorParameters::adaptiveThreshWinSizeMin + private static native int get_adaptiveThreshWinSizeMin_0(long nativeObj); + + // C++: void DetectorParameters::adaptiveThreshWinSizeMin + private static native void set_adaptiveThreshWinSizeMin_0(long nativeObj, int adaptiveThreshWinSizeMin); + + // C++: int DetectorParameters::adaptiveThreshWinSizeMax + private static native int get_adaptiveThreshWinSizeMax_0(long nativeObj); + + // C++: void DetectorParameters::adaptiveThreshWinSizeMax + private static native void set_adaptiveThreshWinSizeMax_0(long nativeObj, int adaptiveThreshWinSizeMax); + + // C++: int DetectorParameters::adaptiveThreshWinSizeStep + private static native int get_adaptiveThreshWinSizeStep_0(long nativeObj); + + // C++: void DetectorParameters::adaptiveThreshWinSizeStep + private static native void set_adaptiveThreshWinSizeStep_0(long nativeObj, int adaptiveThreshWinSizeStep); + + // C++: double DetectorParameters::adaptiveThreshConstant + private static native double get_adaptiveThreshConstant_0(long nativeObj); + + // C++: void DetectorParameters::adaptiveThreshConstant + private static native void set_adaptiveThreshConstant_0(long nativeObj, double adaptiveThreshConstant); + + // C++: double DetectorParameters::minMarkerPerimeterRate + private static native double get_minMarkerPerimeterRate_0(long nativeObj); + + // C++: void DetectorParameters::minMarkerPerimeterRate + private static native void set_minMarkerPerimeterRate_0(long nativeObj, double minMarkerPerimeterRate); + + // C++: double DetectorParameters::maxMarkerPerimeterRate + private static native double get_maxMarkerPerimeterRate_0(long nativeObj); + + // C++: void DetectorParameters::maxMarkerPerimeterRate + private static native void set_maxMarkerPerimeterRate_0(long nativeObj, double maxMarkerPerimeterRate); + + // C++: double DetectorParameters::polygonalApproxAccuracyRate + private static native double get_polygonalApproxAccuracyRate_0(long nativeObj); + + // C++: void DetectorParameters::polygonalApproxAccuracyRate + private static native void set_polygonalApproxAccuracyRate_0(long nativeObj, double polygonalApproxAccuracyRate); + + // C++: double DetectorParameters::minCornerDistanceRate + private static native double get_minCornerDistanceRate_0(long nativeObj); + + // C++: void DetectorParameters::minCornerDistanceRate + private static native void set_minCornerDistanceRate_0(long nativeObj, double minCornerDistanceRate); + + // C++: int DetectorParameters::minDistanceToBorder + private static native int get_minDistanceToBorder_0(long nativeObj); + + // C++: void DetectorParameters::minDistanceToBorder + private static native void set_minDistanceToBorder_0(long nativeObj, int minDistanceToBorder); + + // C++: double DetectorParameters::minMarkerDistanceRate + private static native double get_minMarkerDistanceRate_0(long nativeObj); + + // C++: void DetectorParameters::minMarkerDistanceRate + private static native void set_minMarkerDistanceRate_0(long nativeObj, double minMarkerDistanceRate); + + // C++: int DetectorParameters::cornerRefinementMethod + private static native int get_cornerRefinementMethod_0(long nativeObj); + + // C++: void DetectorParameters::cornerRefinementMethod + private static native void set_cornerRefinementMethod_0(long nativeObj, int cornerRefinementMethod); + + // C++: int DetectorParameters::cornerRefinementWinSize + private static native int get_cornerRefinementWinSize_0(long nativeObj); + + // C++: void DetectorParameters::cornerRefinementWinSize + private static native void set_cornerRefinementWinSize_0(long nativeObj, int cornerRefinementWinSize); + + // C++: int DetectorParameters::cornerRefinementMaxIterations + private static native int get_cornerRefinementMaxIterations_0(long nativeObj); + + // C++: void DetectorParameters::cornerRefinementMaxIterations + private static native void set_cornerRefinementMaxIterations_0(long nativeObj, int cornerRefinementMaxIterations); + + // C++: double DetectorParameters::cornerRefinementMinAccuracy + private static native double get_cornerRefinementMinAccuracy_0(long nativeObj); + + // C++: void DetectorParameters::cornerRefinementMinAccuracy + private static native void set_cornerRefinementMinAccuracy_0(long nativeObj, double cornerRefinementMinAccuracy); + + // C++: int DetectorParameters::markerBorderBits + private static native int get_markerBorderBits_0(long nativeObj); + + // C++: void DetectorParameters::markerBorderBits + private static native void set_markerBorderBits_0(long nativeObj, int markerBorderBits); + + // C++: int DetectorParameters::perspectiveRemovePixelPerCell + private static native int get_perspectiveRemovePixelPerCell_0(long nativeObj); + + // C++: void DetectorParameters::perspectiveRemovePixelPerCell + private static native void set_perspectiveRemovePixelPerCell_0(long nativeObj, int perspectiveRemovePixelPerCell); + + // C++: double DetectorParameters::perspectiveRemoveIgnoredMarginPerCell + private static native double get_perspectiveRemoveIgnoredMarginPerCell_0(long nativeObj); + + // C++: void DetectorParameters::perspectiveRemoveIgnoredMarginPerCell + private static native void set_perspectiveRemoveIgnoredMarginPerCell_0(long nativeObj, double perspectiveRemoveIgnoredMarginPerCell); + + // C++: double DetectorParameters::maxErroneousBitsInBorderRate + private static native double get_maxErroneousBitsInBorderRate_0(long nativeObj); + + // C++: void DetectorParameters::maxErroneousBitsInBorderRate + private static native void set_maxErroneousBitsInBorderRate_0(long nativeObj, double maxErroneousBitsInBorderRate); + + // C++: double DetectorParameters::minOtsuStdDev + private static native double get_minOtsuStdDev_0(long nativeObj); + + // C++: void DetectorParameters::minOtsuStdDev + private static native void set_minOtsuStdDev_0(long nativeObj, double minOtsuStdDev); + + // C++: double DetectorParameters::errorCorrectionRate + private static native double get_errorCorrectionRate_0(long nativeObj); + + // C++: void DetectorParameters::errorCorrectionRate + private static native void set_errorCorrectionRate_0(long nativeObj, double errorCorrectionRate); + + // C++: float DetectorParameters::aprilTagQuadDecimate + private static native float get_aprilTagQuadDecimate_0(long nativeObj); + + // C++: void DetectorParameters::aprilTagQuadDecimate + private static native void set_aprilTagQuadDecimate_0(long nativeObj, float aprilTagQuadDecimate); + + // C++: float DetectorParameters::aprilTagQuadSigma + private static native float get_aprilTagQuadSigma_0(long nativeObj); + + // C++: void DetectorParameters::aprilTagQuadSigma + private static native void set_aprilTagQuadSigma_0(long nativeObj, float aprilTagQuadSigma); + + // C++: int DetectorParameters::aprilTagMinClusterPixels + private static native int get_aprilTagMinClusterPixels_0(long nativeObj); + + // C++: void DetectorParameters::aprilTagMinClusterPixels + private static native void set_aprilTagMinClusterPixels_0(long nativeObj, int aprilTagMinClusterPixels); + + // C++: int DetectorParameters::aprilTagMaxNmaxima + private static native int get_aprilTagMaxNmaxima_0(long nativeObj); + + // C++: void DetectorParameters::aprilTagMaxNmaxima + private static native void set_aprilTagMaxNmaxima_0(long nativeObj, int aprilTagMaxNmaxima); + + // C++: float DetectorParameters::aprilTagCriticalRad + private static native float get_aprilTagCriticalRad_0(long nativeObj); + + // C++: void DetectorParameters::aprilTagCriticalRad + private static native void set_aprilTagCriticalRad_0(long nativeObj, float aprilTagCriticalRad); + + // C++: float DetectorParameters::aprilTagMaxLineFitMse + private static native float get_aprilTagMaxLineFitMse_0(long nativeObj); + + // C++: void DetectorParameters::aprilTagMaxLineFitMse + private static native void set_aprilTagMaxLineFitMse_0(long nativeObj, float aprilTagMaxLineFitMse); + + // C++: int DetectorParameters::aprilTagMinWhiteBlackDiff + private static native int get_aprilTagMinWhiteBlackDiff_0(long nativeObj); + + // C++: void DetectorParameters::aprilTagMinWhiteBlackDiff + private static native void set_aprilTagMinWhiteBlackDiff_0(long nativeObj, int aprilTagMinWhiteBlackDiff); + + // C++: int DetectorParameters::aprilTagDeglitch + private static native int get_aprilTagDeglitch_0(long nativeObj); + + // C++: void DetectorParameters::aprilTagDeglitch + private static native void set_aprilTagDeglitch_0(long nativeObj, int aprilTagDeglitch); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/aruco/Dictionary.java b/OpenCV/src/main/java/org/opencv/aruco/Dictionary.java new file mode 100644 index 00000000..0ce3a1a0 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/aruco/Dictionary.java @@ -0,0 +1,266 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.aruco; + +import org.opencv.aruco.Dictionary; +import org.opencv.core.Mat; + +// C++: class Dictionary +//javadoc: Dictionary + +public class Dictionary { + + protected final long nativeObj; + protected Dictionary(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static Dictionary __fromPtr__(long addr) { return new Dictionary(addr); } + + // + // C++: static Mat cv::aruco::Dictionary::getBitsFromByteList(Mat byteList, int markerSize) + // + + //javadoc: Dictionary::getBitsFromByteList(byteList, markerSize) + public static Mat getBitsFromByteList(Mat byteList, int markerSize) + { + + Mat retVal = new Mat(getBitsFromByteList_0(byteList.nativeObj, markerSize)); + + return retVal; + } + + + // + // C++: static Mat cv::aruco::Dictionary::getByteListFromBits(Mat bits) + // + + //javadoc: Dictionary::getByteListFromBits(bits) + public static Mat getByteListFromBits(Mat bits) + { + + Mat retVal = new Mat(getByteListFromBits_0(bits.nativeObj)); + + return retVal; + } + + + // + // C++: static Ptr_Dictionary cv::aruco::Dictionary::create(int nMarkers, int markerSize, Ptr_Dictionary baseDictionary, int randomSeed = 0) + // + + //javadoc: Dictionary::create_from(nMarkers, markerSize, baseDictionary, randomSeed) + public static Dictionary create_from(int nMarkers, int markerSize, Dictionary baseDictionary, int randomSeed) + { + + Dictionary retVal = Dictionary.__fromPtr__(create_from_0(nMarkers, markerSize, baseDictionary.getNativeObjAddr(), randomSeed)); + + return retVal; + } + + //javadoc: Dictionary::create_from(nMarkers, markerSize, baseDictionary) + public static Dictionary create_from(int nMarkers, int markerSize, Dictionary baseDictionary) + { + + Dictionary retVal = Dictionary.__fromPtr__(create_from_1(nMarkers, markerSize, baseDictionary.getNativeObjAddr())); + + return retVal; + } + + + // + // C++: static Ptr_Dictionary cv::aruco::Dictionary::create(int nMarkers, int markerSize, int randomSeed = 0) + // + + //javadoc: Dictionary::create(nMarkers, markerSize, randomSeed) + public static Dictionary create(int nMarkers, int markerSize, int randomSeed) + { + + Dictionary retVal = Dictionary.__fromPtr__(create_0(nMarkers, markerSize, randomSeed)); + + return retVal; + } + + //javadoc: Dictionary::create(nMarkers, markerSize) + public static Dictionary create(int nMarkers, int markerSize) + { + + Dictionary retVal = Dictionary.__fromPtr__(create_1(nMarkers, markerSize)); + + return retVal; + } + + + // + // C++: static Ptr_Dictionary cv::aruco::Dictionary::get(int dict) + // + + //javadoc: Dictionary::get(dict) + public static Dictionary get(int dict) + { + + Dictionary retVal = Dictionary.__fromPtr__(get_0(dict)); + + return retVal; + } + + + // + // C++: void cv::aruco::Dictionary::drawMarker(int id, int sidePixels, Mat& _img, int borderBits = 1) + // + + //javadoc: Dictionary::drawMarker(id, sidePixels, _img, borderBits) + public void drawMarker(int id, int sidePixels, Mat _img, int borderBits) + { + + drawMarker_0(nativeObj, id, sidePixels, _img.nativeObj, borderBits); + + return; + } + + //javadoc: Dictionary::drawMarker(id, sidePixels, _img) + public void drawMarker(int id, int sidePixels, Mat _img) + { + + drawMarker_1(nativeObj, id, sidePixels, _img.nativeObj); + + return; + } + + + // + // C++: Mat Dictionary::bytesList + // + + //javadoc: Dictionary::get_bytesList() + public Mat get_bytesList() + { + + Mat retVal = new Mat(get_bytesList_0(nativeObj)); + + return retVal; + } + + + // + // C++: void Dictionary::bytesList + // + + //javadoc: Dictionary::set_bytesList(bytesList) + public void set_bytesList(Mat bytesList) + { + + set_bytesList_0(nativeObj, bytesList.nativeObj); + + return; + } + + + // + // C++: int Dictionary::markerSize + // + + //javadoc: Dictionary::get_markerSize() + public int get_markerSize() + { + + int retVal = get_markerSize_0(nativeObj); + + return retVal; + } + + + // + // C++: void Dictionary::markerSize + // + + //javadoc: Dictionary::set_markerSize(markerSize) + public void set_markerSize(int markerSize) + { + + set_markerSize_0(nativeObj, markerSize); + + return; + } + + + // + // C++: int Dictionary::maxCorrectionBits + // + + //javadoc: Dictionary::get_maxCorrectionBits() + public int get_maxCorrectionBits() + { + + int retVal = get_maxCorrectionBits_0(nativeObj); + + return retVal; + } + + + // + // C++: void Dictionary::maxCorrectionBits + // + + //javadoc: Dictionary::set_maxCorrectionBits(maxCorrectionBits) + public void set_maxCorrectionBits(int maxCorrectionBits) + { + + set_maxCorrectionBits_0(nativeObj, maxCorrectionBits); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Mat cv::aruco::Dictionary::getBitsFromByteList(Mat byteList, int markerSize) + private static native long getBitsFromByteList_0(long byteList_nativeObj, int markerSize); + + // C++: static Mat cv::aruco::Dictionary::getByteListFromBits(Mat bits) + private static native long getByteListFromBits_0(long bits_nativeObj); + + // C++: static Ptr_Dictionary cv::aruco::Dictionary::create(int nMarkers, int markerSize, Ptr_Dictionary baseDictionary, int randomSeed = 0) + private static native long create_from_0(int nMarkers, int markerSize, long baseDictionary_nativeObj, int randomSeed); + private static native long create_from_1(int nMarkers, int markerSize, long baseDictionary_nativeObj); + + // C++: static Ptr_Dictionary cv::aruco::Dictionary::create(int nMarkers, int markerSize, int randomSeed = 0) + private static native long create_0(int nMarkers, int markerSize, int randomSeed); + private static native long create_1(int nMarkers, int markerSize); + + // C++: static Ptr_Dictionary cv::aruco::Dictionary::get(int dict) + private static native long get_0(int dict); + + // C++: void cv::aruco::Dictionary::drawMarker(int id, int sidePixels, Mat& _img, int borderBits = 1) + private static native void drawMarker_0(long nativeObj, int id, int sidePixels, long _img_nativeObj, int borderBits); + private static native void drawMarker_1(long nativeObj, int id, int sidePixels, long _img_nativeObj); + + // C++: Mat Dictionary::bytesList + private static native long get_bytesList_0(long nativeObj); + + // C++: void Dictionary::bytesList + private static native void set_bytesList_0(long nativeObj, long bytesList_nativeObj); + + // C++: int Dictionary::markerSize + private static native int get_markerSize_0(long nativeObj); + + // C++: void Dictionary::markerSize + private static native void set_markerSize_0(long nativeObj, int markerSize); + + // C++: int Dictionary::maxCorrectionBits + private static native int get_maxCorrectionBits_0(long nativeObj); + + // C++: void Dictionary::maxCorrectionBits + private static native void set_maxCorrectionBits_0(long nativeObj, int maxCorrectionBits); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/aruco/GridBoard.java b/OpenCV/src/main/java/org/opencv/aruco/GridBoard.java new file mode 100644 index 00000000..47b0471e --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/aruco/GridBoard.java @@ -0,0 +1,147 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.aruco; + +import org.opencv.aruco.Board; +import org.opencv.aruco.Dictionary; +import org.opencv.aruco.GridBoard; +import org.opencv.core.Mat; +import org.opencv.core.Size; + +// C++: class GridBoard +//javadoc: GridBoard + +public class GridBoard extends Board { + + protected GridBoard(long addr) { super(addr); } + + // internal usage only + public static GridBoard __fromPtr__(long addr) { return new GridBoard(addr); } + + // + // C++: static Ptr_GridBoard cv::aruco::GridBoard::create(int markersX, int markersY, float markerLength, float markerSeparation, Ptr_Dictionary dictionary, int firstMarker = 0) + // + + //javadoc: GridBoard::create(markersX, markersY, markerLength, markerSeparation, dictionary, firstMarker) + public static GridBoard create(int markersX, int markersY, float markerLength, float markerSeparation, Dictionary dictionary, int firstMarker) + { + + GridBoard retVal = GridBoard.__fromPtr__(create_0(markersX, markersY, markerLength, markerSeparation, dictionary.getNativeObjAddr(), firstMarker)); + + return retVal; + } + + //javadoc: GridBoard::create(markersX, markersY, markerLength, markerSeparation, dictionary) + public static GridBoard create(int markersX, int markersY, float markerLength, float markerSeparation, Dictionary dictionary) + { + + GridBoard retVal = GridBoard.__fromPtr__(create_1(markersX, markersY, markerLength, markerSeparation, dictionary.getNativeObjAddr())); + + return retVal; + } + + + // + // C++: Size cv::aruco::GridBoard::getGridSize() + // + + //javadoc: GridBoard::getGridSize() + public Size getGridSize() + { + + Size retVal = new Size(getGridSize_0(nativeObj)); + + return retVal; + } + + + // + // C++: float cv::aruco::GridBoard::getMarkerLength() + // + + //javadoc: GridBoard::getMarkerLength() + public float getMarkerLength() + { + + float retVal = getMarkerLength_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::aruco::GridBoard::getMarkerSeparation() + // + + //javadoc: GridBoard::getMarkerSeparation() + public float getMarkerSeparation() + { + + float retVal = getMarkerSeparation_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::aruco::GridBoard::draw(Size outSize, Mat& img, int marginSize = 0, int borderBits = 1) + // + + //javadoc: GridBoard::draw(outSize, img, marginSize, borderBits) + public void draw(Size outSize, Mat img, int marginSize, int borderBits) + { + + draw_0(nativeObj, outSize.width, outSize.height, img.nativeObj, marginSize, borderBits); + + return; + } + + //javadoc: GridBoard::draw(outSize, img, marginSize) + public void draw(Size outSize, Mat img, int marginSize) + { + + draw_1(nativeObj, outSize.width, outSize.height, img.nativeObj, marginSize); + + return; + } + + //javadoc: GridBoard::draw(outSize, img) + public void draw(Size outSize, Mat img) + { + + draw_2(nativeObj, outSize.width, outSize.height, img.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_GridBoard cv::aruco::GridBoard::create(int markersX, int markersY, float markerLength, float markerSeparation, Ptr_Dictionary dictionary, int firstMarker = 0) + private static native long create_0(int markersX, int markersY, float markerLength, float markerSeparation, long dictionary_nativeObj, int firstMarker); + private static native long create_1(int markersX, int markersY, float markerLength, float markerSeparation, long dictionary_nativeObj); + + // C++: Size cv::aruco::GridBoard::getGridSize() + private static native double[] getGridSize_0(long nativeObj); + + // C++: float cv::aruco::GridBoard::getMarkerLength() + private static native float getMarkerLength_0(long nativeObj); + + // C++: float cv::aruco::GridBoard::getMarkerSeparation() + private static native float getMarkerSeparation_0(long nativeObj); + + // C++: void cv::aruco::GridBoard::draw(Size outSize, Mat& img, int marginSize = 0, int borderBits = 1) + private static native void draw_0(long nativeObj, double outSize_width, double outSize_height, long img_nativeObj, int marginSize, int borderBits); + private static native void draw_1(long nativeObj, double outSize_width, double outSize_height, long img_nativeObj, int marginSize); + private static native void draw_2(long nativeObj, double outSize_width, double outSize_height, long img_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/bgsegm/BackgroundSubtractorCNT.java b/OpenCV/src/main/java/org/opencv/bgsegm/BackgroundSubtractorCNT.java new file mode 100644 index 00000000..3b4c30fc --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/bgsegm/BackgroundSubtractorCNT.java @@ -0,0 +1,209 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.bgsegm; + +import org.opencv.core.Mat; +import org.opencv.video.BackgroundSubtractor; + +// C++: class BackgroundSubtractorCNT +//javadoc: BackgroundSubtractorCNT + +public class BackgroundSubtractorCNT extends BackgroundSubtractor { + + protected BackgroundSubtractorCNT(long addr) { super(addr); } + + // internal usage only + public static BackgroundSubtractorCNT __fromPtr__(long addr) { return new BackgroundSubtractorCNT(addr); } + + // + // C++: bool cv::bgsegm::BackgroundSubtractorCNT::getIsParallel() + // + + //javadoc: BackgroundSubtractorCNT::getIsParallel() + public boolean getIsParallel() + { + + boolean retVal = getIsParallel_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::bgsegm::BackgroundSubtractorCNT::getUseHistory() + // + + //javadoc: BackgroundSubtractorCNT::getUseHistory() + public boolean getUseHistory() + { + + boolean retVal = getUseHistory_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::bgsegm::BackgroundSubtractorCNT::getMaxPixelStability() + // + + //javadoc: BackgroundSubtractorCNT::getMaxPixelStability() + public int getMaxPixelStability() + { + + int retVal = getMaxPixelStability_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::bgsegm::BackgroundSubtractorCNT::getMinPixelStability() + // + + //javadoc: BackgroundSubtractorCNT::getMinPixelStability() + public int getMinPixelStability() + { + + int retVal = getMinPixelStability_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorCNT::apply(Mat image, Mat& fgmask, double learningRate = -1) + // + + //javadoc: BackgroundSubtractorCNT::apply(image, fgmask, learningRate) + public void apply(Mat image, Mat fgmask, double learningRate) + { + + apply_0(nativeObj, image.nativeObj, fgmask.nativeObj, learningRate); + + return; + } + + //javadoc: BackgroundSubtractorCNT::apply(image, fgmask) + public void apply(Mat image, Mat fgmask) + { + + apply_1(nativeObj, image.nativeObj, fgmask.nativeObj); + + return; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorCNT::getBackgroundImage(Mat& backgroundImage) + // + + //javadoc: BackgroundSubtractorCNT::getBackgroundImage(backgroundImage) + public void getBackgroundImage(Mat backgroundImage) + { + + getBackgroundImage_0(nativeObj, backgroundImage.nativeObj); + + return; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorCNT::setIsParallel(bool value) + // + + //javadoc: BackgroundSubtractorCNT::setIsParallel(value) + public void setIsParallel(boolean value) + { + + setIsParallel_0(nativeObj, value); + + return; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorCNT::setMaxPixelStability(int value) + // + + //javadoc: BackgroundSubtractorCNT::setMaxPixelStability(value) + public void setMaxPixelStability(int value) + { + + setMaxPixelStability_0(nativeObj, value); + + return; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorCNT::setMinPixelStability(int value) + // + + //javadoc: BackgroundSubtractorCNT::setMinPixelStability(value) + public void setMinPixelStability(int value) + { + + setMinPixelStability_0(nativeObj, value); + + return; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorCNT::setUseHistory(bool value) + // + + //javadoc: BackgroundSubtractorCNT::setUseHistory(value) + public void setUseHistory(boolean value) + { + + setUseHistory_0(nativeObj, value); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: bool cv::bgsegm::BackgroundSubtractorCNT::getIsParallel() + private static native boolean getIsParallel_0(long nativeObj); + + // C++: bool cv::bgsegm::BackgroundSubtractorCNT::getUseHistory() + private static native boolean getUseHistory_0(long nativeObj); + + // C++: int cv::bgsegm::BackgroundSubtractorCNT::getMaxPixelStability() + private static native int getMaxPixelStability_0(long nativeObj); + + // C++: int cv::bgsegm::BackgroundSubtractorCNT::getMinPixelStability() + private static native int getMinPixelStability_0(long nativeObj); + + // C++: void cv::bgsegm::BackgroundSubtractorCNT::apply(Mat image, Mat& fgmask, double learningRate = -1) + private static native void apply_0(long nativeObj, long image_nativeObj, long fgmask_nativeObj, double learningRate); + private static native void apply_1(long nativeObj, long image_nativeObj, long fgmask_nativeObj); + + // C++: void cv::bgsegm::BackgroundSubtractorCNT::getBackgroundImage(Mat& backgroundImage) + private static native void getBackgroundImage_0(long nativeObj, long backgroundImage_nativeObj); + + // C++: void cv::bgsegm::BackgroundSubtractorCNT::setIsParallel(bool value) + private static native void setIsParallel_0(long nativeObj, boolean value); + + // C++: void cv::bgsegm::BackgroundSubtractorCNT::setMaxPixelStability(int value) + private static native void setMaxPixelStability_0(long nativeObj, int value); + + // C++: void cv::bgsegm::BackgroundSubtractorCNT::setMinPixelStability(int value) + private static native void setMinPixelStability_0(long nativeObj, int value); + + // C++: void cv::bgsegm::BackgroundSubtractorCNT::setUseHistory(bool value) + private static native void setUseHistory_0(long nativeObj, boolean value); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/bgsegm/BackgroundSubtractorGMG.java b/OpenCV/src/main/java/org/opencv/bgsegm/BackgroundSubtractorGMG.java new file mode 100644 index 00000000..330afa63 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/bgsegm/BackgroundSubtractorGMG.java @@ -0,0 +1,368 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.bgsegm; + +import org.opencv.video.BackgroundSubtractor; + +// C++: class BackgroundSubtractorGMG +//javadoc: BackgroundSubtractorGMG + +public class BackgroundSubtractorGMG extends BackgroundSubtractor { + + protected BackgroundSubtractorGMG(long addr) { super(addr); } + + // internal usage only + public static BackgroundSubtractorGMG __fromPtr__(long addr) { return new BackgroundSubtractorGMG(addr); } + + // + // C++: bool cv::bgsegm::BackgroundSubtractorGMG::getUpdateBackgroundModel() + // + + //javadoc: BackgroundSubtractorGMG::getUpdateBackgroundModel() + public boolean getUpdateBackgroundModel() + { + + boolean retVal = getUpdateBackgroundModel_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::bgsegm::BackgroundSubtractorGMG::getBackgroundPrior() + // + + //javadoc: BackgroundSubtractorGMG::getBackgroundPrior() + public double getBackgroundPrior() + { + + double retVal = getBackgroundPrior_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::bgsegm::BackgroundSubtractorGMG::getDecisionThreshold() + // + + //javadoc: BackgroundSubtractorGMG::getDecisionThreshold() + public double getDecisionThreshold() + { + + double retVal = getDecisionThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::bgsegm::BackgroundSubtractorGMG::getDefaultLearningRate() + // + + //javadoc: BackgroundSubtractorGMG::getDefaultLearningRate() + public double getDefaultLearningRate() + { + + double retVal = getDefaultLearningRate_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::bgsegm::BackgroundSubtractorGMG::getMaxVal() + // + + //javadoc: BackgroundSubtractorGMG::getMaxVal() + public double getMaxVal() + { + + double retVal = getMaxVal_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::bgsegm::BackgroundSubtractorGMG::getMinVal() + // + + //javadoc: BackgroundSubtractorGMG::getMinVal() + public double getMinVal() + { + + double retVal = getMinVal_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::bgsegm::BackgroundSubtractorGMG::getMaxFeatures() + // + + //javadoc: BackgroundSubtractorGMG::getMaxFeatures() + public int getMaxFeatures() + { + + int retVal = getMaxFeatures_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::bgsegm::BackgroundSubtractorGMG::getNumFrames() + // + + //javadoc: BackgroundSubtractorGMG::getNumFrames() + public int getNumFrames() + { + + int retVal = getNumFrames_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::bgsegm::BackgroundSubtractorGMG::getQuantizationLevels() + // + + //javadoc: BackgroundSubtractorGMG::getQuantizationLevels() + public int getQuantizationLevels() + { + + int retVal = getQuantizationLevels_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::bgsegm::BackgroundSubtractorGMG::getSmoothingRadius() + // + + //javadoc: BackgroundSubtractorGMG::getSmoothingRadius() + public int getSmoothingRadius() + { + + int retVal = getSmoothingRadius_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setBackgroundPrior(double bgprior) + // + + //javadoc: BackgroundSubtractorGMG::setBackgroundPrior(bgprior) + public void setBackgroundPrior(double bgprior) + { + + setBackgroundPrior_0(nativeObj, bgprior); + + return; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setDecisionThreshold(double thresh) + // + + //javadoc: BackgroundSubtractorGMG::setDecisionThreshold(thresh) + public void setDecisionThreshold(double thresh) + { + + setDecisionThreshold_0(nativeObj, thresh); + + return; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setDefaultLearningRate(double lr) + // + + //javadoc: BackgroundSubtractorGMG::setDefaultLearningRate(lr) + public void setDefaultLearningRate(double lr) + { + + setDefaultLearningRate_0(nativeObj, lr); + + return; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setMaxFeatures(int maxFeatures) + // + + //javadoc: BackgroundSubtractorGMG::setMaxFeatures(maxFeatures) + public void setMaxFeatures(int maxFeatures) + { + + setMaxFeatures_0(nativeObj, maxFeatures); + + return; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setMaxVal(double val) + // + + //javadoc: BackgroundSubtractorGMG::setMaxVal(val) + public void setMaxVal(double val) + { + + setMaxVal_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setMinVal(double val) + // + + //javadoc: BackgroundSubtractorGMG::setMinVal(val) + public void setMinVal(double val) + { + + setMinVal_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setNumFrames(int nframes) + // + + //javadoc: BackgroundSubtractorGMG::setNumFrames(nframes) + public void setNumFrames(int nframes) + { + + setNumFrames_0(nativeObj, nframes); + + return; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setQuantizationLevels(int nlevels) + // + + //javadoc: BackgroundSubtractorGMG::setQuantizationLevels(nlevels) + public void setQuantizationLevels(int nlevels) + { + + setQuantizationLevels_0(nativeObj, nlevels); + + return; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setSmoothingRadius(int radius) + // + + //javadoc: BackgroundSubtractorGMG::setSmoothingRadius(radius) + public void setSmoothingRadius(int radius) + { + + setSmoothingRadius_0(nativeObj, radius); + + return; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setUpdateBackgroundModel(bool update) + // + + //javadoc: BackgroundSubtractorGMG::setUpdateBackgroundModel(update) + public void setUpdateBackgroundModel(boolean update) + { + + setUpdateBackgroundModel_0(nativeObj, update); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: bool cv::bgsegm::BackgroundSubtractorGMG::getUpdateBackgroundModel() + private static native boolean getUpdateBackgroundModel_0(long nativeObj); + + // C++: double cv::bgsegm::BackgroundSubtractorGMG::getBackgroundPrior() + private static native double getBackgroundPrior_0(long nativeObj); + + // C++: double cv::bgsegm::BackgroundSubtractorGMG::getDecisionThreshold() + private static native double getDecisionThreshold_0(long nativeObj); + + // C++: double cv::bgsegm::BackgroundSubtractorGMG::getDefaultLearningRate() + private static native double getDefaultLearningRate_0(long nativeObj); + + // C++: double cv::bgsegm::BackgroundSubtractorGMG::getMaxVal() + private static native double getMaxVal_0(long nativeObj); + + // C++: double cv::bgsegm::BackgroundSubtractorGMG::getMinVal() + private static native double getMinVal_0(long nativeObj); + + // C++: int cv::bgsegm::BackgroundSubtractorGMG::getMaxFeatures() + private static native int getMaxFeatures_0(long nativeObj); + + // C++: int cv::bgsegm::BackgroundSubtractorGMG::getNumFrames() + private static native int getNumFrames_0(long nativeObj); + + // C++: int cv::bgsegm::BackgroundSubtractorGMG::getQuantizationLevels() + private static native int getQuantizationLevels_0(long nativeObj); + + // C++: int cv::bgsegm::BackgroundSubtractorGMG::getSmoothingRadius() + private static native int getSmoothingRadius_0(long nativeObj); + + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setBackgroundPrior(double bgprior) + private static native void setBackgroundPrior_0(long nativeObj, double bgprior); + + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setDecisionThreshold(double thresh) + private static native void setDecisionThreshold_0(long nativeObj, double thresh); + + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setDefaultLearningRate(double lr) + private static native void setDefaultLearningRate_0(long nativeObj, double lr); + + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setMaxFeatures(int maxFeatures) + private static native void setMaxFeatures_0(long nativeObj, int maxFeatures); + + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setMaxVal(double val) + private static native void setMaxVal_0(long nativeObj, double val); + + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setMinVal(double val) + private static native void setMinVal_0(long nativeObj, double val); + + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setNumFrames(int nframes) + private static native void setNumFrames_0(long nativeObj, int nframes); + + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setQuantizationLevels(int nlevels) + private static native void setQuantizationLevels_0(long nativeObj, int nlevels); + + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setSmoothingRadius(int radius) + private static native void setSmoothingRadius_0(long nativeObj, int radius); + + // C++: void cv::bgsegm::BackgroundSubtractorGMG::setUpdateBackgroundModel(bool update) + private static native void setUpdateBackgroundModel_0(long nativeObj, boolean update); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/bgsegm/BackgroundSubtractorGSOC.java b/OpenCV/src/main/java/org/opencv/bgsegm/BackgroundSubtractorGSOC.java new file mode 100644 index 00000000..04d0738a --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/bgsegm/BackgroundSubtractorGSOC.java @@ -0,0 +1,73 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.bgsegm; + +import org.opencv.core.Mat; +import org.opencv.video.BackgroundSubtractor; + +// C++: class BackgroundSubtractorGSOC +//javadoc: BackgroundSubtractorGSOC + +public class BackgroundSubtractorGSOC extends BackgroundSubtractor { + + protected BackgroundSubtractorGSOC(long addr) { super(addr); } + + // internal usage only + public static BackgroundSubtractorGSOC __fromPtr__(long addr) { return new BackgroundSubtractorGSOC(addr); } + + // + // C++: void cv::bgsegm::BackgroundSubtractorGSOC::apply(Mat image, Mat& fgmask, double learningRate = -1) + // + + //javadoc: BackgroundSubtractorGSOC::apply(image, fgmask, learningRate) + public void apply(Mat image, Mat fgmask, double learningRate) + { + + apply_0(nativeObj, image.nativeObj, fgmask.nativeObj, learningRate); + + return; + } + + //javadoc: BackgroundSubtractorGSOC::apply(image, fgmask) + public void apply(Mat image, Mat fgmask) + { + + apply_1(nativeObj, image.nativeObj, fgmask.nativeObj); + + return; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorGSOC::getBackgroundImage(Mat& backgroundImage) + // + + //javadoc: BackgroundSubtractorGSOC::getBackgroundImage(backgroundImage) + public void getBackgroundImage(Mat backgroundImage) + { + + getBackgroundImage_0(nativeObj, backgroundImage.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::bgsegm::BackgroundSubtractorGSOC::apply(Mat image, Mat& fgmask, double learningRate = -1) + private static native void apply_0(long nativeObj, long image_nativeObj, long fgmask_nativeObj, double learningRate); + private static native void apply_1(long nativeObj, long image_nativeObj, long fgmask_nativeObj); + + // C++: void cv::bgsegm::BackgroundSubtractorGSOC::getBackgroundImage(Mat& backgroundImage) + private static native void getBackgroundImage_0(long nativeObj, long backgroundImage_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/bgsegm/BackgroundSubtractorLSBP.java b/OpenCV/src/main/java/org/opencv/bgsegm/BackgroundSubtractorLSBP.java new file mode 100644 index 00000000..67a00a21 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/bgsegm/BackgroundSubtractorLSBP.java @@ -0,0 +1,73 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.bgsegm; + +import org.opencv.core.Mat; +import org.opencv.video.BackgroundSubtractor; + +// C++: class BackgroundSubtractorLSBP +//javadoc: BackgroundSubtractorLSBP + +public class BackgroundSubtractorLSBP extends BackgroundSubtractor { + + protected BackgroundSubtractorLSBP(long addr) { super(addr); } + + // internal usage only + public static BackgroundSubtractorLSBP __fromPtr__(long addr) { return new BackgroundSubtractorLSBP(addr); } + + // + // C++: void cv::bgsegm::BackgroundSubtractorLSBP::apply(Mat image, Mat& fgmask, double learningRate = -1) + // + + //javadoc: BackgroundSubtractorLSBP::apply(image, fgmask, learningRate) + public void apply(Mat image, Mat fgmask, double learningRate) + { + + apply_0(nativeObj, image.nativeObj, fgmask.nativeObj, learningRate); + + return; + } + + //javadoc: BackgroundSubtractorLSBP::apply(image, fgmask) + public void apply(Mat image, Mat fgmask) + { + + apply_1(nativeObj, image.nativeObj, fgmask.nativeObj); + + return; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorLSBP::getBackgroundImage(Mat& backgroundImage) + // + + //javadoc: BackgroundSubtractorLSBP::getBackgroundImage(backgroundImage) + public void getBackgroundImage(Mat backgroundImage) + { + + getBackgroundImage_0(nativeObj, backgroundImage.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::bgsegm::BackgroundSubtractorLSBP::apply(Mat image, Mat& fgmask, double learningRate = -1) + private static native void apply_0(long nativeObj, long image_nativeObj, long fgmask_nativeObj, double learningRate); + private static native void apply_1(long nativeObj, long image_nativeObj, long fgmask_nativeObj); + + // C++: void cv::bgsegm::BackgroundSubtractorLSBP::getBackgroundImage(Mat& backgroundImage) + private static native void getBackgroundImage_0(long nativeObj, long backgroundImage_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/bgsegm/BackgroundSubtractorLSBPDesc.java b/OpenCV/src/main/java/org/opencv/bgsegm/BackgroundSubtractorLSBPDesc.java new file mode 100644 index 00000000..e0bf06c4 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/bgsegm/BackgroundSubtractorLSBPDesc.java @@ -0,0 +1,31 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.bgsegm; + + + +// C++: class BackgroundSubtractorLSBPDesc +//javadoc: BackgroundSubtractorLSBPDesc + +public class BackgroundSubtractorLSBPDesc { + + protected final long nativeObj; + protected BackgroundSubtractorLSBPDesc(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static BackgroundSubtractorLSBPDesc __fromPtr__(long addr) { return new BackgroundSubtractorLSBPDesc(addr); } + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/bgsegm/BackgroundSubtractorMOG.java b/OpenCV/src/main/java/org/opencv/bgsegm/BackgroundSubtractorMOG.java new file mode 100644 index 00000000..8190f4c3 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/bgsegm/BackgroundSubtractorMOG.java @@ -0,0 +1,164 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.bgsegm; + +import org.opencv.video.BackgroundSubtractor; + +// C++: class BackgroundSubtractorMOG +//javadoc: BackgroundSubtractorMOG + +public class BackgroundSubtractorMOG extends BackgroundSubtractor { + + protected BackgroundSubtractorMOG(long addr) { super(addr); } + + // internal usage only + public static BackgroundSubtractorMOG __fromPtr__(long addr) { return new BackgroundSubtractorMOG(addr); } + + // + // C++: double cv::bgsegm::BackgroundSubtractorMOG::getBackgroundRatio() + // + + //javadoc: BackgroundSubtractorMOG::getBackgroundRatio() + public double getBackgroundRatio() + { + + double retVal = getBackgroundRatio_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::bgsegm::BackgroundSubtractorMOG::getNoiseSigma() + // + + //javadoc: BackgroundSubtractorMOG::getNoiseSigma() + public double getNoiseSigma() + { + + double retVal = getNoiseSigma_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::bgsegm::BackgroundSubtractorMOG::getHistory() + // + + //javadoc: BackgroundSubtractorMOG::getHistory() + public int getHistory() + { + + int retVal = getHistory_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::bgsegm::BackgroundSubtractorMOG::getNMixtures() + // + + //javadoc: BackgroundSubtractorMOG::getNMixtures() + public int getNMixtures() + { + + int retVal = getNMixtures_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorMOG::setBackgroundRatio(double backgroundRatio) + // + + //javadoc: BackgroundSubtractorMOG::setBackgroundRatio(backgroundRatio) + public void setBackgroundRatio(double backgroundRatio) + { + + setBackgroundRatio_0(nativeObj, backgroundRatio); + + return; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorMOG::setHistory(int nframes) + // + + //javadoc: BackgroundSubtractorMOG::setHistory(nframes) + public void setHistory(int nframes) + { + + setHistory_0(nativeObj, nframes); + + return; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorMOG::setNMixtures(int nmix) + // + + //javadoc: BackgroundSubtractorMOG::setNMixtures(nmix) + public void setNMixtures(int nmix) + { + + setNMixtures_0(nativeObj, nmix); + + return; + } + + + // + // C++: void cv::bgsegm::BackgroundSubtractorMOG::setNoiseSigma(double noiseSigma) + // + + //javadoc: BackgroundSubtractorMOG::setNoiseSigma(noiseSigma) + public void setNoiseSigma(double noiseSigma) + { + + setNoiseSigma_0(nativeObj, noiseSigma); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: double cv::bgsegm::BackgroundSubtractorMOG::getBackgroundRatio() + private static native double getBackgroundRatio_0(long nativeObj); + + // C++: double cv::bgsegm::BackgroundSubtractorMOG::getNoiseSigma() + private static native double getNoiseSigma_0(long nativeObj); + + // C++: int cv::bgsegm::BackgroundSubtractorMOG::getHistory() + private static native int getHistory_0(long nativeObj); + + // C++: int cv::bgsegm::BackgroundSubtractorMOG::getNMixtures() + private static native int getNMixtures_0(long nativeObj); + + // C++: void cv::bgsegm::BackgroundSubtractorMOG::setBackgroundRatio(double backgroundRatio) + private static native void setBackgroundRatio_0(long nativeObj, double backgroundRatio); + + // C++: void cv::bgsegm::BackgroundSubtractorMOG::setHistory(int nframes) + private static native void setHistory_0(long nativeObj, int nframes); + + // C++: void cv::bgsegm::BackgroundSubtractorMOG::setNMixtures(int nmix) + private static native void setNMixtures_0(long nativeObj, int nmix); + + // C++: void cv::bgsegm::BackgroundSubtractorMOG::setNoiseSigma(double noiseSigma) + private static native void setNoiseSigma_0(long nativeObj, double noiseSigma); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/bgsegm/Bgsegm.java b/OpenCV/src/main/java/org/opencv/bgsegm/Bgsegm.java new file mode 100644 index 00000000..63f97bf5 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/bgsegm/Bgsegm.java @@ -0,0 +1,509 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.bgsegm; + +import org.opencv.bgsegm.BackgroundSubtractorCNT; +import org.opencv.bgsegm.BackgroundSubtractorGMG; +import org.opencv.bgsegm.BackgroundSubtractorGSOC; +import org.opencv.bgsegm.BackgroundSubtractorLSBP; +import org.opencv.bgsegm.BackgroundSubtractorMOG; +import org.opencv.bgsegm.SyntheticSequenceGenerator; +import org.opencv.core.Mat; + +// C++: class Bgsegm +//javadoc: Bgsegm + +public class Bgsegm { + + // C++: enum LSBPCameraMotionCompensation + public static final int + LSBP_CAMERA_MOTION_COMPENSATION_NONE = 0, + LSBP_CAMERA_MOTION_COMPENSATION_LK = 0+1; + + + // + // C++: Ptr_BackgroundSubtractorCNT cv::bgsegm::createBackgroundSubtractorCNT(int minPixelStability = 15, bool useHistory = true, int maxPixelStability = 15*60, bool isParallel = true) + // + + //javadoc: createBackgroundSubtractorCNT(minPixelStability, useHistory, maxPixelStability, isParallel) + public static BackgroundSubtractorCNT createBackgroundSubtractorCNT(int minPixelStability, boolean useHistory, int maxPixelStability, boolean isParallel) + { + + BackgroundSubtractorCNT retVal = BackgroundSubtractorCNT.__fromPtr__(createBackgroundSubtractorCNT_0(minPixelStability, useHistory, maxPixelStability, isParallel)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorCNT(minPixelStability, useHistory, maxPixelStability) + public static BackgroundSubtractorCNT createBackgroundSubtractorCNT(int minPixelStability, boolean useHistory, int maxPixelStability) + { + + BackgroundSubtractorCNT retVal = BackgroundSubtractorCNT.__fromPtr__(createBackgroundSubtractorCNT_1(minPixelStability, useHistory, maxPixelStability)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorCNT(minPixelStability, useHistory) + public static BackgroundSubtractorCNT createBackgroundSubtractorCNT(int minPixelStability, boolean useHistory) + { + + BackgroundSubtractorCNT retVal = BackgroundSubtractorCNT.__fromPtr__(createBackgroundSubtractorCNT_2(minPixelStability, useHistory)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorCNT(minPixelStability) + public static BackgroundSubtractorCNT createBackgroundSubtractorCNT(int minPixelStability) + { + + BackgroundSubtractorCNT retVal = BackgroundSubtractorCNT.__fromPtr__(createBackgroundSubtractorCNT_3(minPixelStability)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorCNT() + public static BackgroundSubtractorCNT createBackgroundSubtractorCNT() + { + + BackgroundSubtractorCNT retVal = BackgroundSubtractorCNT.__fromPtr__(createBackgroundSubtractorCNT_4()); + + return retVal; + } + + + // + // C++: Ptr_BackgroundSubtractorGMG cv::bgsegm::createBackgroundSubtractorGMG(int initializationFrames = 120, double decisionThreshold = 0.8) + // + + //javadoc: createBackgroundSubtractorGMG(initializationFrames, decisionThreshold) + public static BackgroundSubtractorGMG createBackgroundSubtractorGMG(int initializationFrames, double decisionThreshold) + { + + BackgroundSubtractorGMG retVal = BackgroundSubtractorGMG.__fromPtr__(createBackgroundSubtractorGMG_0(initializationFrames, decisionThreshold)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorGMG(initializationFrames) + public static BackgroundSubtractorGMG createBackgroundSubtractorGMG(int initializationFrames) + { + + BackgroundSubtractorGMG retVal = BackgroundSubtractorGMG.__fromPtr__(createBackgroundSubtractorGMG_1(initializationFrames)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorGMG() + public static BackgroundSubtractorGMG createBackgroundSubtractorGMG() + { + + BackgroundSubtractorGMG retVal = BackgroundSubtractorGMG.__fromPtr__(createBackgroundSubtractorGMG_2()); + + return retVal; + } + + + // + // C++: Ptr_BackgroundSubtractorGSOC cv::bgsegm::createBackgroundSubtractorGSOC(int mc = LSBP_CAMERA_MOTION_COMPENSATION_NONE, int nSamples = 20, float replaceRate = 0.003f, float propagationRate = 0.01f, int hitsThreshold = 32, float alpha = 0.01f, float beta = 0.0022f, float blinkingSupressionDecay = 0.1f, float blinkingSupressionMultiplier = 0.1f, float noiseRemovalThresholdFacBG = 0.0004f, float noiseRemovalThresholdFacFG = 0.0008f) + // + + //javadoc: createBackgroundSubtractorGSOC(mc, nSamples, replaceRate, propagationRate, hitsThreshold, alpha, beta, blinkingSupressionDecay, blinkingSupressionMultiplier, noiseRemovalThresholdFacBG, noiseRemovalThresholdFacFG) + public static BackgroundSubtractorGSOC createBackgroundSubtractorGSOC(int mc, int nSamples, float replaceRate, float propagationRate, int hitsThreshold, float alpha, float beta, float blinkingSupressionDecay, float blinkingSupressionMultiplier, float noiseRemovalThresholdFacBG, float noiseRemovalThresholdFacFG) + { + + BackgroundSubtractorGSOC retVal = BackgroundSubtractorGSOC.__fromPtr__(createBackgroundSubtractorGSOC_0(mc, nSamples, replaceRate, propagationRate, hitsThreshold, alpha, beta, blinkingSupressionDecay, blinkingSupressionMultiplier, noiseRemovalThresholdFacBG, noiseRemovalThresholdFacFG)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorGSOC(mc, nSamples, replaceRate, propagationRate, hitsThreshold, alpha, beta, blinkingSupressionDecay, blinkingSupressionMultiplier, noiseRemovalThresholdFacBG) + public static BackgroundSubtractorGSOC createBackgroundSubtractorGSOC(int mc, int nSamples, float replaceRate, float propagationRate, int hitsThreshold, float alpha, float beta, float blinkingSupressionDecay, float blinkingSupressionMultiplier, float noiseRemovalThresholdFacBG) + { + + BackgroundSubtractorGSOC retVal = BackgroundSubtractorGSOC.__fromPtr__(createBackgroundSubtractorGSOC_1(mc, nSamples, replaceRate, propagationRate, hitsThreshold, alpha, beta, blinkingSupressionDecay, blinkingSupressionMultiplier, noiseRemovalThresholdFacBG)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorGSOC(mc, nSamples, replaceRate, propagationRate, hitsThreshold, alpha, beta, blinkingSupressionDecay, blinkingSupressionMultiplier) + public static BackgroundSubtractorGSOC createBackgroundSubtractorGSOC(int mc, int nSamples, float replaceRate, float propagationRate, int hitsThreshold, float alpha, float beta, float blinkingSupressionDecay, float blinkingSupressionMultiplier) + { + + BackgroundSubtractorGSOC retVal = BackgroundSubtractorGSOC.__fromPtr__(createBackgroundSubtractorGSOC_2(mc, nSamples, replaceRate, propagationRate, hitsThreshold, alpha, beta, blinkingSupressionDecay, blinkingSupressionMultiplier)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorGSOC(mc, nSamples, replaceRate, propagationRate, hitsThreshold, alpha, beta, blinkingSupressionDecay) + public static BackgroundSubtractorGSOC createBackgroundSubtractorGSOC(int mc, int nSamples, float replaceRate, float propagationRate, int hitsThreshold, float alpha, float beta, float blinkingSupressionDecay) + { + + BackgroundSubtractorGSOC retVal = BackgroundSubtractorGSOC.__fromPtr__(createBackgroundSubtractorGSOC_3(mc, nSamples, replaceRate, propagationRate, hitsThreshold, alpha, beta, blinkingSupressionDecay)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorGSOC(mc, nSamples, replaceRate, propagationRate, hitsThreshold, alpha, beta) + public static BackgroundSubtractorGSOC createBackgroundSubtractorGSOC(int mc, int nSamples, float replaceRate, float propagationRate, int hitsThreshold, float alpha, float beta) + { + + BackgroundSubtractorGSOC retVal = BackgroundSubtractorGSOC.__fromPtr__(createBackgroundSubtractorGSOC_4(mc, nSamples, replaceRate, propagationRate, hitsThreshold, alpha, beta)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorGSOC(mc, nSamples, replaceRate, propagationRate, hitsThreshold, alpha) + public static BackgroundSubtractorGSOC createBackgroundSubtractorGSOC(int mc, int nSamples, float replaceRate, float propagationRate, int hitsThreshold, float alpha) + { + + BackgroundSubtractorGSOC retVal = BackgroundSubtractorGSOC.__fromPtr__(createBackgroundSubtractorGSOC_5(mc, nSamples, replaceRate, propagationRate, hitsThreshold, alpha)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorGSOC(mc, nSamples, replaceRate, propagationRate, hitsThreshold) + public static BackgroundSubtractorGSOC createBackgroundSubtractorGSOC(int mc, int nSamples, float replaceRate, float propagationRate, int hitsThreshold) + { + + BackgroundSubtractorGSOC retVal = BackgroundSubtractorGSOC.__fromPtr__(createBackgroundSubtractorGSOC_6(mc, nSamples, replaceRate, propagationRate, hitsThreshold)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorGSOC(mc, nSamples, replaceRate, propagationRate) + public static BackgroundSubtractorGSOC createBackgroundSubtractorGSOC(int mc, int nSamples, float replaceRate, float propagationRate) + { + + BackgroundSubtractorGSOC retVal = BackgroundSubtractorGSOC.__fromPtr__(createBackgroundSubtractorGSOC_7(mc, nSamples, replaceRate, propagationRate)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorGSOC(mc, nSamples, replaceRate) + public static BackgroundSubtractorGSOC createBackgroundSubtractorGSOC(int mc, int nSamples, float replaceRate) + { + + BackgroundSubtractorGSOC retVal = BackgroundSubtractorGSOC.__fromPtr__(createBackgroundSubtractorGSOC_8(mc, nSamples, replaceRate)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorGSOC(mc, nSamples) + public static BackgroundSubtractorGSOC createBackgroundSubtractorGSOC(int mc, int nSamples) + { + + BackgroundSubtractorGSOC retVal = BackgroundSubtractorGSOC.__fromPtr__(createBackgroundSubtractorGSOC_9(mc, nSamples)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorGSOC(mc) + public static BackgroundSubtractorGSOC createBackgroundSubtractorGSOC(int mc) + { + + BackgroundSubtractorGSOC retVal = BackgroundSubtractorGSOC.__fromPtr__(createBackgroundSubtractorGSOC_10(mc)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorGSOC() + public static BackgroundSubtractorGSOC createBackgroundSubtractorGSOC() + { + + BackgroundSubtractorGSOC retVal = BackgroundSubtractorGSOC.__fromPtr__(createBackgroundSubtractorGSOC_11()); + + return retVal; + } + + + // + // C++: Ptr_BackgroundSubtractorLSBP cv::bgsegm::createBackgroundSubtractorLSBP(int mc = LSBP_CAMERA_MOTION_COMPENSATION_NONE, int nSamples = 20, int LSBPRadius = 16, float Tlower = 2.0f, float Tupper = 32.0f, float Tinc = 1.0f, float Tdec = 0.05f, float Rscale = 10.0f, float Rincdec = 0.005f, float noiseRemovalThresholdFacBG = 0.0004f, float noiseRemovalThresholdFacFG = 0.0008f, int LSBPthreshold = 8, int minCount = 2) + // + + //javadoc: createBackgroundSubtractorLSBP(mc, nSamples, LSBPRadius, Tlower, Tupper, Tinc, Tdec, Rscale, Rincdec, noiseRemovalThresholdFacBG, noiseRemovalThresholdFacFG, LSBPthreshold, minCount) + public static BackgroundSubtractorLSBP createBackgroundSubtractorLSBP(int mc, int nSamples, int LSBPRadius, float Tlower, float Tupper, float Tinc, float Tdec, float Rscale, float Rincdec, float noiseRemovalThresholdFacBG, float noiseRemovalThresholdFacFG, int LSBPthreshold, int minCount) + { + + BackgroundSubtractorLSBP retVal = BackgroundSubtractorLSBP.__fromPtr__(createBackgroundSubtractorLSBP_0(mc, nSamples, LSBPRadius, Tlower, Tupper, Tinc, Tdec, Rscale, Rincdec, noiseRemovalThresholdFacBG, noiseRemovalThresholdFacFG, LSBPthreshold, minCount)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorLSBP(mc, nSamples, LSBPRadius, Tlower, Tupper, Tinc, Tdec, Rscale, Rincdec, noiseRemovalThresholdFacBG, noiseRemovalThresholdFacFG, LSBPthreshold) + public static BackgroundSubtractorLSBP createBackgroundSubtractorLSBP(int mc, int nSamples, int LSBPRadius, float Tlower, float Tupper, float Tinc, float Tdec, float Rscale, float Rincdec, float noiseRemovalThresholdFacBG, float noiseRemovalThresholdFacFG, int LSBPthreshold) + { + + BackgroundSubtractorLSBP retVal = BackgroundSubtractorLSBP.__fromPtr__(createBackgroundSubtractorLSBP_1(mc, nSamples, LSBPRadius, Tlower, Tupper, Tinc, Tdec, Rscale, Rincdec, noiseRemovalThresholdFacBG, noiseRemovalThresholdFacFG, LSBPthreshold)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorLSBP(mc, nSamples, LSBPRadius, Tlower, Tupper, Tinc, Tdec, Rscale, Rincdec, noiseRemovalThresholdFacBG, noiseRemovalThresholdFacFG) + public static BackgroundSubtractorLSBP createBackgroundSubtractorLSBP(int mc, int nSamples, int LSBPRadius, float Tlower, float Tupper, float Tinc, float Tdec, float Rscale, float Rincdec, float noiseRemovalThresholdFacBG, float noiseRemovalThresholdFacFG) + { + + BackgroundSubtractorLSBP retVal = BackgroundSubtractorLSBP.__fromPtr__(createBackgroundSubtractorLSBP_2(mc, nSamples, LSBPRadius, Tlower, Tupper, Tinc, Tdec, Rscale, Rincdec, noiseRemovalThresholdFacBG, noiseRemovalThresholdFacFG)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorLSBP(mc, nSamples, LSBPRadius, Tlower, Tupper, Tinc, Tdec, Rscale, Rincdec, noiseRemovalThresholdFacBG) + public static BackgroundSubtractorLSBP createBackgroundSubtractorLSBP(int mc, int nSamples, int LSBPRadius, float Tlower, float Tupper, float Tinc, float Tdec, float Rscale, float Rincdec, float noiseRemovalThresholdFacBG) + { + + BackgroundSubtractorLSBP retVal = BackgroundSubtractorLSBP.__fromPtr__(createBackgroundSubtractorLSBP_3(mc, nSamples, LSBPRadius, Tlower, Tupper, Tinc, Tdec, Rscale, Rincdec, noiseRemovalThresholdFacBG)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorLSBP(mc, nSamples, LSBPRadius, Tlower, Tupper, Tinc, Tdec, Rscale, Rincdec) + public static BackgroundSubtractorLSBP createBackgroundSubtractorLSBP(int mc, int nSamples, int LSBPRadius, float Tlower, float Tupper, float Tinc, float Tdec, float Rscale, float Rincdec) + { + + BackgroundSubtractorLSBP retVal = BackgroundSubtractorLSBP.__fromPtr__(createBackgroundSubtractorLSBP_4(mc, nSamples, LSBPRadius, Tlower, Tupper, Tinc, Tdec, Rscale, Rincdec)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorLSBP(mc, nSamples, LSBPRadius, Tlower, Tupper, Tinc, Tdec, Rscale) + public static BackgroundSubtractorLSBP createBackgroundSubtractorLSBP(int mc, int nSamples, int LSBPRadius, float Tlower, float Tupper, float Tinc, float Tdec, float Rscale) + { + + BackgroundSubtractorLSBP retVal = BackgroundSubtractorLSBP.__fromPtr__(createBackgroundSubtractorLSBP_5(mc, nSamples, LSBPRadius, Tlower, Tupper, Tinc, Tdec, Rscale)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorLSBP(mc, nSamples, LSBPRadius, Tlower, Tupper, Tinc, Tdec) + public static BackgroundSubtractorLSBP createBackgroundSubtractorLSBP(int mc, int nSamples, int LSBPRadius, float Tlower, float Tupper, float Tinc, float Tdec) + { + + BackgroundSubtractorLSBP retVal = BackgroundSubtractorLSBP.__fromPtr__(createBackgroundSubtractorLSBP_6(mc, nSamples, LSBPRadius, Tlower, Tupper, Tinc, Tdec)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorLSBP(mc, nSamples, LSBPRadius, Tlower, Tupper, Tinc) + public static BackgroundSubtractorLSBP createBackgroundSubtractorLSBP(int mc, int nSamples, int LSBPRadius, float Tlower, float Tupper, float Tinc) + { + + BackgroundSubtractorLSBP retVal = BackgroundSubtractorLSBP.__fromPtr__(createBackgroundSubtractorLSBP_7(mc, nSamples, LSBPRadius, Tlower, Tupper, Tinc)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorLSBP(mc, nSamples, LSBPRadius, Tlower, Tupper) + public static BackgroundSubtractorLSBP createBackgroundSubtractorLSBP(int mc, int nSamples, int LSBPRadius, float Tlower, float Tupper) + { + + BackgroundSubtractorLSBP retVal = BackgroundSubtractorLSBP.__fromPtr__(createBackgroundSubtractorLSBP_8(mc, nSamples, LSBPRadius, Tlower, Tupper)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorLSBP(mc, nSamples, LSBPRadius, Tlower) + public static BackgroundSubtractorLSBP createBackgroundSubtractorLSBP(int mc, int nSamples, int LSBPRadius, float Tlower) + { + + BackgroundSubtractorLSBP retVal = BackgroundSubtractorLSBP.__fromPtr__(createBackgroundSubtractorLSBP_9(mc, nSamples, LSBPRadius, Tlower)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorLSBP(mc, nSamples, LSBPRadius) + public static BackgroundSubtractorLSBP createBackgroundSubtractorLSBP(int mc, int nSamples, int LSBPRadius) + { + + BackgroundSubtractorLSBP retVal = BackgroundSubtractorLSBP.__fromPtr__(createBackgroundSubtractorLSBP_10(mc, nSamples, LSBPRadius)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorLSBP(mc, nSamples) + public static BackgroundSubtractorLSBP createBackgroundSubtractorLSBP(int mc, int nSamples) + { + + BackgroundSubtractorLSBP retVal = BackgroundSubtractorLSBP.__fromPtr__(createBackgroundSubtractorLSBP_11(mc, nSamples)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorLSBP(mc) + public static BackgroundSubtractorLSBP createBackgroundSubtractorLSBP(int mc) + { + + BackgroundSubtractorLSBP retVal = BackgroundSubtractorLSBP.__fromPtr__(createBackgroundSubtractorLSBP_12(mc)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorLSBP() + public static BackgroundSubtractorLSBP createBackgroundSubtractorLSBP() + { + + BackgroundSubtractorLSBP retVal = BackgroundSubtractorLSBP.__fromPtr__(createBackgroundSubtractorLSBP_13()); + + return retVal; + } + + + // + // C++: Ptr_BackgroundSubtractorMOG cv::bgsegm::createBackgroundSubtractorMOG(int history = 200, int nmixtures = 5, double backgroundRatio = 0.7, double noiseSigma = 0) + // + + //javadoc: createBackgroundSubtractorMOG(history, nmixtures, backgroundRatio, noiseSigma) + public static BackgroundSubtractorMOG createBackgroundSubtractorMOG(int history, int nmixtures, double backgroundRatio, double noiseSigma) + { + + BackgroundSubtractorMOG retVal = BackgroundSubtractorMOG.__fromPtr__(createBackgroundSubtractorMOG_0(history, nmixtures, backgroundRatio, noiseSigma)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorMOG(history, nmixtures, backgroundRatio) + public static BackgroundSubtractorMOG createBackgroundSubtractorMOG(int history, int nmixtures, double backgroundRatio) + { + + BackgroundSubtractorMOG retVal = BackgroundSubtractorMOG.__fromPtr__(createBackgroundSubtractorMOG_1(history, nmixtures, backgroundRatio)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorMOG(history, nmixtures) + public static BackgroundSubtractorMOG createBackgroundSubtractorMOG(int history, int nmixtures) + { + + BackgroundSubtractorMOG retVal = BackgroundSubtractorMOG.__fromPtr__(createBackgroundSubtractorMOG_2(history, nmixtures)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorMOG(history) + public static BackgroundSubtractorMOG createBackgroundSubtractorMOG(int history) + { + + BackgroundSubtractorMOG retVal = BackgroundSubtractorMOG.__fromPtr__(createBackgroundSubtractorMOG_3(history)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorMOG() + public static BackgroundSubtractorMOG createBackgroundSubtractorMOG() + { + + BackgroundSubtractorMOG retVal = BackgroundSubtractorMOG.__fromPtr__(createBackgroundSubtractorMOG_4()); + + return retVal; + } + + + // + // C++: Ptr_SyntheticSequenceGenerator cv::bgsegm::createSyntheticSequenceGenerator(Mat background, Mat object, double amplitude = 2.0, double wavelength = 20.0, double wavespeed = 0.2, double objspeed = 6.0) + // + + //javadoc: createSyntheticSequenceGenerator(background, object, amplitude, wavelength, wavespeed, objspeed) + public static SyntheticSequenceGenerator createSyntheticSequenceGenerator(Mat background, Mat object, double amplitude, double wavelength, double wavespeed, double objspeed) + { + + SyntheticSequenceGenerator retVal = SyntheticSequenceGenerator.__fromPtr__(createSyntheticSequenceGenerator_0(background.nativeObj, object.nativeObj, amplitude, wavelength, wavespeed, objspeed)); + + return retVal; + } + + //javadoc: createSyntheticSequenceGenerator(background, object, amplitude, wavelength, wavespeed) + public static SyntheticSequenceGenerator createSyntheticSequenceGenerator(Mat background, Mat object, double amplitude, double wavelength, double wavespeed) + { + + SyntheticSequenceGenerator retVal = SyntheticSequenceGenerator.__fromPtr__(createSyntheticSequenceGenerator_1(background.nativeObj, object.nativeObj, amplitude, wavelength, wavespeed)); + + return retVal; + } + + //javadoc: createSyntheticSequenceGenerator(background, object, amplitude, wavelength) + public static SyntheticSequenceGenerator createSyntheticSequenceGenerator(Mat background, Mat object, double amplitude, double wavelength) + { + + SyntheticSequenceGenerator retVal = SyntheticSequenceGenerator.__fromPtr__(createSyntheticSequenceGenerator_2(background.nativeObj, object.nativeObj, amplitude, wavelength)); + + return retVal; + } + + //javadoc: createSyntheticSequenceGenerator(background, object, amplitude) + public static SyntheticSequenceGenerator createSyntheticSequenceGenerator(Mat background, Mat object, double amplitude) + { + + SyntheticSequenceGenerator retVal = SyntheticSequenceGenerator.__fromPtr__(createSyntheticSequenceGenerator_3(background.nativeObj, object.nativeObj, amplitude)); + + return retVal; + } + + //javadoc: createSyntheticSequenceGenerator(background, object) + public static SyntheticSequenceGenerator createSyntheticSequenceGenerator(Mat background, Mat object) + { + + SyntheticSequenceGenerator retVal = SyntheticSequenceGenerator.__fromPtr__(createSyntheticSequenceGenerator_4(background.nativeObj, object.nativeObj)); + + return retVal; + } + + + + + // C++: Ptr_BackgroundSubtractorCNT cv::bgsegm::createBackgroundSubtractorCNT(int minPixelStability = 15, bool useHistory = true, int maxPixelStability = 15*60, bool isParallel = true) + private static native long createBackgroundSubtractorCNT_0(int minPixelStability, boolean useHistory, int maxPixelStability, boolean isParallel); + private static native long createBackgroundSubtractorCNT_1(int minPixelStability, boolean useHistory, int maxPixelStability); + private static native long createBackgroundSubtractorCNT_2(int minPixelStability, boolean useHistory); + private static native long createBackgroundSubtractorCNT_3(int minPixelStability); + private static native long createBackgroundSubtractorCNT_4(); + + // C++: Ptr_BackgroundSubtractorGMG cv::bgsegm::createBackgroundSubtractorGMG(int initializationFrames = 120, double decisionThreshold = 0.8) + private static native long createBackgroundSubtractorGMG_0(int initializationFrames, double decisionThreshold); + private static native long createBackgroundSubtractorGMG_1(int initializationFrames); + private static native long createBackgroundSubtractorGMG_2(); + + // C++: Ptr_BackgroundSubtractorGSOC cv::bgsegm::createBackgroundSubtractorGSOC(int mc = LSBP_CAMERA_MOTION_COMPENSATION_NONE, int nSamples = 20, float replaceRate = 0.003f, float propagationRate = 0.01f, int hitsThreshold = 32, float alpha = 0.01f, float beta = 0.0022f, float blinkingSupressionDecay = 0.1f, float blinkingSupressionMultiplier = 0.1f, float noiseRemovalThresholdFacBG = 0.0004f, float noiseRemovalThresholdFacFG = 0.0008f) + private static native long createBackgroundSubtractorGSOC_0(int mc, int nSamples, float replaceRate, float propagationRate, int hitsThreshold, float alpha, float beta, float blinkingSupressionDecay, float blinkingSupressionMultiplier, float noiseRemovalThresholdFacBG, float noiseRemovalThresholdFacFG); + private static native long createBackgroundSubtractorGSOC_1(int mc, int nSamples, float replaceRate, float propagationRate, int hitsThreshold, float alpha, float beta, float blinkingSupressionDecay, float blinkingSupressionMultiplier, float noiseRemovalThresholdFacBG); + private static native long createBackgroundSubtractorGSOC_2(int mc, int nSamples, float replaceRate, float propagationRate, int hitsThreshold, float alpha, float beta, float blinkingSupressionDecay, float blinkingSupressionMultiplier); + private static native long createBackgroundSubtractorGSOC_3(int mc, int nSamples, float replaceRate, float propagationRate, int hitsThreshold, float alpha, float beta, float blinkingSupressionDecay); + private static native long createBackgroundSubtractorGSOC_4(int mc, int nSamples, float replaceRate, float propagationRate, int hitsThreshold, float alpha, float beta); + private static native long createBackgroundSubtractorGSOC_5(int mc, int nSamples, float replaceRate, float propagationRate, int hitsThreshold, float alpha); + private static native long createBackgroundSubtractorGSOC_6(int mc, int nSamples, float replaceRate, float propagationRate, int hitsThreshold); + private static native long createBackgroundSubtractorGSOC_7(int mc, int nSamples, float replaceRate, float propagationRate); + private static native long createBackgroundSubtractorGSOC_8(int mc, int nSamples, float replaceRate); + private static native long createBackgroundSubtractorGSOC_9(int mc, int nSamples); + private static native long createBackgroundSubtractorGSOC_10(int mc); + private static native long createBackgroundSubtractorGSOC_11(); + + // C++: Ptr_BackgroundSubtractorLSBP cv::bgsegm::createBackgroundSubtractorLSBP(int mc = LSBP_CAMERA_MOTION_COMPENSATION_NONE, int nSamples = 20, int LSBPRadius = 16, float Tlower = 2.0f, float Tupper = 32.0f, float Tinc = 1.0f, float Tdec = 0.05f, float Rscale = 10.0f, float Rincdec = 0.005f, float noiseRemovalThresholdFacBG = 0.0004f, float noiseRemovalThresholdFacFG = 0.0008f, int LSBPthreshold = 8, int minCount = 2) + private static native long createBackgroundSubtractorLSBP_0(int mc, int nSamples, int LSBPRadius, float Tlower, float Tupper, float Tinc, float Tdec, float Rscale, float Rincdec, float noiseRemovalThresholdFacBG, float noiseRemovalThresholdFacFG, int LSBPthreshold, int minCount); + private static native long createBackgroundSubtractorLSBP_1(int mc, int nSamples, int LSBPRadius, float Tlower, float Tupper, float Tinc, float Tdec, float Rscale, float Rincdec, float noiseRemovalThresholdFacBG, float noiseRemovalThresholdFacFG, int LSBPthreshold); + private static native long createBackgroundSubtractorLSBP_2(int mc, int nSamples, int LSBPRadius, float Tlower, float Tupper, float Tinc, float Tdec, float Rscale, float Rincdec, float noiseRemovalThresholdFacBG, float noiseRemovalThresholdFacFG); + private static native long createBackgroundSubtractorLSBP_3(int mc, int nSamples, int LSBPRadius, float Tlower, float Tupper, float Tinc, float Tdec, float Rscale, float Rincdec, float noiseRemovalThresholdFacBG); + private static native long createBackgroundSubtractorLSBP_4(int mc, int nSamples, int LSBPRadius, float Tlower, float Tupper, float Tinc, float Tdec, float Rscale, float Rincdec); + private static native long createBackgroundSubtractorLSBP_5(int mc, int nSamples, int LSBPRadius, float Tlower, float Tupper, float Tinc, float Tdec, float Rscale); + private static native long createBackgroundSubtractorLSBP_6(int mc, int nSamples, int LSBPRadius, float Tlower, float Tupper, float Tinc, float Tdec); + private static native long createBackgroundSubtractorLSBP_7(int mc, int nSamples, int LSBPRadius, float Tlower, float Tupper, float Tinc); + private static native long createBackgroundSubtractorLSBP_8(int mc, int nSamples, int LSBPRadius, float Tlower, float Tupper); + private static native long createBackgroundSubtractorLSBP_9(int mc, int nSamples, int LSBPRadius, float Tlower); + private static native long createBackgroundSubtractorLSBP_10(int mc, int nSamples, int LSBPRadius); + private static native long createBackgroundSubtractorLSBP_11(int mc, int nSamples); + private static native long createBackgroundSubtractorLSBP_12(int mc); + private static native long createBackgroundSubtractorLSBP_13(); + + // C++: Ptr_BackgroundSubtractorMOG cv::bgsegm::createBackgroundSubtractorMOG(int history = 200, int nmixtures = 5, double backgroundRatio = 0.7, double noiseSigma = 0) + private static native long createBackgroundSubtractorMOG_0(int history, int nmixtures, double backgroundRatio, double noiseSigma); + private static native long createBackgroundSubtractorMOG_1(int history, int nmixtures, double backgroundRatio); + private static native long createBackgroundSubtractorMOG_2(int history, int nmixtures); + private static native long createBackgroundSubtractorMOG_3(int history); + private static native long createBackgroundSubtractorMOG_4(); + + // C++: Ptr_SyntheticSequenceGenerator cv::bgsegm::createSyntheticSequenceGenerator(Mat background, Mat object, double amplitude = 2.0, double wavelength = 20.0, double wavespeed = 0.2, double objspeed = 6.0) + private static native long createSyntheticSequenceGenerator_0(long background_nativeObj, long object_nativeObj, double amplitude, double wavelength, double wavespeed, double objspeed); + private static native long createSyntheticSequenceGenerator_1(long background_nativeObj, long object_nativeObj, double amplitude, double wavelength, double wavespeed); + private static native long createSyntheticSequenceGenerator_2(long background_nativeObj, long object_nativeObj, double amplitude, double wavelength); + private static native long createSyntheticSequenceGenerator_3(long background_nativeObj, long object_nativeObj, double amplitude); + private static native long createSyntheticSequenceGenerator_4(long background_nativeObj, long object_nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/bgsegm/SyntheticSequenceGenerator.java b/OpenCV/src/main/java/org/opencv/bgsegm/SyntheticSequenceGenerator.java new file mode 100644 index 00000000..7c89977e --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/bgsegm/SyntheticSequenceGenerator.java @@ -0,0 +1,63 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.bgsegm; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class SyntheticSequenceGenerator +//javadoc: SyntheticSequenceGenerator + +public class SyntheticSequenceGenerator extends Algorithm { + + protected SyntheticSequenceGenerator(long addr) { super(addr); } + + // internal usage only + public static SyntheticSequenceGenerator __fromPtr__(long addr) { return new SyntheticSequenceGenerator(addr); } + + // + // C++: cv::bgsegm::SyntheticSequenceGenerator::SyntheticSequenceGenerator(Mat background, Mat object, double amplitude, double wavelength, double wavespeed, double objspeed) + // + + //javadoc: SyntheticSequenceGenerator::SyntheticSequenceGenerator(background, object, amplitude, wavelength, wavespeed, objspeed) + public SyntheticSequenceGenerator(Mat background, Mat object, double amplitude, double wavelength, double wavespeed, double objspeed) + { + + super( SyntheticSequenceGenerator_0(background.nativeObj, object.nativeObj, amplitude, wavelength, wavespeed, objspeed) ); + + return; + } + + + // + // C++: void cv::bgsegm::SyntheticSequenceGenerator::getNextFrame(Mat& frame, Mat& gtMask) + // + + //javadoc: SyntheticSequenceGenerator::getNextFrame(frame, gtMask) + public void getNextFrame(Mat frame, Mat gtMask) + { + + getNextFrame_0(nativeObj, frame.nativeObj, gtMask.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: cv::bgsegm::SyntheticSequenceGenerator::SyntheticSequenceGenerator(Mat background, Mat object, double amplitude, double wavelength, double wavespeed, double objspeed) + private static native long SyntheticSequenceGenerator_0(long background_nativeObj, long object_nativeObj, double amplitude, double wavelength, double wavespeed, double objspeed); + + // C++: void cv::bgsegm::SyntheticSequenceGenerator::getNextFrame(Mat& frame, Mat& gtMask) + private static native void getNextFrame_0(long nativeObj, long frame_nativeObj, long gtMask_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/bioinspired/Bioinspired.java b/OpenCV/src/main/java/org/opencv/bioinspired/Bioinspired.java new file mode 100644 index 00000000..0d3c1bab --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/bioinspired/Bioinspired.java @@ -0,0 +1,22 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.bioinspired; + + + +// C++: class Bioinspired +//javadoc: Bioinspired + +public class Bioinspired { + + // C++: enum + public static final int + RETINA_COLOR_RANDOM = 0, + RETINA_COLOR_DIAGONAL = 1, + RETINA_COLOR_BAYER = 2; + + + + +} diff --git a/OpenCV/src/main/java/org/opencv/bioinspired/Retina.java b/OpenCV/src/main/java/org/opencv/bioinspired/Retina.java new file mode 100644 index 00000000..b8f84506 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/bioinspired/Retina.java @@ -0,0 +1,639 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.bioinspired; + +import java.lang.String; +import org.opencv.bioinspired.Retina; +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.core.Size; + +// C++: class Retina +//javadoc: Retina + +public class Retina extends Algorithm { + + protected Retina(long addr) { super(addr); } + + // internal usage only + public static Retina __fromPtr__(long addr) { return new Retina(addr); } + + // + // C++: Mat cv::bioinspired::Retina::getMagnoRAW() + // + + //javadoc: Retina::getMagnoRAW() + public Mat getMagnoRAW() + { + + Mat retVal = new Mat(getMagnoRAW_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::bioinspired::Retina::getParvoRAW() + // + + //javadoc: Retina::getParvoRAW() + public Mat getParvoRAW() + { + + Mat retVal = new Mat(getParvoRAW_0(nativeObj)); + + return retVal; + } + + + // + // C++: static Ptr_Retina cv::bioinspired::Retina::create(Size inputSize, bool colorMode, int colorSamplingMethod = RETINA_COLOR_BAYER, bool useRetinaLogSampling = false, float reductionFactor = 1.0f, float samplingStrenght = 10.0f) + // + + //javadoc: Retina::create(inputSize, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght) + public static Retina create(Size inputSize, boolean colorMode, int colorSamplingMethod, boolean useRetinaLogSampling, float reductionFactor, float samplingStrenght) + { + + Retina retVal = Retina.__fromPtr__(create_0(inputSize.width, inputSize.height, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor, samplingStrenght)); + + return retVal; + } + + //javadoc: Retina::create(inputSize, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor) + public static Retina create(Size inputSize, boolean colorMode, int colorSamplingMethod, boolean useRetinaLogSampling, float reductionFactor) + { + + Retina retVal = Retina.__fromPtr__(create_1(inputSize.width, inputSize.height, colorMode, colorSamplingMethod, useRetinaLogSampling, reductionFactor)); + + return retVal; + } + + //javadoc: Retina::create(inputSize, colorMode, colorSamplingMethod, useRetinaLogSampling) + public static Retina create(Size inputSize, boolean colorMode, int colorSamplingMethod, boolean useRetinaLogSampling) + { + + Retina retVal = Retina.__fromPtr__(create_2(inputSize.width, inputSize.height, colorMode, colorSamplingMethod, useRetinaLogSampling)); + + return retVal; + } + + //javadoc: Retina::create(inputSize, colorMode, colorSamplingMethod) + public static Retina create(Size inputSize, boolean colorMode, int colorSamplingMethod) + { + + Retina retVal = Retina.__fromPtr__(create_3(inputSize.width, inputSize.height, colorMode, colorSamplingMethod)); + + return retVal; + } + + //javadoc: Retina::create(inputSize, colorMode) + public static Retina create(Size inputSize, boolean colorMode) + { + + Retina retVal = Retina.__fromPtr__(create_4(inputSize.width, inputSize.height, colorMode)); + + return retVal; + } + + + // + // C++: static Ptr_Retina cv::bioinspired::Retina::create(Size inputSize) + // + + //javadoc: Retina::create(inputSize) + public static Retina create(Size inputSize) + { + + Retina retVal = Retina.__fromPtr__(create_5(inputSize.width, inputSize.height)); + + return retVal; + } + + + // + // C++: Size cv::bioinspired::Retina::getInputSize() + // + + //javadoc: Retina::getInputSize() + public Size getInputSize() + { + + Size retVal = new Size(getInputSize_0(nativeObj)); + + return retVal; + } + + + // + // C++: Size cv::bioinspired::Retina::getOutputSize() + // + + //javadoc: Retina::getOutputSize() + public Size getOutputSize() + { + + Size retVal = new Size(getOutputSize_0(nativeObj)); + + return retVal; + } + + + // + // C++: String cv::bioinspired::Retina::printSetup() + // + + //javadoc: Retina::printSetup() + public String printSetup() + { + + String retVal = printSetup_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::bioinspired::Retina::activateContoursProcessing(bool activate) + // + + //javadoc: Retina::activateContoursProcessing(activate) + public void activateContoursProcessing(boolean activate) + { + + activateContoursProcessing_0(nativeObj, activate); + + return; + } + + + // + // C++: void cv::bioinspired::Retina::activateMovingContoursProcessing(bool activate) + // + + //javadoc: Retina::activateMovingContoursProcessing(activate) + public void activateMovingContoursProcessing(boolean activate) + { + + activateMovingContoursProcessing_0(nativeObj, activate); + + return; + } + + + // + // C++: void cv::bioinspired::Retina::applyFastToneMapping(Mat inputImage, Mat& outputToneMappedImage) + // + + //javadoc: Retina::applyFastToneMapping(inputImage, outputToneMappedImage) + public void applyFastToneMapping(Mat inputImage, Mat outputToneMappedImage) + { + + applyFastToneMapping_0(nativeObj, inputImage.nativeObj, outputToneMappedImage.nativeObj); + + return; + } + + + // + // C++: void cv::bioinspired::Retina::clearBuffers() + // + + //javadoc: Retina::clearBuffers() + public void clearBuffers() + { + + clearBuffers_0(nativeObj); + + return; + } + + + // + // C++: void cv::bioinspired::Retina::getMagno(Mat& retinaOutput_magno) + // + + //javadoc: Retina::getMagno(retinaOutput_magno) + public void getMagno(Mat retinaOutput_magno) + { + + getMagno_0(nativeObj, retinaOutput_magno.nativeObj); + + return; + } + + + // + // C++: void cv::bioinspired::Retina::getMagnoRAW(Mat& retinaOutput_magno) + // + + //javadoc: Retina::getMagnoRAW(retinaOutput_magno) + public void getMagnoRAW(Mat retinaOutput_magno) + { + + getMagnoRAW_1(nativeObj, retinaOutput_magno.nativeObj); + + return; + } + + + // + // C++: void cv::bioinspired::Retina::getParvo(Mat& retinaOutput_parvo) + // + + //javadoc: Retina::getParvo(retinaOutput_parvo) + public void getParvo(Mat retinaOutput_parvo) + { + + getParvo_0(nativeObj, retinaOutput_parvo.nativeObj); + + return; + } + + + // + // C++: void cv::bioinspired::Retina::getParvoRAW(Mat& retinaOutput_parvo) + // + + //javadoc: Retina::getParvoRAW(retinaOutput_parvo) + public void getParvoRAW(Mat retinaOutput_parvo) + { + + getParvoRAW_1(nativeObj, retinaOutput_parvo.nativeObj); + + return; + } + + + // + // C++: void cv::bioinspired::Retina::run(Mat inputImage) + // + + //javadoc: Retina::run(inputImage) + public void run(Mat inputImage) + { + + run_0(nativeObj, inputImage.nativeObj); + + return; + } + + + // + // C++: void cv::bioinspired::Retina::setColorSaturation(bool saturateColors = true, float colorSaturationValue = 4.0f) + // + + //javadoc: Retina::setColorSaturation(saturateColors, colorSaturationValue) + public void setColorSaturation(boolean saturateColors, float colorSaturationValue) + { + + setColorSaturation_0(nativeObj, saturateColors, colorSaturationValue); + + return; + } + + //javadoc: Retina::setColorSaturation(saturateColors) + public void setColorSaturation(boolean saturateColors) + { + + setColorSaturation_1(nativeObj, saturateColors); + + return; + } + + //javadoc: Retina::setColorSaturation() + public void setColorSaturation() + { + + setColorSaturation_2(nativeObj); + + return; + } + + + // + // C++: void cv::bioinspired::Retina::setup(String retinaParameterFile = "", bool applyDefaultSetupOnFailure = true) + // + + //javadoc: Retina::setup(retinaParameterFile, applyDefaultSetupOnFailure) + public void setup(String retinaParameterFile, boolean applyDefaultSetupOnFailure) + { + + setup_0(nativeObj, retinaParameterFile, applyDefaultSetupOnFailure); + + return; + } + + //javadoc: Retina::setup(retinaParameterFile) + public void setup(String retinaParameterFile) + { + + setup_1(nativeObj, retinaParameterFile); + + return; + } + + //javadoc: Retina::setup() + public void setup() + { + + setup_2(nativeObj); + + return; + } + + + // + // C++: void cv::bioinspired::Retina::setupIPLMagnoChannel(bool normaliseOutput = true, float parasolCells_beta = 0.f, float parasolCells_tau = 0.f, float parasolCells_k = 7.f, float amacrinCellsTemporalCutFrequency = 1.2f, float V0CompressionParameter = 0.95f, float localAdaptintegration_tau = 0.f, float localAdaptintegration_k = 7.f) + // + + //javadoc: Retina::setupIPLMagnoChannel(normaliseOutput, parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, V0CompressionParameter, localAdaptintegration_tau, localAdaptintegration_k) + public void setupIPLMagnoChannel(boolean normaliseOutput, float parasolCells_beta, float parasolCells_tau, float parasolCells_k, float amacrinCellsTemporalCutFrequency, float V0CompressionParameter, float localAdaptintegration_tau, float localAdaptintegration_k) + { + + setupIPLMagnoChannel_0(nativeObj, normaliseOutput, parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, V0CompressionParameter, localAdaptintegration_tau, localAdaptintegration_k); + + return; + } + + //javadoc: Retina::setupIPLMagnoChannel(normaliseOutput, parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, V0CompressionParameter, localAdaptintegration_tau) + public void setupIPLMagnoChannel(boolean normaliseOutput, float parasolCells_beta, float parasolCells_tau, float parasolCells_k, float amacrinCellsTemporalCutFrequency, float V0CompressionParameter, float localAdaptintegration_tau) + { + + setupIPLMagnoChannel_1(nativeObj, normaliseOutput, parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, V0CompressionParameter, localAdaptintegration_tau); + + return; + } + + //javadoc: Retina::setupIPLMagnoChannel(normaliseOutput, parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, V0CompressionParameter) + public void setupIPLMagnoChannel(boolean normaliseOutput, float parasolCells_beta, float parasolCells_tau, float parasolCells_k, float amacrinCellsTemporalCutFrequency, float V0CompressionParameter) + { + + setupIPLMagnoChannel_2(nativeObj, normaliseOutput, parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency, V0CompressionParameter); + + return; + } + + //javadoc: Retina::setupIPLMagnoChannel(normaliseOutput, parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency) + public void setupIPLMagnoChannel(boolean normaliseOutput, float parasolCells_beta, float parasolCells_tau, float parasolCells_k, float amacrinCellsTemporalCutFrequency) + { + + setupIPLMagnoChannel_3(nativeObj, normaliseOutput, parasolCells_beta, parasolCells_tau, parasolCells_k, amacrinCellsTemporalCutFrequency); + + return; + } + + //javadoc: Retina::setupIPLMagnoChannel(normaliseOutput, parasolCells_beta, parasolCells_tau, parasolCells_k) + public void setupIPLMagnoChannel(boolean normaliseOutput, float parasolCells_beta, float parasolCells_tau, float parasolCells_k) + { + + setupIPLMagnoChannel_4(nativeObj, normaliseOutput, parasolCells_beta, parasolCells_tau, parasolCells_k); + + return; + } + + //javadoc: Retina::setupIPLMagnoChannel(normaliseOutput, parasolCells_beta, parasolCells_tau) + public void setupIPLMagnoChannel(boolean normaliseOutput, float parasolCells_beta, float parasolCells_tau) + { + + setupIPLMagnoChannel_5(nativeObj, normaliseOutput, parasolCells_beta, parasolCells_tau); + + return; + } + + //javadoc: Retina::setupIPLMagnoChannel(normaliseOutput, parasolCells_beta) + public void setupIPLMagnoChannel(boolean normaliseOutput, float parasolCells_beta) + { + + setupIPLMagnoChannel_6(nativeObj, normaliseOutput, parasolCells_beta); + + return; + } + + //javadoc: Retina::setupIPLMagnoChannel(normaliseOutput) + public void setupIPLMagnoChannel(boolean normaliseOutput) + { + + setupIPLMagnoChannel_7(nativeObj, normaliseOutput); + + return; + } + + //javadoc: Retina::setupIPLMagnoChannel() + public void setupIPLMagnoChannel() + { + + setupIPLMagnoChannel_8(nativeObj); + + return; + } + + + // + // C++: void cv::bioinspired::Retina::setupOPLandIPLParvoChannel(bool colorMode = true, bool normaliseOutput = true, float photoreceptorsLocalAdaptationSensitivity = 0.7f, float photoreceptorsTemporalConstant = 0.5f, float photoreceptorsSpatialConstant = 0.53f, float horizontalCellsGain = 0.f, float HcellsTemporalConstant = 1.f, float HcellsSpatialConstant = 7.f, float ganglionCellsSensitivity = 0.7f) + // + + //javadoc: Retina::setupOPLandIPLParvoChannel(colorMode, normaliseOutput, photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain, HcellsTemporalConstant, HcellsSpatialConstant, ganglionCellsSensitivity) + public void setupOPLandIPLParvoChannel(boolean colorMode, boolean normaliseOutput, float photoreceptorsLocalAdaptationSensitivity, float photoreceptorsTemporalConstant, float photoreceptorsSpatialConstant, float horizontalCellsGain, float HcellsTemporalConstant, float HcellsSpatialConstant, float ganglionCellsSensitivity) + { + + setupOPLandIPLParvoChannel_0(nativeObj, colorMode, normaliseOutput, photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain, HcellsTemporalConstant, HcellsSpatialConstant, ganglionCellsSensitivity); + + return; + } + + //javadoc: Retina::setupOPLandIPLParvoChannel(colorMode, normaliseOutput, photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain, HcellsTemporalConstant, HcellsSpatialConstant) + public void setupOPLandIPLParvoChannel(boolean colorMode, boolean normaliseOutput, float photoreceptorsLocalAdaptationSensitivity, float photoreceptorsTemporalConstant, float photoreceptorsSpatialConstant, float horizontalCellsGain, float HcellsTemporalConstant, float HcellsSpatialConstant) + { + + setupOPLandIPLParvoChannel_1(nativeObj, colorMode, normaliseOutput, photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain, HcellsTemporalConstant, HcellsSpatialConstant); + + return; + } + + //javadoc: Retina::setupOPLandIPLParvoChannel(colorMode, normaliseOutput, photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain, HcellsTemporalConstant) + public void setupOPLandIPLParvoChannel(boolean colorMode, boolean normaliseOutput, float photoreceptorsLocalAdaptationSensitivity, float photoreceptorsTemporalConstant, float photoreceptorsSpatialConstant, float horizontalCellsGain, float HcellsTemporalConstant) + { + + setupOPLandIPLParvoChannel_2(nativeObj, colorMode, normaliseOutput, photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain, HcellsTemporalConstant); + + return; + } + + //javadoc: Retina::setupOPLandIPLParvoChannel(colorMode, normaliseOutput, photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain) + public void setupOPLandIPLParvoChannel(boolean colorMode, boolean normaliseOutput, float photoreceptorsLocalAdaptationSensitivity, float photoreceptorsTemporalConstant, float photoreceptorsSpatialConstant, float horizontalCellsGain) + { + + setupOPLandIPLParvoChannel_3(nativeObj, colorMode, normaliseOutput, photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant, horizontalCellsGain); + + return; + } + + //javadoc: Retina::setupOPLandIPLParvoChannel(colorMode, normaliseOutput, photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant) + public void setupOPLandIPLParvoChannel(boolean colorMode, boolean normaliseOutput, float photoreceptorsLocalAdaptationSensitivity, float photoreceptorsTemporalConstant, float photoreceptorsSpatialConstant) + { + + setupOPLandIPLParvoChannel_4(nativeObj, colorMode, normaliseOutput, photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant, photoreceptorsSpatialConstant); + + return; + } + + //javadoc: Retina::setupOPLandIPLParvoChannel(colorMode, normaliseOutput, photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant) + public void setupOPLandIPLParvoChannel(boolean colorMode, boolean normaliseOutput, float photoreceptorsLocalAdaptationSensitivity, float photoreceptorsTemporalConstant) + { + + setupOPLandIPLParvoChannel_5(nativeObj, colorMode, normaliseOutput, photoreceptorsLocalAdaptationSensitivity, photoreceptorsTemporalConstant); + + return; + } + + //javadoc: Retina::setupOPLandIPLParvoChannel(colorMode, normaliseOutput, photoreceptorsLocalAdaptationSensitivity) + public void setupOPLandIPLParvoChannel(boolean colorMode, boolean normaliseOutput, float photoreceptorsLocalAdaptationSensitivity) + { + + setupOPLandIPLParvoChannel_6(nativeObj, colorMode, normaliseOutput, photoreceptorsLocalAdaptationSensitivity); + + return; + } + + //javadoc: Retina::setupOPLandIPLParvoChannel(colorMode, normaliseOutput) + public void setupOPLandIPLParvoChannel(boolean colorMode, boolean normaliseOutput) + { + + setupOPLandIPLParvoChannel_7(nativeObj, colorMode, normaliseOutput); + + return; + } + + //javadoc: Retina::setupOPLandIPLParvoChannel(colorMode) + public void setupOPLandIPLParvoChannel(boolean colorMode) + { + + setupOPLandIPLParvoChannel_8(nativeObj, colorMode); + + return; + } + + //javadoc: Retina::setupOPLandIPLParvoChannel() + public void setupOPLandIPLParvoChannel() + { + + setupOPLandIPLParvoChannel_9(nativeObj); + + return; + } + + + // + // C++: void cv::bioinspired::Retina::write(String fs) + // + + //javadoc: Retina::write(fs) + public void write(String fs) + { + + write_0(nativeObj, fs); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: Mat cv::bioinspired::Retina::getMagnoRAW() + private static native long getMagnoRAW_0(long nativeObj); + + // C++: Mat cv::bioinspired::Retina::getParvoRAW() + private static native long getParvoRAW_0(long nativeObj); + + // C++: static Ptr_Retina cv::bioinspired::Retina::create(Size inputSize, bool colorMode, int colorSamplingMethod = RETINA_COLOR_BAYER, bool useRetinaLogSampling = false, float reductionFactor = 1.0f, float samplingStrenght = 10.0f) + private static native long create_0(double inputSize_width, double inputSize_height, boolean colorMode, int colorSamplingMethod, boolean useRetinaLogSampling, float reductionFactor, float samplingStrenght); + private static native long create_1(double inputSize_width, double inputSize_height, boolean colorMode, int colorSamplingMethod, boolean useRetinaLogSampling, float reductionFactor); + private static native long create_2(double inputSize_width, double inputSize_height, boolean colorMode, int colorSamplingMethod, boolean useRetinaLogSampling); + private static native long create_3(double inputSize_width, double inputSize_height, boolean colorMode, int colorSamplingMethod); + private static native long create_4(double inputSize_width, double inputSize_height, boolean colorMode); + + // C++: static Ptr_Retina cv::bioinspired::Retina::create(Size inputSize) + private static native long create_5(double inputSize_width, double inputSize_height); + + // C++: Size cv::bioinspired::Retina::getInputSize() + private static native double[] getInputSize_0(long nativeObj); + + // C++: Size cv::bioinspired::Retina::getOutputSize() + private static native double[] getOutputSize_0(long nativeObj); + + // C++: String cv::bioinspired::Retina::printSetup() + private static native String printSetup_0(long nativeObj); + + // C++: void cv::bioinspired::Retina::activateContoursProcessing(bool activate) + private static native void activateContoursProcessing_0(long nativeObj, boolean activate); + + // C++: void cv::bioinspired::Retina::activateMovingContoursProcessing(bool activate) + private static native void activateMovingContoursProcessing_0(long nativeObj, boolean activate); + + // C++: void cv::bioinspired::Retina::applyFastToneMapping(Mat inputImage, Mat& outputToneMappedImage) + private static native void applyFastToneMapping_0(long nativeObj, long inputImage_nativeObj, long outputToneMappedImage_nativeObj); + + // C++: void cv::bioinspired::Retina::clearBuffers() + private static native void clearBuffers_0(long nativeObj); + + // C++: void cv::bioinspired::Retina::getMagno(Mat& retinaOutput_magno) + private static native void getMagno_0(long nativeObj, long retinaOutput_magno_nativeObj); + + // C++: void cv::bioinspired::Retina::getMagnoRAW(Mat& retinaOutput_magno) + private static native void getMagnoRAW_1(long nativeObj, long retinaOutput_magno_nativeObj); + + // C++: void cv::bioinspired::Retina::getParvo(Mat& retinaOutput_parvo) + private static native void getParvo_0(long nativeObj, long retinaOutput_parvo_nativeObj); + + // C++: void cv::bioinspired::Retina::getParvoRAW(Mat& retinaOutput_parvo) + private static native void getParvoRAW_1(long nativeObj, long retinaOutput_parvo_nativeObj); + + // C++: void cv::bioinspired::Retina::run(Mat inputImage) + private static native void run_0(long nativeObj, long inputImage_nativeObj); + + // C++: void cv::bioinspired::Retina::setColorSaturation(bool saturateColors = true, float colorSaturationValue = 4.0f) + private static native void setColorSaturation_0(long nativeObj, boolean saturateColors, float colorSaturationValue); + private static native void setColorSaturation_1(long nativeObj, boolean saturateColors); + private static native void setColorSaturation_2(long nativeObj); + + // C++: void cv::bioinspired::Retina::setup(String retinaParameterFile = "", bool applyDefaultSetupOnFailure = true) + private static native void setup_0(long nativeObj, String retinaParameterFile, boolean applyDefaultSetupOnFailure); + private static native void setup_1(long nativeObj, String retinaParameterFile); + private static native void setup_2(long nativeObj); + + // C++: void cv::bioinspired::Retina::setupIPLMagnoChannel(bool normaliseOutput = true, float parasolCells_beta = 0.f, float parasolCells_tau = 0.f, float parasolCells_k = 7.f, float amacrinCellsTemporalCutFrequency = 1.2f, float V0CompressionParameter = 0.95f, float localAdaptintegration_tau = 0.f, float localAdaptintegration_k = 7.f) + private static native void setupIPLMagnoChannel_0(long nativeObj, boolean normaliseOutput, float parasolCells_beta, float parasolCells_tau, float parasolCells_k, float amacrinCellsTemporalCutFrequency, float V0CompressionParameter, float localAdaptintegration_tau, float localAdaptintegration_k); + private static native void setupIPLMagnoChannel_1(long nativeObj, boolean normaliseOutput, float parasolCells_beta, float parasolCells_tau, float parasolCells_k, float amacrinCellsTemporalCutFrequency, float V0CompressionParameter, float localAdaptintegration_tau); + private static native void setupIPLMagnoChannel_2(long nativeObj, boolean normaliseOutput, float parasolCells_beta, float parasolCells_tau, float parasolCells_k, float amacrinCellsTemporalCutFrequency, float V0CompressionParameter); + private static native void setupIPLMagnoChannel_3(long nativeObj, boolean normaliseOutput, float parasolCells_beta, float parasolCells_tau, float parasolCells_k, float amacrinCellsTemporalCutFrequency); + private static native void setupIPLMagnoChannel_4(long nativeObj, boolean normaliseOutput, float parasolCells_beta, float parasolCells_tau, float parasolCells_k); + private static native void setupIPLMagnoChannel_5(long nativeObj, boolean normaliseOutput, float parasolCells_beta, float parasolCells_tau); + private static native void setupIPLMagnoChannel_6(long nativeObj, boolean normaliseOutput, float parasolCells_beta); + private static native void setupIPLMagnoChannel_7(long nativeObj, boolean normaliseOutput); + private static native void setupIPLMagnoChannel_8(long nativeObj); + + // C++: void cv::bioinspired::Retina::setupOPLandIPLParvoChannel(bool colorMode = true, bool normaliseOutput = true, float photoreceptorsLocalAdaptationSensitivity = 0.7f, float photoreceptorsTemporalConstant = 0.5f, float photoreceptorsSpatialConstant = 0.53f, float horizontalCellsGain = 0.f, float HcellsTemporalConstant = 1.f, float HcellsSpatialConstant = 7.f, float ganglionCellsSensitivity = 0.7f) + private static native void setupOPLandIPLParvoChannel_0(long nativeObj, boolean colorMode, boolean normaliseOutput, float photoreceptorsLocalAdaptationSensitivity, float photoreceptorsTemporalConstant, float photoreceptorsSpatialConstant, float horizontalCellsGain, float HcellsTemporalConstant, float HcellsSpatialConstant, float ganglionCellsSensitivity); + private static native void setupOPLandIPLParvoChannel_1(long nativeObj, boolean colorMode, boolean normaliseOutput, float photoreceptorsLocalAdaptationSensitivity, float photoreceptorsTemporalConstant, float photoreceptorsSpatialConstant, float horizontalCellsGain, float HcellsTemporalConstant, float HcellsSpatialConstant); + private static native void setupOPLandIPLParvoChannel_2(long nativeObj, boolean colorMode, boolean normaliseOutput, float photoreceptorsLocalAdaptationSensitivity, float photoreceptorsTemporalConstant, float photoreceptorsSpatialConstant, float horizontalCellsGain, float HcellsTemporalConstant); + private static native void setupOPLandIPLParvoChannel_3(long nativeObj, boolean colorMode, boolean normaliseOutput, float photoreceptorsLocalAdaptationSensitivity, float photoreceptorsTemporalConstant, float photoreceptorsSpatialConstant, float horizontalCellsGain); + private static native void setupOPLandIPLParvoChannel_4(long nativeObj, boolean colorMode, boolean normaliseOutput, float photoreceptorsLocalAdaptationSensitivity, float photoreceptorsTemporalConstant, float photoreceptorsSpatialConstant); + private static native void setupOPLandIPLParvoChannel_5(long nativeObj, boolean colorMode, boolean normaliseOutput, float photoreceptorsLocalAdaptationSensitivity, float photoreceptorsTemporalConstant); + private static native void setupOPLandIPLParvoChannel_6(long nativeObj, boolean colorMode, boolean normaliseOutput, float photoreceptorsLocalAdaptationSensitivity); + private static native void setupOPLandIPLParvoChannel_7(long nativeObj, boolean colorMode, boolean normaliseOutput); + private static native void setupOPLandIPLParvoChannel_8(long nativeObj, boolean colorMode); + private static native void setupOPLandIPLParvoChannel_9(long nativeObj); + + // C++: void cv::bioinspired::Retina::write(String fs) + private static native void write_0(long nativeObj, String fs); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/bioinspired/RetinaFastToneMapping.java b/OpenCV/src/main/java/org/opencv/bioinspired/RetinaFastToneMapping.java new file mode 100644 index 00000000..eee0ec4c --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/bioinspired/RetinaFastToneMapping.java @@ -0,0 +1,112 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.bioinspired; + +import org.opencv.bioinspired.RetinaFastToneMapping; +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.core.Size; + +// C++: class RetinaFastToneMapping +//javadoc: RetinaFastToneMapping + +public class RetinaFastToneMapping extends Algorithm { + + protected RetinaFastToneMapping(long addr) { super(addr); } + + // internal usage only + public static RetinaFastToneMapping __fromPtr__(long addr) { return new RetinaFastToneMapping(addr); } + + // + // C++: static Ptr_RetinaFastToneMapping cv::bioinspired::RetinaFastToneMapping::create(Size inputSize) + // + + //javadoc: RetinaFastToneMapping::create(inputSize) + public static RetinaFastToneMapping create(Size inputSize) + { + + RetinaFastToneMapping retVal = RetinaFastToneMapping.__fromPtr__(create_0(inputSize.width, inputSize.height)); + + return retVal; + } + + + // + // C++: void cv::bioinspired::RetinaFastToneMapping::applyFastToneMapping(Mat inputImage, Mat& outputToneMappedImage) + // + + //javadoc: RetinaFastToneMapping::applyFastToneMapping(inputImage, outputToneMappedImage) + public void applyFastToneMapping(Mat inputImage, Mat outputToneMappedImage) + { + + applyFastToneMapping_0(nativeObj, inputImage.nativeObj, outputToneMappedImage.nativeObj); + + return; + } + + + // + // C++: void cv::bioinspired::RetinaFastToneMapping::setup(float photoreceptorsNeighborhoodRadius = 3.f, float ganglioncellsNeighborhoodRadius = 1.f, float meanLuminanceModulatorK = 1.f) + // + + //javadoc: RetinaFastToneMapping::setup(photoreceptorsNeighborhoodRadius, ganglioncellsNeighborhoodRadius, meanLuminanceModulatorK) + public void setup(float photoreceptorsNeighborhoodRadius, float ganglioncellsNeighborhoodRadius, float meanLuminanceModulatorK) + { + + setup_0(nativeObj, photoreceptorsNeighborhoodRadius, ganglioncellsNeighborhoodRadius, meanLuminanceModulatorK); + + return; + } + + //javadoc: RetinaFastToneMapping::setup(photoreceptorsNeighborhoodRadius, ganglioncellsNeighborhoodRadius) + public void setup(float photoreceptorsNeighborhoodRadius, float ganglioncellsNeighborhoodRadius) + { + + setup_1(nativeObj, photoreceptorsNeighborhoodRadius, ganglioncellsNeighborhoodRadius); + + return; + } + + //javadoc: RetinaFastToneMapping::setup(photoreceptorsNeighborhoodRadius) + public void setup(float photoreceptorsNeighborhoodRadius) + { + + setup_2(nativeObj, photoreceptorsNeighborhoodRadius); + + return; + } + + //javadoc: RetinaFastToneMapping::setup() + public void setup() + { + + setup_3(nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_RetinaFastToneMapping cv::bioinspired::RetinaFastToneMapping::create(Size inputSize) + private static native long create_0(double inputSize_width, double inputSize_height); + + // C++: void cv::bioinspired::RetinaFastToneMapping::applyFastToneMapping(Mat inputImage, Mat& outputToneMappedImage) + private static native void applyFastToneMapping_0(long nativeObj, long inputImage_nativeObj, long outputToneMappedImage_nativeObj); + + // C++: void cv::bioinspired::RetinaFastToneMapping::setup(float photoreceptorsNeighborhoodRadius = 3.f, float ganglioncellsNeighborhoodRadius = 1.f, float meanLuminanceModulatorK = 1.f) + private static native void setup_0(long nativeObj, float photoreceptorsNeighborhoodRadius, float ganglioncellsNeighborhoodRadius, float meanLuminanceModulatorK); + private static native void setup_1(long nativeObj, float photoreceptorsNeighborhoodRadius, float ganglioncellsNeighborhoodRadius); + private static native void setup_2(long nativeObj, float photoreceptorsNeighborhoodRadius); + private static native void setup_3(long nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/bioinspired/TransientAreasSegmentationModule.java b/OpenCV/src/main/java/org/opencv/bioinspired/TransientAreasSegmentationModule.java new file mode 100644 index 00000000..13587aef --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/bioinspired/TransientAreasSegmentationModule.java @@ -0,0 +1,198 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.bioinspired; + +import java.lang.String; +import org.opencv.bioinspired.TransientAreasSegmentationModule; +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.core.Size; + +// C++: class TransientAreasSegmentationModule +//javadoc: TransientAreasSegmentationModule + +public class TransientAreasSegmentationModule extends Algorithm { + + protected TransientAreasSegmentationModule(long addr) { super(addr); } + + // internal usage only + public static TransientAreasSegmentationModule __fromPtr__(long addr) { return new TransientAreasSegmentationModule(addr); } + + // + // C++: static Ptr_TransientAreasSegmentationModule cv::bioinspired::TransientAreasSegmentationModule::create(Size inputSize) + // + + //javadoc: TransientAreasSegmentationModule::create(inputSize) + public static TransientAreasSegmentationModule create(Size inputSize) + { + + TransientAreasSegmentationModule retVal = TransientAreasSegmentationModule.__fromPtr__(create_0(inputSize.width, inputSize.height)); + + return retVal; + } + + + // + // C++: Size cv::bioinspired::TransientAreasSegmentationModule::getSize() + // + + //javadoc: TransientAreasSegmentationModule::getSize() + public Size getSize() + { + + Size retVal = new Size(getSize_0(nativeObj)); + + return retVal; + } + + + // + // C++: String cv::bioinspired::TransientAreasSegmentationModule::printSetup() + // + + //javadoc: TransientAreasSegmentationModule::printSetup() + public String printSetup() + { + + String retVal = printSetup_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::bioinspired::TransientAreasSegmentationModule::clearAllBuffers() + // + + //javadoc: TransientAreasSegmentationModule::clearAllBuffers() + public void clearAllBuffers() + { + + clearAllBuffers_0(nativeObj); + + return; + } + + + // + // C++: void cv::bioinspired::TransientAreasSegmentationModule::getSegmentationPicture(Mat& transientAreas) + // + + //javadoc: TransientAreasSegmentationModule::getSegmentationPicture(transientAreas) + public void getSegmentationPicture(Mat transientAreas) + { + + getSegmentationPicture_0(nativeObj, transientAreas.nativeObj); + + return; + } + + + // + // C++: void cv::bioinspired::TransientAreasSegmentationModule::run(Mat inputToSegment, int channelIndex = 0) + // + + //javadoc: TransientAreasSegmentationModule::run(inputToSegment, channelIndex) + public void run(Mat inputToSegment, int channelIndex) + { + + run_0(nativeObj, inputToSegment.nativeObj, channelIndex); + + return; + } + + //javadoc: TransientAreasSegmentationModule::run(inputToSegment) + public void run(Mat inputToSegment) + { + + run_1(nativeObj, inputToSegment.nativeObj); + + return; + } + + + // + // C++: void cv::bioinspired::TransientAreasSegmentationModule::setup(String segmentationParameterFile = "", bool applyDefaultSetupOnFailure = true) + // + + //javadoc: TransientAreasSegmentationModule::setup(segmentationParameterFile, applyDefaultSetupOnFailure) + public void setup(String segmentationParameterFile, boolean applyDefaultSetupOnFailure) + { + + setup_0(nativeObj, segmentationParameterFile, applyDefaultSetupOnFailure); + + return; + } + + //javadoc: TransientAreasSegmentationModule::setup(segmentationParameterFile) + public void setup(String segmentationParameterFile) + { + + setup_1(nativeObj, segmentationParameterFile); + + return; + } + + //javadoc: TransientAreasSegmentationModule::setup() + public void setup() + { + + setup_2(nativeObj); + + return; + } + + + // + // C++: void cv::bioinspired::TransientAreasSegmentationModule::write(String fs) + // + + //javadoc: TransientAreasSegmentationModule::write(fs) + public void write(String fs) + { + + write_0(nativeObj, fs); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_TransientAreasSegmentationModule cv::bioinspired::TransientAreasSegmentationModule::create(Size inputSize) + private static native long create_0(double inputSize_width, double inputSize_height); + + // C++: Size cv::bioinspired::TransientAreasSegmentationModule::getSize() + private static native double[] getSize_0(long nativeObj); + + // C++: String cv::bioinspired::TransientAreasSegmentationModule::printSetup() + private static native String printSetup_0(long nativeObj); + + // C++: void cv::bioinspired::TransientAreasSegmentationModule::clearAllBuffers() + private static native void clearAllBuffers_0(long nativeObj); + + // C++: void cv::bioinspired::TransientAreasSegmentationModule::getSegmentationPicture(Mat& transientAreas) + private static native void getSegmentationPicture_0(long nativeObj, long transientAreas_nativeObj); + + // C++: void cv::bioinspired::TransientAreasSegmentationModule::run(Mat inputToSegment, int channelIndex = 0) + private static native void run_0(long nativeObj, long inputToSegment_nativeObj, int channelIndex); + private static native void run_1(long nativeObj, long inputToSegment_nativeObj); + + // C++: void cv::bioinspired::TransientAreasSegmentationModule::setup(String segmentationParameterFile = "", bool applyDefaultSetupOnFailure = true) + private static native void setup_0(long nativeObj, String segmentationParameterFile, boolean applyDefaultSetupOnFailure); + private static native void setup_1(long nativeObj, String segmentationParameterFile); + private static native void setup_2(long nativeObj); + + // C++: void cv::bioinspired::TransientAreasSegmentationModule::write(String fs) + private static native void write_0(long nativeObj, String fs); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/calib3d/Calib3d.java b/OpenCV/src/main/java/org/opencv/calib3d/Calib3d.java new file mode 100644 index 00000000..fca1b4af --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/calib3d/Calib3d.java @@ -0,0 +1,2782 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.calib3d; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfDouble; +import org.opencv.core.MatOfPoint2f; +import org.opencv.core.MatOfPoint3f; +import org.opencv.core.Point; +import org.opencv.core.Rect; +import org.opencv.core.Size; +import org.opencv.core.TermCriteria; +import org.opencv.utils.Converters; + +// C++: class Calib3d +//javadoc: Calib3d + +public class Calib3d { + + // C++: enum + public static final int + CV_ITERATIVE = 0, + CV_EPNP = 1, + CV_P3P = 2, + CV_DLS = 3, + CvLevMarq_DONE = 0, + CvLevMarq_STARTED = 1, + CvLevMarq_CALC_J = 2, + CvLevMarq_CHECK_ERR = 3, + LMEDS = 4, + RANSAC = 8, + RHO = 16, + CALIB_CB_ADAPTIVE_THRESH = 1, + CALIB_CB_NORMALIZE_IMAGE = 2, + CALIB_CB_FILTER_QUADS = 4, + CALIB_CB_FAST_CHECK = 8, + CALIB_CB_EXHAUSTIVE = 16, + CALIB_CB_ACCURACY = 32, + CALIB_CB_SYMMETRIC_GRID = 1, + CALIB_CB_ASYMMETRIC_GRID = 2, + CALIB_CB_CLUSTERING = 4, + CALIB_NINTRINSIC = 18, + CALIB_USE_INTRINSIC_GUESS = 0x00001, + CALIB_FIX_ASPECT_RATIO = 0x00002, + CALIB_FIX_PRINCIPAL_POINT = 0x00004, + CALIB_ZERO_TANGENT_DIST = 0x00008, + CALIB_FIX_FOCAL_LENGTH = 0x00010, + CALIB_FIX_K1 = 0x00020, + CALIB_FIX_K2 = 0x00040, + CALIB_FIX_K3 = 0x00080, + CALIB_FIX_K4 = 0x00800, + CALIB_FIX_K5 = 0x01000, + CALIB_FIX_K6 = 0x02000, + CALIB_RATIONAL_MODEL = 0x04000, + CALIB_THIN_PRISM_MODEL = 0x08000, + CALIB_FIX_S1_S2_S3_S4 = 0x10000, + CALIB_TILTED_MODEL = 0x40000, + CALIB_FIX_TAUX_TAUY = 0x80000, + CALIB_USE_QR = 0x100000, + CALIB_FIX_TANGENT_DIST = 0x200000, + CALIB_FIX_INTRINSIC = 0x00100, + CALIB_SAME_FOCAL_LENGTH = 0x00200, + CALIB_ZERO_DISPARITY = 0x00400, + CALIB_USE_LU = (1 << 17), + CALIB_USE_EXTRINSIC_GUESS = (1 << 22), + FM_7POINT = 1, + FM_8POINT = 2, + FM_LMEDS = 4, + FM_RANSAC = 8, + fisheye_CALIB_USE_INTRINSIC_GUESS = 1 << 0, + fisheye_CALIB_RECOMPUTE_EXTRINSIC = 1 << 1, + fisheye_CALIB_CHECK_COND = 1 << 2, + fisheye_CALIB_FIX_SKEW = 1 << 3, + fisheye_CALIB_FIX_K1 = 1 << 4, + fisheye_CALIB_FIX_K2 = 1 << 5, + fisheye_CALIB_FIX_K3 = 1 << 6, + fisheye_CALIB_FIX_K4 = 1 << 7, + fisheye_CALIB_FIX_INTRINSIC = 1 << 8, + fisheye_CALIB_FIX_PRINCIPAL_POINT = 1 << 9; + + + // C++: enum UndistortTypes + public static final int + PROJ_SPHERICAL_ORTHO = 0, + PROJ_SPHERICAL_EQRECT = 1; + + + // C++: enum SolvePnPMethod + public static final int + SOLVEPNP_ITERATIVE = 0, + SOLVEPNP_EPNP = 1, + SOLVEPNP_P3P = 2, + SOLVEPNP_DLS = 3, + SOLVEPNP_UPNP = 4, + SOLVEPNP_AP3P = 5, + SOLVEPNP_IPPE = 6, + SOLVEPNP_IPPE_SQUARE = 7, + SOLVEPNP_MAX_COUNT = 7+1; + + + // C++: enum HandEyeCalibrationMethod + public static final int + CALIB_HAND_EYE_TSAI = 0, + CALIB_HAND_EYE_PARK = 1, + CALIB_HAND_EYE_HORAUD = 2, + CALIB_HAND_EYE_ANDREFF = 3, + CALIB_HAND_EYE_DANIILIDIS = 4; + + + // C++: enum GridType + public static final int + CirclesGridFinderParameters_SYMMETRIC_GRID = 0, + CirclesGridFinderParameters_ASYMMETRIC_GRID = 1; + + + // + // C++: Mat cv::estimateAffine2D(Mat from, Mat to, Mat& inliers = Mat(), int method = RANSAC, double ransacReprojThreshold = 3, size_t maxIters = 2000, double confidence = 0.99, size_t refineIters = 10) + // + + //javadoc: estimateAffine2D(from, to, inliers, method, ransacReprojThreshold, maxIters, confidence, refineIters) + public static Mat estimateAffine2D(Mat from, Mat to, Mat inliers, int method, double ransacReprojThreshold, long maxIters, double confidence, long refineIters) + { + + Mat retVal = new Mat(estimateAffine2D_0(from.nativeObj, to.nativeObj, inliers.nativeObj, method, ransacReprojThreshold, maxIters, confidence, refineIters)); + + return retVal; + } + + //javadoc: estimateAffine2D(from, to, inliers, method, ransacReprojThreshold, maxIters, confidence) + public static Mat estimateAffine2D(Mat from, Mat to, Mat inliers, int method, double ransacReprojThreshold, long maxIters, double confidence) + { + + Mat retVal = new Mat(estimateAffine2D_1(from.nativeObj, to.nativeObj, inliers.nativeObj, method, ransacReprojThreshold, maxIters, confidence)); + + return retVal; + } + + //javadoc: estimateAffine2D(from, to, inliers, method, ransacReprojThreshold, maxIters) + public static Mat estimateAffine2D(Mat from, Mat to, Mat inliers, int method, double ransacReprojThreshold, long maxIters) + { + + Mat retVal = new Mat(estimateAffine2D_2(from.nativeObj, to.nativeObj, inliers.nativeObj, method, ransacReprojThreshold, maxIters)); + + return retVal; + } + + //javadoc: estimateAffine2D(from, to, inliers, method, ransacReprojThreshold) + public static Mat estimateAffine2D(Mat from, Mat to, Mat inliers, int method, double ransacReprojThreshold) + { + + Mat retVal = new Mat(estimateAffine2D_3(from.nativeObj, to.nativeObj, inliers.nativeObj, method, ransacReprojThreshold)); + + return retVal; + } + + //javadoc: estimateAffine2D(from, to, inliers, method) + public static Mat estimateAffine2D(Mat from, Mat to, Mat inliers, int method) + { + + Mat retVal = new Mat(estimateAffine2D_4(from.nativeObj, to.nativeObj, inliers.nativeObj, method)); + + return retVal; + } + + //javadoc: estimateAffine2D(from, to, inliers) + public static Mat estimateAffine2D(Mat from, Mat to, Mat inliers) + { + + Mat retVal = new Mat(estimateAffine2D_5(from.nativeObj, to.nativeObj, inliers.nativeObj)); + + return retVal; + } + + //javadoc: estimateAffine2D(from, to) + public static Mat estimateAffine2D(Mat from, Mat to) + { + + Mat retVal = new Mat(estimateAffine2D_6(from.nativeObj, to.nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::estimateAffinePartial2D(Mat from, Mat to, Mat& inliers = Mat(), int method = RANSAC, double ransacReprojThreshold = 3, size_t maxIters = 2000, double confidence = 0.99, size_t refineIters = 10) + // + + //javadoc: estimateAffinePartial2D(from, to, inliers, method, ransacReprojThreshold, maxIters, confidence, refineIters) + public static Mat estimateAffinePartial2D(Mat from, Mat to, Mat inliers, int method, double ransacReprojThreshold, long maxIters, double confidence, long refineIters) + { + + Mat retVal = new Mat(estimateAffinePartial2D_0(from.nativeObj, to.nativeObj, inliers.nativeObj, method, ransacReprojThreshold, maxIters, confidence, refineIters)); + + return retVal; + } + + //javadoc: estimateAffinePartial2D(from, to, inliers, method, ransacReprojThreshold, maxIters, confidence) + public static Mat estimateAffinePartial2D(Mat from, Mat to, Mat inliers, int method, double ransacReprojThreshold, long maxIters, double confidence) + { + + Mat retVal = new Mat(estimateAffinePartial2D_1(from.nativeObj, to.nativeObj, inliers.nativeObj, method, ransacReprojThreshold, maxIters, confidence)); + + return retVal; + } + + //javadoc: estimateAffinePartial2D(from, to, inliers, method, ransacReprojThreshold, maxIters) + public static Mat estimateAffinePartial2D(Mat from, Mat to, Mat inliers, int method, double ransacReprojThreshold, long maxIters) + { + + Mat retVal = new Mat(estimateAffinePartial2D_2(from.nativeObj, to.nativeObj, inliers.nativeObj, method, ransacReprojThreshold, maxIters)); + + return retVal; + } + + //javadoc: estimateAffinePartial2D(from, to, inliers, method, ransacReprojThreshold) + public static Mat estimateAffinePartial2D(Mat from, Mat to, Mat inliers, int method, double ransacReprojThreshold) + { + + Mat retVal = new Mat(estimateAffinePartial2D_3(from.nativeObj, to.nativeObj, inliers.nativeObj, method, ransacReprojThreshold)); + + return retVal; + } + + //javadoc: estimateAffinePartial2D(from, to, inliers, method) + public static Mat estimateAffinePartial2D(Mat from, Mat to, Mat inliers, int method) + { + + Mat retVal = new Mat(estimateAffinePartial2D_4(from.nativeObj, to.nativeObj, inliers.nativeObj, method)); + + return retVal; + } + + //javadoc: estimateAffinePartial2D(from, to, inliers) + public static Mat estimateAffinePartial2D(Mat from, Mat to, Mat inliers) + { + + Mat retVal = new Mat(estimateAffinePartial2D_5(from.nativeObj, to.nativeObj, inliers.nativeObj)); + + return retVal; + } + + //javadoc: estimateAffinePartial2D(from, to) + public static Mat estimateAffinePartial2D(Mat from, Mat to) + { + + Mat retVal = new Mat(estimateAffinePartial2D_6(from.nativeObj, to.nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::findEssentialMat(Mat points1, Mat points2, Mat cameraMatrix, int method = RANSAC, double prob = 0.999, double threshold = 1.0, Mat& mask = Mat()) + // + + //javadoc: findEssentialMat(points1, points2, cameraMatrix, method, prob, threshold, mask) + public static Mat findEssentialMat(Mat points1, Mat points2, Mat cameraMatrix, int method, double prob, double threshold, Mat mask) + { + + Mat retVal = new Mat(findEssentialMat_0(points1.nativeObj, points2.nativeObj, cameraMatrix.nativeObj, method, prob, threshold, mask.nativeObj)); + + return retVal; + } + + //javadoc: findEssentialMat(points1, points2, cameraMatrix, method, prob, threshold) + public static Mat findEssentialMat(Mat points1, Mat points2, Mat cameraMatrix, int method, double prob, double threshold) + { + + Mat retVal = new Mat(findEssentialMat_1(points1.nativeObj, points2.nativeObj, cameraMatrix.nativeObj, method, prob, threshold)); + + return retVal; + } + + //javadoc: findEssentialMat(points1, points2, cameraMatrix, method, prob) + public static Mat findEssentialMat(Mat points1, Mat points2, Mat cameraMatrix, int method, double prob) + { + + Mat retVal = new Mat(findEssentialMat_2(points1.nativeObj, points2.nativeObj, cameraMatrix.nativeObj, method, prob)); + + return retVal; + } + + //javadoc: findEssentialMat(points1, points2, cameraMatrix, method) + public static Mat findEssentialMat(Mat points1, Mat points2, Mat cameraMatrix, int method) + { + + Mat retVal = new Mat(findEssentialMat_3(points1.nativeObj, points2.nativeObj, cameraMatrix.nativeObj, method)); + + return retVal; + } + + //javadoc: findEssentialMat(points1, points2, cameraMatrix) + public static Mat findEssentialMat(Mat points1, Mat points2, Mat cameraMatrix) + { + + Mat retVal = new Mat(findEssentialMat_4(points1.nativeObj, points2.nativeObj, cameraMatrix.nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::findEssentialMat(Mat points1, Mat points2, double focal = 1.0, Point2d pp = Point2d(0, 0), int method = RANSAC, double prob = 0.999, double threshold = 1.0, Mat& mask = Mat()) + // + + //javadoc: findEssentialMat(points1, points2, focal, pp, method, prob, threshold, mask) + public static Mat findEssentialMat(Mat points1, Mat points2, double focal, Point pp, int method, double prob, double threshold, Mat mask) + { + + Mat retVal = new Mat(findEssentialMat_5(points1.nativeObj, points2.nativeObj, focal, pp.x, pp.y, method, prob, threshold, mask.nativeObj)); + + return retVal; + } + + //javadoc: findEssentialMat(points1, points2, focal, pp, method, prob, threshold) + public static Mat findEssentialMat(Mat points1, Mat points2, double focal, Point pp, int method, double prob, double threshold) + { + + Mat retVal = new Mat(findEssentialMat_6(points1.nativeObj, points2.nativeObj, focal, pp.x, pp.y, method, prob, threshold)); + + return retVal; + } + + //javadoc: findEssentialMat(points1, points2, focal, pp, method, prob) + public static Mat findEssentialMat(Mat points1, Mat points2, double focal, Point pp, int method, double prob) + { + + Mat retVal = new Mat(findEssentialMat_7(points1.nativeObj, points2.nativeObj, focal, pp.x, pp.y, method, prob)); + + return retVal; + } + + //javadoc: findEssentialMat(points1, points2, focal, pp, method) + public static Mat findEssentialMat(Mat points1, Mat points2, double focal, Point pp, int method) + { + + Mat retVal = new Mat(findEssentialMat_8(points1.nativeObj, points2.nativeObj, focal, pp.x, pp.y, method)); + + return retVal; + } + + //javadoc: findEssentialMat(points1, points2, focal, pp) + public static Mat findEssentialMat(Mat points1, Mat points2, double focal, Point pp) + { + + Mat retVal = new Mat(findEssentialMat_9(points1.nativeObj, points2.nativeObj, focal, pp.x, pp.y)); + + return retVal; + } + + //javadoc: findEssentialMat(points1, points2, focal) + public static Mat findEssentialMat(Mat points1, Mat points2, double focal) + { + + Mat retVal = new Mat(findEssentialMat_10(points1.nativeObj, points2.nativeObj, focal)); + + return retVal; + } + + //javadoc: findEssentialMat(points1, points2) + public static Mat findEssentialMat(Mat points1, Mat points2) + { + + Mat retVal = new Mat(findEssentialMat_11(points1.nativeObj, points2.nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::findFundamentalMat(vector_Point2f points1, vector_Point2f points2, int method = FM_RANSAC, double ransacReprojThreshold = 3., double confidence = 0.99, Mat& mask = Mat()) + // + + //javadoc: findFundamentalMat(points1, points2, method, ransacReprojThreshold, confidence, mask) + public static Mat findFundamentalMat(MatOfPoint2f points1, MatOfPoint2f points2, int method, double ransacReprojThreshold, double confidence, Mat mask) + { + Mat points1_mat = points1; + Mat points2_mat = points2; + Mat retVal = new Mat(findFundamentalMat_0(points1_mat.nativeObj, points2_mat.nativeObj, method, ransacReprojThreshold, confidence, mask.nativeObj)); + + return retVal; + } + + //javadoc: findFundamentalMat(points1, points2, method, ransacReprojThreshold, confidence) + public static Mat findFundamentalMat(MatOfPoint2f points1, MatOfPoint2f points2, int method, double ransacReprojThreshold, double confidence) + { + Mat points1_mat = points1; + Mat points2_mat = points2; + Mat retVal = new Mat(findFundamentalMat_1(points1_mat.nativeObj, points2_mat.nativeObj, method, ransacReprojThreshold, confidence)); + + return retVal; + } + + //javadoc: findFundamentalMat(points1, points2, method, ransacReprojThreshold) + public static Mat findFundamentalMat(MatOfPoint2f points1, MatOfPoint2f points2, int method, double ransacReprojThreshold) + { + Mat points1_mat = points1; + Mat points2_mat = points2; + Mat retVal = new Mat(findFundamentalMat_2(points1_mat.nativeObj, points2_mat.nativeObj, method, ransacReprojThreshold)); + + return retVal; + } + + //javadoc: findFundamentalMat(points1, points2, method) + public static Mat findFundamentalMat(MatOfPoint2f points1, MatOfPoint2f points2, int method) + { + Mat points1_mat = points1; + Mat points2_mat = points2; + Mat retVal = new Mat(findFundamentalMat_3(points1_mat.nativeObj, points2_mat.nativeObj, method)); + + return retVal; + } + + //javadoc: findFundamentalMat(points1, points2) + public static Mat findFundamentalMat(MatOfPoint2f points1, MatOfPoint2f points2) + { + Mat points1_mat = points1; + Mat points2_mat = points2; + Mat retVal = new Mat(findFundamentalMat_4(points1_mat.nativeObj, points2_mat.nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::findHomography(vector_Point2f srcPoints, vector_Point2f dstPoints, int method = 0, double ransacReprojThreshold = 3, Mat& mask = Mat(), int maxIters = 2000, double confidence = 0.995) + // + + //javadoc: findHomography(srcPoints, dstPoints, method, ransacReprojThreshold, mask, maxIters, confidence) + public static Mat findHomography(MatOfPoint2f srcPoints, MatOfPoint2f dstPoints, int method, double ransacReprojThreshold, Mat mask, int maxIters, double confidence) + { + Mat srcPoints_mat = srcPoints; + Mat dstPoints_mat = dstPoints; + Mat retVal = new Mat(findHomography_0(srcPoints_mat.nativeObj, dstPoints_mat.nativeObj, method, ransacReprojThreshold, mask.nativeObj, maxIters, confidence)); + + return retVal; + } + + //javadoc: findHomography(srcPoints, dstPoints, method, ransacReprojThreshold, mask, maxIters) + public static Mat findHomography(MatOfPoint2f srcPoints, MatOfPoint2f dstPoints, int method, double ransacReprojThreshold, Mat mask, int maxIters) + { + Mat srcPoints_mat = srcPoints; + Mat dstPoints_mat = dstPoints; + Mat retVal = new Mat(findHomography_1(srcPoints_mat.nativeObj, dstPoints_mat.nativeObj, method, ransacReprojThreshold, mask.nativeObj, maxIters)); + + return retVal; + } + + //javadoc: findHomography(srcPoints, dstPoints, method, ransacReprojThreshold, mask) + public static Mat findHomography(MatOfPoint2f srcPoints, MatOfPoint2f dstPoints, int method, double ransacReprojThreshold, Mat mask) + { + Mat srcPoints_mat = srcPoints; + Mat dstPoints_mat = dstPoints; + Mat retVal = new Mat(findHomography_2(srcPoints_mat.nativeObj, dstPoints_mat.nativeObj, method, ransacReprojThreshold, mask.nativeObj)); + + return retVal; + } + + //javadoc: findHomography(srcPoints, dstPoints, method, ransacReprojThreshold) + public static Mat findHomography(MatOfPoint2f srcPoints, MatOfPoint2f dstPoints, int method, double ransacReprojThreshold) + { + Mat srcPoints_mat = srcPoints; + Mat dstPoints_mat = dstPoints; + Mat retVal = new Mat(findHomography_3(srcPoints_mat.nativeObj, dstPoints_mat.nativeObj, method, ransacReprojThreshold)); + + return retVal; + } + + //javadoc: findHomography(srcPoints, dstPoints, method) + public static Mat findHomography(MatOfPoint2f srcPoints, MatOfPoint2f dstPoints, int method) + { + Mat srcPoints_mat = srcPoints; + Mat dstPoints_mat = dstPoints; + Mat retVal = new Mat(findHomography_4(srcPoints_mat.nativeObj, dstPoints_mat.nativeObj, method)); + + return retVal; + } + + //javadoc: findHomography(srcPoints, dstPoints) + public static Mat findHomography(MatOfPoint2f srcPoints, MatOfPoint2f dstPoints) + { + Mat srcPoints_mat = srcPoints; + Mat dstPoints_mat = dstPoints; + Mat retVal = new Mat(findHomography_5(srcPoints_mat.nativeObj, dstPoints_mat.nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::getDefaultNewCameraMatrix(Mat cameraMatrix, Size imgsize = Size(), bool centerPrincipalPoint = false) + // + + //javadoc: getDefaultNewCameraMatrix(cameraMatrix, imgsize, centerPrincipalPoint) + public static Mat getDefaultNewCameraMatrix(Mat cameraMatrix, Size imgsize, boolean centerPrincipalPoint) + { + + Mat retVal = new Mat(getDefaultNewCameraMatrix_0(cameraMatrix.nativeObj, imgsize.width, imgsize.height, centerPrincipalPoint)); + + return retVal; + } + + //javadoc: getDefaultNewCameraMatrix(cameraMatrix, imgsize) + public static Mat getDefaultNewCameraMatrix(Mat cameraMatrix, Size imgsize) + { + + Mat retVal = new Mat(getDefaultNewCameraMatrix_1(cameraMatrix.nativeObj, imgsize.width, imgsize.height)); + + return retVal; + } + + //javadoc: getDefaultNewCameraMatrix(cameraMatrix) + public static Mat getDefaultNewCameraMatrix(Mat cameraMatrix) + { + + Mat retVal = new Mat(getDefaultNewCameraMatrix_2(cameraMatrix.nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::getOptimalNewCameraMatrix(Mat cameraMatrix, Mat distCoeffs, Size imageSize, double alpha, Size newImgSize = Size(), Rect* validPixROI = 0, bool centerPrincipalPoint = false) + // + + //javadoc: getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, alpha, newImgSize, validPixROI, centerPrincipalPoint) + public static Mat getOptimalNewCameraMatrix(Mat cameraMatrix, Mat distCoeffs, Size imageSize, double alpha, Size newImgSize, Rect validPixROI, boolean centerPrincipalPoint) + { + double[] validPixROI_out = new double[4]; + Mat retVal = new Mat(getOptimalNewCameraMatrix_0(cameraMatrix.nativeObj, distCoeffs.nativeObj, imageSize.width, imageSize.height, alpha, newImgSize.width, newImgSize.height, validPixROI_out, centerPrincipalPoint)); + if(validPixROI!=null){ validPixROI.x = (int)validPixROI_out[0]; validPixROI.y = (int)validPixROI_out[1]; validPixROI.width = (int)validPixROI_out[2]; validPixROI.height = (int)validPixROI_out[3]; } + return retVal; + } + + //javadoc: getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, alpha, newImgSize, validPixROI) + public static Mat getOptimalNewCameraMatrix(Mat cameraMatrix, Mat distCoeffs, Size imageSize, double alpha, Size newImgSize, Rect validPixROI) + { + double[] validPixROI_out = new double[4]; + Mat retVal = new Mat(getOptimalNewCameraMatrix_1(cameraMatrix.nativeObj, distCoeffs.nativeObj, imageSize.width, imageSize.height, alpha, newImgSize.width, newImgSize.height, validPixROI_out)); + if(validPixROI!=null){ validPixROI.x = (int)validPixROI_out[0]; validPixROI.y = (int)validPixROI_out[1]; validPixROI.width = (int)validPixROI_out[2]; validPixROI.height = (int)validPixROI_out[3]; } + return retVal; + } + + //javadoc: getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, alpha, newImgSize) + public static Mat getOptimalNewCameraMatrix(Mat cameraMatrix, Mat distCoeffs, Size imageSize, double alpha, Size newImgSize) + { + + Mat retVal = new Mat(getOptimalNewCameraMatrix_2(cameraMatrix.nativeObj, distCoeffs.nativeObj, imageSize.width, imageSize.height, alpha, newImgSize.width, newImgSize.height)); + + return retVal; + } + + //javadoc: getOptimalNewCameraMatrix(cameraMatrix, distCoeffs, imageSize, alpha) + public static Mat getOptimalNewCameraMatrix(Mat cameraMatrix, Mat distCoeffs, Size imageSize, double alpha) + { + + Mat retVal = new Mat(getOptimalNewCameraMatrix_3(cameraMatrix.nativeObj, distCoeffs.nativeObj, imageSize.width, imageSize.height, alpha)); + + return retVal; + } + + + // + // C++: Mat cv::initCameraMatrix2D(vector_vector_Point3f objectPoints, vector_vector_Point2f imagePoints, Size imageSize, double aspectRatio = 1.0) + // + + //javadoc: initCameraMatrix2D(objectPoints, imagePoints, imageSize, aspectRatio) + public static Mat initCameraMatrix2D(List objectPoints, List imagePoints, Size imageSize, double aspectRatio) + { + List objectPoints_tmplm = new ArrayList((objectPoints != null) ? objectPoints.size() : 0); + Mat objectPoints_mat = Converters.vector_vector_Point3f_to_Mat(objectPoints, objectPoints_tmplm); + List imagePoints_tmplm = new ArrayList((imagePoints != null) ? imagePoints.size() : 0); + Mat imagePoints_mat = Converters.vector_vector_Point2f_to_Mat(imagePoints, imagePoints_tmplm); + Mat retVal = new Mat(initCameraMatrix2D_0(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, imageSize.width, imageSize.height, aspectRatio)); + + return retVal; + } + + //javadoc: initCameraMatrix2D(objectPoints, imagePoints, imageSize) + public static Mat initCameraMatrix2D(List objectPoints, List imagePoints, Size imageSize) + { + List objectPoints_tmplm = new ArrayList((objectPoints != null) ? objectPoints.size() : 0); + Mat objectPoints_mat = Converters.vector_vector_Point3f_to_Mat(objectPoints, objectPoints_tmplm); + List imagePoints_tmplm = new ArrayList((imagePoints != null) ? imagePoints.size() : 0); + Mat imagePoints_mat = Converters.vector_vector_Point2f_to_Mat(imagePoints, imagePoints_tmplm); + Mat retVal = new Mat(initCameraMatrix2D_1(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, imageSize.width, imageSize.height)); + + return retVal; + } + + + // + // C++: Rect cv::getValidDisparityROI(Rect roi1, Rect roi2, int minDisparity, int numberOfDisparities, int SADWindowSize) + // + + //javadoc: getValidDisparityROI(roi1, roi2, minDisparity, numberOfDisparities, SADWindowSize) + public static Rect getValidDisparityROI(Rect roi1, Rect roi2, int minDisparity, int numberOfDisparities, int SADWindowSize) + { + + Rect retVal = new Rect(getValidDisparityROI_0(roi1.x, roi1.y, roi1.width, roi1.height, roi2.x, roi2.y, roi2.width, roi2.height, minDisparity, numberOfDisparities, SADWindowSize)); + + return retVal; + } + + + // + // C++: Vec3d cv::RQDecomp3x3(Mat src, Mat& mtxR, Mat& mtxQ, Mat& Qx = Mat(), Mat& Qy = Mat(), Mat& Qz = Mat()) + // + + //javadoc: RQDecomp3x3(src, mtxR, mtxQ, Qx, Qy, Qz) + public static double[] RQDecomp3x3(Mat src, Mat mtxR, Mat mtxQ, Mat Qx, Mat Qy, Mat Qz) + { + + double[] retVal = RQDecomp3x3_0(src.nativeObj, mtxR.nativeObj, mtxQ.nativeObj, Qx.nativeObj, Qy.nativeObj, Qz.nativeObj); + + return retVal; + } + + //javadoc: RQDecomp3x3(src, mtxR, mtxQ, Qx, Qy) + public static double[] RQDecomp3x3(Mat src, Mat mtxR, Mat mtxQ, Mat Qx, Mat Qy) + { + + double[] retVal = RQDecomp3x3_1(src.nativeObj, mtxR.nativeObj, mtxQ.nativeObj, Qx.nativeObj, Qy.nativeObj); + + return retVal; + } + + //javadoc: RQDecomp3x3(src, mtxR, mtxQ, Qx) + public static double[] RQDecomp3x3(Mat src, Mat mtxR, Mat mtxQ, Mat Qx) + { + + double[] retVal = RQDecomp3x3_2(src.nativeObj, mtxR.nativeObj, mtxQ.nativeObj, Qx.nativeObj); + + return retVal; + } + + //javadoc: RQDecomp3x3(src, mtxR, mtxQ) + public static double[] RQDecomp3x3(Mat src, Mat mtxR, Mat mtxQ) + { + + double[] retVal = RQDecomp3x3_3(src.nativeObj, mtxR.nativeObj, mtxQ.nativeObj); + + return retVal; + } + + + // + // C++: bool cv::checkChessboard(Mat img, Size size) + // + + //javadoc: checkChessboard(img, size) + public static boolean checkChessboard(Mat img, Size size) + { + + boolean retVal = checkChessboard_0(img.nativeObj, size.width, size.height); + + return retVal; + } + + + // + // C++: bool cv::find4QuadCornerSubpix(Mat img, Mat& corners, Size region_size) + // + + //javadoc: find4QuadCornerSubpix(img, corners, region_size) + public static boolean find4QuadCornerSubpix(Mat img, Mat corners, Size region_size) + { + + boolean retVal = find4QuadCornerSubpix_0(img.nativeObj, corners.nativeObj, region_size.width, region_size.height); + + return retVal; + } + + + // + // C++: bool cv::findChessboardCorners(Mat image, Size patternSize, vector_Point2f& corners, int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE) + // + + //javadoc: findChessboardCorners(image, patternSize, corners, flags) + public static boolean findChessboardCorners(Mat image, Size patternSize, MatOfPoint2f corners, int flags) + { + Mat corners_mat = corners; + boolean retVal = findChessboardCorners_0(image.nativeObj, patternSize.width, patternSize.height, corners_mat.nativeObj, flags); + + return retVal; + } + + //javadoc: findChessboardCorners(image, patternSize, corners) + public static boolean findChessboardCorners(Mat image, Size patternSize, MatOfPoint2f corners) + { + Mat corners_mat = corners; + boolean retVal = findChessboardCorners_1(image.nativeObj, patternSize.width, patternSize.height, corners_mat.nativeObj); + + return retVal; + } + + + // + // C++: bool cv::findChessboardCornersSB(Mat image, Size patternSize, Mat& corners, int flags = 0) + // + + //javadoc: findChessboardCornersSB(image, patternSize, corners, flags) + public static boolean findChessboardCornersSB(Mat image, Size patternSize, Mat corners, int flags) + { + + boolean retVal = findChessboardCornersSB_0(image.nativeObj, patternSize.width, patternSize.height, corners.nativeObj, flags); + + return retVal; + } + + //javadoc: findChessboardCornersSB(image, patternSize, corners) + public static boolean findChessboardCornersSB(Mat image, Size patternSize, Mat corners) + { + + boolean retVal = findChessboardCornersSB_1(image.nativeObj, patternSize.width, patternSize.height, corners.nativeObj); + + return retVal; + } + + + // + // C++: bool cv::findCirclesGrid(Mat image, Size patternSize, Mat& centers, int flags, Ptr_FeatureDetector blobDetector, CirclesGridFinderParameters parameters) + // + + // Unknown type 'Ptr_FeatureDetector' (I), skipping the function + + + // + // C++: bool cv::findCirclesGrid(Mat image, Size patternSize, Mat& centers, int flags = CALIB_CB_SYMMETRIC_GRID, Ptr_FeatureDetector blobDetector = SimpleBlobDetector::create()) + // + + //javadoc: findCirclesGrid(image, patternSize, centers, flags) + public static boolean findCirclesGrid(Mat image, Size patternSize, Mat centers, int flags) + { + + boolean retVal = findCirclesGrid_0(image.nativeObj, patternSize.width, patternSize.height, centers.nativeObj, flags); + + return retVal; + } + + //javadoc: findCirclesGrid(image, patternSize, centers) + public static boolean findCirclesGrid(Mat image, Size patternSize, Mat centers) + { + + boolean retVal = findCirclesGrid_2(image.nativeObj, patternSize.width, patternSize.height, centers.nativeObj); + + return retVal; + } + + + // + // C++: bool cv::solvePnP(vector_Point3f objectPoints, vector_Point2f imagePoints, Mat cameraMatrix, vector_double distCoeffs, Mat& rvec, Mat& tvec, bool useExtrinsicGuess = false, int flags = SOLVEPNP_ITERATIVE) + // + + //javadoc: solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec, useExtrinsicGuess, flags) + public static boolean solvePnP(MatOfPoint3f objectPoints, MatOfPoint2f imagePoints, Mat cameraMatrix, MatOfDouble distCoeffs, Mat rvec, Mat tvec, boolean useExtrinsicGuess, int flags) + { + Mat objectPoints_mat = objectPoints; + Mat imagePoints_mat = imagePoints; + Mat distCoeffs_mat = distCoeffs; + boolean retVal = solvePnP_0(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, cameraMatrix.nativeObj, distCoeffs_mat.nativeObj, rvec.nativeObj, tvec.nativeObj, useExtrinsicGuess, flags); + + return retVal; + } + + //javadoc: solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec, useExtrinsicGuess) + public static boolean solvePnP(MatOfPoint3f objectPoints, MatOfPoint2f imagePoints, Mat cameraMatrix, MatOfDouble distCoeffs, Mat rvec, Mat tvec, boolean useExtrinsicGuess) + { + Mat objectPoints_mat = objectPoints; + Mat imagePoints_mat = imagePoints; + Mat distCoeffs_mat = distCoeffs; + boolean retVal = solvePnP_1(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, cameraMatrix.nativeObj, distCoeffs_mat.nativeObj, rvec.nativeObj, tvec.nativeObj, useExtrinsicGuess); + + return retVal; + } + + //javadoc: solvePnP(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec) + public static boolean solvePnP(MatOfPoint3f objectPoints, MatOfPoint2f imagePoints, Mat cameraMatrix, MatOfDouble distCoeffs, Mat rvec, Mat tvec) + { + Mat objectPoints_mat = objectPoints; + Mat imagePoints_mat = imagePoints; + Mat distCoeffs_mat = distCoeffs; + boolean retVal = solvePnP_2(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, cameraMatrix.nativeObj, distCoeffs_mat.nativeObj, rvec.nativeObj, tvec.nativeObj); + + return retVal; + } + + + // + // C++: bool cv::solvePnPRansac(vector_Point3f objectPoints, vector_Point2f imagePoints, Mat cameraMatrix, vector_double distCoeffs, Mat& rvec, Mat& tvec, bool useExtrinsicGuess = false, int iterationsCount = 100, float reprojectionError = 8.0, double confidence = 0.99, Mat& inliers = Mat(), int flags = SOLVEPNP_ITERATIVE) + // + + //javadoc: solvePnPRansac(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec, useExtrinsicGuess, iterationsCount, reprojectionError, confidence, inliers, flags) + public static boolean solvePnPRansac(MatOfPoint3f objectPoints, MatOfPoint2f imagePoints, Mat cameraMatrix, MatOfDouble distCoeffs, Mat rvec, Mat tvec, boolean useExtrinsicGuess, int iterationsCount, float reprojectionError, double confidence, Mat inliers, int flags) + { + Mat objectPoints_mat = objectPoints; + Mat imagePoints_mat = imagePoints; + Mat distCoeffs_mat = distCoeffs; + boolean retVal = solvePnPRansac_0(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, cameraMatrix.nativeObj, distCoeffs_mat.nativeObj, rvec.nativeObj, tvec.nativeObj, useExtrinsicGuess, iterationsCount, reprojectionError, confidence, inliers.nativeObj, flags); + + return retVal; + } + + //javadoc: solvePnPRansac(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec, useExtrinsicGuess, iterationsCount, reprojectionError, confidence, inliers) + public static boolean solvePnPRansac(MatOfPoint3f objectPoints, MatOfPoint2f imagePoints, Mat cameraMatrix, MatOfDouble distCoeffs, Mat rvec, Mat tvec, boolean useExtrinsicGuess, int iterationsCount, float reprojectionError, double confidence, Mat inliers) + { + Mat objectPoints_mat = objectPoints; + Mat imagePoints_mat = imagePoints; + Mat distCoeffs_mat = distCoeffs; + boolean retVal = solvePnPRansac_1(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, cameraMatrix.nativeObj, distCoeffs_mat.nativeObj, rvec.nativeObj, tvec.nativeObj, useExtrinsicGuess, iterationsCount, reprojectionError, confidence, inliers.nativeObj); + + return retVal; + } + + //javadoc: solvePnPRansac(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec, useExtrinsicGuess, iterationsCount, reprojectionError, confidence) + public static boolean solvePnPRansac(MatOfPoint3f objectPoints, MatOfPoint2f imagePoints, Mat cameraMatrix, MatOfDouble distCoeffs, Mat rvec, Mat tvec, boolean useExtrinsicGuess, int iterationsCount, float reprojectionError, double confidence) + { + Mat objectPoints_mat = objectPoints; + Mat imagePoints_mat = imagePoints; + Mat distCoeffs_mat = distCoeffs; + boolean retVal = solvePnPRansac_2(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, cameraMatrix.nativeObj, distCoeffs_mat.nativeObj, rvec.nativeObj, tvec.nativeObj, useExtrinsicGuess, iterationsCount, reprojectionError, confidence); + + return retVal; + } + + //javadoc: solvePnPRansac(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec, useExtrinsicGuess, iterationsCount, reprojectionError) + public static boolean solvePnPRansac(MatOfPoint3f objectPoints, MatOfPoint2f imagePoints, Mat cameraMatrix, MatOfDouble distCoeffs, Mat rvec, Mat tvec, boolean useExtrinsicGuess, int iterationsCount, float reprojectionError) + { + Mat objectPoints_mat = objectPoints; + Mat imagePoints_mat = imagePoints; + Mat distCoeffs_mat = distCoeffs; + boolean retVal = solvePnPRansac_3(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, cameraMatrix.nativeObj, distCoeffs_mat.nativeObj, rvec.nativeObj, tvec.nativeObj, useExtrinsicGuess, iterationsCount, reprojectionError); + + return retVal; + } + + //javadoc: solvePnPRansac(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec, useExtrinsicGuess, iterationsCount) + public static boolean solvePnPRansac(MatOfPoint3f objectPoints, MatOfPoint2f imagePoints, Mat cameraMatrix, MatOfDouble distCoeffs, Mat rvec, Mat tvec, boolean useExtrinsicGuess, int iterationsCount) + { + Mat objectPoints_mat = objectPoints; + Mat imagePoints_mat = imagePoints; + Mat distCoeffs_mat = distCoeffs; + boolean retVal = solvePnPRansac_4(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, cameraMatrix.nativeObj, distCoeffs_mat.nativeObj, rvec.nativeObj, tvec.nativeObj, useExtrinsicGuess, iterationsCount); + + return retVal; + } + + //javadoc: solvePnPRansac(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec, useExtrinsicGuess) + public static boolean solvePnPRansac(MatOfPoint3f objectPoints, MatOfPoint2f imagePoints, Mat cameraMatrix, MatOfDouble distCoeffs, Mat rvec, Mat tvec, boolean useExtrinsicGuess) + { + Mat objectPoints_mat = objectPoints; + Mat imagePoints_mat = imagePoints; + Mat distCoeffs_mat = distCoeffs; + boolean retVal = solvePnPRansac_5(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, cameraMatrix.nativeObj, distCoeffs_mat.nativeObj, rvec.nativeObj, tvec.nativeObj, useExtrinsicGuess); + + return retVal; + } + + //javadoc: solvePnPRansac(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec) + public static boolean solvePnPRansac(MatOfPoint3f objectPoints, MatOfPoint2f imagePoints, Mat cameraMatrix, MatOfDouble distCoeffs, Mat rvec, Mat tvec) + { + Mat objectPoints_mat = objectPoints; + Mat imagePoints_mat = imagePoints; + Mat distCoeffs_mat = distCoeffs; + boolean retVal = solvePnPRansac_6(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, cameraMatrix.nativeObj, distCoeffs_mat.nativeObj, rvec.nativeObj, tvec.nativeObj); + + return retVal; + } + + + // + // C++: bool cv::stereoRectifyUncalibrated(Mat points1, Mat points2, Mat F, Size imgSize, Mat& H1, Mat& H2, double threshold = 5) + // + + //javadoc: stereoRectifyUncalibrated(points1, points2, F, imgSize, H1, H2, threshold) + public static boolean stereoRectifyUncalibrated(Mat points1, Mat points2, Mat F, Size imgSize, Mat H1, Mat H2, double threshold) + { + + boolean retVal = stereoRectifyUncalibrated_0(points1.nativeObj, points2.nativeObj, F.nativeObj, imgSize.width, imgSize.height, H1.nativeObj, H2.nativeObj, threshold); + + return retVal; + } + + //javadoc: stereoRectifyUncalibrated(points1, points2, F, imgSize, H1, H2) + public static boolean stereoRectifyUncalibrated(Mat points1, Mat points2, Mat F, Size imgSize, Mat H1, Mat H2) + { + + boolean retVal = stereoRectifyUncalibrated_1(points1.nativeObj, points2.nativeObj, F.nativeObj, imgSize.width, imgSize.height, H1.nativeObj, H2.nativeObj); + + return retVal; + } + + + // + // C++: double cv::calibrateCamera(vector_Mat objectPoints, vector_Mat imagePoints, Size imageSize, Mat& cameraMatrix, Mat& distCoeffs, vector_Mat& rvecs, vector_Mat& tvecs, Mat& stdDeviationsIntrinsics, Mat& stdDeviationsExtrinsics, Mat& perViewErrors, int flags = 0, TermCriteria criteria = TermCriteria( TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)) + // + + //javadoc: calibrateCameraExtended(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, stdDeviationsIntrinsics, stdDeviationsExtrinsics, perViewErrors, flags, criteria) + public static double calibrateCameraExtended(List objectPoints, List imagePoints, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, Mat stdDeviationsIntrinsics, Mat stdDeviationsExtrinsics, Mat perViewErrors, int flags, TermCriteria criteria) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints_mat = Converters.vector_Mat_to_Mat(imagePoints); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraExtended_0(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, stdDeviationsIntrinsics.nativeObj, stdDeviationsExtrinsics.nativeObj, perViewErrors.nativeObj, flags, criteria.type, criteria.maxCount, criteria.epsilon); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCameraExtended(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, stdDeviationsIntrinsics, stdDeviationsExtrinsics, perViewErrors, flags) + public static double calibrateCameraExtended(List objectPoints, List imagePoints, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, Mat stdDeviationsIntrinsics, Mat stdDeviationsExtrinsics, Mat perViewErrors, int flags) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints_mat = Converters.vector_Mat_to_Mat(imagePoints); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraExtended_1(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, stdDeviationsIntrinsics.nativeObj, stdDeviationsExtrinsics.nativeObj, perViewErrors.nativeObj, flags); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCameraExtended(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, stdDeviationsIntrinsics, stdDeviationsExtrinsics, perViewErrors) + public static double calibrateCameraExtended(List objectPoints, List imagePoints, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, Mat stdDeviationsIntrinsics, Mat stdDeviationsExtrinsics, Mat perViewErrors) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints_mat = Converters.vector_Mat_to_Mat(imagePoints); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraExtended_2(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, stdDeviationsIntrinsics.nativeObj, stdDeviationsExtrinsics.nativeObj, perViewErrors.nativeObj); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + + // + // C++: double cv::calibrateCamera(vector_Mat objectPoints, vector_Mat imagePoints, Size imageSize, Mat& cameraMatrix, Mat& distCoeffs, vector_Mat& rvecs, vector_Mat& tvecs, int flags = 0, TermCriteria criteria = TermCriteria( TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)) + // + + //javadoc: calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, flags, criteria) + public static double calibrateCamera(List objectPoints, List imagePoints, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, int flags, TermCriteria criteria) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints_mat = Converters.vector_Mat_to_Mat(imagePoints); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCamera_0(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, flags, criteria.type, criteria.maxCount, criteria.epsilon); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs, flags) + public static double calibrateCamera(List objectPoints, List imagePoints, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, int flags) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints_mat = Converters.vector_Mat_to_Mat(imagePoints); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCamera_1(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, flags); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCamera(objectPoints, imagePoints, imageSize, cameraMatrix, distCoeffs, rvecs, tvecs) + public static double calibrateCamera(List objectPoints, List imagePoints, Size imageSize, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints_mat = Converters.vector_Mat_to_Mat(imagePoints); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCamera_2(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, imageSize.width, imageSize.height, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + + // + // C++: double cv::calibrateCameraRO(vector_Mat objectPoints, vector_Mat imagePoints, Size imageSize, int iFixedPoint, Mat& cameraMatrix, Mat& distCoeffs, vector_Mat& rvecs, vector_Mat& tvecs, Mat& newObjPoints, Mat& stdDeviationsIntrinsics, Mat& stdDeviationsExtrinsics, Mat& stdDeviationsObjPoints, Mat& perViewErrors, int flags = 0, TermCriteria criteria = TermCriteria( TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)) + // + + //javadoc: calibrateCameraROExtended(objectPoints, imagePoints, imageSize, iFixedPoint, cameraMatrix, distCoeffs, rvecs, tvecs, newObjPoints, stdDeviationsIntrinsics, stdDeviationsExtrinsics, stdDeviationsObjPoints, perViewErrors, flags, criteria) + public static double calibrateCameraROExtended(List objectPoints, List imagePoints, Size imageSize, int iFixedPoint, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, Mat newObjPoints, Mat stdDeviationsIntrinsics, Mat stdDeviationsExtrinsics, Mat stdDeviationsObjPoints, Mat perViewErrors, int flags, TermCriteria criteria) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints_mat = Converters.vector_Mat_to_Mat(imagePoints); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraROExtended_0(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, imageSize.width, imageSize.height, iFixedPoint, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, newObjPoints.nativeObj, stdDeviationsIntrinsics.nativeObj, stdDeviationsExtrinsics.nativeObj, stdDeviationsObjPoints.nativeObj, perViewErrors.nativeObj, flags, criteria.type, criteria.maxCount, criteria.epsilon); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCameraROExtended(objectPoints, imagePoints, imageSize, iFixedPoint, cameraMatrix, distCoeffs, rvecs, tvecs, newObjPoints, stdDeviationsIntrinsics, stdDeviationsExtrinsics, stdDeviationsObjPoints, perViewErrors, flags) + public static double calibrateCameraROExtended(List objectPoints, List imagePoints, Size imageSize, int iFixedPoint, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, Mat newObjPoints, Mat stdDeviationsIntrinsics, Mat stdDeviationsExtrinsics, Mat stdDeviationsObjPoints, Mat perViewErrors, int flags) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints_mat = Converters.vector_Mat_to_Mat(imagePoints); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraROExtended_1(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, imageSize.width, imageSize.height, iFixedPoint, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, newObjPoints.nativeObj, stdDeviationsIntrinsics.nativeObj, stdDeviationsExtrinsics.nativeObj, stdDeviationsObjPoints.nativeObj, perViewErrors.nativeObj, flags); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCameraROExtended(objectPoints, imagePoints, imageSize, iFixedPoint, cameraMatrix, distCoeffs, rvecs, tvecs, newObjPoints, stdDeviationsIntrinsics, stdDeviationsExtrinsics, stdDeviationsObjPoints, perViewErrors) + public static double calibrateCameraROExtended(List objectPoints, List imagePoints, Size imageSize, int iFixedPoint, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, Mat newObjPoints, Mat stdDeviationsIntrinsics, Mat stdDeviationsExtrinsics, Mat stdDeviationsObjPoints, Mat perViewErrors) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints_mat = Converters.vector_Mat_to_Mat(imagePoints); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraROExtended_2(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, imageSize.width, imageSize.height, iFixedPoint, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, newObjPoints.nativeObj, stdDeviationsIntrinsics.nativeObj, stdDeviationsExtrinsics.nativeObj, stdDeviationsObjPoints.nativeObj, perViewErrors.nativeObj); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + + // + // C++: double cv::calibrateCameraRO(vector_Mat objectPoints, vector_Mat imagePoints, Size imageSize, int iFixedPoint, Mat& cameraMatrix, Mat& distCoeffs, vector_Mat& rvecs, vector_Mat& tvecs, Mat& newObjPoints, int flags = 0, TermCriteria criteria = TermCriteria( TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)) + // + + //javadoc: calibrateCameraRO(objectPoints, imagePoints, imageSize, iFixedPoint, cameraMatrix, distCoeffs, rvecs, tvecs, newObjPoints, flags, criteria) + public static double calibrateCameraRO(List objectPoints, List imagePoints, Size imageSize, int iFixedPoint, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, Mat newObjPoints, int flags, TermCriteria criteria) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints_mat = Converters.vector_Mat_to_Mat(imagePoints); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraRO_0(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, imageSize.width, imageSize.height, iFixedPoint, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, newObjPoints.nativeObj, flags, criteria.type, criteria.maxCount, criteria.epsilon); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCameraRO(objectPoints, imagePoints, imageSize, iFixedPoint, cameraMatrix, distCoeffs, rvecs, tvecs, newObjPoints, flags) + public static double calibrateCameraRO(List objectPoints, List imagePoints, Size imageSize, int iFixedPoint, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, Mat newObjPoints, int flags) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints_mat = Converters.vector_Mat_to_Mat(imagePoints); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraRO_1(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, imageSize.width, imageSize.height, iFixedPoint, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, newObjPoints.nativeObj, flags); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: calibrateCameraRO(objectPoints, imagePoints, imageSize, iFixedPoint, cameraMatrix, distCoeffs, rvecs, tvecs, newObjPoints) + public static double calibrateCameraRO(List objectPoints, List imagePoints, Size imageSize, int iFixedPoint, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, Mat newObjPoints) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints_mat = Converters.vector_Mat_to_Mat(imagePoints); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = calibrateCameraRO_2(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, imageSize.width, imageSize.height, iFixedPoint, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, newObjPoints.nativeObj); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + + // + // C++: double cv::sampsonDistance(Mat pt1, Mat pt2, Mat F) + // + + //javadoc: sampsonDistance(pt1, pt2, F) + public static double sampsonDistance(Mat pt1, Mat pt2, Mat F) + { + + double retVal = sampsonDistance_0(pt1.nativeObj, pt2.nativeObj, F.nativeObj); + + return retVal; + } + + + // + // C++: double cv::stereoCalibrate(vector_Mat objectPoints, vector_Mat imagePoints1, vector_Mat imagePoints2, Mat& cameraMatrix1, Mat& distCoeffs1, Mat& cameraMatrix2, Mat& distCoeffs2, Size imageSize, Mat& R, Mat& T, Mat& E, Mat& F, Mat& perViewErrors, int flags = CALIB_FIX_INTRINSIC, TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 1e-6)) + // + + //javadoc: stereoCalibrateExtended(objectPoints, imagePoints1, imagePoints2, cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, R, T, E, F, perViewErrors, flags, criteria) + public static double stereoCalibrateExtended(List objectPoints, List imagePoints1, List imagePoints2, Mat cameraMatrix1, Mat distCoeffs1, Mat cameraMatrix2, Mat distCoeffs2, Size imageSize, Mat R, Mat T, Mat E, Mat F, Mat perViewErrors, int flags, TermCriteria criteria) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints1_mat = Converters.vector_Mat_to_Mat(imagePoints1); + Mat imagePoints2_mat = Converters.vector_Mat_to_Mat(imagePoints2); + double retVal = stereoCalibrateExtended_0(objectPoints_mat.nativeObj, imagePoints1_mat.nativeObj, imagePoints2_mat.nativeObj, cameraMatrix1.nativeObj, distCoeffs1.nativeObj, cameraMatrix2.nativeObj, distCoeffs2.nativeObj, imageSize.width, imageSize.height, R.nativeObj, T.nativeObj, E.nativeObj, F.nativeObj, perViewErrors.nativeObj, flags, criteria.type, criteria.maxCount, criteria.epsilon); + + return retVal; + } + + //javadoc: stereoCalibrateExtended(objectPoints, imagePoints1, imagePoints2, cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, R, T, E, F, perViewErrors, flags) + public static double stereoCalibrateExtended(List objectPoints, List imagePoints1, List imagePoints2, Mat cameraMatrix1, Mat distCoeffs1, Mat cameraMatrix2, Mat distCoeffs2, Size imageSize, Mat R, Mat T, Mat E, Mat F, Mat perViewErrors, int flags) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints1_mat = Converters.vector_Mat_to_Mat(imagePoints1); + Mat imagePoints2_mat = Converters.vector_Mat_to_Mat(imagePoints2); + double retVal = stereoCalibrateExtended_1(objectPoints_mat.nativeObj, imagePoints1_mat.nativeObj, imagePoints2_mat.nativeObj, cameraMatrix1.nativeObj, distCoeffs1.nativeObj, cameraMatrix2.nativeObj, distCoeffs2.nativeObj, imageSize.width, imageSize.height, R.nativeObj, T.nativeObj, E.nativeObj, F.nativeObj, perViewErrors.nativeObj, flags); + + return retVal; + } + + //javadoc: stereoCalibrateExtended(objectPoints, imagePoints1, imagePoints2, cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, R, T, E, F, perViewErrors) + public static double stereoCalibrateExtended(List objectPoints, List imagePoints1, List imagePoints2, Mat cameraMatrix1, Mat distCoeffs1, Mat cameraMatrix2, Mat distCoeffs2, Size imageSize, Mat R, Mat T, Mat E, Mat F, Mat perViewErrors) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints1_mat = Converters.vector_Mat_to_Mat(imagePoints1); + Mat imagePoints2_mat = Converters.vector_Mat_to_Mat(imagePoints2); + double retVal = stereoCalibrateExtended_2(objectPoints_mat.nativeObj, imagePoints1_mat.nativeObj, imagePoints2_mat.nativeObj, cameraMatrix1.nativeObj, distCoeffs1.nativeObj, cameraMatrix2.nativeObj, distCoeffs2.nativeObj, imageSize.width, imageSize.height, R.nativeObj, T.nativeObj, E.nativeObj, F.nativeObj, perViewErrors.nativeObj); + + return retVal; + } + + + // + // C++: double cv::stereoCalibrate(vector_Mat objectPoints, vector_Mat imagePoints1, vector_Mat imagePoints2, Mat& cameraMatrix1, Mat& distCoeffs1, Mat& cameraMatrix2, Mat& distCoeffs2, Size imageSize, Mat& R, Mat& T, Mat& E, Mat& F, int flags = CALIB_FIX_INTRINSIC, TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 1e-6)) + // + + //javadoc: stereoCalibrate(objectPoints, imagePoints1, imagePoints2, cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, R, T, E, F, flags, criteria) + public static double stereoCalibrate(List objectPoints, List imagePoints1, List imagePoints2, Mat cameraMatrix1, Mat distCoeffs1, Mat cameraMatrix2, Mat distCoeffs2, Size imageSize, Mat R, Mat T, Mat E, Mat F, int flags, TermCriteria criteria) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints1_mat = Converters.vector_Mat_to_Mat(imagePoints1); + Mat imagePoints2_mat = Converters.vector_Mat_to_Mat(imagePoints2); + double retVal = stereoCalibrate_0(objectPoints_mat.nativeObj, imagePoints1_mat.nativeObj, imagePoints2_mat.nativeObj, cameraMatrix1.nativeObj, distCoeffs1.nativeObj, cameraMatrix2.nativeObj, distCoeffs2.nativeObj, imageSize.width, imageSize.height, R.nativeObj, T.nativeObj, E.nativeObj, F.nativeObj, flags, criteria.type, criteria.maxCount, criteria.epsilon); + + return retVal; + } + + //javadoc: stereoCalibrate(objectPoints, imagePoints1, imagePoints2, cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, R, T, E, F, flags) + public static double stereoCalibrate(List objectPoints, List imagePoints1, List imagePoints2, Mat cameraMatrix1, Mat distCoeffs1, Mat cameraMatrix2, Mat distCoeffs2, Size imageSize, Mat R, Mat T, Mat E, Mat F, int flags) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints1_mat = Converters.vector_Mat_to_Mat(imagePoints1); + Mat imagePoints2_mat = Converters.vector_Mat_to_Mat(imagePoints2); + double retVal = stereoCalibrate_1(objectPoints_mat.nativeObj, imagePoints1_mat.nativeObj, imagePoints2_mat.nativeObj, cameraMatrix1.nativeObj, distCoeffs1.nativeObj, cameraMatrix2.nativeObj, distCoeffs2.nativeObj, imageSize.width, imageSize.height, R.nativeObj, T.nativeObj, E.nativeObj, F.nativeObj, flags); + + return retVal; + } + + //javadoc: stereoCalibrate(objectPoints, imagePoints1, imagePoints2, cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, R, T, E, F) + public static double stereoCalibrate(List objectPoints, List imagePoints1, List imagePoints2, Mat cameraMatrix1, Mat distCoeffs1, Mat cameraMatrix2, Mat distCoeffs2, Size imageSize, Mat R, Mat T, Mat E, Mat F) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints1_mat = Converters.vector_Mat_to_Mat(imagePoints1); + Mat imagePoints2_mat = Converters.vector_Mat_to_Mat(imagePoints2); + double retVal = stereoCalibrate_2(objectPoints_mat.nativeObj, imagePoints1_mat.nativeObj, imagePoints2_mat.nativeObj, cameraMatrix1.nativeObj, distCoeffs1.nativeObj, cameraMatrix2.nativeObj, distCoeffs2.nativeObj, imageSize.width, imageSize.height, R.nativeObj, T.nativeObj, E.nativeObj, F.nativeObj); + + return retVal; + } + + + // + // C++: double cv::fisheye::calibrate(vector_Mat objectPoints, vector_Mat imagePoints, Size image_size, Mat& K, Mat& D, vector_Mat& rvecs, vector_Mat& tvecs, int flags = 0, TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON)) + // + + //javadoc: fisheye_calibrate(objectPoints, imagePoints, image_size, K, D, rvecs, tvecs, flags, criteria) + public static double fisheye_calibrate(List objectPoints, List imagePoints, Size image_size, Mat K, Mat D, List rvecs, List tvecs, int flags, TermCriteria criteria) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints_mat = Converters.vector_Mat_to_Mat(imagePoints); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = fisheye_calibrate_0(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, image_size.width, image_size.height, K.nativeObj, D.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, flags, criteria.type, criteria.maxCount, criteria.epsilon); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: fisheye_calibrate(objectPoints, imagePoints, image_size, K, D, rvecs, tvecs, flags) + public static double fisheye_calibrate(List objectPoints, List imagePoints, Size image_size, Mat K, Mat D, List rvecs, List tvecs, int flags) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints_mat = Converters.vector_Mat_to_Mat(imagePoints); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = fisheye_calibrate_1(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, image_size.width, image_size.height, K.nativeObj, D.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, flags); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: fisheye_calibrate(objectPoints, imagePoints, image_size, K, D, rvecs, tvecs) + public static double fisheye_calibrate(List objectPoints, List imagePoints, Size image_size, Mat K, Mat D, List rvecs, List tvecs) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints_mat = Converters.vector_Mat_to_Mat(imagePoints); + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + double retVal = fisheye_calibrate_2(objectPoints_mat.nativeObj, imagePoints_mat.nativeObj, image_size.width, image_size.height, K.nativeObj, D.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + + // + // C++: double cv::fisheye::stereoCalibrate(vector_Mat objectPoints, vector_Mat imagePoints1, vector_Mat imagePoints2, Mat& K1, Mat& D1, Mat& K2, Mat& D2, Size imageSize, Mat& R, Mat& T, int flags = fisheye::CALIB_FIX_INTRINSIC, TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON)) + // + + //javadoc: fisheye_stereoCalibrate(objectPoints, imagePoints1, imagePoints2, K1, D1, K2, D2, imageSize, R, T, flags, criteria) + public static double fisheye_stereoCalibrate(List objectPoints, List imagePoints1, List imagePoints2, Mat K1, Mat D1, Mat K2, Mat D2, Size imageSize, Mat R, Mat T, int flags, TermCriteria criteria) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints1_mat = Converters.vector_Mat_to_Mat(imagePoints1); + Mat imagePoints2_mat = Converters.vector_Mat_to_Mat(imagePoints2); + double retVal = fisheye_stereoCalibrate_0(objectPoints_mat.nativeObj, imagePoints1_mat.nativeObj, imagePoints2_mat.nativeObj, K1.nativeObj, D1.nativeObj, K2.nativeObj, D2.nativeObj, imageSize.width, imageSize.height, R.nativeObj, T.nativeObj, flags, criteria.type, criteria.maxCount, criteria.epsilon); + + return retVal; + } + + //javadoc: fisheye_stereoCalibrate(objectPoints, imagePoints1, imagePoints2, K1, D1, K2, D2, imageSize, R, T, flags) + public static double fisheye_stereoCalibrate(List objectPoints, List imagePoints1, List imagePoints2, Mat K1, Mat D1, Mat K2, Mat D2, Size imageSize, Mat R, Mat T, int flags) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints1_mat = Converters.vector_Mat_to_Mat(imagePoints1); + Mat imagePoints2_mat = Converters.vector_Mat_to_Mat(imagePoints2); + double retVal = fisheye_stereoCalibrate_1(objectPoints_mat.nativeObj, imagePoints1_mat.nativeObj, imagePoints2_mat.nativeObj, K1.nativeObj, D1.nativeObj, K2.nativeObj, D2.nativeObj, imageSize.width, imageSize.height, R.nativeObj, T.nativeObj, flags); + + return retVal; + } + + //javadoc: fisheye_stereoCalibrate(objectPoints, imagePoints1, imagePoints2, K1, D1, K2, D2, imageSize, R, T) + public static double fisheye_stereoCalibrate(List objectPoints, List imagePoints1, List imagePoints2, Mat K1, Mat D1, Mat K2, Mat D2, Size imageSize, Mat R, Mat T) + { + Mat objectPoints_mat = Converters.vector_Mat_to_Mat(objectPoints); + Mat imagePoints1_mat = Converters.vector_Mat_to_Mat(imagePoints1); + Mat imagePoints2_mat = Converters.vector_Mat_to_Mat(imagePoints2); + double retVal = fisheye_stereoCalibrate_2(objectPoints_mat.nativeObj, imagePoints1_mat.nativeObj, imagePoints2_mat.nativeObj, K1.nativeObj, D1.nativeObj, K2.nativeObj, D2.nativeObj, imageSize.width, imageSize.height, R.nativeObj, T.nativeObj); + + return retVal; + } + + + // + // C++: float cv::rectify3Collinear(Mat cameraMatrix1, Mat distCoeffs1, Mat cameraMatrix2, Mat distCoeffs2, Mat cameraMatrix3, Mat distCoeffs3, vector_Mat imgpt1, vector_Mat imgpt3, Size imageSize, Mat R12, Mat T12, Mat R13, Mat T13, Mat& R1, Mat& R2, Mat& R3, Mat& P1, Mat& P2, Mat& P3, Mat& Q, double alpha, Size newImgSize, Rect* roi1, Rect* roi2, int flags) + // + + //javadoc: rectify3Collinear(cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, cameraMatrix3, distCoeffs3, imgpt1, imgpt3, imageSize, R12, T12, R13, T13, R1, R2, R3, P1, P2, P3, Q, alpha, newImgSize, roi1, roi2, flags) + public static float rectify3Collinear(Mat cameraMatrix1, Mat distCoeffs1, Mat cameraMatrix2, Mat distCoeffs2, Mat cameraMatrix3, Mat distCoeffs3, List imgpt1, List imgpt3, Size imageSize, Mat R12, Mat T12, Mat R13, Mat T13, Mat R1, Mat R2, Mat R3, Mat P1, Mat P2, Mat P3, Mat Q, double alpha, Size newImgSize, Rect roi1, Rect roi2, int flags) + { + Mat imgpt1_mat = Converters.vector_Mat_to_Mat(imgpt1); + Mat imgpt3_mat = Converters.vector_Mat_to_Mat(imgpt3); + double[] roi1_out = new double[4]; + double[] roi2_out = new double[4]; + float retVal = rectify3Collinear_0(cameraMatrix1.nativeObj, distCoeffs1.nativeObj, cameraMatrix2.nativeObj, distCoeffs2.nativeObj, cameraMatrix3.nativeObj, distCoeffs3.nativeObj, imgpt1_mat.nativeObj, imgpt3_mat.nativeObj, imageSize.width, imageSize.height, R12.nativeObj, T12.nativeObj, R13.nativeObj, T13.nativeObj, R1.nativeObj, R2.nativeObj, R3.nativeObj, P1.nativeObj, P2.nativeObj, P3.nativeObj, Q.nativeObj, alpha, newImgSize.width, newImgSize.height, roi1_out, roi2_out, flags); + if(roi1!=null){ roi1.x = (int)roi1_out[0]; roi1.y = (int)roi1_out[1]; roi1.width = (int)roi1_out[2]; roi1.height = (int)roi1_out[3]; } + if(roi2!=null){ roi2.x = (int)roi2_out[0]; roi2.y = (int)roi2_out[1]; roi2.width = (int)roi2_out[2]; roi2.height = (int)roi2_out[3]; } + return retVal; + } + + + // + // C++: int cv::decomposeHomographyMat(Mat H, Mat K, vector_Mat& rotations, vector_Mat& translations, vector_Mat& normals) + // + + //javadoc: decomposeHomographyMat(H, K, rotations, translations, normals) + public static int decomposeHomographyMat(Mat H, Mat K, List rotations, List translations, List normals) + { + Mat rotations_mat = new Mat(); + Mat translations_mat = new Mat(); + Mat normals_mat = new Mat(); + int retVal = decomposeHomographyMat_0(H.nativeObj, K.nativeObj, rotations_mat.nativeObj, translations_mat.nativeObj, normals_mat.nativeObj); + Converters.Mat_to_vector_Mat(rotations_mat, rotations); + rotations_mat.release(); + Converters.Mat_to_vector_Mat(translations_mat, translations); + translations_mat.release(); + Converters.Mat_to_vector_Mat(normals_mat, normals); + normals_mat.release(); + return retVal; + } + + + // + // C++: int cv::estimateAffine3D(Mat src, Mat dst, Mat& out, Mat& inliers, double ransacThreshold = 3, double confidence = 0.99) + // + + //javadoc: estimateAffine3D(src, dst, out, inliers, ransacThreshold, confidence) + public static int estimateAffine3D(Mat src, Mat dst, Mat out, Mat inliers, double ransacThreshold, double confidence) + { + + int retVal = estimateAffine3D_0(src.nativeObj, dst.nativeObj, out.nativeObj, inliers.nativeObj, ransacThreshold, confidence); + + return retVal; + } + + //javadoc: estimateAffine3D(src, dst, out, inliers, ransacThreshold) + public static int estimateAffine3D(Mat src, Mat dst, Mat out, Mat inliers, double ransacThreshold) + { + + int retVal = estimateAffine3D_1(src.nativeObj, dst.nativeObj, out.nativeObj, inliers.nativeObj, ransacThreshold); + + return retVal; + } + + //javadoc: estimateAffine3D(src, dst, out, inliers) + public static int estimateAffine3D(Mat src, Mat dst, Mat out, Mat inliers) + { + + int retVal = estimateAffine3D_2(src.nativeObj, dst.nativeObj, out.nativeObj, inliers.nativeObj); + + return retVal; + } + + + // + // C++: int cv::recoverPose(Mat E, Mat points1, Mat points2, Mat& R, Mat& t, double focal = 1.0, Point2d pp = Point2d(0, 0), Mat& mask = Mat()) + // + + //javadoc: recoverPose(E, points1, points2, R, t, focal, pp, mask) + public static int recoverPose(Mat E, Mat points1, Mat points2, Mat R, Mat t, double focal, Point pp, Mat mask) + { + + int retVal = recoverPose_0(E.nativeObj, points1.nativeObj, points2.nativeObj, R.nativeObj, t.nativeObj, focal, pp.x, pp.y, mask.nativeObj); + + return retVal; + } + + //javadoc: recoverPose(E, points1, points2, R, t, focal, pp) + public static int recoverPose(Mat E, Mat points1, Mat points2, Mat R, Mat t, double focal, Point pp) + { + + int retVal = recoverPose_1(E.nativeObj, points1.nativeObj, points2.nativeObj, R.nativeObj, t.nativeObj, focal, pp.x, pp.y); + + return retVal; + } + + //javadoc: recoverPose(E, points1, points2, R, t, focal) + public static int recoverPose(Mat E, Mat points1, Mat points2, Mat R, Mat t, double focal) + { + + int retVal = recoverPose_2(E.nativeObj, points1.nativeObj, points2.nativeObj, R.nativeObj, t.nativeObj, focal); + + return retVal; + } + + //javadoc: recoverPose(E, points1, points2, R, t) + public static int recoverPose(Mat E, Mat points1, Mat points2, Mat R, Mat t) + { + + int retVal = recoverPose_3(E.nativeObj, points1.nativeObj, points2.nativeObj, R.nativeObj, t.nativeObj); + + return retVal; + } + + + // + // C++: int cv::recoverPose(Mat E, Mat points1, Mat points2, Mat cameraMatrix, Mat& R, Mat& t, Mat& mask = Mat()) + // + + //javadoc: recoverPose(E, points1, points2, cameraMatrix, R, t, mask) + public static int recoverPose(Mat E, Mat points1, Mat points2, Mat cameraMatrix, Mat R, Mat t, Mat mask) + { + + int retVal = recoverPose_4(E.nativeObj, points1.nativeObj, points2.nativeObj, cameraMatrix.nativeObj, R.nativeObj, t.nativeObj, mask.nativeObj); + + return retVal; + } + + //javadoc: recoverPose(E, points1, points2, cameraMatrix, R, t) + public static int recoverPose(Mat E, Mat points1, Mat points2, Mat cameraMatrix, Mat R, Mat t) + { + + int retVal = recoverPose_5(E.nativeObj, points1.nativeObj, points2.nativeObj, cameraMatrix.nativeObj, R.nativeObj, t.nativeObj); + + return retVal; + } + + + // + // C++: int cv::recoverPose(Mat E, Mat points1, Mat points2, Mat cameraMatrix, Mat& R, Mat& t, double distanceThresh, Mat& mask = Mat(), Mat& triangulatedPoints = Mat()) + // + + //javadoc: recoverPose(E, points1, points2, cameraMatrix, R, t, distanceThresh, mask, triangulatedPoints) + public static int recoverPose(Mat E, Mat points1, Mat points2, Mat cameraMatrix, Mat R, Mat t, double distanceThresh, Mat mask, Mat triangulatedPoints) + { + + int retVal = recoverPose_6(E.nativeObj, points1.nativeObj, points2.nativeObj, cameraMatrix.nativeObj, R.nativeObj, t.nativeObj, distanceThresh, mask.nativeObj, triangulatedPoints.nativeObj); + + return retVal; + } + + //javadoc: recoverPose(E, points1, points2, cameraMatrix, R, t, distanceThresh, mask) + public static int recoverPose(Mat E, Mat points1, Mat points2, Mat cameraMatrix, Mat R, Mat t, double distanceThresh, Mat mask) + { + + int retVal = recoverPose_7(E.nativeObj, points1.nativeObj, points2.nativeObj, cameraMatrix.nativeObj, R.nativeObj, t.nativeObj, distanceThresh, mask.nativeObj); + + return retVal; + } + + //javadoc: recoverPose(E, points1, points2, cameraMatrix, R, t, distanceThresh) + public static int recoverPose(Mat E, Mat points1, Mat points2, Mat cameraMatrix, Mat R, Mat t, double distanceThresh) + { + + int retVal = recoverPose_8(E.nativeObj, points1.nativeObj, points2.nativeObj, cameraMatrix.nativeObj, R.nativeObj, t.nativeObj, distanceThresh); + + return retVal; + } + + + // + // C++: int cv::solveP3P(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, vector_Mat& rvecs, vector_Mat& tvecs, int flags) + // + + //javadoc: solveP3P(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvecs, tvecs, flags) + public static int solveP3P(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, int flags) + { + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + int retVal = solveP3P_0(objectPoints.nativeObj, imagePoints.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, flags); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + + // + // C++: int cv::solvePnPGeneric(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, vector_Mat& rvecs, vector_Mat& tvecs, bool useExtrinsicGuess = false, SolvePnPMethod flags = SOLVEPNP_ITERATIVE, Mat rvec = Mat(), Mat tvec = Mat(), Mat& reprojectionError = Mat()) + // + + //javadoc: solvePnPGeneric(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvecs, tvecs, useExtrinsicGuess, flags, rvec, tvec, reprojectionError) + public static int solvePnPGeneric(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, boolean useExtrinsicGuess, int flags, Mat rvec, Mat tvec, Mat reprojectionError) + { + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + int retVal = solvePnPGeneric_0(objectPoints.nativeObj, imagePoints.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, useExtrinsicGuess, flags, rvec.nativeObj, tvec.nativeObj, reprojectionError.nativeObj); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: solvePnPGeneric(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvecs, tvecs, useExtrinsicGuess, flags, rvec, tvec) + public static int solvePnPGeneric(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, boolean useExtrinsicGuess, int flags, Mat rvec, Mat tvec) + { + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + int retVal = solvePnPGeneric_1(objectPoints.nativeObj, imagePoints.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, useExtrinsicGuess, flags, rvec.nativeObj, tvec.nativeObj); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: solvePnPGeneric(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvecs, tvecs, useExtrinsicGuess, flags, rvec) + public static int solvePnPGeneric(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, boolean useExtrinsicGuess, int flags, Mat rvec) + { + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + int retVal = solvePnPGeneric_2(objectPoints.nativeObj, imagePoints.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, useExtrinsicGuess, flags, rvec.nativeObj); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: solvePnPGeneric(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvecs, tvecs, useExtrinsicGuess, flags) + public static int solvePnPGeneric(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, boolean useExtrinsicGuess, int flags) + { + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + int retVal = solvePnPGeneric_3(objectPoints.nativeObj, imagePoints.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, useExtrinsicGuess, flags); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: solvePnPGeneric(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvecs, tvecs, useExtrinsicGuess) + public static int solvePnPGeneric(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs, boolean useExtrinsicGuess) + { + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + int retVal = solvePnPGeneric_4(objectPoints.nativeObj, imagePoints.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj, useExtrinsicGuess); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + //javadoc: solvePnPGeneric(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvecs, tvecs) + public static int solvePnPGeneric(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, List rvecs, List tvecs) + { + Mat rvecs_mat = new Mat(); + Mat tvecs_mat = new Mat(); + int retVal = solvePnPGeneric_5(objectPoints.nativeObj, imagePoints.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvecs_mat.nativeObj, tvecs_mat.nativeObj); + Converters.Mat_to_vector_Mat(rvecs_mat, rvecs); + rvecs_mat.release(); + Converters.Mat_to_vector_Mat(tvecs_mat, tvecs); + tvecs_mat.release(); + return retVal; + } + + + // + // C++: void cv::Rodrigues(Mat src, Mat& dst, Mat& jacobian = Mat()) + // + + //javadoc: Rodrigues(src, dst, jacobian) + public static void Rodrigues(Mat src, Mat dst, Mat jacobian) + { + + Rodrigues_0(src.nativeObj, dst.nativeObj, jacobian.nativeObj); + + return; + } + + //javadoc: Rodrigues(src, dst) + public static void Rodrigues(Mat src, Mat dst) + { + + Rodrigues_1(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::calibrateHandEye(vector_Mat R_gripper2base, vector_Mat t_gripper2base, vector_Mat R_target2cam, vector_Mat t_target2cam, Mat& R_cam2gripper, Mat& t_cam2gripper, HandEyeCalibrationMethod method = CALIB_HAND_EYE_TSAI) + // + + //javadoc: calibrateHandEye(R_gripper2base, t_gripper2base, R_target2cam, t_target2cam, R_cam2gripper, t_cam2gripper, method) + public static void calibrateHandEye(List R_gripper2base, List t_gripper2base, List R_target2cam, List t_target2cam, Mat R_cam2gripper, Mat t_cam2gripper, int method) + { + Mat R_gripper2base_mat = Converters.vector_Mat_to_Mat(R_gripper2base); + Mat t_gripper2base_mat = Converters.vector_Mat_to_Mat(t_gripper2base); + Mat R_target2cam_mat = Converters.vector_Mat_to_Mat(R_target2cam); + Mat t_target2cam_mat = Converters.vector_Mat_to_Mat(t_target2cam); + calibrateHandEye_0(R_gripper2base_mat.nativeObj, t_gripper2base_mat.nativeObj, R_target2cam_mat.nativeObj, t_target2cam_mat.nativeObj, R_cam2gripper.nativeObj, t_cam2gripper.nativeObj, method); + + return; + } + + //javadoc: calibrateHandEye(R_gripper2base, t_gripper2base, R_target2cam, t_target2cam, R_cam2gripper, t_cam2gripper) + public static void calibrateHandEye(List R_gripper2base, List t_gripper2base, List R_target2cam, List t_target2cam, Mat R_cam2gripper, Mat t_cam2gripper) + { + Mat R_gripper2base_mat = Converters.vector_Mat_to_Mat(R_gripper2base); + Mat t_gripper2base_mat = Converters.vector_Mat_to_Mat(t_gripper2base); + Mat R_target2cam_mat = Converters.vector_Mat_to_Mat(R_target2cam); + Mat t_target2cam_mat = Converters.vector_Mat_to_Mat(t_target2cam); + calibrateHandEye_1(R_gripper2base_mat.nativeObj, t_gripper2base_mat.nativeObj, R_target2cam_mat.nativeObj, t_target2cam_mat.nativeObj, R_cam2gripper.nativeObj, t_cam2gripper.nativeObj); + + return; + } + + + // + // C++: void cv::calibrationMatrixValues(Mat cameraMatrix, Size imageSize, double apertureWidth, double apertureHeight, double& fovx, double& fovy, double& focalLength, Point2d& principalPoint, double& aspectRatio) + // + + //javadoc: calibrationMatrixValues(cameraMatrix, imageSize, apertureWidth, apertureHeight, fovx, fovy, focalLength, principalPoint, aspectRatio) + public static void calibrationMatrixValues(Mat cameraMatrix, Size imageSize, double apertureWidth, double apertureHeight, double[] fovx, double[] fovy, double[] focalLength, Point principalPoint, double[] aspectRatio) + { + double[] fovx_out = new double[1]; + double[] fovy_out = new double[1]; + double[] focalLength_out = new double[1]; + double[] principalPoint_out = new double[2]; + double[] aspectRatio_out = new double[1]; + calibrationMatrixValues_0(cameraMatrix.nativeObj, imageSize.width, imageSize.height, apertureWidth, apertureHeight, fovx_out, fovy_out, focalLength_out, principalPoint_out, aspectRatio_out); + if(fovx!=null) fovx[0] = (double)fovx_out[0]; + if(fovy!=null) fovy[0] = (double)fovy_out[0]; + if(focalLength!=null) focalLength[0] = (double)focalLength_out[0]; + if(principalPoint!=null){ principalPoint.x = principalPoint_out[0]; principalPoint.y = principalPoint_out[1]; } + if(aspectRatio!=null) aspectRatio[0] = (double)aspectRatio_out[0]; + return; + } + + + // + // C++: void cv::composeRT(Mat rvec1, Mat tvec1, Mat rvec2, Mat tvec2, Mat& rvec3, Mat& tvec3, Mat& dr3dr1 = Mat(), Mat& dr3dt1 = Mat(), Mat& dr3dr2 = Mat(), Mat& dr3dt2 = Mat(), Mat& dt3dr1 = Mat(), Mat& dt3dt1 = Mat(), Mat& dt3dr2 = Mat(), Mat& dt3dt2 = Mat()) + // + + //javadoc: composeRT(rvec1, tvec1, rvec2, tvec2, rvec3, tvec3, dr3dr1, dr3dt1, dr3dr2, dr3dt2, dt3dr1, dt3dt1, dt3dr2, dt3dt2) + public static void composeRT(Mat rvec1, Mat tvec1, Mat rvec2, Mat tvec2, Mat rvec3, Mat tvec3, Mat dr3dr1, Mat dr3dt1, Mat dr3dr2, Mat dr3dt2, Mat dt3dr1, Mat dt3dt1, Mat dt3dr2, Mat dt3dt2) + { + + composeRT_0(rvec1.nativeObj, tvec1.nativeObj, rvec2.nativeObj, tvec2.nativeObj, rvec3.nativeObj, tvec3.nativeObj, dr3dr1.nativeObj, dr3dt1.nativeObj, dr3dr2.nativeObj, dr3dt2.nativeObj, dt3dr1.nativeObj, dt3dt1.nativeObj, dt3dr2.nativeObj, dt3dt2.nativeObj); + + return; + } + + //javadoc: composeRT(rvec1, tvec1, rvec2, tvec2, rvec3, tvec3, dr3dr1, dr3dt1, dr3dr2, dr3dt2, dt3dr1, dt3dt1, dt3dr2) + public static void composeRT(Mat rvec1, Mat tvec1, Mat rvec2, Mat tvec2, Mat rvec3, Mat tvec3, Mat dr3dr1, Mat dr3dt1, Mat dr3dr2, Mat dr3dt2, Mat dt3dr1, Mat dt3dt1, Mat dt3dr2) + { + + composeRT_1(rvec1.nativeObj, tvec1.nativeObj, rvec2.nativeObj, tvec2.nativeObj, rvec3.nativeObj, tvec3.nativeObj, dr3dr1.nativeObj, dr3dt1.nativeObj, dr3dr2.nativeObj, dr3dt2.nativeObj, dt3dr1.nativeObj, dt3dt1.nativeObj, dt3dr2.nativeObj); + + return; + } + + //javadoc: composeRT(rvec1, tvec1, rvec2, tvec2, rvec3, tvec3, dr3dr1, dr3dt1, dr3dr2, dr3dt2, dt3dr1, dt3dt1) + public static void composeRT(Mat rvec1, Mat tvec1, Mat rvec2, Mat tvec2, Mat rvec3, Mat tvec3, Mat dr3dr1, Mat dr3dt1, Mat dr3dr2, Mat dr3dt2, Mat dt3dr1, Mat dt3dt1) + { + + composeRT_2(rvec1.nativeObj, tvec1.nativeObj, rvec2.nativeObj, tvec2.nativeObj, rvec3.nativeObj, tvec3.nativeObj, dr3dr1.nativeObj, dr3dt1.nativeObj, dr3dr2.nativeObj, dr3dt2.nativeObj, dt3dr1.nativeObj, dt3dt1.nativeObj); + + return; + } + + //javadoc: composeRT(rvec1, tvec1, rvec2, tvec2, rvec3, tvec3, dr3dr1, dr3dt1, dr3dr2, dr3dt2, dt3dr1) + public static void composeRT(Mat rvec1, Mat tvec1, Mat rvec2, Mat tvec2, Mat rvec3, Mat tvec3, Mat dr3dr1, Mat dr3dt1, Mat dr3dr2, Mat dr3dt2, Mat dt3dr1) + { + + composeRT_3(rvec1.nativeObj, tvec1.nativeObj, rvec2.nativeObj, tvec2.nativeObj, rvec3.nativeObj, tvec3.nativeObj, dr3dr1.nativeObj, dr3dt1.nativeObj, dr3dr2.nativeObj, dr3dt2.nativeObj, dt3dr1.nativeObj); + + return; + } + + //javadoc: composeRT(rvec1, tvec1, rvec2, tvec2, rvec3, tvec3, dr3dr1, dr3dt1, dr3dr2, dr3dt2) + public static void composeRT(Mat rvec1, Mat tvec1, Mat rvec2, Mat tvec2, Mat rvec3, Mat tvec3, Mat dr3dr1, Mat dr3dt1, Mat dr3dr2, Mat dr3dt2) + { + + composeRT_4(rvec1.nativeObj, tvec1.nativeObj, rvec2.nativeObj, tvec2.nativeObj, rvec3.nativeObj, tvec3.nativeObj, dr3dr1.nativeObj, dr3dt1.nativeObj, dr3dr2.nativeObj, dr3dt2.nativeObj); + + return; + } + + //javadoc: composeRT(rvec1, tvec1, rvec2, tvec2, rvec3, tvec3, dr3dr1, dr3dt1, dr3dr2) + public static void composeRT(Mat rvec1, Mat tvec1, Mat rvec2, Mat tvec2, Mat rvec3, Mat tvec3, Mat dr3dr1, Mat dr3dt1, Mat dr3dr2) + { + + composeRT_5(rvec1.nativeObj, tvec1.nativeObj, rvec2.nativeObj, tvec2.nativeObj, rvec3.nativeObj, tvec3.nativeObj, dr3dr1.nativeObj, dr3dt1.nativeObj, dr3dr2.nativeObj); + + return; + } + + //javadoc: composeRT(rvec1, tvec1, rvec2, tvec2, rvec3, tvec3, dr3dr1, dr3dt1) + public static void composeRT(Mat rvec1, Mat tvec1, Mat rvec2, Mat tvec2, Mat rvec3, Mat tvec3, Mat dr3dr1, Mat dr3dt1) + { + + composeRT_6(rvec1.nativeObj, tvec1.nativeObj, rvec2.nativeObj, tvec2.nativeObj, rvec3.nativeObj, tvec3.nativeObj, dr3dr1.nativeObj, dr3dt1.nativeObj); + + return; + } + + //javadoc: composeRT(rvec1, tvec1, rvec2, tvec2, rvec3, tvec3, dr3dr1) + public static void composeRT(Mat rvec1, Mat tvec1, Mat rvec2, Mat tvec2, Mat rvec3, Mat tvec3, Mat dr3dr1) + { + + composeRT_7(rvec1.nativeObj, tvec1.nativeObj, rvec2.nativeObj, tvec2.nativeObj, rvec3.nativeObj, tvec3.nativeObj, dr3dr1.nativeObj); + + return; + } + + //javadoc: composeRT(rvec1, tvec1, rvec2, tvec2, rvec3, tvec3) + public static void composeRT(Mat rvec1, Mat tvec1, Mat rvec2, Mat tvec2, Mat rvec3, Mat tvec3) + { + + composeRT_8(rvec1.nativeObj, tvec1.nativeObj, rvec2.nativeObj, tvec2.nativeObj, rvec3.nativeObj, tvec3.nativeObj); + + return; + } + + + // + // C++: void cv::computeCorrespondEpilines(Mat points, int whichImage, Mat F, Mat& lines) + // + + //javadoc: computeCorrespondEpilines(points, whichImage, F, lines) + public static void computeCorrespondEpilines(Mat points, int whichImage, Mat F, Mat lines) + { + + computeCorrespondEpilines_0(points.nativeObj, whichImage, F.nativeObj, lines.nativeObj); + + return; + } + + + // + // C++: void cv::convertPointsFromHomogeneous(Mat src, Mat& dst) + // + + //javadoc: convertPointsFromHomogeneous(src, dst) + public static void convertPointsFromHomogeneous(Mat src, Mat dst) + { + + convertPointsFromHomogeneous_0(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::convertPointsToHomogeneous(Mat src, Mat& dst) + // + + //javadoc: convertPointsToHomogeneous(src, dst) + public static void convertPointsToHomogeneous(Mat src, Mat dst) + { + + convertPointsToHomogeneous_0(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::correctMatches(Mat F, Mat points1, Mat points2, Mat& newPoints1, Mat& newPoints2) + // + + //javadoc: correctMatches(F, points1, points2, newPoints1, newPoints2) + public static void correctMatches(Mat F, Mat points1, Mat points2, Mat newPoints1, Mat newPoints2) + { + + correctMatches_0(F.nativeObj, points1.nativeObj, points2.nativeObj, newPoints1.nativeObj, newPoints2.nativeObj); + + return; + } + + + // + // C++: void cv::decomposeEssentialMat(Mat E, Mat& R1, Mat& R2, Mat& t) + // + + //javadoc: decomposeEssentialMat(E, R1, R2, t) + public static void decomposeEssentialMat(Mat E, Mat R1, Mat R2, Mat t) + { + + decomposeEssentialMat_0(E.nativeObj, R1.nativeObj, R2.nativeObj, t.nativeObj); + + return; + } + + + // + // C++: void cv::decomposeProjectionMatrix(Mat projMatrix, Mat& cameraMatrix, Mat& rotMatrix, Mat& transVect, Mat& rotMatrixX = Mat(), Mat& rotMatrixY = Mat(), Mat& rotMatrixZ = Mat(), Mat& eulerAngles = Mat()) + // + + //javadoc: decomposeProjectionMatrix(projMatrix, cameraMatrix, rotMatrix, transVect, rotMatrixX, rotMatrixY, rotMatrixZ, eulerAngles) + public static void decomposeProjectionMatrix(Mat projMatrix, Mat cameraMatrix, Mat rotMatrix, Mat transVect, Mat rotMatrixX, Mat rotMatrixY, Mat rotMatrixZ, Mat eulerAngles) + { + + decomposeProjectionMatrix_0(projMatrix.nativeObj, cameraMatrix.nativeObj, rotMatrix.nativeObj, transVect.nativeObj, rotMatrixX.nativeObj, rotMatrixY.nativeObj, rotMatrixZ.nativeObj, eulerAngles.nativeObj); + + return; + } + + //javadoc: decomposeProjectionMatrix(projMatrix, cameraMatrix, rotMatrix, transVect, rotMatrixX, rotMatrixY, rotMatrixZ) + public static void decomposeProjectionMatrix(Mat projMatrix, Mat cameraMatrix, Mat rotMatrix, Mat transVect, Mat rotMatrixX, Mat rotMatrixY, Mat rotMatrixZ) + { + + decomposeProjectionMatrix_1(projMatrix.nativeObj, cameraMatrix.nativeObj, rotMatrix.nativeObj, transVect.nativeObj, rotMatrixX.nativeObj, rotMatrixY.nativeObj, rotMatrixZ.nativeObj); + + return; + } + + //javadoc: decomposeProjectionMatrix(projMatrix, cameraMatrix, rotMatrix, transVect, rotMatrixX, rotMatrixY) + public static void decomposeProjectionMatrix(Mat projMatrix, Mat cameraMatrix, Mat rotMatrix, Mat transVect, Mat rotMatrixX, Mat rotMatrixY) + { + + decomposeProjectionMatrix_2(projMatrix.nativeObj, cameraMatrix.nativeObj, rotMatrix.nativeObj, transVect.nativeObj, rotMatrixX.nativeObj, rotMatrixY.nativeObj); + + return; + } + + //javadoc: decomposeProjectionMatrix(projMatrix, cameraMatrix, rotMatrix, transVect, rotMatrixX) + public static void decomposeProjectionMatrix(Mat projMatrix, Mat cameraMatrix, Mat rotMatrix, Mat transVect, Mat rotMatrixX) + { + + decomposeProjectionMatrix_3(projMatrix.nativeObj, cameraMatrix.nativeObj, rotMatrix.nativeObj, transVect.nativeObj, rotMatrixX.nativeObj); + + return; + } + + //javadoc: decomposeProjectionMatrix(projMatrix, cameraMatrix, rotMatrix, transVect) + public static void decomposeProjectionMatrix(Mat projMatrix, Mat cameraMatrix, Mat rotMatrix, Mat transVect) + { + + decomposeProjectionMatrix_4(projMatrix.nativeObj, cameraMatrix.nativeObj, rotMatrix.nativeObj, transVect.nativeObj); + + return; + } + + + // + // C++: void cv::drawChessboardCorners(Mat& image, Size patternSize, vector_Point2f corners, bool patternWasFound) + // + + //javadoc: drawChessboardCorners(image, patternSize, corners, patternWasFound) + public static void drawChessboardCorners(Mat image, Size patternSize, MatOfPoint2f corners, boolean patternWasFound) + { + Mat corners_mat = corners; + drawChessboardCorners_0(image.nativeObj, patternSize.width, patternSize.height, corners_mat.nativeObj, patternWasFound); + + return; + } + + + // + // C++: void cv::drawFrameAxes(Mat& image, Mat cameraMatrix, Mat distCoeffs, Mat rvec, Mat tvec, float length, int thickness = 3) + // + + //javadoc: drawFrameAxes(image, cameraMatrix, distCoeffs, rvec, tvec, length, thickness) + public static void drawFrameAxes(Mat image, Mat cameraMatrix, Mat distCoeffs, Mat rvec, Mat tvec, float length, int thickness) + { + + drawFrameAxes_0(image.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvec.nativeObj, tvec.nativeObj, length, thickness); + + return; + } + + //javadoc: drawFrameAxes(image, cameraMatrix, distCoeffs, rvec, tvec, length) + public static void drawFrameAxes(Mat image, Mat cameraMatrix, Mat distCoeffs, Mat rvec, Mat tvec, float length) + { + + drawFrameAxes_1(image.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvec.nativeObj, tvec.nativeObj, length); + + return; + } + + + // + // C++: void cv::filterHomographyDecompByVisibleRefpoints(vector_Mat rotations, vector_Mat normals, Mat beforePoints, Mat afterPoints, Mat& possibleSolutions, Mat pointsMask = Mat()) + // + + //javadoc: filterHomographyDecompByVisibleRefpoints(rotations, normals, beforePoints, afterPoints, possibleSolutions, pointsMask) + public static void filterHomographyDecompByVisibleRefpoints(List rotations, List normals, Mat beforePoints, Mat afterPoints, Mat possibleSolutions, Mat pointsMask) + { + Mat rotations_mat = Converters.vector_Mat_to_Mat(rotations); + Mat normals_mat = Converters.vector_Mat_to_Mat(normals); + filterHomographyDecompByVisibleRefpoints_0(rotations_mat.nativeObj, normals_mat.nativeObj, beforePoints.nativeObj, afterPoints.nativeObj, possibleSolutions.nativeObj, pointsMask.nativeObj); + + return; + } + + //javadoc: filterHomographyDecompByVisibleRefpoints(rotations, normals, beforePoints, afterPoints, possibleSolutions) + public static void filterHomographyDecompByVisibleRefpoints(List rotations, List normals, Mat beforePoints, Mat afterPoints, Mat possibleSolutions) + { + Mat rotations_mat = Converters.vector_Mat_to_Mat(rotations); + Mat normals_mat = Converters.vector_Mat_to_Mat(normals); + filterHomographyDecompByVisibleRefpoints_1(rotations_mat.nativeObj, normals_mat.nativeObj, beforePoints.nativeObj, afterPoints.nativeObj, possibleSolutions.nativeObj); + + return; + } + + + // + // C++: void cv::filterSpeckles(Mat& img, double newVal, int maxSpeckleSize, double maxDiff, Mat& buf = Mat()) + // + + //javadoc: filterSpeckles(img, newVal, maxSpeckleSize, maxDiff, buf) + public static void filterSpeckles(Mat img, double newVal, int maxSpeckleSize, double maxDiff, Mat buf) + { + + filterSpeckles_0(img.nativeObj, newVal, maxSpeckleSize, maxDiff, buf.nativeObj); + + return; + } + + //javadoc: filterSpeckles(img, newVal, maxSpeckleSize, maxDiff) + public static void filterSpeckles(Mat img, double newVal, int maxSpeckleSize, double maxDiff) + { + + filterSpeckles_1(img.nativeObj, newVal, maxSpeckleSize, maxDiff); + + return; + } + + + // + // C++: void cv::initUndistortRectifyMap(Mat cameraMatrix, Mat distCoeffs, Mat R, Mat newCameraMatrix, Size size, int m1type, Mat& map1, Mat& map2) + // + + //javadoc: initUndistortRectifyMap(cameraMatrix, distCoeffs, R, newCameraMatrix, size, m1type, map1, map2) + public static void initUndistortRectifyMap(Mat cameraMatrix, Mat distCoeffs, Mat R, Mat newCameraMatrix, Size size, int m1type, Mat map1, Mat map2) + { + + initUndistortRectifyMap_0(cameraMatrix.nativeObj, distCoeffs.nativeObj, R.nativeObj, newCameraMatrix.nativeObj, size.width, size.height, m1type, map1.nativeObj, map2.nativeObj); + + return; + } + + + // + // C++: void cv::matMulDeriv(Mat A, Mat B, Mat& dABdA, Mat& dABdB) + // + + //javadoc: matMulDeriv(A, B, dABdA, dABdB) + public static void matMulDeriv(Mat A, Mat B, Mat dABdA, Mat dABdB) + { + + matMulDeriv_0(A.nativeObj, B.nativeObj, dABdA.nativeObj, dABdB.nativeObj); + + return; + } + + + // + // C++: void cv::projectPoints(vector_Point3f objectPoints, Mat rvec, Mat tvec, Mat cameraMatrix, vector_double distCoeffs, vector_Point2f& imagePoints, Mat& jacobian = Mat(), double aspectRatio = 0) + // + + //javadoc: projectPoints(objectPoints, rvec, tvec, cameraMatrix, distCoeffs, imagePoints, jacobian, aspectRatio) + public static void projectPoints(MatOfPoint3f objectPoints, Mat rvec, Mat tvec, Mat cameraMatrix, MatOfDouble distCoeffs, MatOfPoint2f imagePoints, Mat jacobian, double aspectRatio) + { + Mat objectPoints_mat = objectPoints; + Mat distCoeffs_mat = distCoeffs; + Mat imagePoints_mat = imagePoints; + projectPoints_0(objectPoints_mat.nativeObj, rvec.nativeObj, tvec.nativeObj, cameraMatrix.nativeObj, distCoeffs_mat.nativeObj, imagePoints_mat.nativeObj, jacobian.nativeObj, aspectRatio); + + return; + } + + //javadoc: projectPoints(objectPoints, rvec, tvec, cameraMatrix, distCoeffs, imagePoints, jacobian) + public static void projectPoints(MatOfPoint3f objectPoints, Mat rvec, Mat tvec, Mat cameraMatrix, MatOfDouble distCoeffs, MatOfPoint2f imagePoints, Mat jacobian) + { + Mat objectPoints_mat = objectPoints; + Mat distCoeffs_mat = distCoeffs; + Mat imagePoints_mat = imagePoints; + projectPoints_1(objectPoints_mat.nativeObj, rvec.nativeObj, tvec.nativeObj, cameraMatrix.nativeObj, distCoeffs_mat.nativeObj, imagePoints_mat.nativeObj, jacobian.nativeObj); + + return; + } + + //javadoc: projectPoints(objectPoints, rvec, tvec, cameraMatrix, distCoeffs, imagePoints) + public static void projectPoints(MatOfPoint3f objectPoints, Mat rvec, Mat tvec, Mat cameraMatrix, MatOfDouble distCoeffs, MatOfPoint2f imagePoints) + { + Mat objectPoints_mat = objectPoints; + Mat distCoeffs_mat = distCoeffs; + Mat imagePoints_mat = imagePoints; + projectPoints_2(objectPoints_mat.nativeObj, rvec.nativeObj, tvec.nativeObj, cameraMatrix.nativeObj, distCoeffs_mat.nativeObj, imagePoints_mat.nativeObj); + + return; + } + + + // + // C++: void cv::reprojectImageTo3D(Mat disparity, Mat& _3dImage, Mat Q, bool handleMissingValues = false, int ddepth = -1) + // + + //javadoc: reprojectImageTo3D(disparity, _3dImage, Q, handleMissingValues, ddepth) + public static void reprojectImageTo3D(Mat disparity, Mat _3dImage, Mat Q, boolean handleMissingValues, int ddepth) + { + + reprojectImageTo3D_0(disparity.nativeObj, _3dImage.nativeObj, Q.nativeObj, handleMissingValues, ddepth); + + return; + } + + //javadoc: reprojectImageTo3D(disparity, _3dImage, Q, handleMissingValues) + public static void reprojectImageTo3D(Mat disparity, Mat _3dImage, Mat Q, boolean handleMissingValues) + { + + reprojectImageTo3D_1(disparity.nativeObj, _3dImage.nativeObj, Q.nativeObj, handleMissingValues); + + return; + } + + //javadoc: reprojectImageTo3D(disparity, _3dImage, Q) + public static void reprojectImageTo3D(Mat disparity, Mat _3dImage, Mat Q) + { + + reprojectImageTo3D_2(disparity.nativeObj, _3dImage.nativeObj, Q.nativeObj); + + return; + } + + + // + // C++: void cv::solvePnPRefineLM(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, Mat& rvec, Mat& tvec, TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 20, FLT_EPSILON)) + // + + //javadoc: solvePnPRefineLM(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec, criteria) + public static void solvePnPRefineLM(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, Mat rvec, Mat tvec, TermCriteria criteria) + { + + solvePnPRefineLM_0(objectPoints.nativeObj, imagePoints.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvec.nativeObj, tvec.nativeObj, criteria.type, criteria.maxCount, criteria.epsilon); + + return; + } + + //javadoc: solvePnPRefineLM(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec) + public static void solvePnPRefineLM(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, Mat rvec, Mat tvec) + { + + solvePnPRefineLM_1(objectPoints.nativeObj, imagePoints.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvec.nativeObj, tvec.nativeObj); + + return; + } + + + // + // C++: void cv::solvePnPRefineVVS(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, Mat& rvec, Mat& tvec, TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 20, FLT_EPSILON), double VVSlambda = 1) + // + + //javadoc: solvePnPRefineVVS(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec, criteria, VVSlambda) + public static void solvePnPRefineVVS(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, Mat rvec, Mat tvec, TermCriteria criteria, double VVSlambda) + { + + solvePnPRefineVVS_0(objectPoints.nativeObj, imagePoints.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvec.nativeObj, tvec.nativeObj, criteria.type, criteria.maxCount, criteria.epsilon, VVSlambda); + + return; + } + + //javadoc: solvePnPRefineVVS(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec, criteria) + public static void solvePnPRefineVVS(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, Mat rvec, Mat tvec, TermCriteria criteria) + { + + solvePnPRefineVVS_1(objectPoints.nativeObj, imagePoints.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvec.nativeObj, tvec.nativeObj, criteria.type, criteria.maxCount, criteria.epsilon); + + return; + } + + //javadoc: solvePnPRefineVVS(objectPoints, imagePoints, cameraMatrix, distCoeffs, rvec, tvec) + public static void solvePnPRefineVVS(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, Mat rvec, Mat tvec) + { + + solvePnPRefineVVS_2(objectPoints.nativeObj, imagePoints.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, rvec.nativeObj, tvec.nativeObj); + + return; + } + + + // + // C++: void cv::stereoRectify(Mat cameraMatrix1, Mat distCoeffs1, Mat cameraMatrix2, Mat distCoeffs2, Size imageSize, Mat R, Mat T, Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q, int flags = CALIB_ZERO_DISPARITY, double alpha = -1, Size newImageSize = Size(), Rect* validPixROI1 = 0, Rect* validPixROI2 = 0) + // + + //javadoc: stereoRectify(cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, R, T, R1, R2, P1, P2, Q, flags, alpha, newImageSize, validPixROI1, validPixROI2) + public static void stereoRectify(Mat cameraMatrix1, Mat distCoeffs1, Mat cameraMatrix2, Mat distCoeffs2, Size imageSize, Mat R, Mat T, Mat R1, Mat R2, Mat P1, Mat P2, Mat Q, int flags, double alpha, Size newImageSize, Rect validPixROI1, Rect validPixROI2) + { + double[] validPixROI1_out = new double[4]; + double[] validPixROI2_out = new double[4]; + stereoRectify_0(cameraMatrix1.nativeObj, distCoeffs1.nativeObj, cameraMatrix2.nativeObj, distCoeffs2.nativeObj, imageSize.width, imageSize.height, R.nativeObj, T.nativeObj, R1.nativeObj, R2.nativeObj, P1.nativeObj, P2.nativeObj, Q.nativeObj, flags, alpha, newImageSize.width, newImageSize.height, validPixROI1_out, validPixROI2_out); + if(validPixROI1!=null){ validPixROI1.x = (int)validPixROI1_out[0]; validPixROI1.y = (int)validPixROI1_out[1]; validPixROI1.width = (int)validPixROI1_out[2]; validPixROI1.height = (int)validPixROI1_out[3]; } + if(validPixROI2!=null){ validPixROI2.x = (int)validPixROI2_out[0]; validPixROI2.y = (int)validPixROI2_out[1]; validPixROI2.width = (int)validPixROI2_out[2]; validPixROI2.height = (int)validPixROI2_out[3]; } + return; + } + + //javadoc: stereoRectify(cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, R, T, R1, R2, P1, P2, Q, flags, alpha, newImageSize, validPixROI1) + public static void stereoRectify(Mat cameraMatrix1, Mat distCoeffs1, Mat cameraMatrix2, Mat distCoeffs2, Size imageSize, Mat R, Mat T, Mat R1, Mat R2, Mat P1, Mat P2, Mat Q, int flags, double alpha, Size newImageSize, Rect validPixROI1) + { + double[] validPixROI1_out = new double[4]; + stereoRectify_1(cameraMatrix1.nativeObj, distCoeffs1.nativeObj, cameraMatrix2.nativeObj, distCoeffs2.nativeObj, imageSize.width, imageSize.height, R.nativeObj, T.nativeObj, R1.nativeObj, R2.nativeObj, P1.nativeObj, P2.nativeObj, Q.nativeObj, flags, alpha, newImageSize.width, newImageSize.height, validPixROI1_out); + if(validPixROI1!=null){ validPixROI1.x = (int)validPixROI1_out[0]; validPixROI1.y = (int)validPixROI1_out[1]; validPixROI1.width = (int)validPixROI1_out[2]; validPixROI1.height = (int)validPixROI1_out[3]; } + return; + } + + //javadoc: stereoRectify(cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, R, T, R1, R2, P1, P2, Q, flags, alpha, newImageSize) + public static void stereoRectify(Mat cameraMatrix1, Mat distCoeffs1, Mat cameraMatrix2, Mat distCoeffs2, Size imageSize, Mat R, Mat T, Mat R1, Mat R2, Mat P1, Mat P2, Mat Q, int flags, double alpha, Size newImageSize) + { + + stereoRectify_2(cameraMatrix1.nativeObj, distCoeffs1.nativeObj, cameraMatrix2.nativeObj, distCoeffs2.nativeObj, imageSize.width, imageSize.height, R.nativeObj, T.nativeObj, R1.nativeObj, R2.nativeObj, P1.nativeObj, P2.nativeObj, Q.nativeObj, flags, alpha, newImageSize.width, newImageSize.height); + + return; + } + + //javadoc: stereoRectify(cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, R, T, R1, R2, P1, P2, Q, flags, alpha) + public static void stereoRectify(Mat cameraMatrix1, Mat distCoeffs1, Mat cameraMatrix2, Mat distCoeffs2, Size imageSize, Mat R, Mat T, Mat R1, Mat R2, Mat P1, Mat P2, Mat Q, int flags, double alpha) + { + + stereoRectify_3(cameraMatrix1.nativeObj, distCoeffs1.nativeObj, cameraMatrix2.nativeObj, distCoeffs2.nativeObj, imageSize.width, imageSize.height, R.nativeObj, T.nativeObj, R1.nativeObj, R2.nativeObj, P1.nativeObj, P2.nativeObj, Q.nativeObj, flags, alpha); + + return; + } + + //javadoc: stereoRectify(cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, R, T, R1, R2, P1, P2, Q, flags) + public static void stereoRectify(Mat cameraMatrix1, Mat distCoeffs1, Mat cameraMatrix2, Mat distCoeffs2, Size imageSize, Mat R, Mat T, Mat R1, Mat R2, Mat P1, Mat P2, Mat Q, int flags) + { + + stereoRectify_4(cameraMatrix1.nativeObj, distCoeffs1.nativeObj, cameraMatrix2.nativeObj, distCoeffs2.nativeObj, imageSize.width, imageSize.height, R.nativeObj, T.nativeObj, R1.nativeObj, R2.nativeObj, P1.nativeObj, P2.nativeObj, Q.nativeObj, flags); + + return; + } + + //javadoc: stereoRectify(cameraMatrix1, distCoeffs1, cameraMatrix2, distCoeffs2, imageSize, R, T, R1, R2, P1, P2, Q) + public static void stereoRectify(Mat cameraMatrix1, Mat distCoeffs1, Mat cameraMatrix2, Mat distCoeffs2, Size imageSize, Mat R, Mat T, Mat R1, Mat R2, Mat P1, Mat P2, Mat Q) + { + + stereoRectify_5(cameraMatrix1.nativeObj, distCoeffs1.nativeObj, cameraMatrix2.nativeObj, distCoeffs2.nativeObj, imageSize.width, imageSize.height, R.nativeObj, T.nativeObj, R1.nativeObj, R2.nativeObj, P1.nativeObj, P2.nativeObj, Q.nativeObj); + + return; + } + + + // + // C++: void cv::triangulatePoints(Mat projMatr1, Mat projMatr2, Mat projPoints1, Mat projPoints2, Mat& points4D) + // + + //javadoc: triangulatePoints(projMatr1, projMatr2, projPoints1, projPoints2, points4D) + public static void triangulatePoints(Mat projMatr1, Mat projMatr2, Mat projPoints1, Mat projPoints2, Mat points4D) + { + + triangulatePoints_0(projMatr1.nativeObj, projMatr2.nativeObj, projPoints1.nativeObj, projPoints2.nativeObj, points4D.nativeObj); + + return; + } + + + // + // C++: void cv::undistort(Mat src, Mat& dst, Mat cameraMatrix, Mat distCoeffs, Mat newCameraMatrix = Mat()) + // + + //javadoc: undistort(src, dst, cameraMatrix, distCoeffs, newCameraMatrix) + public static void undistort(Mat src, Mat dst, Mat cameraMatrix, Mat distCoeffs, Mat newCameraMatrix) + { + + undistort_0(src.nativeObj, dst.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, newCameraMatrix.nativeObj); + + return; + } + + //javadoc: undistort(src, dst, cameraMatrix, distCoeffs) + public static void undistort(Mat src, Mat dst, Mat cameraMatrix, Mat distCoeffs) + { + + undistort_1(src.nativeObj, dst.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj); + + return; + } + + + // + // C++: void cv::undistortPoints(Mat src, Mat& dst, Mat cameraMatrix, Mat distCoeffs, Mat R, Mat P, TermCriteria criteria) + // + + //javadoc: undistortPointsIter(src, dst, cameraMatrix, distCoeffs, R, P, criteria) + public static void undistortPointsIter(Mat src, Mat dst, Mat cameraMatrix, Mat distCoeffs, Mat R, Mat P, TermCriteria criteria) + { + + undistortPointsIter_0(src.nativeObj, dst.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, R.nativeObj, P.nativeObj, criteria.type, criteria.maxCount, criteria.epsilon); + + return; + } + + + // + // C++: void cv::undistortPoints(vector_Point2f src, vector_Point2f& dst, Mat cameraMatrix, Mat distCoeffs, Mat R = Mat(), Mat P = Mat()) + // + + //javadoc: undistortPoints(src, dst, cameraMatrix, distCoeffs, R, P) + public static void undistortPoints(MatOfPoint2f src, MatOfPoint2f dst, Mat cameraMatrix, Mat distCoeffs, Mat R, Mat P) + { + Mat src_mat = src; + Mat dst_mat = dst; + undistortPoints_0(src_mat.nativeObj, dst_mat.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, R.nativeObj, P.nativeObj); + + return; + } + + //javadoc: undistortPoints(src, dst, cameraMatrix, distCoeffs, R) + public static void undistortPoints(MatOfPoint2f src, MatOfPoint2f dst, Mat cameraMatrix, Mat distCoeffs, Mat R) + { + Mat src_mat = src; + Mat dst_mat = dst; + undistortPoints_1(src_mat.nativeObj, dst_mat.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj, R.nativeObj); + + return; + } + + //javadoc: undistortPoints(src, dst, cameraMatrix, distCoeffs) + public static void undistortPoints(MatOfPoint2f src, MatOfPoint2f dst, Mat cameraMatrix, Mat distCoeffs) + { + Mat src_mat = src; + Mat dst_mat = dst; + undistortPoints_2(src_mat.nativeObj, dst_mat.nativeObj, cameraMatrix.nativeObj, distCoeffs.nativeObj); + + return; + } + + + // + // C++: void cv::validateDisparity(Mat& disparity, Mat cost, int minDisparity, int numberOfDisparities, int disp12MaxDisp = 1) + // + + //javadoc: validateDisparity(disparity, cost, minDisparity, numberOfDisparities, disp12MaxDisp) + public static void validateDisparity(Mat disparity, Mat cost, int minDisparity, int numberOfDisparities, int disp12MaxDisp) + { + + validateDisparity_0(disparity.nativeObj, cost.nativeObj, minDisparity, numberOfDisparities, disp12MaxDisp); + + return; + } + + //javadoc: validateDisparity(disparity, cost, minDisparity, numberOfDisparities) + public static void validateDisparity(Mat disparity, Mat cost, int minDisparity, int numberOfDisparities) + { + + validateDisparity_1(disparity.nativeObj, cost.nativeObj, minDisparity, numberOfDisparities); + + return; + } + + + // + // C++: void cv::fisheye::distortPoints(Mat undistorted, Mat& distorted, Mat K, Mat D, double alpha = 0) + // + + //javadoc: fisheye_distortPoints(undistorted, distorted, K, D, alpha) + public static void fisheye_distortPoints(Mat undistorted, Mat distorted, Mat K, Mat D, double alpha) + { + + fisheye_distortPoints_0(undistorted.nativeObj, distorted.nativeObj, K.nativeObj, D.nativeObj, alpha); + + return; + } + + //javadoc: fisheye_distortPoints(undistorted, distorted, K, D) + public static void fisheye_distortPoints(Mat undistorted, Mat distorted, Mat K, Mat D) + { + + fisheye_distortPoints_1(undistorted.nativeObj, distorted.nativeObj, K.nativeObj, D.nativeObj); + + return; + } + + + // + // C++: void cv::fisheye::estimateNewCameraMatrixForUndistortRectify(Mat K, Mat D, Size image_size, Mat R, Mat& P, double balance = 0.0, Size new_size = Size(), double fov_scale = 1.0) + // + + //javadoc: fisheye_estimateNewCameraMatrixForUndistortRectify(K, D, image_size, R, P, balance, new_size, fov_scale) + public static void fisheye_estimateNewCameraMatrixForUndistortRectify(Mat K, Mat D, Size image_size, Mat R, Mat P, double balance, Size new_size, double fov_scale) + { + + fisheye_estimateNewCameraMatrixForUndistortRectify_0(K.nativeObj, D.nativeObj, image_size.width, image_size.height, R.nativeObj, P.nativeObj, balance, new_size.width, new_size.height, fov_scale); + + return; + } + + //javadoc: fisheye_estimateNewCameraMatrixForUndistortRectify(K, D, image_size, R, P, balance, new_size) + public static void fisheye_estimateNewCameraMatrixForUndistortRectify(Mat K, Mat D, Size image_size, Mat R, Mat P, double balance, Size new_size) + { + + fisheye_estimateNewCameraMatrixForUndistortRectify_1(K.nativeObj, D.nativeObj, image_size.width, image_size.height, R.nativeObj, P.nativeObj, balance, new_size.width, new_size.height); + + return; + } + + //javadoc: fisheye_estimateNewCameraMatrixForUndistortRectify(K, D, image_size, R, P, balance) + public static void fisheye_estimateNewCameraMatrixForUndistortRectify(Mat K, Mat D, Size image_size, Mat R, Mat P, double balance) + { + + fisheye_estimateNewCameraMatrixForUndistortRectify_2(K.nativeObj, D.nativeObj, image_size.width, image_size.height, R.nativeObj, P.nativeObj, balance); + + return; + } + + //javadoc: fisheye_estimateNewCameraMatrixForUndistortRectify(K, D, image_size, R, P) + public static void fisheye_estimateNewCameraMatrixForUndistortRectify(Mat K, Mat D, Size image_size, Mat R, Mat P) + { + + fisheye_estimateNewCameraMatrixForUndistortRectify_3(K.nativeObj, D.nativeObj, image_size.width, image_size.height, R.nativeObj, P.nativeObj); + + return; + } + + + // + // C++: void cv::fisheye::initUndistortRectifyMap(Mat K, Mat D, Mat R, Mat P, Size size, int m1type, Mat& map1, Mat& map2) + // + + //javadoc: fisheye_initUndistortRectifyMap(K, D, R, P, size, m1type, map1, map2) + public static void fisheye_initUndistortRectifyMap(Mat K, Mat D, Mat R, Mat P, Size size, int m1type, Mat map1, Mat map2) + { + + fisheye_initUndistortRectifyMap_0(K.nativeObj, D.nativeObj, R.nativeObj, P.nativeObj, size.width, size.height, m1type, map1.nativeObj, map2.nativeObj); + + return; + } + + + // + // C++: void cv::fisheye::projectPoints(Mat objectPoints, Mat& imagePoints, Mat rvec, Mat tvec, Mat K, Mat D, double alpha = 0, Mat& jacobian = Mat()) + // + + //javadoc: fisheye_projectPoints(objectPoints, imagePoints, rvec, tvec, K, D, alpha, jacobian) + public static void fisheye_projectPoints(Mat objectPoints, Mat imagePoints, Mat rvec, Mat tvec, Mat K, Mat D, double alpha, Mat jacobian) + { + + fisheye_projectPoints_0(objectPoints.nativeObj, imagePoints.nativeObj, rvec.nativeObj, tvec.nativeObj, K.nativeObj, D.nativeObj, alpha, jacobian.nativeObj); + + return; + } + + //javadoc: fisheye_projectPoints(objectPoints, imagePoints, rvec, tvec, K, D, alpha) + public static void fisheye_projectPoints(Mat objectPoints, Mat imagePoints, Mat rvec, Mat tvec, Mat K, Mat D, double alpha) + { + + fisheye_projectPoints_1(objectPoints.nativeObj, imagePoints.nativeObj, rvec.nativeObj, tvec.nativeObj, K.nativeObj, D.nativeObj, alpha); + + return; + } + + //javadoc: fisheye_projectPoints(objectPoints, imagePoints, rvec, tvec, K, D) + public static void fisheye_projectPoints(Mat objectPoints, Mat imagePoints, Mat rvec, Mat tvec, Mat K, Mat D) + { + + fisheye_projectPoints_2(objectPoints.nativeObj, imagePoints.nativeObj, rvec.nativeObj, tvec.nativeObj, K.nativeObj, D.nativeObj); + + return; + } + + + // + // C++: void cv::fisheye::stereoRectify(Mat K1, Mat D1, Mat K2, Mat D2, Size imageSize, Mat R, Mat tvec, Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q, int flags, Size newImageSize = Size(), double balance = 0.0, double fov_scale = 1.0) + // + + //javadoc: fisheye_stereoRectify(K1, D1, K2, D2, imageSize, R, tvec, R1, R2, P1, P2, Q, flags, newImageSize, balance, fov_scale) + public static void fisheye_stereoRectify(Mat K1, Mat D1, Mat K2, Mat D2, Size imageSize, Mat R, Mat tvec, Mat R1, Mat R2, Mat P1, Mat P2, Mat Q, int flags, Size newImageSize, double balance, double fov_scale) + { + + fisheye_stereoRectify_0(K1.nativeObj, D1.nativeObj, K2.nativeObj, D2.nativeObj, imageSize.width, imageSize.height, R.nativeObj, tvec.nativeObj, R1.nativeObj, R2.nativeObj, P1.nativeObj, P2.nativeObj, Q.nativeObj, flags, newImageSize.width, newImageSize.height, balance, fov_scale); + + return; + } + + //javadoc: fisheye_stereoRectify(K1, D1, K2, D2, imageSize, R, tvec, R1, R2, P1, P2, Q, flags, newImageSize, balance) + public static void fisheye_stereoRectify(Mat K1, Mat D1, Mat K2, Mat D2, Size imageSize, Mat R, Mat tvec, Mat R1, Mat R2, Mat P1, Mat P2, Mat Q, int flags, Size newImageSize, double balance) + { + + fisheye_stereoRectify_1(K1.nativeObj, D1.nativeObj, K2.nativeObj, D2.nativeObj, imageSize.width, imageSize.height, R.nativeObj, tvec.nativeObj, R1.nativeObj, R2.nativeObj, P1.nativeObj, P2.nativeObj, Q.nativeObj, flags, newImageSize.width, newImageSize.height, balance); + + return; + } + + //javadoc: fisheye_stereoRectify(K1, D1, K2, D2, imageSize, R, tvec, R1, R2, P1, P2, Q, flags, newImageSize) + public static void fisheye_stereoRectify(Mat K1, Mat D1, Mat K2, Mat D2, Size imageSize, Mat R, Mat tvec, Mat R1, Mat R2, Mat P1, Mat P2, Mat Q, int flags, Size newImageSize) + { + + fisheye_stereoRectify_2(K1.nativeObj, D1.nativeObj, K2.nativeObj, D2.nativeObj, imageSize.width, imageSize.height, R.nativeObj, tvec.nativeObj, R1.nativeObj, R2.nativeObj, P1.nativeObj, P2.nativeObj, Q.nativeObj, flags, newImageSize.width, newImageSize.height); + + return; + } + + //javadoc: fisheye_stereoRectify(K1, D1, K2, D2, imageSize, R, tvec, R1, R2, P1, P2, Q, flags) + public static void fisheye_stereoRectify(Mat K1, Mat D1, Mat K2, Mat D2, Size imageSize, Mat R, Mat tvec, Mat R1, Mat R2, Mat P1, Mat P2, Mat Q, int flags) + { + + fisheye_stereoRectify_3(K1.nativeObj, D1.nativeObj, K2.nativeObj, D2.nativeObj, imageSize.width, imageSize.height, R.nativeObj, tvec.nativeObj, R1.nativeObj, R2.nativeObj, P1.nativeObj, P2.nativeObj, Q.nativeObj, flags); + + return; + } + + + // + // C++: void cv::fisheye::undistortImage(Mat distorted, Mat& undistorted, Mat K, Mat D, Mat Knew = cv::Mat(), Size new_size = Size()) + // + + //javadoc: fisheye_undistortImage(distorted, undistorted, K, D, Knew, new_size) + public static void fisheye_undistortImage(Mat distorted, Mat undistorted, Mat K, Mat D, Mat Knew, Size new_size) + { + + fisheye_undistortImage_0(distorted.nativeObj, undistorted.nativeObj, K.nativeObj, D.nativeObj, Knew.nativeObj, new_size.width, new_size.height); + + return; + } + + //javadoc: fisheye_undistortImage(distorted, undistorted, K, D, Knew) + public static void fisheye_undistortImage(Mat distorted, Mat undistorted, Mat K, Mat D, Mat Knew) + { + + fisheye_undistortImage_1(distorted.nativeObj, undistorted.nativeObj, K.nativeObj, D.nativeObj, Knew.nativeObj); + + return; + } + + //javadoc: fisheye_undistortImage(distorted, undistorted, K, D) + public static void fisheye_undistortImage(Mat distorted, Mat undistorted, Mat K, Mat D) + { + + fisheye_undistortImage_2(distorted.nativeObj, undistorted.nativeObj, K.nativeObj, D.nativeObj); + + return; + } + + + // + // C++: void cv::fisheye::undistortPoints(Mat distorted, Mat& undistorted, Mat K, Mat D, Mat R = Mat(), Mat P = Mat()) + // + + //javadoc: fisheye_undistortPoints(distorted, undistorted, K, D, R, P) + public static void fisheye_undistortPoints(Mat distorted, Mat undistorted, Mat K, Mat D, Mat R, Mat P) + { + + fisheye_undistortPoints_0(distorted.nativeObj, undistorted.nativeObj, K.nativeObj, D.nativeObj, R.nativeObj, P.nativeObj); + + return; + } + + //javadoc: fisheye_undistortPoints(distorted, undistorted, K, D, R) + public static void fisheye_undistortPoints(Mat distorted, Mat undistorted, Mat K, Mat D, Mat R) + { + + fisheye_undistortPoints_1(distorted.nativeObj, undistorted.nativeObj, K.nativeObj, D.nativeObj, R.nativeObj); + + return; + } + + //javadoc: fisheye_undistortPoints(distorted, undistorted, K, D) + public static void fisheye_undistortPoints(Mat distorted, Mat undistorted, Mat K, Mat D) + { + + fisheye_undistortPoints_2(distorted.nativeObj, undistorted.nativeObj, K.nativeObj, D.nativeObj); + + return; + } + + + + + // C++: Mat cv::estimateAffine2D(Mat from, Mat to, Mat& inliers = Mat(), int method = RANSAC, double ransacReprojThreshold = 3, size_t maxIters = 2000, double confidence = 0.99, size_t refineIters = 10) + private static native long estimateAffine2D_0(long from_nativeObj, long to_nativeObj, long inliers_nativeObj, int method, double ransacReprojThreshold, long maxIters, double confidence, long refineIters); + private static native long estimateAffine2D_1(long from_nativeObj, long to_nativeObj, long inliers_nativeObj, int method, double ransacReprojThreshold, long maxIters, double confidence); + private static native long estimateAffine2D_2(long from_nativeObj, long to_nativeObj, long inliers_nativeObj, int method, double ransacReprojThreshold, long maxIters); + private static native long estimateAffine2D_3(long from_nativeObj, long to_nativeObj, long inliers_nativeObj, int method, double ransacReprojThreshold); + private static native long estimateAffine2D_4(long from_nativeObj, long to_nativeObj, long inliers_nativeObj, int method); + private static native long estimateAffine2D_5(long from_nativeObj, long to_nativeObj, long inliers_nativeObj); + private static native long estimateAffine2D_6(long from_nativeObj, long to_nativeObj); + + // C++: Mat cv::estimateAffinePartial2D(Mat from, Mat to, Mat& inliers = Mat(), int method = RANSAC, double ransacReprojThreshold = 3, size_t maxIters = 2000, double confidence = 0.99, size_t refineIters = 10) + private static native long estimateAffinePartial2D_0(long from_nativeObj, long to_nativeObj, long inliers_nativeObj, int method, double ransacReprojThreshold, long maxIters, double confidence, long refineIters); + private static native long estimateAffinePartial2D_1(long from_nativeObj, long to_nativeObj, long inliers_nativeObj, int method, double ransacReprojThreshold, long maxIters, double confidence); + private static native long estimateAffinePartial2D_2(long from_nativeObj, long to_nativeObj, long inliers_nativeObj, int method, double ransacReprojThreshold, long maxIters); + private static native long estimateAffinePartial2D_3(long from_nativeObj, long to_nativeObj, long inliers_nativeObj, int method, double ransacReprojThreshold); + private static native long estimateAffinePartial2D_4(long from_nativeObj, long to_nativeObj, long inliers_nativeObj, int method); + private static native long estimateAffinePartial2D_5(long from_nativeObj, long to_nativeObj, long inliers_nativeObj); + private static native long estimateAffinePartial2D_6(long from_nativeObj, long to_nativeObj); + + // C++: Mat cv::findEssentialMat(Mat points1, Mat points2, Mat cameraMatrix, int method = RANSAC, double prob = 0.999, double threshold = 1.0, Mat& mask = Mat()) + private static native long findEssentialMat_0(long points1_nativeObj, long points2_nativeObj, long cameraMatrix_nativeObj, int method, double prob, double threshold, long mask_nativeObj); + private static native long findEssentialMat_1(long points1_nativeObj, long points2_nativeObj, long cameraMatrix_nativeObj, int method, double prob, double threshold); + private static native long findEssentialMat_2(long points1_nativeObj, long points2_nativeObj, long cameraMatrix_nativeObj, int method, double prob); + private static native long findEssentialMat_3(long points1_nativeObj, long points2_nativeObj, long cameraMatrix_nativeObj, int method); + private static native long findEssentialMat_4(long points1_nativeObj, long points2_nativeObj, long cameraMatrix_nativeObj); + + // C++: Mat cv::findEssentialMat(Mat points1, Mat points2, double focal = 1.0, Point2d pp = Point2d(0, 0), int method = RANSAC, double prob = 0.999, double threshold = 1.0, Mat& mask = Mat()) + private static native long findEssentialMat_5(long points1_nativeObj, long points2_nativeObj, double focal, double pp_x, double pp_y, int method, double prob, double threshold, long mask_nativeObj); + private static native long findEssentialMat_6(long points1_nativeObj, long points2_nativeObj, double focal, double pp_x, double pp_y, int method, double prob, double threshold); + private static native long findEssentialMat_7(long points1_nativeObj, long points2_nativeObj, double focal, double pp_x, double pp_y, int method, double prob); + private static native long findEssentialMat_8(long points1_nativeObj, long points2_nativeObj, double focal, double pp_x, double pp_y, int method); + private static native long findEssentialMat_9(long points1_nativeObj, long points2_nativeObj, double focal, double pp_x, double pp_y); + private static native long findEssentialMat_10(long points1_nativeObj, long points2_nativeObj, double focal); + private static native long findEssentialMat_11(long points1_nativeObj, long points2_nativeObj); + + // C++: Mat cv::findFundamentalMat(vector_Point2f points1, vector_Point2f points2, int method = FM_RANSAC, double ransacReprojThreshold = 3., double confidence = 0.99, Mat& mask = Mat()) + private static native long findFundamentalMat_0(long points1_mat_nativeObj, long points2_mat_nativeObj, int method, double ransacReprojThreshold, double confidence, long mask_nativeObj); + private static native long findFundamentalMat_1(long points1_mat_nativeObj, long points2_mat_nativeObj, int method, double ransacReprojThreshold, double confidence); + private static native long findFundamentalMat_2(long points1_mat_nativeObj, long points2_mat_nativeObj, int method, double ransacReprojThreshold); + private static native long findFundamentalMat_3(long points1_mat_nativeObj, long points2_mat_nativeObj, int method); + private static native long findFundamentalMat_4(long points1_mat_nativeObj, long points2_mat_nativeObj); + + // C++: Mat cv::findHomography(vector_Point2f srcPoints, vector_Point2f dstPoints, int method = 0, double ransacReprojThreshold = 3, Mat& mask = Mat(), int maxIters = 2000, double confidence = 0.995) + private static native long findHomography_0(long srcPoints_mat_nativeObj, long dstPoints_mat_nativeObj, int method, double ransacReprojThreshold, long mask_nativeObj, int maxIters, double confidence); + private static native long findHomography_1(long srcPoints_mat_nativeObj, long dstPoints_mat_nativeObj, int method, double ransacReprojThreshold, long mask_nativeObj, int maxIters); + private static native long findHomography_2(long srcPoints_mat_nativeObj, long dstPoints_mat_nativeObj, int method, double ransacReprojThreshold, long mask_nativeObj); + private static native long findHomography_3(long srcPoints_mat_nativeObj, long dstPoints_mat_nativeObj, int method, double ransacReprojThreshold); + private static native long findHomography_4(long srcPoints_mat_nativeObj, long dstPoints_mat_nativeObj, int method); + private static native long findHomography_5(long srcPoints_mat_nativeObj, long dstPoints_mat_nativeObj); + + // C++: Mat cv::getDefaultNewCameraMatrix(Mat cameraMatrix, Size imgsize = Size(), bool centerPrincipalPoint = false) + private static native long getDefaultNewCameraMatrix_0(long cameraMatrix_nativeObj, double imgsize_width, double imgsize_height, boolean centerPrincipalPoint); + private static native long getDefaultNewCameraMatrix_1(long cameraMatrix_nativeObj, double imgsize_width, double imgsize_height); + private static native long getDefaultNewCameraMatrix_2(long cameraMatrix_nativeObj); + + // C++: Mat cv::getOptimalNewCameraMatrix(Mat cameraMatrix, Mat distCoeffs, Size imageSize, double alpha, Size newImgSize = Size(), Rect* validPixROI = 0, bool centerPrincipalPoint = false) + private static native long getOptimalNewCameraMatrix_0(long cameraMatrix_nativeObj, long distCoeffs_nativeObj, double imageSize_width, double imageSize_height, double alpha, double newImgSize_width, double newImgSize_height, double[] validPixROI_out, boolean centerPrincipalPoint); + private static native long getOptimalNewCameraMatrix_1(long cameraMatrix_nativeObj, long distCoeffs_nativeObj, double imageSize_width, double imageSize_height, double alpha, double newImgSize_width, double newImgSize_height, double[] validPixROI_out); + private static native long getOptimalNewCameraMatrix_2(long cameraMatrix_nativeObj, long distCoeffs_nativeObj, double imageSize_width, double imageSize_height, double alpha, double newImgSize_width, double newImgSize_height); + private static native long getOptimalNewCameraMatrix_3(long cameraMatrix_nativeObj, long distCoeffs_nativeObj, double imageSize_width, double imageSize_height, double alpha); + + // C++: Mat cv::initCameraMatrix2D(vector_vector_Point3f objectPoints, vector_vector_Point2f imagePoints, Size imageSize, double aspectRatio = 1.0) + private static native long initCameraMatrix2D_0(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, double imageSize_width, double imageSize_height, double aspectRatio); + private static native long initCameraMatrix2D_1(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, double imageSize_width, double imageSize_height); + + // C++: Rect cv::getValidDisparityROI(Rect roi1, Rect roi2, int minDisparity, int numberOfDisparities, int SADWindowSize) + private static native double[] getValidDisparityROI_0(int roi1_x, int roi1_y, int roi1_width, int roi1_height, int roi2_x, int roi2_y, int roi2_width, int roi2_height, int minDisparity, int numberOfDisparities, int SADWindowSize); + + // C++: Vec3d cv::RQDecomp3x3(Mat src, Mat& mtxR, Mat& mtxQ, Mat& Qx = Mat(), Mat& Qy = Mat(), Mat& Qz = Mat()) + private static native double[] RQDecomp3x3_0(long src_nativeObj, long mtxR_nativeObj, long mtxQ_nativeObj, long Qx_nativeObj, long Qy_nativeObj, long Qz_nativeObj); + private static native double[] RQDecomp3x3_1(long src_nativeObj, long mtxR_nativeObj, long mtxQ_nativeObj, long Qx_nativeObj, long Qy_nativeObj); + private static native double[] RQDecomp3x3_2(long src_nativeObj, long mtxR_nativeObj, long mtxQ_nativeObj, long Qx_nativeObj); + private static native double[] RQDecomp3x3_3(long src_nativeObj, long mtxR_nativeObj, long mtxQ_nativeObj); + + // C++: bool cv::checkChessboard(Mat img, Size size) + private static native boolean checkChessboard_0(long img_nativeObj, double size_width, double size_height); + + // C++: bool cv::find4QuadCornerSubpix(Mat img, Mat& corners, Size region_size) + private static native boolean find4QuadCornerSubpix_0(long img_nativeObj, long corners_nativeObj, double region_size_width, double region_size_height); + + // C++: bool cv::findChessboardCorners(Mat image, Size patternSize, vector_Point2f& corners, int flags = CALIB_CB_ADAPTIVE_THRESH + CALIB_CB_NORMALIZE_IMAGE) + private static native boolean findChessboardCorners_0(long image_nativeObj, double patternSize_width, double patternSize_height, long corners_mat_nativeObj, int flags); + private static native boolean findChessboardCorners_1(long image_nativeObj, double patternSize_width, double patternSize_height, long corners_mat_nativeObj); + + // C++: bool cv::findChessboardCornersSB(Mat image, Size patternSize, Mat& corners, int flags = 0) + private static native boolean findChessboardCornersSB_0(long image_nativeObj, double patternSize_width, double patternSize_height, long corners_nativeObj, int flags); + private static native boolean findChessboardCornersSB_1(long image_nativeObj, double patternSize_width, double patternSize_height, long corners_nativeObj); + + // C++: bool cv::findCirclesGrid(Mat image, Size patternSize, Mat& centers, int flags = CALIB_CB_SYMMETRIC_GRID, Ptr_FeatureDetector blobDetector = SimpleBlobDetector::create()) + private static native boolean findCirclesGrid_0(long image_nativeObj, double patternSize_width, double patternSize_height, long centers_nativeObj, int flags); + private static native boolean findCirclesGrid_2(long image_nativeObj, double patternSize_width, double patternSize_height, long centers_nativeObj); + + // C++: bool cv::solvePnP(vector_Point3f objectPoints, vector_Point2f imagePoints, Mat cameraMatrix, vector_double distCoeffs, Mat& rvec, Mat& tvec, bool useExtrinsicGuess = false, int flags = SOLVEPNP_ITERATIVE) + private static native boolean solvePnP_0(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_mat_nativeObj, long rvec_nativeObj, long tvec_nativeObj, boolean useExtrinsicGuess, int flags); + private static native boolean solvePnP_1(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_mat_nativeObj, long rvec_nativeObj, long tvec_nativeObj, boolean useExtrinsicGuess); + private static native boolean solvePnP_2(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_mat_nativeObj, long rvec_nativeObj, long tvec_nativeObj); + + // C++: bool cv::solvePnPRansac(vector_Point3f objectPoints, vector_Point2f imagePoints, Mat cameraMatrix, vector_double distCoeffs, Mat& rvec, Mat& tvec, bool useExtrinsicGuess = false, int iterationsCount = 100, float reprojectionError = 8.0, double confidence = 0.99, Mat& inliers = Mat(), int flags = SOLVEPNP_ITERATIVE) + private static native boolean solvePnPRansac_0(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_mat_nativeObj, long rvec_nativeObj, long tvec_nativeObj, boolean useExtrinsicGuess, int iterationsCount, float reprojectionError, double confidence, long inliers_nativeObj, int flags); + private static native boolean solvePnPRansac_1(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_mat_nativeObj, long rvec_nativeObj, long tvec_nativeObj, boolean useExtrinsicGuess, int iterationsCount, float reprojectionError, double confidence, long inliers_nativeObj); + private static native boolean solvePnPRansac_2(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_mat_nativeObj, long rvec_nativeObj, long tvec_nativeObj, boolean useExtrinsicGuess, int iterationsCount, float reprojectionError, double confidence); + private static native boolean solvePnPRansac_3(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_mat_nativeObj, long rvec_nativeObj, long tvec_nativeObj, boolean useExtrinsicGuess, int iterationsCount, float reprojectionError); + private static native boolean solvePnPRansac_4(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_mat_nativeObj, long rvec_nativeObj, long tvec_nativeObj, boolean useExtrinsicGuess, int iterationsCount); + private static native boolean solvePnPRansac_5(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_mat_nativeObj, long rvec_nativeObj, long tvec_nativeObj, boolean useExtrinsicGuess); + private static native boolean solvePnPRansac_6(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_mat_nativeObj, long rvec_nativeObj, long tvec_nativeObj); + + // C++: bool cv::stereoRectifyUncalibrated(Mat points1, Mat points2, Mat F, Size imgSize, Mat& H1, Mat& H2, double threshold = 5) + private static native boolean stereoRectifyUncalibrated_0(long points1_nativeObj, long points2_nativeObj, long F_nativeObj, double imgSize_width, double imgSize_height, long H1_nativeObj, long H2_nativeObj, double threshold); + private static native boolean stereoRectifyUncalibrated_1(long points1_nativeObj, long points2_nativeObj, long F_nativeObj, double imgSize_width, double imgSize_height, long H1_nativeObj, long H2_nativeObj); + + // C++: double cv::calibrateCamera(vector_Mat objectPoints, vector_Mat imagePoints, Size imageSize, Mat& cameraMatrix, Mat& distCoeffs, vector_Mat& rvecs, vector_Mat& tvecs, Mat& stdDeviationsIntrinsics, Mat& stdDeviationsExtrinsics, Mat& perViewErrors, int flags = 0, TermCriteria criteria = TermCriteria( TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)) + private static native double calibrateCameraExtended_0(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, long stdDeviationsIntrinsics_nativeObj, long stdDeviationsExtrinsics_nativeObj, long perViewErrors_nativeObj, int flags, int criteria_type, int criteria_maxCount, double criteria_epsilon); + private static native double calibrateCameraExtended_1(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, long stdDeviationsIntrinsics_nativeObj, long stdDeviationsExtrinsics_nativeObj, long perViewErrors_nativeObj, int flags); + private static native double calibrateCameraExtended_2(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, long stdDeviationsIntrinsics_nativeObj, long stdDeviationsExtrinsics_nativeObj, long perViewErrors_nativeObj); + + // C++: double cv::calibrateCamera(vector_Mat objectPoints, vector_Mat imagePoints, Size imageSize, Mat& cameraMatrix, Mat& distCoeffs, vector_Mat& rvecs, vector_Mat& tvecs, int flags = 0, TermCriteria criteria = TermCriteria( TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)) + private static native double calibrateCamera_0(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, int flags, int criteria_type, int criteria_maxCount, double criteria_epsilon); + private static native double calibrateCamera_1(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, int flags); + private static native double calibrateCamera_2(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, double imageSize_width, double imageSize_height, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj); + + // C++: double cv::calibrateCameraRO(vector_Mat objectPoints, vector_Mat imagePoints, Size imageSize, int iFixedPoint, Mat& cameraMatrix, Mat& distCoeffs, vector_Mat& rvecs, vector_Mat& tvecs, Mat& newObjPoints, Mat& stdDeviationsIntrinsics, Mat& stdDeviationsExtrinsics, Mat& stdDeviationsObjPoints, Mat& perViewErrors, int flags = 0, TermCriteria criteria = TermCriteria( TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)) + private static native double calibrateCameraROExtended_0(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, double imageSize_width, double imageSize_height, int iFixedPoint, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, long newObjPoints_nativeObj, long stdDeviationsIntrinsics_nativeObj, long stdDeviationsExtrinsics_nativeObj, long stdDeviationsObjPoints_nativeObj, long perViewErrors_nativeObj, int flags, int criteria_type, int criteria_maxCount, double criteria_epsilon); + private static native double calibrateCameraROExtended_1(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, double imageSize_width, double imageSize_height, int iFixedPoint, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, long newObjPoints_nativeObj, long stdDeviationsIntrinsics_nativeObj, long stdDeviationsExtrinsics_nativeObj, long stdDeviationsObjPoints_nativeObj, long perViewErrors_nativeObj, int flags); + private static native double calibrateCameraROExtended_2(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, double imageSize_width, double imageSize_height, int iFixedPoint, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, long newObjPoints_nativeObj, long stdDeviationsIntrinsics_nativeObj, long stdDeviationsExtrinsics_nativeObj, long stdDeviationsObjPoints_nativeObj, long perViewErrors_nativeObj); + + // C++: double cv::calibrateCameraRO(vector_Mat objectPoints, vector_Mat imagePoints, Size imageSize, int iFixedPoint, Mat& cameraMatrix, Mat& distCoeffs, vector_Mat& rvecs, vector_Mat& tvecs, Mat& newObjPoints, int flags = 0, TermCriteria criteria = TermCriteria( TermCriteria::COUNT + TermCriteria::EPS, 30, DBL_EPSILON)) + private static native double calibrateCameraRO_0(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, double imageSize_width, double imageSize_height, int iFixedPoint, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, long newObjPoints_nativeObj, int flags, int criteria_type, int criteria_maxCount, double criteria_epsilon); + private static native double calibrateCameraRO_1(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, double imageSize_width, double imageSize_height, int iFixedPoint, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, long newObjPoints_nativeObj, int flags); + private static native double calibrateCameraRO_2(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, double imageSize_width, double imageSize_height, int iFixedPoint, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, long newObjPoints_nativeObj); + + // C++: double cv::sampsonDistance(Mat pt1, Mat pt2, Mat F) + private static native double sampsonDistance_0(long pt1_nativeObj, long pt2_nativeObj, long F_nativeObj); + + // C++: double cv::stereoCalibrate(vector_Mat objectPoints, vector_Mat imagePoints1, vector_Mat imagePoints2, Mat& cameraMatrix1, Mat& distCoeffs1, Mat& cameraMatrix2, Mat& distCoeffs2, Size imageSize, Mat& R, Mat& T, Mat& E, Mat& F, Mat& perViewErrors, int flags = CALIB_FIX_INTRINSIC, TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 1e-6)) + private static native double stereoCalibrateExtended_0(long objectPoints_mat_nativeObj, long imagePoints1_mat_nativeObj, long imagePoints2_mat_nativeObj, long cameraMatrix1_nativeObj, long distCoeffs1_nativeObj, long cameraMatrix2_nativeObj, long distCoeffs2_nativeObj, double imageSize_width, double imageSize_height, long R_nativeObj, long T_nativeObj, long E_nativeObj, long F_nativeObj, long perViewErrors_nativeObj, int flags, int criteria_type, int criteria_maxCount, double criteria_epsilon); + private static native double stereoCalibrateExtended_1(long objectPoints_mat_nativeObj, long imagePoints1_mat_nativeObj, long imagePoints2_mat_nativeObj, long cameraMatrix1_nativeObj, long distCoeffs1_nativeObj, long cameraMatrix2_nativeObj, long distCoeffs2_nativeObj, double imageSize_width, double imageSize_height, long R_nativeObj, long T_nativeObj, long E_nativeObj, long F_nativeObj, long perViewErrors_nativeObj, int flags); + private static native double stereoCalibrateExtended_2(long objectPoints_mat_nativeObj, long imagePoints1_mat_nativeObj, long imagePoints2_mat_nativeObj, long cameraMatrix1_nativeObj, long distCoeffs1_nativeObj, long cameraMatrix2_nativeObj, long distCoeffs2_nativeObj, double imageSize_width, double imageSize_height, long R_nativeObj, long T_nativeObj, long E_nativeObj, long F_nativeObj, long perViewErrors_nativeObj); + + // C++: double cv::stereoCalibrate(vector_Mat objectPoints, vector_Mat imagePoints1, vector_Mat imagePoints2, Mat& cameraMatrix1, Mat& distCoeffs1, Mat& cameraMatrix2, Mat& distCoeffs2, Size imageSize, Mat& R, Mat& T, Mat& E, Mat& F, int flags = CALIB_FIX_INTRINSIC, TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 1e-6)) + private static native double stereoCalibrate_0(long objectPoints_mat_nativeObj, long imagePoints1_mat_nativeObj, long imagePoints2_mat_nativeObj, long cameraMatrix1_nativeObj, long distCoeffs1_nativeObj, long cameraMatrix2_nativeObj, long distCoeffs2_nativeObj, double imageSize_width, double imageSize_height, long R_nativeObj, long T_nativeObj, long E_nativeObj, long F_nativeObj, int flags, int criteria_type, int criteria_maxCount, double criteria_epsilon); + private static native double stereoCalibrate_1(long objectPoints_mat_nativeObj, long imagePoints1_mat_nativeObj, long imagePoints2_mat_nativeObj, long cameraMatrix1_nativeObj, long distCoeffs1_nativeObj, long cameraMatrix2_nativeObj, long distCoeffs2_nativeObj, double imageSize_width, double imageSize_height, long R_nativeObj, long T_nativeObj, long E_nativeObj, long F_nativeObj, int flags); + private static native double stereoCalibrate_2(long objectPoints_mat_nativeObj, long imagePoints1_mat_nativeObj, long imagePoints2_mat_nativeObj, long cameraMatrix1_nativeObj, long distCoeffs1_nativeObj, long cameraMatrix2_nativeObj, long distCoeffs2_nativeObj, double imageSize_width, double imageSize_height, long R_nativeObj, long T_nativeObj, long E_nativeObj, long F_nativeObj); + + // C++: double cv::fisheye::calibrate(vector_Mat objectPoints, vector_Mat imagePoints, Size image_size, Mat& K, Mat& D, vector_Mat& rvecs, vector_Mat& tvecs, int flags = 0, TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON)) + private static native double fisheye_calibrate_0(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, double image_size_width, double image_size_height, long K_nativeObj, long D_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, int flags, int criteria_type, int criteria_maxCount, double criteria_epsilon); + private static native double fisheye_calibrate_1(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, double image_size_width, double image_size_height, long K_nativeObj, long D_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, int flags); + private static native double fisheye_calibrate_2(long objectPoints_mat_nativeObj, long imagePoints_mat_nativeObj, double image_size_width, double image_size_height, long K_nativeObj, long D_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj); + + // C++: double cv::fisheye::stereoCalibrate(vector_Mat objectPoints, vector_Mat imagePoints1, vector_Mat imagePoints2, Mat& K1, Mat& D1, Mat& K2, Mat& D2, Size imageSize, Mat& R, Mat& T, int flags = fisheye::CALIB_FIX_INTRINSIC, TermCriteria criteria = TermCriteria(TermCriteria::COUNT + TermCriteria::EPS, 100, DBL_EPSILON)) + private static native double fisheye_stereoCalibrate_0(long objectPoints_mat_nativeObj, long imagePoints1_mat_nativeObj, long imagePoints2_mat_nativeObj, long K1_nativeObj, long D1_nativeObj, long K2_nativeObj, long D2_nativeObj, double imageSize_width, double imageSize_height, long R_nativeObj, long T_nativeObj, int flags, int criteria_type, int criteria_maxCount, double criteria_epsilon); + private static native double fisheye_stereoCalibrate_1(long objectPoints_mat_nativeObj, long imagePoints1_mat_nativeObj, long imagePoints2_mat_nativeObj, long K1_nativeObj, long D1_nativeObj, long K2_nativeObj, long D2_nativeObj, double imageSize_width, double imageSize_height, long R_nativeObj, long T_nativeObj, int flags); + private static native double fisheye_stereoCalibrate_2(long objectPoints_mat_nativeObj, long imagePoints1_mat_nativeObj, long imagePoints2_mat_nativeObj, long K1_nativeObj, long D1_nativeObj, long K2_nativeObj, long D2_nativeObj, double imageSize_width, double imageSize_height, long R_nativeObj, long T_nativeObj); + + // C++: float cv::rectify3Collinear(Mat cameraMatrix1, Mat distCoeffs1, Mat cameraMatrix2, Mat distCoeffs2, Mat cameraMatrix3, Mat distCoeffs3, vector_Mat imgpt1, vector_Mat imgpt3, Size imageSize, Mat R12, Mat T12, Mat R13, Mat T13, Mat& R1, Mat& R2, Mat& R3, Mat& P1, Mat& P2, Mat& P3, Mat& Q, double alpha, Size newImgSize, Rect* roi1, Rect* roi2, int flags) + private static native float rectify3Collinear_0(long cameraMatrix1_nativeObj, long distCoeffs1_nativeObj, long cameraMatrix2_nativeObj, long distCoeffs2_nativeObj, long cameraMatrix3_nativeObj, long distCoeffs3_nativeObj, long imgpt1_mat_nativeObj, long imgpt3_mat_nativeObj, double imageSize_width, double imageSize_height, long R12_nativeObj, long T12_nativeObj, long R13_nativeObj, long T13_nativeObj, long R1_nativeObj, long R2_nativeObj, long R3_nativeObj, long P1_nativeObj, long P2_nativeObj, long P3_nativeObj, long Q_nativeObj, double alpha, double newImgSize_width, double newImgSize_height, double[] roi1_out, double[] roi2_out, int flags); + + // C++: int cv::decomposeHomographyMat(Mat H, Mat K, vector_Mat& rotations, vector_Mat& translations, vector_Mat& normals) + private static native int decomposeHomographyMat_0(long H_nativeObj, long K_nativeObj, long rotations_mat_nativeObj, long translations_mat_nativeObj, long normals_mat_nativeObj); + + // C++: int cv::estimateAffine3D(Mat src, Mat dst, Mat& out, Mat& inliers, double ransacThreshold = 3, double confidence = 0.99) + private static native int estimateAffine3D_0(long src_nativeObj, long dst_nativeObj, long out_nativeObj, long inliers_nativeObj, double ransacThreshold, double confidence); + private static native int estimateAffine3D_1(long src_nativeObj, long dst_nativeObj, long out_nativeObj, long inliers_nativeObj, double ransacThreshold); + private static native int estimateAffine3D_2(long src_nativeObj, long dst_nativeObj, long out_nativeObj, long inliers_nativeObj); + + // C++: int cv::recoverPose(Mat E, Mat points1, Mat points2, Mat& R, Mat& t, double focal = 1.0, Point2d pp = Point2d(0, 0), Mat& mask = Mat()) + private static native int recoverPose_0(long E_nativeObj, long points1_nativeObj, long points2_nativeObj, long R_nativeObj, long t_nativeObj, double focal, double pp_x, double pp_y, long mask_nativeObj); + private static native int recoverPose_1(long E_nativeObj, long points1_nativeObj, long points2_nativeObj, long R_nativeObj, long t_nativeObj, double focal, double pp_x, double pp_y); + private static native int recoverPose_2(long E_nativeObj, long points1_nativeObj, long points2_nativeObj, long R_nativeObj, long t_nativeObj, double focal); + private static native int recoverPose_3(long E_nativeObj, long points1_nativeObj, long points2_nativeObj, long R_nativeObj, long t_nativeObj); + + // C++: int cv::recoverPose(Mat E, Mat points1, Mat points2, Mat cameraMatrix, Mat& R, Mat& t, Mat& mask = Mat()) + private static native int recoverPose_4(long E_nativeObj, long points1_nativeObj, long points2_nativeObj, long cameraMatrix_nativeObj, long R_nativeObj, long t_nativeObj, long mask_nativeObj); + private static native int recoverPose_5(long E_nativeObj, long points1_nativeObj, long points2_nativeObj, long cameraMatrix_nativeObj, long R_nativeObj, long t_nativeObj); + + // C++: int cv::recoverPose(Mat E, Mat points1, Mat points2, Mat cameraMatrix, Mat& R, Mat& t, double distanceThresh, Mat& mask = Mat(), Mat& triangulatedPoints = Mat()) + private static native int recoverPose_6(long E_nativeObj, long points1_nativeObj, long points2_nativeObj, long cameraMatrix_nativeObj, long R_nativeObj, long t_nativeObj, double distanceThresh, long mask_nativeObj, long triangulatedPoints_nativeObj); + private static native int recoverPose_7(long E_nativeObj, long points1_nativeObj, long points2_nativeObj, long cameraMatrix_nativeObj, long R_nativeObj, long t_nativeObj, double distanceThresh, long mask_nativeObj); + private static native int recoverPose_8(long E_nativeObj, long points1_nativeObj, long points2_nativeObj, long cameraMatrix_nativeObj, long R_nativeObj, long t_nativeObj, double distanceThresh); + + // C++: int cv::solveP3P(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, vector_Mat& rvecs, vector_Mat& tvecs, int flags) + private static native int solveP3P_0(long objectPoints_nativeObj, long imagePoints_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, int flags); + + // C++: int cv::solvePnPGeneric(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, vector_Mat& rvecs, vector_Mat& tvecs, bool useExtrinsicGuess = false, SolvePnPMethod flags = SOLVEPNP_ITERATIVE, Mat rvec = Mat(), Mat tvec = Mat(), Mat& reprojectionError = Mat()) + private static native int solvePnPGeneric_0(long objectPoints_nativeObj, long imagePoints_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, boolean useExtrinsicGuess, int flags, long rvec_nativeObj, long tvec_nativeObj, long reprojectionError_nativeObj); + private static native int solvePnPGeneric_1(long objectPoints_nativeObj, long imagePoints_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, boolean useExtrinsicGuess, int flags, long rvec_nativeObj, long tvec_nativeObj); + private static native int solvePnPGeneric_2(long objectPoints_nativeObj, long imagePoints_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, boolean useExtrinsicGuess, int flags, long rvec_nativeObj); + private static native int solvePnPGeneric_3(long objectPoints_nativeObj, long imagePoints_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, boolean useExtrinsicGuess, int flags); + private static native int solvePnPGeneric_4(long objectPoints_nativeObj, long imagePoints_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj, boolean useExtrinsicGuess); + private static native int solvePnPGeneric_5(long objectPoints_nativeObj, long imagePoints_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvecs_mat_nativeObj, long tvecs_mat_nativeObj); + + // C++: void cv::Rodrigues(Mat src, Mat& dst, Mat& jacobian = Mat()) + private static native void Rodrigues_0(long src_nativeObj, long dst_nativeObj, long jacobian_nativeObj); + private static native void Rodrigues_1(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::calibrateHandEye(vector_Mat R_gripper2base, vector_Mat t_gripper2base, vector_Mat R_target2cam, vector_Mat t_target2cam, Mat& R_cam2gripper, Mat& t_cam2gripper, HandEyeCalibrationMethod method = CALIB_HAND_EYE_TSAI) + private static native void calibrateHandEye_0(long R_gripper2base_mat_nativeObj, long t_gripper2base_mat_nativeObj, long R_target2cam_mat_nativeObj, long t_target2cam_mat_nativeObj, long R_cam2gripper_nativeObj, long t_cam2gripper_nativeObj, int method); + private static native void calibrateHandEye_1(long R_gripper2base_mat_nativeObj, long t_gripper2base_mat_nativeObj, long R_target2cam_mat_nativeObj, long t_target2cam_mat_nativeObj, long R_cam2gripper_nativeObj, long t_cam2gripper_nativeObj); + + // C++: void cv::calibrationMatrixValues(Mat cameraMatrix, Size imageSize, double apertureWidth, double apertureHeight, double& fovx, double& fovy, double& focalLength, Point2d& principalPoint, double& aspectRatio) + private static native void calibrationMatrixValues_0(long cameraMatrix_nativeObj, double imageSize_width, double imageSize_height, double apertureWidth, double apertureHeight, double[] fovx_out, double[] fovy_out, double[] focalLength_out, double[] principalPoint_out, double[] aspectRatio_out); + + // C++: void cv::composeRT(Mat rvec1, Mat tvec1, Mat rvec2, Mat tvec2, Mat& rvec3, Mat& tvec3, Mat& dr3dr1 = Mat(), Mat& dr3dt1 = Mat(), Mat& dr3dr2 = Mat(), Mat& dr3dt2 = Mat(), Mat& dt3dr1 = Mat(), Mat& dt3dt1 = Mat(), Mat& dt3dr2 = Mat(), Mat& dt3dt2 = Mat()) + private static native void composeRT_0(long rvec1_nativeObj, long tvec1_nativeObj, long rvec2_nativeObj, long tvec2_nativeObj, long rvec3_nativeObj, long tvec3_nativeObj, long dr3dr1_nativeObj, long dr3dt1_nativeObj, long dr3dr2_nativeObj, long dr3dt2_nativeObj, long dt3dr1_nativeObj, long dt3dt1_nativeObj, long dt3dr2_nativeObj, long dt3dt2_nativeObj); + private static native void composeRT_1(long rvec1_nativeObj, long tvec1_nativeObj, long rvec2_nativeObj, long tvec2_nativeObj, long rvec3_nativeObj, long tvec3_nativeObj, long dr3dr1_nativeObj, long dr3dt1_nativeObj, long dr3dr2_nativeObj, long dr3dt2_nativeObj, long dt3dr1_nativeObj, long dt3dt1_nativeObj, long dt3dr2_nativeObj); + private static native void composeRT_2(long rvec1_nativeObj, long tvec1_nativeObj, long rvec2_nativeObj, long tvec2_nativeObj, long rvec3_nativeObj, long tvec3_nativeObj, long dr3dr1_nativeObj, long dr3dt1_nativeObj, long dr3dr2_nativeObj, long dr3dt2_nativeObj, long dt3dr1_nativeObj, long dt3dt1_nativeObj); + private static native void composeRT_3(long rvec1_nativeObj, long tvec1_nativeObj, long rvec2_nativeObj, long tvec2_nativeObj, long rvec3_nativeObj, long tvec3_nativeObj, long dr3dr1_nativeObj, long dr3dt1_nativeObj, long dr3dr2_nativeObj, long dr3dt2_nativeObj, long dt3dr1_nativeObj); + private static native void composeRT_4(long rvec1_nativeObj, long tvec1_nativeObj, long rvec2_nativeObj, long tvec2_nativeObj, long rvec3_nativeObj, long tvec3_nativeObj, long dr3dr1_nativeObj, long dr3dt1_nativeObj, long dr3dr2_nativeObj, long dr3dt2_nativeObj); + private static native void composeRT_5(long rvec1_nativeObj, long tvec1_nativeObj, long rvec2_nativeObj, long tvec2_nativeObj, long rvec3_nativeObj, long tvec3_nativeObj, long dr3dr1_nativeObj, long dr3dt1_nativeObj, long dr3dr2_nativeObj); + private static native void composeRT_6(long rvec1_nativeObj, long tvec1_nativeObj, long rvec2_nativeObj, long tvec2_nativeObj, long rvec3_nativeObj, long tvec3_nativeObj, long dr3dr1_nativeObj, long dr3dt1_nativeObj); + private static native void composeRT_7(long rvec1_nativeObj, long tvec1_nativeObj, long rvec2_nativeObj, long tvec2_nativeObj, long rvec3_nativeObj, long tvec3_nativeObj, long dr3dr1_nativeObj); + private static native void composeRT_8(long rvec1_nativeObj, long tvec1_nativeObj, long rvec2_nativeObj, long tvec2_nativeObj, long rvec3_nativeObj, long tvec3_nativeObj); + + // C++: void cv::computeCorrespondEpilines(Mat points, int whichImage, Mat F, Mat& lines) + private static native void computeCorrespondEpilines_0(long points_nativeObj, int whichImage, long F_nativeObj, long lines_nativeObj); + + // C++: void cv::convertPointsFromHomogeneous(Mat src, Mat& dst) + private static native void convertPointsFromHomogeneous_0(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::convertPointsToHomogeneous(Mat src, Mat& dst) + private static native void convertPointsToHomogeneous_0(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::correctMatches(Mat F, Mat points1, Mat points2, Mat& newPoints1, Mat& newPoints2) + private static native void correctMatches_0(long F_nativeObj, long points1_nativeObj, long points2_nativeObj, long newPoints1_nativeObj, long newPoints2_nativeObj); + + // C++: void cv::decomposeEssentialMat(Mat E, Mat& R1, Mat& R2, Mat& t) + private static native void decomposeEssentialMat_0(long E_nativeObj, long R1_nativeObj, long R2_nativeObj, long t_nativeObj); + + // C++: void cv::decomposeProjectionMatrix(Mat projMatrix, Mat& cameraMatrix, Mat& rotMatrix, Mat& transVect, Mat& rotMatrixX = Mat(), Mat& rotMatrixY = Mat(), Mat& rotMatrixZ = Mat(), Mat& eulerAngles = Mat()) + private static native void decomposeProjectionMatrix_0(long projMatrix_nativeObj, long cameraMatrix_nativeObj, long rotMatrix_nativeObj, long transVect_nativeObj, long rotMatrixX_nativeObj, long rotMatrixY_nativeObj, long rotMatrixZ_nativeObj, long eulerAngles_nativeObj); + private static native void decomposeProjectionMatrix_1(long projMatrix_nativeObj, long cameraMatrix_nativeObj, long rotMatrix_nativeObj, long transVect_nativeObj, long rotMatrixX_nativeObj, long rotMatrixY_nativeObj, long rotMatrixZ_nativeObj); + private static native void decomposeProjectionMatrix_2(long projMatrix_nativeObj, long cameraMatrix_nativeObj, long rotMatrix_nativeObj, long transVect_nativeObj, long rotMatrixX_nativeObj, long rotMatrixY_nativeObj); + private static native void decomposeProjectionMatrix_3(long projMatrix_nativeObj, long cameraMatrix_nativeObj, long rotMatrix_nativeObj, long transVect_nativeObj, long rotMatrixX_nativeObj); + private static native void decomposeProjectionMatrix_4(long projMatrix_nativeObj, long cameraMatrix_nativeObj, long rotMatrix_nativeObj, long transVect_nativeObj); + + // C++: void cv::drawChessboardCorners(Mat& image, Size patternSize, vector_Point2f corners, bool patternWasFound) + private static native void drawChessboardCorners_0(long image_nativeObj, double patternSize_width, double patternSize_height, long corners_mat_nativeObj, boolean patternWasFound); + + // C++: void cv::drawFrameAxes(Mat& image, Mat cameraMatrix, Mat distCoeffs, Mat rvec, Mat tvec, float length, int thickness = 3) + private static native void drawFrameAxes_0(long image_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvec_nativeObj, long tvec_nativeObj, float length, int thickness); + private static native void drawFrameAxes_1(long image_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvec_nativeObj, long tvec_nativeObj, float length); + + // C++: void cv::filterHomographyDecompByVisibleRefpoints(vector_Mat rotations, vector_Mat normals, Mat beforePoints, Mat afterPoints, Mat& possibleSolutions, Mat pointsMask = Mat()) + private static native void filterHomographyDecompByVisibleRefpoints_0(long rotations_mat_nativeObj, long normals_mat_nativeObj, long beforePoints_nativeObj, long afterPoints_nativeObj, long possibleSolutions_nativeObj, long pointsMask_nativeObj); + private static native void filterHomographyDecompByVisibleRefpoints_1(long rotations_mat_nativeObj, long normals_mat_nativeObj, long beforePoints_nativeObj, long afterPoints_nativeObj, long possibleSolutions_nativeObj); + + // C++: void cv::filterSpeckles(Mat& img, double newVal, int maxSpeckleSize, double maxDiff, Mat& buf = Mat()) + private static native void filterSpeckles_0(long img_nativeObj, double newVal, int maxSpeckleSize, double maxDiff, long buf_nativeObj); + private static native void filterSpeckles_1(long img_nativeObj, double newVal, int maxSpeckleSize, double maxDiff); + + // C++: void cv::initUndistortRectifyMap(Mat cameraMatrix, Mat distCoeffs, Mat R, Mat newCameraMatrix, Size size, int m1type, Mat& map1, Mat& map2) + private static native void initUndistortRectifyMap_0(long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long R_nativeObj, long newCameraMatrix_nativeObj, double size_width, double size_height, int m1type, long map1_nativeObj, long map2_nativeObj); + + // C++: void cv::matMulDeriv(Mat A, Mat B, Mat& dABdA, Mat& dABdB) + private static native void matMulDeriv_0(long A_nativeObj, long B_nativeObj, long dABdA_nativeObj, long dABdB_nativeObj); + + // C++: void cv::projectPoints(vector_Point3f objectPoints, Mat rvec, Mat tvec, Mat cameraMatrix, vector_double distCoeffs, vector_Point2f& imagePoints, Mat& jacobian = Mat(), double aspectRatio = 0) + private static native void projectPoints_0(long objectPoints_mat_nativeObj, long rvec_nativeObj, long tvec_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_mat_nativeObj, long imagePoints_mat_nativeObj, long jacobian_nativeObj, double aspectRatio); + private static native void projectPoints_1(long objectPoints_mat_nativeObj, long rvec_nativeObj, long tvec_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_mat_nativeObj, long imagePoints_mat_nativeObj, long jacobian_nativeObj); + private static native void projectPoints_2(long objectPoints_mat_nativeObj, long rvec_nativeObj, long tvec_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_mat_nativeObj, long imagePoints_mat_nativeObj); + + // C++: void cv::reprojectImageTo3D(Mat disparity, Mat& _3dImage, Mat Q, bool handleMissingValues = false, int ddepth = -1) + private static native void reprojectImageTo3D_0(long disparity_nativeObj, long _3dImage_nativeObj, long Q_nativeObj, boolean handleMissingValues, int ddepth); + private static native void reprojectImageTo3D_1(long disparity_nativeObj, long _3dImage_nativeObj, long Q_nativeObj, boolean handleMissingValues); + private static native void reprojectImageTo3D_2(long disparity_nativeObj, long _3dImage_nativeObj, long Q_nativeObj); + + // C++: void cv::solvePnPRefineLM(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, Mat& rvec, Mat& tvec, TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 20, FLT_EPSILON)) + private static native void solvePnPRefineLM_0(long objectPoints_nativeObj, long imagePoints_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvec_nativeObj, long tvec_nativeObj, int criteria_type, int criteria_maxCount, double criteria_epsilon); + private static native void solvePnPRefineLM_1(long objectPoints_nativeObj, long imagePoints_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvec_nativeObj, long tvec_nativeObj); + + // C++: void cv::solvePnPRefineVVS(Mat objectPoints, Mat imagePoints, Mat cameraMatrix, Mat distCoeffs, Mat& rvec, Mat& tvec, TermCriteria criteria = TermCriteria(TermCriteria::EPS + TermCriteria::COUNT, 20, FLT_EPSILON), double VVSlambda = 1) + private static native void solvePnPRefineVVS_0(long objectPoints_nativeObj, long imagePoints_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvec_nativeObj, long tvec_nativeObj, int criteria_type, int criteria_maxCount, double criteria_epsilon, double VVSlambda); + private static native void solvePnPRefineVVS_1(long objectPoints_nativeObj, long imagePoints_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvec_nativeObj, long tvec_nativeObj, int criteria_type, int criteria_maxCount, double criteria_epsilon); + private static native void solvePnPRefineVVS_2(long objectPoints_nativeObj, long imagePoints_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long rvec_nativeObj, long tvec_nativeObj); + + // C++: void cv::stereoRectify(Mat cameraMatrix1, Mat distCoeffs1, Mat cameraMatrix2, Mat distCoeffs2, Size imageSize, Mat R, Mat T, Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q, int flags = CALIB_ZERO_DISPARITY, double alpha = -1, Size newImageSize = Size(), Rect* validPixROI1 = 0, Rect* validPixROI2 = 0) + private static native void stereoRectify_0(long cameraMatrix1_nativeObj, long distCoeffs1_nativeObj, long cameraMatrix2_nativeObj, long distCoeffs2_nativeObj, double imageSize_width, double imageSize_height, long R_nativeObj, long T_nativeObj, long R1_nativeObj, long R2_nativeObj, long P1_nativeObj, long P2_nativeObj, long Q_nativeObj, int flags, double alpha, double newImageSize_width, double newImageSize_height, double[] validPixROI1_out, double[] validPixROI2_out); + private static native void stereoRectify_1(long cameraMatrix1_nativeObj, long distCoeffs1_nativeObj, long cameraMatrix2_nativeObj, long distCoeffs2_nativeObj, double imageSize_width, double imageSize_height, long R_nativeObj, long T_nativeObj, long R1_nativeObj, long R2_nativeObj, long P1_nativeObj, long P2_nativeObj, long Q_nativeObj, int flags, double alpha, double newImageSize_width, double newImageSize_height, double[] validPixROI1_out); + private static native void stereoRectify_2(long cameraMatrix1_nativeObj, long distCoeffs1_nativeObj, long cameraMatrix2_nativeObj, long distCoeffs2_nativeObj, double imageSize_width, double imageSize_height, long R_nativeObj, long T_nativeObj, long R1_nativeObj, long R2_nativeObj, long P1_nativeObj, long P2_nativeObj, long Q_nativeObj, int flags, double alpha, double newImageSize_width, double newImageSize_height); + private static native void stereoRectify_3(long cameraMatrix1_nativeObj, long distCoeffs1_nativeObj, long cameraMatrix2_nativeObj, long distCoeffs2_nativeObj, double imageSize_width, double imageSize_height, long R_nativeObj, long T_nativeObj, long R1_nativeObj, long R2_nativeObj, long P1_nativeObj, long P2_nativeObj, long Q_nativeObj, int flags, double alpha); + private static native void stereoRectify_4(long cameraMatrix1_nativeObj, long distCoeffs1_nativeObj, long cameraMatrix2_nativeObj, long distCoeffs2_nativeObj, double imageSize_width, double imageSize_height, long R_nativeObj, long T_nativeObj, long R1_nativeObj, long R2_nativeObj, long P1_nativeObj, long P2_nativeObj, long Q_nativeObj, int flags); + private static native void stereoRectify_5(long cameraMatrix1_nativeObj, long distCoeffs1_nativeObj, long cameraMatrix2_nativeObj, long distCoeffs2_nativeObj, double imageSize_width, double imageSize_height, long R_nativeObj, long T_nativeObj, long R1_nativeObj, long R2_nativeObj, long P1_nativeObj, long P2_nativeObj, long Q_nativeObj); + + // C++: void cv::triangulatePoints(Mat projMatr1, Mat projMatr2, Mat projPoints1, Mat projPoints2, Mat& points4D) + private static native void triangulatePoints_0(long projMatr1_nativeObj, long projMatr2_nativeObj, long projPoints1_nativeObj, long projPoints2_nativeObj, long points4D_nativeObj); + + // C++: void cv::undistort(Mat src, Mat& dst, Mat cameraMatrix, Mat distCoeffs, Mat newCameraMatrix = Mat()) + private static native void undistort_0(long src_nativeObj, long dst_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long newCameraMatrix_nativeObj); + private static native void undistort_1(long src_nativeObj, long dst_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj); + + // C++: void cv::undistortPoints(Mat src, Mat& dst, Mat cameraMatrix, Mat distCoeffs, Mat R, Mat P, TermCriteria criteria) + private static native void undistortPointsIter_0(long src_nativeObj, long dst_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long R_nativeObj, long P_nativeObj, int criteria_type, int criteria_maxCount, double criteria_epsilon); + + // C++: void cv::undistortPoints(vector_Point2f src, vector_Point2f& dst, Mat cameraMatrix, Mat distCoeffs, Mat R = Mat(), Mat P = Mat()) + private static native void undistortPoints_0(long src_mat_nativeObj, long dst_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long R_nativeObj, long P_nativeObj); + private static native void undistortPoints_1(long src_mat_nativeObj, long dst_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj, long R_nativeObj); + private static native void undistortPoints_2(long src_mat_nativeObj, long dst_mat_nativeObj, long cameraMatrix_nativeObj, long distCoeffs_nativeObj); + + // C++: void cv::validateDisparity(Mat& disparity, Mat cost, int minDisparity, int numberOfDisparities, int disp12MaxDisp = 1) + private static native void validateDisparity_0(long disparity_nativeObj, long cost_nativeObj, int minDisparity, int numberOfDisparities, int disp12MaxDisp); + private static native void validateDisparity_1(long disparity_nativeObj, long cost_nativeObj, int minDisparity, int numberOfDisparities); + + // C++: void cv::fisheye::distortPoints(Mat undistorted, Mat& distorted, Mat K, Mat D, double alpha = 0) + private static native void fisheye_distortPoints_0(long undistorted_nativeObj, long distorted_nativeObj, long K_nativeObj, long D_nativeObj, double alpha); + private static native void fisheye_distortPoints_1(long undistorted_nativeObj, long distorted_nativeObj, long K_nativeObj, long D_nativeObj); + + // C++: void cv::fisheye::estimateNewCameraMatrixForUndistortRectify(Mat K, Mat D, Size image_size, Mat R, Mat& P, double balance = 0.0, Size new_size = Size(), double fov_scale = 1.0) + private static native void fisheye_estimateNewCameraMatrixForUndistortRectify_0(long K_nativeObj, long D_nativeObj, double image_size_width, double image_size_height, long R_nativeObj, long P_nativeObj, double balance, double new_size_width, double new_size_height, double fov_scale); + private static native void fisheye_estimateNewCameraMatrixForUndistortRectify_1(long K_nativeObj, long D_nativeObj, double image_size_width, double image_size_height, long R_nativeObj, long P_nativeObj, double balance, double new_size_width, double new_size_height); + private static native void fisheye_estimateNewCameraMatrixForUndistortRectify_2(long K_nativeObj, long D_nativeObj, double image_size_width, double image_size_height, long R_nativeObj, long P_nativeObj, double balance); + private static native void fisheye_estimateNewCameraMatrixForUndistortRectify_3(long K_nativeObj, long D_nativeObj, double image_size_width, double image_size_height, long R_nativeObj, long P_nativeObj); + + // C++: void cv::fisheye::initUndistortRectifyMap(Mat K, Mat D, Mat R, Mat P, Size size, int m1type, Mat& map1, Mat& map2) + private static native void fisheye_initUndistortRectifyMap_0(long K_nativeObj, long D_nativeObj, long R_nativeObj, long P_nativeObj, double size_width, double size_height, int m1type, long map1_nativeObj, long map2_nativeObj); + + // C++: void cv::fisheye::projectPoints(Mat objectPoints, Mat& imagePoints, Mat rvec, Mat tvec, Mat K, Mat D, double alpha = 0, Mat& jacobian = Mat()) + private static native void fisheye_projectPoints_0(long objectPoints_nativeObj, long imagePoints_nativeObj, long rvec_nativeObj, long tvec_nativeObj, long K_nativeObj, long D_nativeObj, double alpha, long jacobian_nativeObj); + private static native void fisheye_projectPoints_1(long objectPoints_nativeObj, long imagePoints_nativeObj, long rvec_nativeObj, long tvec_nativeObj, long K_nativeObj, long D_nativeObj, double alpha); + private static native void fisheye_projectPoints_2(long objectPoints_nativeObj, long imagePoints_nativeObj, long rvec_nativeObj, long tvec_nativeObj, long K_nativeObj, long D_nativeObj); + + // C++: void cv::fisheye::stereoRectify(Mat K1, Mat D1, Mat K2, Mat D2, Size imageSize, Mat R, Mat tvec, Mat& R1, Mat& R2, Mat& P1, Mat& P2, Mat& Q, int flags, Size newImageSize = Size(), double balance = 0.0, double fov_scale = 1.0) + private static native void fisheye_stereoRectify_0(long K1_nativeObj, long D1_nativeObj, long K2_nativeObj, long D2_nativeObj, double imageSize_width, double imageSize_height, long R_nativeObj, long tvec_nativeObj, long R1_nativeObj, long R2_nativeObj, long P1_nativeObj, long P2_nativeObj, long Q_nativeObj, int flags, double newImageSize_width, double newImageSize_height, double balance, double fov_scale); + private static native void fisheye_stereoRectify_1(long K1_nativeObj, long D1_nativeObj, long K2_nativeObj, long D2_nativeObj, double imageSize_width, double imageSize_height, long R_nativeObj, long tvec_nativeObj, long R1_nativeObj, long R2_nativeObj, long P1_nativeObj, long P2_nativeObj, long Q_nativeObj, int flags, double newImageSize_width, double newImageSize_height, double balance); + private static native void fisheye_stereoRectify_2(long K1_nativeObj, long D1_nativeObj, long K2_nativeObj, long D2_nativeObj, double imageSize_width, double imageSize_height, long R_nativeObj, long tvec_nativeObj, long R1_nativeObj, long R2_nativeObj, long P1_nativeObj, long P2_nativeObj, long Q_nativeObj, int flags, double newImageSize_width, double newImageSize_height); + private static native void fisheye_stereoRectify_3(long K1_nativeObj, long D1_nativeObj, long K2_nativeObj, long D2_nativeObj, double imageSize_width, double imageSize_height, long R_nativeObj, long tvec_nativeObj, long R1_nativeObj, long R2_nativeObj, long P1_nativeObj, long P2_nativeObj, long Q_nativeObj, int flags); + + // C++: void cv::fisheye::undistortImage(Mat distorted, Mat& undistorted, Mat K, Mat D, Mat Knew = cv::Mat(), Size new_size = Size()) + private static native void fisheye_undistortImage_0(long distorted_nativeObj, long undistorted_nativeObj, long K_nativeObj, long D_nativeObj, long Knew_nativeObj, double new_size_width, double new_size_height); + private static native void fisheye_undistortImage_1(long distorted_nativeObj, long undistorted_nativeObj, long K_nativeObj, long D_nativeObj, long Knew_nativeObj); + private static native void fisheye_undistortImage_2(long distorted_nativeObj, long undistorted_nativeObj, long K_nativeObj, long D_nativeObj); + + // C++: void cv::fisheye::undistortPoints(Mat distorted, Mat& undistorted, Mat K, Mat D, Mat R = Mat(), Mat P = Mat()) + private static native void fisheye_undistortPoints_0(long distorted_nativeObj, long undistorted_nativeObj, long K_nativeObj, long D_nativeObj, long R_nativeObj, long P_nativeObj); + private static native void fisheye_undistortPoints_1(long distorted_nativeObj, long undistorted_nativeObj, long K_nativeObj, long D_nativeObj, long R_nativeObj); + private static native void fisheye_undistortPoints_2(long distorted_nativeObj, long undistorted_nativeObj, long K_nativeObj, long D_nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/calib3d/StereoBM.java b/OpenCV/src/main/java/org/opencv/calib3d/StereoBM.java new file mode 100644 index 00000000..2502c646 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/calib3d/StereoBM.java @@ -0,0 +1,345 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.calib3d; + +import org.opencv.calib3d.StereoBM; +import org.opencv.calib3d.StereoMatcher; +import org.opencv.core.Rect; + +// C++: class StereoBM +//javadoc: StereoBM + +public class StereoBM extends StereoMatcher { + + protected StereoBM(long addr) { super(addr); } + + // internal usage only + public static StereoBM __fromPtr__(long addr) { return new StereoBM(addr); } + + // C++: enum + public static final int + PREFILTER_NORMALIZED_RESPONSE = 0, + PREFILTER_XSOBEL = 1; + + + // + // C++: static Ptr_StereoBM cv::StereoBM::create(int numDisparities = 0, int blockSize = 21) + // + + //javadoc: StereoBM::create(numDisparities, blockSize) + public static StereoBM create(int numDisparities, int blockSize) + { + + StereoBM retVal = StereoBM.__fromPtr__(create_0(numDisparities, blockSize)); + + return retVal; + } + + //javadoc: StereoBM::create(numDisparities) + public static StereoBM create(int numDisparities) + { + + StereoBM retVal = StereoBM.__fromPtr__(create_1(numDisparities)); + + return retVal; + } + + //javadoc: StereoBM::create() + public static StereoBM create() + { + + StereoBM retVal = StereoBM.__fromPtr__(create_2()); + + return retVal; + } + + + // + // C++: Rect cv::StereoBM::getROI1() + // + + //javadoc: StereoBM::getROI1() + public Rect getROI1() + { + + Rect retVal = new Rect(getROI1_0(nativeObj)); + + return retVal; + } + + + // + // C++: Rect cv::StereoBM::getROI2() + // + + //javadoc: StereoBM::getROI2() + public Rect getROI2() + { + + Rect retVal = new Rect(getROI2_0(nativeObj)); + + return retVal; + } + + + // + // C++: int cv::StereoBM::getPreFilterCap() + // + + //javadoc: StereoBM::getPreFilterCap() + public int getPreFilterCap() + { + + int retVal = getPreFilterCap_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::StereoBM::getPreFilterSize() + // + + //javadoc: StereoBM::getPreFilterSize() + public int getPreFilterSize() + { + + int retVal = getPreFilterSize_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::StereoBM::getPreFilterType() + // + + //javadoc: StereoBM::getPreFilterType() + public int getPreFilterType() + { + + int retVal = getPreFilterType_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::StereoBM::getSmallerBlockSize() + // + + //javadoc: StereoBM::getSmallerBlockSize() + public int getSmallerBlockSize() + { + + int retVal = getSmallerBlockSize_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::StereoBM::getTextureThreshold() + // + + //javadoc: StereoBM::getTextureThreshold() + public int getTextureThreshold() + { + + int retVal = getTextureThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::StereoBM::getUniquenessRatio() + // + + //javadoc: StereoBM::getUniquenessRatio() + public int getUniquenessRatio() + { + + int retVal = getUniquenessRatio_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::StereoBM::setPreFilterCap(int preFilterCap) + // + + //javadoc: StereoBM::setPreFilterCap(preFilterCap) + public void setPreFilterCap(int preFilterCap) + { + + setPreFilterCap_0(nativeObj, preFilterCap); + + return; + } + + + // + // C++: void cv::StereoBM::setPreFilterSize(int preFilterSize) + // + + //javadoc: StereoBM::setPreFilterSize(preFilterSize) + public void setPreFilterSize(int preFilterSize) + { + + setPreFilterSize_0(nativeObj, preFilterSize); + + return; + } + + + // + // C++: void cv::StereoBM::setPreFilterType(int preFilterType) + // + + //javadoc: StereoBM::setPreFilterType(preFilterType) + public void setPreFilterType(int preFilterType) + { + + setPreFilterType_0(nativeObj, preFilterType); + + return; + } + + + // + // C++: void cv::StereoBM::setROI1(Rect roi1) + // + + //javadoc: StereoBM::setROI1(roi1) + public void setROI1(Rect roi1) + { + + setROI1_0(nativeObj, roi1.x, roi1.y, roi1.width, roi1.height); + + return; + } + + + // + // C++: void cv::StereoBM::setROI2(Rect roi2) + // + + //javadoc: StereoBM::setROI2(roi2) + public void setROI2(Rect roi2) + { + + setROI2_0(nativeObj, roi2.x, roi2.y, roi2.width, roi2.height); + + return; + } + + + // + // C++: void cv::StereoBM::setSmallerBlockSize(int blockSize) + // + + //javadoc: StereoBM::setSmallerBlockSize(blockSize) + public void setSmallerBlockSize(int blockSize) + { + + setSmallerBlockSize_0(nativeObj, blockSize); + + return; + } + + + // + // C++: void cv::StereoBM::setTextureThreshold(int textureThreshold) + // + + //javadoc: StereoBM::setTextureThreshold(textureThreshold) + public void setTextureThreshold(int textureThreshold) + { + + setTextureThreshold_0(nativeObj, textureThreshold); + + return; + } + + + // + // C++: void cv::StereoBM::setUniquenessRatio(int uniquenessRatio) + // + + //javadoc: StereoBM::setUniquenessRatio(uniquenessRatio) + public void setUniquenessRatio(int uniquenessRatio) + { + + setUniquenessRatio_0(nativeObj, uniquenessRatio); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_StereoBM cv::StereoBM::create(int numDisparities = 0, int blockSize = 21) + private static native long create_0(int numDisparities, int blockSize); + private static native long create_1(int numDisparities); + private static native long create_2(); + + // C++: Rect cv::StereoBM::getROI1() + private static native double[] getROI1_0(long nativeObj); + + // C++: Rect cv::StereoBM::getROI2() + private static native double[] getROI2_0(long nativeObj); + + // C++: int cv::StereoBM::getPreFilterCap() + private static native int getPreFilterCap_0(long nativeObj); + + // C++: int cv::StereoBM::getPreFilterSize() + private static native int getPreFilterSize_0(long nativeObj); + + // C++: int cv::StereoBM::getPreFilterType() + private static native int getPreFilterType_0(long nativeObj); + + // C++: int cv::StereoBM::getSmallerBlockSize() + private static native int getSmallerBlockSize_0(long nativeObj); + + // C++: int cv::StereoBM::getTextureThreshold() + private static native int getTextureThreshold_0(long nativeObj); + + // C++: int cv::StereoBM::getUniquenessRatio() + private static native int getUniquenessRatio_0(long nativeObj); + + // C++: void cv::StereoBM::setPreFilterCap(int preFilterCap) + private static native void setPreFilterCap_0(long nativeObj, int preFilterCap); + + // C++: void cv::StereoBM::setPreFilterSize(int preFilterSize) + private static native void setPreFilterSize_0(long nativeObj, int preFilterSize); + + // C++: void cv::StereoBM::setPreFilterType(int preFilterType) + private static native void setPreFilterType_0(long nativeObj, int preFilterType); + + // C++: void cv::StereoBM::setROI1(Rect roi1) + private static native void setROI1_0(long nativeObj, int roi1_x, int roi1_y, int roi1_width, int roi1_height); + + // C++: void cv::StereoBM::setROI2(Rect roi2) + private static native void setROI2_0(long nativeObj, int roi2_x, int roi2_y, int roi2_width, int roi2_height); + + // C++: void cv::StereoBM::setSmallerBlockSize(int blockSize) + private static native void setSmallerBlockSize_0(long nativeObj, int blockSize); + + // C++: void cv::StereoBM::setTextureThreshold(int textureThreshold) + private static native void setTextureThreshold_0(long nativeObj, int textureThreshold); + + // C++: void cv::StereoBM::setUniquenessRatio(int uniquenessRatio) + private static native void setUniquenessRatio_0(long nativeObj, int uniquenessRatio); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/calib3d/StereoMatcher.java b/OpenCV/src/main/java/org/opencv/calib3d/StereoMatcher.java new file mode 100644 index 00000000..fbeb58d6 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/calib3d/StereoMatcher.java @@ -0,0 +1,256 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.calib3d; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class StereoMatcher +//javadoc: StereoMatcher + +public class StereoMatcher extends Algorithm { + + protected StereoMatcher(long addr) { super(addr); } + + // internal usage only + public static StereoMatcher __fromPtr__(long addr) { return new StereoMatcher(addr); } + + // C++: enum + public static final int + DISP_SHIFT = 4, + DISP_SCALE = (1 << DISP_SHIFT); + + + // + // C++: int cv::StereoMatcher::getBlockSize() + // + + //javadoc: StereoMatcher::getBlockSize() + public int getBlockSize() + { + + int retVal = getBlockSize_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::StereoMatcher::getDisp12MaxDiff() + // + + //javadoc: StereoMatcher::getDisp12MaxDiff() + public int getDisp12MaxDiff() + { + + int retVal = getDisp12MaxDiff_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::StereoMatcher::getMinDisparity() + // + + //javadoc: StereoMatcher::getMinDisparity() + public int getMinDisparity() + { + + int retVal = getMinDisparity_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::StereoMatcher::getNumDisparities() + // + + //javadoc: StereoMatcher::getNumDisparities() + public int getNumDisparities() + { + + int retVal = getNumDisparities_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::StereoMatcher::getSpeckleRange() + // + + //javadoc: StereoMatcher::getSpeckleRange() + public int getSpeckleRange() + { + + int retVal = getSpeckleRange_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::StereoMatcher::getSpeckleWindowSize() + // + + //javadoc: StereoMatcher::getSpeckleWindowSize() + public int getSpeckleWindowSize() + { + + int retVal = getSpeckleWindowSize_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::StereoMatcher::compute(Mat left, Mat right, Mat& disparity) + // + + //javadoc: StereoMatcher::compute(left, right, disparity) + public void compute(Mat left, Mat right, Mat disparity) + { + + compute_0(nativeObj, left.nativeObj, right.nativeObj, disparity.nativeObj); + + return; + } + + + // + // C++: void cv::StereoMatcher::setBlockSize(int blockSize) + // + + //javadoc: StereoMatcher::setBlockSize(blockSize) + public void setBlockSize(int blockSize) + { + + setBlockSize_0(nativeObj, blockSize); + + return; + } + + + // + // C++: void cv::StereoMatcher::setDisp12MaxDiff(int disp12MaxDiff) + // + + //javadoc: StereoMatcher::setDisp12MaxDiff(disp12MaxDiff) + public void setDisp12MaxDiff(int disp12MaxDiff) + { + + setDisp12MaxDiff_0(nativeObj, disp12MaxDiff); + + return; + } + + + // + // C++: void cv::StereoMatcher::setMinDisparity(int minDisparity) + // + + //javadoc: StereoMatcher::setMinDisparity(minDisparity) + public void setMinDisparity(int minDisparity) + { + + setMinDisparity_0(nativeObj, minDisparity); + + return; + } + + + // + // C++: void cv::StereoMatcher::setNumDisparities(int numDisparities) + // + + //javadoc: StereoMatcher::setNumDisparities(numDisparities) + public void setNumDisparities(int numDisparities) + { + + setNumDisparities_0(nativeObj, numDisparities); + + return; + } + + + // + // C++: void cv::StereoMatcher::setSpeckleRange(int speckleRange) + // + + //javadoc: StereoMatcher::setSpeckleRange(speckleRange) + public void setSpeckleRange(int speckleRange) + { + + setSpeckleRange_0(nativeObj, speckleRange); + + return; + } + + + // + // C++: void cv::StereoMatcher::setSpeckleWindowSize(int speckleWindowSize) + // + + //javadoc: StereoMatcher::setSpeckleWindowSize(speckleWindowSize) + public void setSpeckleWindowSize(int speckleWindowSize) + { + + setSpeckleWindowSize_0(nativeObj, speckleWindowSize); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: int cv::StereoMatcher::getBlockSize() + private static native int getBlockSize_0(long nativeObj); + + // C++: int cv::StereoMatcher::getDisp12MaxDiff() + private static native int getDisp12MaxDiff_0(long nativeObj); + + // C++: int cv::StereoMatcher::getMinDisparity() + private static native int getMinDisparity_0(long nativeObj); + + // C++: int cv::StereoMatcher::getNumDisparities() + private static native int getNumDisparities_0(long nativeObj); + + // C++: int cv::StereoMatcher::getSpeckleRange() + private static native int getSpeckleRange_0(long nativeObj); + + // C++: int cv::StereoMatcher::getSpeckleWindowSize() + private static native int getSpeckleWindowSize_0(long nativeObj); + + // C++: void cv::StereoMatcher::compute(Mat left, Mat right, Mat& disparity) + private static native void compute_0(long nativeObj, long left_nativeObj, long right_nativeObj, long disparity_nativeObj); + + // C++: void cv::StereoMatcher::setBlockSize(int blockSize) + private static native void setBlockSize_0(long nativeObj, int blockSize); + + // C++: void cv::StereoMatcher::setDisp12MaxDiff(int disp12MaxDiff) + private static native void setDisp12MaxDiff_0(long nativeObj, int disp12MaxDiff); + + // C++: void cv::StereoMatcher::setMinDisparity(int minDisparity) + private static native void setMinDisparity_0(long nativeObj, int minDisparity); + + // C++: void cv::StereoMatcher::setNumDisparities(int numDisparities) + private static native void setNumDisparities_0(long nativeObj, int numDisparities); + + // C++: void cv::StereoMatcher::setSpeckleRange(int speckleRange) + private static native void setSpeckleRange_0(long nativeObj, int speckleRange); + + // C++: void cv::StereoMatcher::setSpeckleWindowSize(int speckleWindowSize) + private static native void setSpeckleWindowSize_0(long nativeObj, int speckleWindowSize); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/calib3d/StereoSGBM.java b/OpenCV/src/main/java/org/opencv/calib3d/StereoSGBM.java new file mode 100644 index 00000000..7efdcdef --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/calib3d/StereoSGBM.java @@ -0,0 +1,334 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.calib3d; + +import org.opencv.calib3d.StereoMatcher; +import org.opencv.calib3d.StereoSGBM; + +// C++: class StereoSGBM +//javadoc: StereoSGBM + +public class StereoSGBM extends StereoMatcher { + + protected StereoSGBM(long addr) { super(addr); } + + // internal usage only + public static StereoSGBM __fromPtr__(long addr) { return new StereoSGBM(addr); } + + // C++: enum + public static final int + MODE_SGBM = 0, + MODE_HH = 1, + MODE_SGBM_3WAY = 2, + MODE_HH4 = 3; + + + // + // C++: static Ptr_StereoSGBM cv::StereoSGBM::create(int minDisparity = 0, int numDisparities = 16, int blockSize = 3, int P1 = 0, int P2 = 0, int disp12MaxDiff = 0, int preFilterCap = 0, int uniquenessRatio = 0, int speckleWindowSize = 0, int speckleRange = 0, int mode = StereoSGBM::MODE_SGBM) + // + + //javadoc: StereoSGBM::create(minDisparity, numDisparities, blockSize, P1, P2, disp12MaxDiff, preFilterCap, uniquenessRatio, speckleWindowSize, speckleRange, mode) + public static StereoSGBM create(int minDisparity, int numDisparities, int blockSize, int P1, int P2, int disp12MaxDiff, int preFilterCap, int uniquenessRatio, int speckleWindowSize, int speckleRange, int mode) + { + + StereoSGBM retVal = StereoSGBM.__fromPtr__(create_0(minDisparity, numDisparities, blockSize, P1, P2, disp12MaxDiff, preFilterCap, uniquenessRatio, speckleWindowSize, speckleRange, mode)); + + return retVal; + } + + //javadoc: StereoSGBM::create(minDisparity, numDisparities, blockSize, P1, P2, disp12MaxDiff, preFilterCap, uniquenessRatio, speckleWindowSize, speckleRange) + public static StereoSGBM create(int minDisparity, int numDisparities, int blockSize, int P1, int P2, int disp12MaxDiff, int preFilterCap, int uniquenessRatio, int speckleWindowSize, int speckleRange) + { + + StereoSGBM retVal = StereoSGBM.__fromPtr__(create_1(minDisparity, numDisparities, blockSize, P1, P2, disp12MaxDiff, preFilterCap, uniquenessRatio, speckleWindowSize, speckleRange)); + + return retVal; + } + + //javadoc: StereoSGBM::create(minDisparity, numDisparities, blockSize, P1, P2, disp12MaxDiff, preFilterCap, uniquenessRatio, speckleWindowSize) + public static StereoSGBM create(int minDisparity, int numDisparities, int blockSize, int P1, int P2, int disp12MaxDiff, int preFilterCap, int uniquenessRatio, int speckleWindowSize) + { + + StereoSGBM retVal = StereoSGBM.__fromPtr__(create_2(minDisparity, numDisparities, blockSize, P1, P2, disp12MaxDiff, preFilterCap, uniquenessRatio, speckleWindowSize)); + + return retVal; + } + + //javadoc: StereoSGBM::create(minDisparity, numDisparities, blockSize, P1, P2, disp12MaxDiff, preFilterCap, uniquenessRatio) + public static StereoSGBM create(int minDisparity, int numDisparities, int blockSize, int P1, int P2, int disp12MaxDiff, int preFilterCap, int uniquenessRatio) + { + + StereoSGBM retVal = StereoSGBM.__fromPtr__(create_3(minDisparity, numDisparities, blockSize, P1, P2, disp12MaxDiff, preFilterCap, uniquenessRatio)); + + return retVal; + } + + //javadoc: StereoSGBM::create(minDisparity, numDisparities, blockSize, P1, P2, disp12MaxDiff, preFilterCap) + public static StereoSGBM create(int minDisparity, int numDisparities, int blockSize, int P1, int P2, int disp12MaxDiff, int preFilterCap) + { + + StereoSGBM retVal = StereoSGBM.__fromPtr__(create_4(minDisparity, numDisparities, blockSize, P1, P2, disp12MaxDiff, preFilterCap)); + + return retVal; + } + + //javadoc: StereoSGBM::create(minDisparity, numDisparities, blockSize, P1, P2, disp12MaxDiff) + public static StereoSGBM create(int minDisparity, int numDisparities, int blockSize, int P1, int P2, int disp12MaxDiff) + { + + StereoSGBM retVal = StereoSGBM.__fromPtr__(create_5(minDisparity, numDisparities, blockSize, P1, P2, disp12MaxDiff)); + + return retVal; + } + + //javadoc: StereoSGBM::create(minDisparity, numDisparities, blockSize, P1, P2) + public static StereoSGBM create(int minDisparity, int numDisparities, int blockSize, int P1, int P2) + { + + StereoSGBM retVal = StereoSGBM.__fromPtr__(create_6(minDisparity, numDisparities, blockSize, P1, P2)); + + return retVal; + } + + //javadoc: StereoSGBM::create(minDisparity, numDisparities, blockSize, P1) + public static StereoSGBM create(int minDisparity, int numDisparities, int blockSize, int P1) + { + + StereoSGBM retVal = StereoSGBM.__fromPtr__(create_7(minDisparity, numDisparities, blockSize, P1)); + + return retVal; + } + + //javadoc: StereoSGBM::create(minDisparity, numDisparities, blockSize) + public static StereoSGBM create(int minDisparity, int numDisparities, int blockSize) + { + + StereoSGBM retVal = StereoSGBM.__fromPtr__(create_8(minDisparity, numDisparities, blockSize)); + + return retVal; + } + + //javadoc: StereoSGBM::create(minDisparity, numDisparities) + public static StereoSGBM create(int minDisparity, int numDisparities) + { + + StereoSGBM retVal = StereoSGBM.__fromPtr__(create_9(minDisparity, numDisparities)); + + return retVal; + } + + //javadoc: StereoSGBM::create(minDisparity) + public static StereoSGBM create(int minDisparity) + { + + StereoSGBM retVal = StereoSGBM.__fromPtr__(create_10(minDisparity)); + + return retVal; + } + + //javadoc: StereoSGBM::create() + public static StereoSGBM create() + { + + StereoSGBM retVal = StereoSGBM.__fromPtr__(create_11()); + + return retVal; + } + + + // + // C++: int cv::StereoSGBM::getMode() + // + + //javadoc: StereoSGBM::getMode() + public int getMode() + { + + int retVal = getMode_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::StereoSGBM::getP1() + // + + //javadoc: StereoSGBM::getP1() + public int getP1() + { + + int retVal = getP1_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::StereoSGBM::getP2() + // + + //javadoc: StereoSGBM::getP2() + public int getP2() + { + + int retVal = getP2_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::StereoSGBM::getPreFilterCap() + // + + //javadoc: StereoSGBM::getPreFilterCap() + public int getPreFilterCap() + { + + int retVal = getPreFilterCap_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::StereoSGBM::getUniquenessRatio() + // + + //javadoc: StereoSGBM::getUniquenessRatio() + public int getUniquenessRatio() + { + + int retVal = getUniquenessRatio_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::StereoSGBM::setMode(int mode) + // + + //javadoc: StereoSGBM::setMode(mode) + public void setMode(int mode) + { + + setMode_0(nativeObj, mode); + + return; + } + + + // + // C++: void cv::StereoSGBM::setP1(int P1) + // + + //javadoc: StereoSGBM::setP1(P1) + public void setP1(int P1) + { + + setP1_0(nativeObj, P1); + + return; + } + + + // + // C++: void cv::StereoSGBM::setP2(int P2) + // + + //javadoc: StereoSGBM::setP2(P2) + public void setP2(int P2) + { + + setP2_0(nativeObj, P2); + + return; + } + + + // + // C++: void cv::StereoSGBM::setPreFilterCap(int preFilterCap) + // + + //javadoc: StereoSGBM::setPreFilterCap(preFilterCap) + public void setPreFilterCap(int preFilterCap) + { + + setPreFilterCap_0(nativeObj, preFilterCap); + + return; + } + + + // + // C++: void cv::StereoSGBM::setUniquenessRatio(int uniquenessRatio) + // + + //javadoc: StereoSGBM::setUniquenessRatio(uniquenessRatio) + public void setUniquenessRatio(int uniquenessRatio) + { + + setUniquenessRatio_0(nativeObj, uniquenessRatio); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_StereoSGBM cv::StereoSGBM::create(int minDisparity = 0, int numDisparities = 16, int blockSize = 3, int P1 = 0, int P2 = 0, int disp12MaxDiff = 0, int preFilterCap = 0, int uniquenessRatio = 0, int speckleWindowSize = 0, int speckleRange = 0, int mode = StereoSGBM::MODE_SGBM) + private static native long create_0(int minDisparity, int numDisparities, int blockSize, int P1, int P2, int disp12MaxDiff, int preFilterCap, int uniquenessRatio, int speckleWindowSize, int speckleRange, int mode); + private static native long create_1(int minDisparity, int numDisparities, int blockSize, int P1, int P2, int disp12MaxDiff, int preFilterCap, int uniquenessRatio, int speckleWindowSize, int speckleRange); + private static native long create_2(int minDisparity, int numDisparities, int blockSize, int P1, int P2, int disp12MaxDiff, int preFilterCap, int uniquenessRatio, int speckleWindowSize); + private static native long create_3(int minDisparity, int numDisparities, int blockSize, int P1, int P2, int disp12MaxDiff, int preFilterCap, int uniquenessRatio); + private static native long create_4(int minDisparity, int numDisparities, int blockSize, int P1, int P2, int disp12MaxDiff, int preFilterCap); + private static native long create_5(int minDisparity, int numDisparities, int blockSize, int P1, int P2, int disp12MaxDiff); + private static native long create_6(int minDisparity, int numDisparities, int blockSize, int P1, int P2); + private static native long create_7(int minDisparity, int numDisparities, int blockSize, int P1); + private static native long create_8(int minDisparity, int numDisparities, int blockSize); + private static native long create_9(int minDisparity, int numDisparities); + private static native long create_10(int minDisparity); + private static native long create_11(); + + // C++: int cv::StereoSGBM::getMode() + private static native int getMode_0(long nativeObj); + + // C++: int cv::StereoSGBM::getP1() + private static native int getP1_0(long nativeObj); + + // C++: int cv::StereoSGBM::getP2() + private static native int getP2_0(long nativeObj); + + // C++: int cv::StereoSGBM::getPreFilterCap() + private static native int getPreFilterCap_0(long nativeObj); + + // C++: int cv::StereoSGBM::getUniquenessRatio() + private static native int getUniquenessRatio_0(long nativeObj); + + // C++: void cv::StereoSGBM::setMode(int mode) + private static native void setMode_0(long nativeObj, int mode); + + // C++: void cv::StereoSGBM::setP1(int P1) + private static native void setP1_0(long nativeObj, int P1); + + // C++: void cv::StereoSGBM::setP2(int P2) + private static native void setP2_0(long nativeObj, int P2); + + // C++: void cv::StereoSGBM::setPreFilterCap(int preFilterCap) + private static native void setPreFilterCap_0(long nativeObj, int preFilterCap); + + // C++: void cv::StereoSGBM::setUniquenessRatio(int uniquenessRatio) + private static native void setUniquenessRatio_0(long nativeObj, int uniquenessRatio); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/core/Algorithm.java b/OpenCV/src/main/java/org/opencv/core/Algorithm.java new file mode 100644 index 00000000..8db0fe01 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/Algorithm.java @@ -0,0 +1,113 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.core; + +import java.lang.String; + +// C++: class Algorithm +//javadoc: Algorithm + +public class Algorithm { + + protected final long nativeObj; + protected Algorithm(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static Algorithm __fromPtr__(long addr) { return new Algorithm(addr); } + + // + // C++: String cv::Algorithm::getDefaultName() + // + + //javadoc: Algorithm::getDefaultName() + public String getDefaultName() + { + + String retVal = getDefaultName_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::Algorithm::empty() + // + + //javadoc: Algorithm::empty() + public boolean empty() + { + + boolean retVal = empty_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::Algorithm::clear() + // + + //javadoc: Algorithm::clear() + public void clear() + { + + clear_0(nativeObj); + + return; + } + + + // + // C++: void cv::Algorithm::read(FileNode fn) + // + + // Unknown type 'FileNode' (I), skipping the function + + + // + // C++: void cv::Algorithm::save(String filename) + // + + //javadoc: Algorithm::save(filename) + public void save(String filename) + { + + save_0(nativeObj, filename); + + return; + } + + + // + // C++: void cv::Algorithm::write(Ptr_FileStorage fs, String name = String()) + // + + // Unknown type 'Ptr_FileStorage' (I), skipping the function + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: String cv::Algorithm::getDefaultName() + private static native String getDefaultName_0(long nativeObj); + + // C++: bool cv::Algorithm::empty() + private static native boolean empty_0(long nativeObj); + + // C++: void cv::Algorithm::clear() + private static native void clear_0(long nativeObj); + + // C++: void cv::Algorithm::save(String filename) + private static native void save_0(long nativeObj, String filename); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/core/Core.java b/OpenCV/src/main/java/org/opencv/core/Core.java new file mode 100644 index 00000000..227cc1c8 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/Core.java @@ -0,0 +1,3188 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.core; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfDouble; +import org.opencv.core.MatOfInt; +import org.opencv.core.Scalar; +import org.opencv.core.TermCriteria; +import org.opencv.utils.Converters; + +// C++: class Core +//javadoc: Core + +public class Core { + // these constants are wrapped inside functions to prevent inlining + private static String getVersion() { return "4.1.0-dev"; } + private static String getNativeLibraryName() { return "opencv_java410"; } + private static int getVersionMajorJ() { return 4; } + private static int getVersionMinorJ() { return 1; } + private static int getVersionRevisionJ() { return 0; } + private static String getVersionStatusJ() { return "-dev"; } + + public static final String VERSION = getVersion(); + public static final String NATIVE_LIBRARY_NAME = getNativeLibraryName(); + public static final int VERSION_MAJOR = getVersionMajorJ(); + public static final int VERSION_MINOR = getVersionMinorJ(); + public static final int VERSION_REVISION = getVersionRevisionJ(); + public static final String VERSION_STATUS = getVersionStatusJ(); + + private static final int + CV_8U = 0, + CV_8S = 1, + CV_16U = 2, + CV_16S = 3, + CV_32S = 4, + CV_32F = 5, + CV_64F = 6, + CV_USRTYPE1 = 7; + + + // C++: enum DecompTypes + public static final int + DECOMP_LU = 0, + DECOMP_SVD = 1, + DECOMP_EIG = 2, + DECOMP_CHOLESKY = 3, + DECOMP_QR = 4, + DECOMP_NORMAL = 16; + + + // C++: enum BorderTypes + public static final int + BORDER_CONSTANT = 0, + BORDER_REPLICATE = 1, + BORDER_REFLECT = 2, + BORDER_WRAP = 3, + BORDER_REFLECT_101 = 4, + BORDER_TRANSPARENT = 5, + BORDER_REFLECT101 = BORDER_REFLECT_101, + BORDER_DEFAULT = BORDER_REFLECT_101, + BORDER_ISOLATED = 16; + + + // C++: enum GemmFlags + public static final int + GEMM_1_T = 1, + GEMM_2_T = 2, + GEMM_3_T = 4; + + + // C++: enum KmeansFlags + public static final int + KMEANS_RANDOM_CENTERS = 0, + KMEANS_PP_CENTERS = 2, + KMEANS_USE_INITIAL_LABELS = 1; + + + // C++: enum CmpTypes + public static final int + CMP_EQ = 0, + CMP_GT = 1, + CMP_GE = 2, + CMP_LT = 3, + CMP_LE = 4, + CMP_NE = 5; + + + // C++: enum Flags + public static final int + PCA_DATA_AS_ROW = 0, + PCA_DATA_AS_COL = 1, + PCA_USE_AVG = 2; + + + // C++: enum DftFlags + public static final int + DFT_INVERSE = 1, + DFT_SCALE = 2, + DFT_ROWS = 4, + DFT_COMPLEX_OUTPUT = 16, + DFT_REAL_OUTPUT = 32, + DFT_COMPLEX_INPUT = 64, + DCT_INVERSE = DFT_INVERSE, + DCT_ROWS = DFT_ROWS; + + + // C++: enum + public static final int + SVD_MODIFY_A = 1, + SVD_NO_UV = 2, + SVD_FULL_UV = 4, + FILLED = -1, + REDUCE_SUM = 0, + REDUCE_AVG = 1, + REDUCE_MAX = 2, + REDUCE_MIN = 3, + RNG_UNIFORM = 0, + RNG_NORMAL = 1; + + + // C++: enum IMPL + public static final int + IMPL_PLAIN = 0, + IMPL_IPP = 0+1, + IMPL_OPENCL = 0+2; + + + // C++: enum FLAGS + public static final int + FLAGS_NONE = 0, + FLAGS_MAPPING = 0x01, + FLAGS_EXPAND_SAME_NAMES = 0x02; + + + // C++: enum TYPE + public static final int + TYPE_GENERAL = 0, + TYPE_MARKER = 0+1, + TYPE_WRAPPER = 0+2, + TYPE_FUN = 0+3; + + + // C++: enum FormatType + public static final int + Formatter_FMT_DEFAULT = 0, + Formatter_FMT_MATLAB = 1, + Formatter_FMT_CSV = 2, + Formatter_FMT_PYTHON = 3, + Formatter_FMT_NUMPY = 4, + Formatter_FMT_C = 5; + + + // C++: enum SortFlags + public static final int + SORT_EVERY_ROW = 0, + SORT_EVERY_COLUMN = 1, + SORT_ASCENDING = 0, + SORT_DESCENDING = 16; + + + // C++: enum CovarFlags + public static final int + COVAR_SCRAMBLED = 0, + COVAR_NORMAL = 1, + COVAR_USE_AVG = 2, + COVAR_SCALE = 4, + COVAR_ROWS = 8, + COVAR_COLS = 16; + + + // C++: enum Param + public static final int + Param_INT = 0, + Param_BOOLEAN = 1, + Param_REAL = 2, + Param_STRING = 3, + Param_MAT = 4, + Param_MAT_VECTOR = 5, + Param_ALGORITHM = 6, + Param_FLOAT = 7, + Param_UNSIGNED_INT = 8, + Param_UINT64 = 9, + Param_UCHAR = 11, + Param_SCALAR = 12; + + + // C++: enum NormTypes + public static final int + NORM_INF = 1, + NORM_L1 = 2, + NORM_L2 = 4, + NORM_L2SQR = 5, + NORM_HAMMING = 6, + NORM_HAMMING2 = 7, + NORM_TYPE_MASK = 7, + NORM_RELATIVE = 8, + NORM_MINMAX = 32; + + + // C++: enum RotateFlags + public static final int + ROTATE_90_CLOCKWISE = 0, + ROTATE_180 = 1, + ROTATE_90_COUNTERCLOCKWISE = 2; + + + // C++: enum Code + public static final int + StsOk = 0, + StsBackTrace = -1, + StsError = -2, + StsInternal = -3, + StsNoMem = -4, + StsBadArg = -5, + StsBadFunc = -6, + StsNoConv = -7, + StsAutoTrace = -8, + HeaderIsNull = -9, + BadImageSize = -10, + BadOffset = -11, + BadDataPtr = -12, + BadStep = -13, + BadModelOrChSeq = -14, + BadNumChannels = -15, + BadNumChannel1U = -16, + BadDepth = -17, + BadAlphaChannel = -18, + BadOrder = -19, + BadOrigin = -20, + BadAlign = -21, + BadCallBack = -22, + BadTileSize = -23, + BadCOI = -24, + BadROISize = -25, + MaskIsTiled = -26, + StsNullPtr = -27, + StsVecLengthErr = -28, + StsFilterStructContentErr = -29, + StsKernelStructContentErr = -30, + StsFilterOffsetErr = -31, + StsBadSize = -201, + StsDivByZero = -202, + StsInplaceNotSupported = -203, + StsObjectNotFound = -204, + StsUnmatchedFormats = -205, + StsBadFlag = -206, + StsBadPoint = -207, + StsBadMask = -208, + StsUnmatchedSizes = -209, + StsUnsupportedFormat = -210, + StsOutOfRange = -211, + StsParseError = -212, + StsNotImplemented = -213, + StsBadMemBlock = -214, + StsAssert = -215, + GpuNotSupported = -216, + GpuApiCallError = -217, + OpenGlNotSupported = -218, + OpenGlApiCallError = -219, + OpenCLApiCallError = -220, + OpenCLDoubleNotSupported = -221, + OpenCLInitError = -222, + OpenCLNoAMDBlasFft = -223; + + + // + // C++: Scalar cv::mean(Mat src, Mat mask = Mat()) + // + + //javadoc: mean(src, mask) + public static Scalar mean(Mat src, Mat mask) + { + + Scalar retVal = new Scalar(mean_0(src.nativeObj, mask.nativeObj)); + + return retVal; + } + + //javadoc: mean(src) + public static Scalar mean(Mat src) + { + + Scalar retVal = new Scalar(mean_1(src.nativeObj)); + + return retVal; + } + + + // + // C++: Scalar cv::sum(Mat src) + // + + //javadoc: sumElems(src) + public static Scalar sumElems(Mat src) + { + + Scalar retVal = new Scalar(sumElems_0(src.nativeObj)); + + return retVal; + } + + + // + // C++: Scalar cv::trace(Mat mtx) + // + + //javadoc: trace(mtx) + public static Scalar trace(Mat mtx) + { + + Scalar retVal = new Scalar(trace_0(mtx.nativeObj)); + + return retVal; + } + + + // + // C++: String cv::getBuildInformation() + // + + //javadoc: getBuildInformation() + public static String getBuildInformation() + { + + String retVal = getBuildInformation_0(); + + return retVal; + } + + + // + // C++: String cv::getHardwareFeatureName(int feature) + // + + //javadoc: getHardwareFeatureName(feature) + public static String getHardwareFeatureName(int feature) + { + + String retVal = getHardwareFeatureName_0(feature); + + return retVal; + } + + + // + // C++: String cv::getVersionString() + // + + //javadoc: getVersionString() + public static String getVersionString() + { + + String retVal = getVersionString_0(); + + return retVal; + } + + + // + // C++: String cv::ipp::getIppVersion() + // + + //javadoc: getIppVersion() + public static String getIppVersion() + { + + String retVal = getIppVersion_0(); + + return retVal; + } + + + // + // C++: String cv::samples::findFile(String relative_path, bool required = true, bool silentMode = false) + // + + //javadoc: findFile(relative_path, required, silentMode) + public static String findFile(String relative_path, boolean required, boolean silentMode) + { + + String retVal = findFile_0(relative_path, required, silentMode); + + return retVal; + } + + //javadoc: findFile(relative_path, required) + public static String findFile(String relative_path, boolean required) + { + + String retVal = findFile_1(relative_path, required); + + return retVal; + } + + //javadoc: findFile(relative_path) + public static String findFile(String relative_path) + { + + String retVal = findFile_2(relative_path); + + return retVal; + } + + + // + // C++: String cv::samples::findFileOrKeep(String relative_path, bool silentMode = false) + // + + //javadoc: findFileOrKeep(relative_path, silentMode) + public static String findFileOrKeep(String relative_path, boolean silentMode) + { + + String retVal = findFileOrKeep_0(relative_path, silentMode); + + return retVal; + } + + //javadoc: findFileOrKeep(relative_path) + public static String findFileOrKeep(String relative_path) + { + + String retVal = findFileOrKeep_1(relative_path); + + return retVal; + } + + + // + // C++: bool cv::checkRange(Mat a, bool quiet = true, _hidden_ * pos = 0, double minVal = -DBL_MAX, double maxVal = DBL_MAX) + // + + //javadoc: checkRange(a, quiet, minVal, maxVal) + public static boolean checkRange(Mat a, boolean quiet, double minVal, double maxVal) + { + + boolean retVal = checkRange_0(a.nativeObj, quiet, minVal, maxVal); + + return retVal; + } + + //javadoc: checkRange(a, quiet, minVal) + public static boolean checkRange(Mat a, boolean quiet, double minVal) + { + + boolean retVal = checkRange_1(a.nativeObj, quiet, minVal); + + return retVal; + } + + //javadoc: checkRange(a, quiet) + public static boolean checkRange(Mat a, boolean quiet) + { + + boolean retVal = checkRange_2(a.nativeObj, quiet); + + return retVal; + } + + //javadoc: checkRange(a) + public static boolean checkRange(Mat a) + { + + boolean retVal = checkRange_4(a.nativeObj); + + return retVal; + } + + + // + // C++: bool cv::eigen(Mat src, Mat& eigenvalues, Mat& eigenvectors = Mat()) + // + + //javadoc: eigen(src, eigenvalues, eigenvectors) + public static boolean eigen(Mat src, Mat eigenvalues, Mat eigenvectors) + { + + boolean retVal = eigen_0(src.nativeObj, eigenvalues.nativeObj, eigenvectors.nativeObj); + + return retVal; + } + + //javadoc: eigen(src, eigenvalues) + public static boolean eigen(Mat src, Mat eigenvalues) + { + + boolean retVal = eigen_1(src.nativeObj, eigenvalues.nativeObj); + + return retVal; + } + + + // + // C++: bool cv::solve(Mat src1, Mat src2, Mat& dst, int flags = DECOMP_LU) + // + + //javadoc: solve(src1, src2, dst, flags) + public static boolean solve(Mat src1, Mat src2, Mat dst, int flags) + { + + boolean retVal = solve_0(src1.nativeObj, src2.nativeObj, dst.nativeObj, flags); + + return retVal; + } + + //javadoc: solve(src1, src2, dst) + public static boolean solve(Mat src1, Mat src2, Mat dst) + { + + boolean retVal = solve_1(src1.nativeObj, src2.nativeObj, dst.nativeObj); + + return retVal; + } + + + // + // C++: bool cv::ipp::useIPP() + // + + //javadoc: useIPP() + public static boolean useIPP() + { + + boolean retVal = useIPP_0(); + + return retVal; + } + + + // + // C++: bool cv::ipp::useIPP_NotExact() + // + + //javadoc: useIPP_NotExact() + public static boolean useIPP_NotExact() + { + + boolean retVal = useIPP_NotExact_0(); + + return retVal; + } + + + // + // C++: double cv::Mahalanobis(Mat v1, Mat v2, Mat icovar) + // + + //javadoc: Mahalanobis(v1, v2, icovar) + public static double Mahalanobis(Mat v1, Mat v2, Mat icovar) + { + + double retVal = Mahalanobis_0(v1.nativeObj, v2.nativeObj, icovar.nativeObj); + + return retVal; + } + + + // + // C++: double cv::PSNR(Mat src1, Mat src2, double R = 255.) + // + + //javadoc: PSNR(src1, src2, R) + public static double PSNR(Mat src1, Mat src2, double R) + { + + double retVal = PSNR_0(src1.nativeObj, src2.nativeObj, R); + + return retVal; + } + + //javadoc: PSNR(src1, src2) + public static double PSNR(Mat src1, Mat src2) + { + + double retVal = PSNR_1(src1.nativeObj, src2.nativeObj); + + return retVal; + } + + + // + // C++: double cv::determinant(Mat mtx) + // + + //javadoc: determinant(mtx) + public static double determinant(Mat mtx) + { + + double retVal = determinant_0(mtx.nativeObj); + + return retVal; + } + + + // + // C++: double cv::getTickFrequency() + // + + //javadoc: getTickFrequency() + public static double getTickFrequency() + { + + double retVal = getTickFrequency_0(); + + return retVal; + } + + + // + // C++: double cv::invert(Mat src, Mat& dst, int flags = DECOMP_LU) + // + + //javadoc: invert(src, dst, flags) + public static double invert(Mat src, Mat dst, int flags) + { + + double retVal = invert_0(src.nativeObj, dst.nativeObj, flags); + + return retVal; + } + + //javadoc: invert(src, dst) + public static double invert(Mat src, Mat dst) + { + + double retVal = invert_1(src.nativeObj, dst.nativeObj); + + return retVal; + } + + + // + // C++: double cv::kmeans(Mat data, int K, Mat& bestLabels, TermCriteria criteria, int attempts, int flags, Mat& centers = Mat()) + // + + //javadoc: kmeans(data, K, bestLabels, criteria, attempts, flags, centers) + public static double kmeans(Mat data, int K, Mat bestLabels, TermCriteria criteria, int attempts, int flags, Mat centers) + { + + double retVal = kmeans_0(data.nativeObj, K, bestLabels.nativeObj, criteria.type, criteria.maxCount, criteria.epsilon, attempts, flags, centers.nativeObj); + + return retVal; + } + + //javadoc: kmeans(data, K, bestLabels, criteria, attempts, flags) + public static double kmeans(Mat data, int K, Mat bestLabels, TermCriteria criteria, int attempts, int flags) + { + + double retVal = kmeans_1(data.nativeObj, K, bestLabels.nativeObj, criteria.type, criteria.maxCount, criteria.epsilon, attempts, flags); + + return retVal; + } + + + // + // C++: double cv::norm(Mat src1, Mat src2, int normType = NORM_L2, Mat mask = Mat()) + // + + //javadoc: norm(src1, src2, normType, mask) + public static double norm(Mat src1, Mat src2, int normType, Mat mask) + { + + double retVal = norm_0(src1.nativeObj, src2.nativeObj, normType, mask.nativeObj); + + return retVal; + } + + //javadoc: norm(src1, src2, normType) + public static double norm(Mat src1, Mat src2, int normType) + { + + double retVal = norm_1(src1.nativeObj, src2.nativeObj, normType); + + return retVal; + } + + //javadoc: norm(src1, src2) + public static double norm(Mat src1, Mat src2) + { + + double retVal = norm_2(src1.nativeObj, src2.nativeObj); + + return retVal; + } + + + // + // C++: double cv::norm(Mat src1, int normType = NORM_L2, Mat mask = Mat()) + // + + //javadoc: norm(src1, normType, mask) + public static double norm(Mat src1, int normType, Mat mask) + { + + double retVal = norm_3(src1.nativeObj, normType, mask.nativeObj); + + return retVal; + } + + //javadoc: norm(src1, normType) + public static double norm(Mat src1, int normType) + { + + double retVal = norm_4(src1.nativeObj, normType); + + return retVal; + } + + //javadoc: norm(src1) + public static double norm(Mat src1) + { + + double retVal = norm_5(src1.nativeObj); + + return retVal; + } + + + // + // C++: double cv::solvePoly(Mat coeffs, Mat& roots, int maxIters = 300) + // + + //javadoc: solvePoly(coeffs, roots, maxIters) + public static double solvePoly(Mat coeffs, Mat roots, int maxIters) + { + + double retVal = solvePoly_0(coeffs.nativeObj, roots.nativeObj, maxIters); + + return retVal; + } + + //javadoc: solvePoly(coeffs, roots) + public static double solvePoly(Mat coeffs, Mat roots) + { + + double retVal = solvePoly_1(coeffs.nativeObj, roots.nativeObj); + + return retVal; + } + + + // + // C++: float cv::cubeRoot(float val) + // + + //javadoc: cubeRoot(val) + public static float cubeRoot(float val) + { + + float retVal = cubeRoot_0(val); + + return retVal; + } + + + // + // C++: float cv::fastAtan2(float y, float x) + // + + //javadoc: fastAtan2(y, x) + public static float fastAtan2(float y, float x) + { + + float retVal = fastAtan2_0(y, x); + + return retVal; + } + + + // + // C++: int cv::borderInterpolate(int p, int len, int borderType) + // + + //javadoc: borderInterpolate(p, len, borderType) + public static int borderInterpolate(int p, int len, int borderType) + { + + int retVal = borderInterpolate_0(p, len, borderType); + + return retVal; + } + + + // + // C++: int cv::countNonZero(Mat src) + // + + //javadoc: countNonZero(src) + public static int countNonZero(Mat src) + { + + int retVal = countNonZero_0(src.nativeObj); + + return retVal; + } + + + // + // C++: int cv::getNumThreads() + // + + //javadoc: getNumThreads() + public static int getNumThreads() + { + + int retVal = getNumThreads_0(); + + return retVal; + } + + + // + // C++: int cv::getNumberOfCPUs() + // + + //javadoc: getNumberOfCPUs() + public static int getNumberOfCPUs() + { + + int retVal = getNumberOfCPUs_0(); + + return retVal; + } + + + // + // C++: int cv::getOptimalDFTSize(int vecsize) + // + + //javadoc: getOptimalDFTSize(vecsize) + public static int getOptimalDFTSize(int vecsize) + { + + int retVal = getOptimalDFTSize_0(vecsize); + + return retVal; + } + + + // + // C++: int cv::getThreadNum() + // + + //javadoc: getThreadNum() + @Deprecated + public static int getThreadNum() + { + + int retVal = getThreadNum_0(); + + return retVal; + } + + + // + // C++: int cv::getVersionMajor() + // + + //javadoc: getVersionMajor() + public static int getVersionMajor() + { + + int retVal = getVersionMajor_0(); + + return retVal; + } + + + // + // C++: int cv::getVersionMinor() + // + + //javadoc: getVersionMinor() + public static int getVersionMinor() + { + + int retVal = getVersionMinor_0(); + + return retVal; + } + + + // + // C++: int cv::getVersionRevision() + // + + //javadoc: getVersionRevision() + public static int getVersionRevision() + { + + int retVal = getVersionRevision_0(); + + return retVal; + } + + + // + // C++: int cv::solveCubic(Mat coeffs, Mat& roots) + // + + //javadoc: solveCubic(coeffs, roots) + public static int solveCubic(Mat coeffs, Mat roots) + { + + int retVal = solveCubic_0(coeffs.nativeObj, roots.nativeObj); + + return retVal; + } + + + // + // C++: int64 cv::getCPUTickCount() + // + + //javadoc: getCPUTickCount() + public static long getCPUTickCount() + { + + long retVal = getCPUTickCount_0(); + + return retVal; + } + + + // + // C++: int64 cv::getTickCount() + // + + //javadoc: getTickCount() + public static long getTickCount() + { + + long retVal = getTickCount_0(); + + return retVal; + } + + + // + // C++: void cv::LUT(Mat src, Mat lut, Mat& dst) + // + + //javadoc: LUT(src, lut, dst) + public static void LUT(Mat src, Mat lut, Mat dst) + { + + LUT_0(src.nativeObj, lut.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::PCABackProject(Mat data, Mat mean, Mat eigenvectors, Mat& result) + // + + //javadoc: PCABackProject(data, mean, eigenvectors, result) + public static void PCABackProject(Mat data, Mat mean, Mat eigenvectors, Mat result) + { + + PCABackProject_0(data.nativeObj, mean.nativeObj, eigenvectors.nativeObj, result.nativeObj); + + return; + } + + + // + // C++: void cv::PCACompute(Mat data, Mat& mean, Mat& eigenvectors, Mat& eigenvalues, double retainedVariance) + // + + //javadoc: PCACompute2(data, mean, eigenvectors, eigenvalues, retainedVariance) + public static void PCACompute2(Mat data, Mat mean, Mat eigenvectors, Mat eigenvalues, double retainedVariance) + { + + PCACompute2_0(data.nativeObj, mean.nativeObj, eigenvectors.nativeObj, eigenvalues.nativeObj, retainedVariance); + + return; + } + + + // + // C++: void cv::PCACompute(Mat data, Mat& mean, Mat& eigenvectors, Mat& eigenvalues, int maxComponents = 0) + // + + //javadoc: PCACompute2(data, mean, eigenvectors, eigenvalues, maxComponents) + public static void PCACompute2(Mat data, Mat mean, Mat eigenvectors, Mat eigenvalues, int maxComponents) + { + + PCACompute2_1(data.nativeObj, mean.nativeObj, eigenvectors.nativeObj, eigenvalues.nativeObj, maxComponents); + + return; + } + + //javadoc: PCACompute2(data, mean, eigenvectors, eigenvalues) + public static void PCACompute2(Mat data, Mat mean, Mat eigenvectors, Mat eigenvalues) + { + + PCACompute2_2(data.nativeObj, mean.nativeObj, eigenvectors.nativeObj, eigenvalues.nativeObj); + + return; + } + + + // + // C++: void cv::PCACompute(Mat data, Mat& mean, Mat& eigenvectors, double retainedVariance) + // + + //javadoc: PCACompute(data, mean, eigenvectors, retainedVariance) + public static void PCACompute(Mat data, Mat mean, Mat eigenvectors, double retainedVariance) + { + + PCACompute_0(data.nativeObj, mean.nativeObj, eigenvectors.nativeObj, retainedVariance); + + return; + } + + + // + // C++: void cv::PCACompute(Mat data, Mat& mean, Mat& eigenvectors, int maxComponents = 0) + // + + //javadoc: PCACompute(data, mean, eigenvectors, maxComponents) + public static void PCACompute(Mat data, Mat mean, Mat eigenvectors, int maxComponents) + { + + PCACompute_1(data.nativeObj, mean.nativeObj, eigenvectors.nativeObj, maxComponents); + + return; + } + + //javadoc: PCACompute(data, mean, eigenvectors) + public static void PCACompute(Mat data, Mat mean, Mat eigenvectors) + { + + PCACompute_2(data.nativeObj, mean.nativeObj, eigenvectors.nativeObj); + + return; + } + + + // + // C++: void cv::PCAProject(Mat data, Mat mean, Mat eigenvectors, Mat& result) + // + + //javadoc: PCAProject(data, mean, eigenvectors, result) + public static void PCAProject(Mat data, Mat mean, Mat eigenvectors, Mat result) + { + + PCAProject_0(data.nativeObj, mean.nativeObj, eigenvectors.nativeObj, result.nativeObj); + + return; + } + + + // + // C++: void cv::SVBackSubst(Mat w, Mat u, Mat vt, Mat rhs, Mat& dst) + // + + //javadoc: SVBackSubst(w, u, vt, rhs, dst) + public static void SVBackSubst(Mat w, Mat u, Mat vt, Mat rhs, Mat dst) + { + + SVBackSubst_0(w.nativeObj, u.nativeObj, vt.nativeObj, rhs.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::SVDecomp(Mat src, Mat& w, Mat& u, Mat& vt, int flags = 0) + // + + //javadoc: SVDecomp(src, w, u, vt, flags) + public static void SVDecomp(Mat src, Mat w, Mat u, Mat vt, int flags) + { + + SVDecomp_0(src.nativeObj, w.nativeObj, u.nativeObj, vt.nativeObj, flags); + + return; + } + + //javadoc: SVDecomp(src, w, u, vt) + public static void SVDecomp(Mat src, Mat w, Mat u, Mat vt) + { + + SVDecomp_1(src.nativeObj, w.nativeObj, u.nativeObj, vt.nativeObj); + + return; + } + + + // + // C++: void cv::absdiff(Mat src1, Mat src2, Mat& dst) + // + + //javadoc: absdiff(src1, src2, dst) + public static void absdiff(Mat src1, Mat src2, Mat dst) + { + + absdiff_0(src1.nativeObj, src2.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::absdiff(Mat src1, Scalar src2, Mat& dst) + // + + //javadoc: absdiff(src1, src2, dst) + public static void absdiff(Mat src1, Scalar src2, Mat dst) + { + + absdiff_1(src1.nativeObj, src2.val[0], src2.val[1], src2.val[2], src2.val[3], dst.nativeObj); + + return; + } + + + // + // C++: void cv::add(Mat src1, Mat src2, Mat& dst, Mat mask = Mat(), int dtype = -1) + // + + //javadoc: add(src1, src2, dst, mask, dtype) + public static void add(Mat src1, Mat src2, Mat dst, Mat mask, int dtype) + { + + add_0(src1.nativeObj, src2.nativeObj, dst.nativeObj, mask.nativeObj, dtype); + + return; + } + + //javadoc: add(src1, src2, dst, mask) + public static void add(Mat src1, Mat src2, Mat dst, Mat mask) + { + + add_1(src1.nativeObj, src2.nativeObj, dst.nativeObj, mask.nativeObj); + + return; + } + + //javadoc: add(src1, src2, dst) + public static void add(Mat src1, Mat src2, Mat dst) + { + + add_2(src1.nativeObj, src2.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::add(Mat src1, Scalar src2, Mat& dst, Mat mask = Mat(), int dtype = -1) + // + + //javadoc: add(src1, src2, dst, mask, dtype) + public static void add(Mat src1, Scalar src2, Mat dst, Mat mask, int dtype) + { + + add_3(src1.nativeObj, src2.val[0], src2.val[1], src2.val[2], src2.val[3], dst.nativeObj, mask.nativeObj, dtype); + + return; + } + + //javadoc: add(src1, src2, dst, mask) + public static void add(Mat src1, Scalar src2, Mat dst, Mat mask) + { + + add_4(src1.nativeObj, src2.val[0], src2.val[1], src2.val[2], src2.val[3], dst.nativeObj, mask.nativeObj); + + return; + } + + //javadoc: add(src1, src2, dst) + public static void add(Mat src1, Scalar src2, Mat dst) + { + + add_5(src1.nativeObj, src2.val[0], src2.val[1], src2.val[2], src2.val[3], dst.nativeObj); + + return; + } + + + // + // C++: void cv::addWeighted(Mat src1, double alpha, Mat src2, double beta, double gamma, Mat& dst, int dtype = -1) + // + + //javadoc: addWeighted(src1, alpha, src2, beta, gamma, dst, dtype) + public static void addWeighted(Mat src1, double alpha, Mat src2, double beta, double gamma, Mat dst, int dtype) + { + + addWeighted_0(src1.nativeObj, alpha, src2.nativeObj, beta, gamma, dst.nativeObj, dtype); + + return; + } + + //javadoc: addWeighted(src1, alpha, src2, beta, gamma, dst) + public static void addWeighted(Mat src1, double alpha, Mat src2, double beta, double gamma, Mat dst) + { + + addWeighted_1(src1.nativeObj, alpha, src2.nativeObj, beta, gamma, dst.nativeObj); + + return; + } + + + // + // C++: void cv::batchDistance(Mat src1, Mat src2, Mat& dist, int dtype, Mat& nidx, int normType = NORM_L2, int K = 0, Mat mask = Mat(), int update = 0, bool crosscheck = false) + // + + //javadoc: batchDistance(src1, src2, dist, dtype, nidx, normType, K, mask, update, crosscheck) + public static void batchDistance(Mat src1, Mat src2, Mat dist, int dtype, Mat nidx, int normType, int K, Mat mask, int update, boolean crosscheck) + { + + batchDistance_0(src1.nativeObj, src2.nativeObj, dist.nativeObj, dtype, nidx.nativeObj, normType, K, mask.nativeObj, update, crosscheck); + + return; + } + + //javadoc: batchDistance(src1, src2, dist, dtype, nidx, normType, K, mask, update) + public static void batchDistance(Mat src1, Mat src2, Mat dist, int dtype, Mat nidx, int normType, int K, Mat mask, int update) + { + + batchDistance_1(src1.nativeObj, src2.nativeObj, dist.nativeObj, dtype, nidx.nativeObj, normType, K, mask.nativeObj, update); + + return; + } + + //javadoc: batchDistance(src1, src2, dist, dtype, nidx, normType, K, mask) + public static void batchDistance(Mat src1, Mat src2, Mat dist, int dtype, Mat nidx, int normType, int K, Mat mask) + { + + batchDistance_2(src1.nativeObj, src2.nativeObj, dist.nativeObj, dtype, nidx.nativeObj, normType, K, mask.nativeObj); + + return; + } + + //javadoc: batchDistance(src1, src2, dist, dtype, nidx, normType, K) + public static void batchDistance(Mat src1, Mat src2, Mat dist, int dtype, Mat nidx, int normType, int K) + { + + batchDistance_3(src1.nativeObj, src2.nativeObj, dist.nativeObj, dtype, nidx.nativeObj, normType, K); + + return; + } + + //javadoc: batchDistance(src1, src2, dist, dtype, nidx, normType) + public static void batchDistance(Mat src1, Mat src2, Mat dist, int dtype, Mat nidx, int normType) + { + + batchDistance_4(src1.nativeObj, src2.nativeObj, dist.nativeObj, dtype, nidx.nativeObj, normType); + + return; + } + + //javadoc: batchDistance(src1, src2, dist, dtype, nidx) + public static void batchDistance(Mat src1, Mat src2, Mat dist, int dtype, Mat nidx) + { + + batchDistance_5(src1.nativeObj, src2.nativeObj, dist.nativeObj, dtype, nidx.nativeObj); + + return; + } + + + // + // C++: void cv::bitwise_and(Mat src1, Mat src2, Mat& dst, Mat mask = Mat()) + // + + //javadoc: bitwise_and(src1, src2, dst, mask) + public static void bitwise_and(Mat src1, Mat src2, Mat dst, Mat mask) + { + + bitwise_and_0(src1.nativeObj, src2.nativeObj, dst.nativeObj, mask.nativeObj); + + return; + } + + //javadoc: bitwise_and(src1, src2, dst) + public static void bitwise_and(Mat src1, Mat src2, Mat dst) + { + + bitwise_and_1(src1.nativeObj, src2.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::bitwise_not(Mat src, Mat& dst, Mat mask = Mat()) + // + + //javadoc: bitwise_not(src, dst, mask) + public static void bitwise_not(Mat src, Mat dst, Mat mask) + { + + bitwise_not_0(src.nativeObj, dst.nativeObj, mask.nativeObj); + + return; + } + + //javadoc: bitwise_not(src, dst) + public static void bitwise_not(Mat src, Mat dst) + { + + bitwise_not_1(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::bitwise_or(Mat src1, Mat src2, Mat& dst, Mat mask = Mat()) + // + + //javadoc: bitwise_or(src1, src2, dst, mask) + public static void bitwise_or(Mat src1, Mat src2, Mat dst, Mat mask) + { + + bitwise_or_0(src1.nativeObj, src2.nativeObj, dst.nativeObj, mask.nativeObj); + + return; + } + + //javadoc: bitwise_or(src1, src2, dst) + public static void bitwise_or(Mat src1, Mat src2, Mat dst) + { + + bitwise_or_1(src1.nativeObj, src2.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::bitwise_xor(Mat src1, Mat src2, Mat& dst, Mat mask = Mat()) + // + + //javadoc: bitwise_xor(src1, src2, dst, mask) + public static void bitwise_xor(Mat src1, Mat src2, Mat dst, Mat mask) + { + + bitwise_xor_0(src1.nativeObj, src2.nativeObj, dst.nativeObj, mask.nativeObj); + + return; + } + + //javadoc: bitwise_xor(src1, src2, dst) + public static void bitwise_xor(Mat src1, Mat src2, Mat dst) + { + + bitwise_xor_1(src1.nativeObj, src2.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::calcCovarMatrix(Mat samples, Mat& covar, Mat& mean, int flags, int ctype = CV_64F) + // + + //javadoc: calcCovarMatrix(samples, covar, mean, flags, ctype) + public static void calcCovarMatrix(Mat samples, Mat covar, Mat mean, int flags, int ctype) + { + + calcCovarMatrix_0(samples.nativeObj, covar.nativeObj, mean.nativeObj, flags, ctype); + + return; + } + + //javadoc: calcCovarMatrix(samples, covar, mean, flags) + public static void calcCovarMatrix(Mat samples, Mat covar, Mat mean, int flags) + { + + calcCovarMatrix_1(samples.nativeObj, covar.nativeObj, mean.nativeObj, flags); + + return; + } + + + // + // C++: void cv::cartToPolar(Mat x, Mat y, Mat& magnitude, Mat& angle, bool angleInDegrees = false) + // + + //javadoc: cartToPolar(x, y, magnitude, angle, angleInDegrees) + public static void cartToPolar(Mat x, Mat y, Mat magnitude, Mat angle, boolean angleInDegrees) + { + + cartToPolar_0(x.nativeObj, y.nativeObj, magnitude.nativeObj, angle.nativeObj, angleInDegrees); + + return; + } + + //javadoc: cartToPolar(x, y, magnitude, angle) + public static void cartToPolar(Mat x, Mat y, Mat magnitude, Mat angle) + { + + cartToPolar_1(x.nativeObj, y.nativeObj, magnitude.nativeObj, angle.nativeObj); + + return; + } + + + // + // C++: void cv::compare(Mat src1, Mat src2, Mat& dst, int cmpop) + // + + //javadoc: compare(src1, src2, dst, cmpop) + public static void compare(Mat src1, Mat src2, Mat dst, int cmpop) + { + + compare_0(src1.nativeObj, src2.nativeObj, dst.nativeObj, cmpop); + + return; + } + + + // + // C++: void cv::compare(Mat src1, Scalar src2, Mat& dst, int cmpop) + // + + //javadoc: compare(src1, src2, dst, cmpop) + public static void compare(Mat src1, Scalar src2, Mat dst, int cmpop) + { + + compare_1(src1.nativeObj, src2.val[0], src2.val[1], src2.val[2], src2.val[3], dst.nativeObj, cmpop); + + return; + } + + + // + // C++: void cv::completeSymm(Mat& m, bool lowerToUpper = false) + // + + //javadoc: completeSymm(m, lowerToUpper) + public static void completeSymm(Mat m, boolean lowerToUpper) + { + + completeSymm_0(m.nativeObj, lowerToUpper); + + return; + } + + //javadoc: completeSymm(m) + public static void completeSymm(Mat m) + { + + completeSymm_1(m.nativeObj); + + return; + } + + + // + // C++: void cv::convertFp16(Mat src, Mat& dst) + // + + //javadoc: convertFp16(src, dst) + public static void convertFp16(Mat src, Mat dst) + { + + convertFp16_0(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::convertScaleAbs(Mat src, Mat& dst, double alpha = 1, double beta = 0) + // + + //javadoc: convertScaleAbs(src, dst, alpha, beta) + public static void convertScaleAbs(Mat src, Mat dst, double alpha, double beta) + { + + convertScaleAbs_0(src.nativeObj, dst.nativeObj, alpha, beta); + + return; + } + + //javadoc: convertScaleAbs(src, dst, alpha) + public static void convertScaleAbs(Mat src, Mat dst, double alpha) + { + + convertScaleAbs_1(src.nativeObj, dst.nativeObj, alpha); + + return; + } + + //javadoc: convertScaleAbs(src, dst) + public static void convertScaleAbs(Mat src, Mat dst) + { + + convertScaleAbs_2(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::copyMakeBorder(Mat src, Mat& dst, int top, int bottom, int left, int right, int borderType, Scalar value = Scalar()) + // + + //javadoc: copyMakeBorder(src, dst, top, bottom, left, right, borderType, value) + public static void copyMakeBorder(Mat src, Mat dst, int top, int bottom, int left, int right, int borderType, Scalar value) + { + + copyMakeBorder_0(src.nativeObj, dst.nativeObj, top, bottom, left, right, borderType, value.val[0], value.val[1], value.val[2], value.val[3]); + + return; + } + + //javadoc: copyMakeBorder(src, dst, top, bottom, left, right, borderType) + public static void copyMakeBorder(Mat src, Mat dst, int top, int bottom, int left, int right, int borderType) + { + + copyMakeBorder_1(src.nativeObj, dst.nativeObj, top, bottom, left, right, borderType); + + return; + } + + + // + // C++: void cv::copyTo(Mat src, Mat& dst, Mat mask) + // + + //javadoc: copyTo(src, dst, mask) + public static void copyTo(Mat src, Mat dst, Mat mask) + { + + copyTo_0(src.nativeObj, dst.nativeObj, mask.nativeObj); + + return; + } + + + // + // C++: void cv::dct(Mat src, Mat& dst, int flags = 0) + // + + //javadoc: dct(src, dst, flags) + public static void dct(Mat src, Mat dst, int flags) + { + + dct_0(src.nativeObj, dst.nativeObj, flags); + + return; + } + + //javadoc: dct(src, dst) + public static void dct(Mat src, Mat dst) + { + + dct_1(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::dft(Mat src, Mat& dst, int flags = 0, int nonzeroRows = 0) + // + + //javadoc: dft(src, dst, flags, nonzeroRows) + public static void dft(Mat src, Mat dst, int flags, int nonzeroRows) + { + + dft_0(src.nativeObj, dst.nativeObj, flags, nonzeroRows); + + return; + } + + //javadoc: dft(src, dst, flags) + public static void dft(Mat src, Mat dst, int flags) + { + + dft_1(src.nativeObj, dst.nativeObj, flags); + + return; + } + + //javadoc: dft(src, dst) + public static void dft(Mat src, Mat dst) + { + + dft_2(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::divide(Mat src1, Mat src2, Mat& dst, double scale = 1, int dtype = -1) + // + + //javadoc: divide(src1, src2, dst, scale, dtype) + public static void divide(Mat src1, Mat src2, Mat dst, double scale, int dtype) + { + + divide_0(src1.nativeObj, src2.nativeObj, dst.nativeObj, scale, dtype); + + return; + } + + //javadoc: divide(src1, src2, dst, scale) + public static void divide(Mat src1, Mat src2, Mat dst, double scale) + { + + divide_1(src1.nativeObj, src2.nativeObj, dst.nativeObj, scale); + + return; + } + + //javadoc: divide(src1, src2, dst) + public static void divide(Mat src1, Mat src2, Mat dst) + { + + divide_2(src1.nativeObj, src2.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::divide(Mat src1, Scalar src2, Mat& dst, double scale = 1, int dtype = -1) + // + + //javadoc: divide(src1, src2, dst, scale, dtype) + public static void divide(Mat src1, Scalar src2, Mat dst, double scale, int dtype) + { + + divide_3(src1.nativeObj, src2.val[0], src2.val[1], src2.val[2], src2.val[3], dst.nativeObj, scale, dtype); + + return; + } + + //javadoc: divide(src1, src2, dst, scale) + public static void divide(Mat src1, Scalar src2, Mat dst, double scale) + { + + divide_4(src1.nativeObj, src2.val[0], src2.val[1], src2.val[2], src2.val[3], dst.nativeObj, scale); + + return; + } + + //javadoc: divide(src1, src2, dst) + public static void divide(Mat src1, Scalar src2, Mat dst) + { + + divide_5(src1.nativeObj, src2.val[0], src2.val[1], src2.val[2], src2.val[3], dst.nativeObj); + + return; + } + + + // + // C++: void cv::divide(double scale, Mat src2, Mat& dst, int dtype = -1) + // + + //javadoc: divide(scale, src2, dst, dtype) + public static void divide(double scale, Mat src2, Mat dst, int dtype) + { + + divide_6(scale, src2.nativeObj, dst.nativeObj, dtype); + + return; + } + + //javadoc: divide(scale, src2, dst) + public static void divide(double scale, Mat src2, Mat dst) + { + + divide_7(scale, src2.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::eigenNonSymmetric(Mat src, Mat& eigenvalues, Mat& eigenvectors) + // + + //javadoc: eigenNonSymmetric(src, eigenvalues, eigenvectors) + public static void eigenNonSymmetric(Mat src, Mat eigenvalues, Mat eigenvectors) + { + + eigenNonSymmetric_0(src.nativeObj, eigenvalues.nativeObj, eigenvectors.nativeObj); + + return; + } + + + // + // C++: void cv::exp(Mat src, Mat& dst) + // + + //javadoc: exp(src, dst) + public static void exp(Mat src, Mat dst) + { + + exp_0(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::extractChannel(Mat src, Mat& dst, int coi) + // + + //javadoc: extractChannel(src, dst, coi) + public static void extractChannel(Mat src, Mat dst, int coi) + { + + extractChannel_0(src.nativeObj, dst.nativeObj, coi); + + return; + } + + + // + // C++: void cv::findNonZero(Mat src, Mat& idx) + // + + //javadoc: findNonZero(src, idx) + public static void findNonZero(Mat src, Mat idx) + { + + findNonZero_0(src.nativeObj, idx.nativeObj); + + return; + } + + + // + // C++: void cv::flip(Mat src, Mat& dst, int flipCode) + // + + //javadoc: flip(src, dst, flipCode) + public static void flip(Mat src, Mat dst, int flipCode) + { + + flip_0(src.nativeObj, dst.nativeObj, flipCode); + + return; + } + + + // + // C++: void cv::gemm(Mat src1, Mat src2, double alpha, Mat src3, double beta, Mat& dst, int flags = 0) + // + + //javadoc: gemm(src1, src2, alpha, src3, beta, dst, flags) + public static void gemm(Mat src1, Mat src2, double alpha, Mat src3, double beta, Mat dst, int flags) + { + + gemm_0(src1.nativeObj, src2.nativeObj, alpha, src3.nativeObj, beta, dst.nativeObj, flags); + + return; + } + + //javadoc: gemm(src1, src2, alpha, src3, beta, dst) + public static void gemm(Mat src1, Mat src2, double alpha, Mat src3, double beta, Mat dst) + { + + gemm_1(src1.nativeObj, src2.nativeObj, alpha, src3.nativeObj, beta, dst.nativeObj); + + return; + } + + + // + // C++: void cv::hconcat(vector_Mat src, Mat& dst) + // + + //javadoc: hconcat(src, dst) + public static void hconcat(List src, Mat dst) + { + Mat src_mat = Converters.vector_Mat_to_Mat(src); + hconcat_0(src_mat.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::idct(Mat src, Mat& dst, int flags = 0) + // + + //javadoc: idct(src, dst, flags) + public static void idct(Mat src, Mat dst, int flags) + { + + idct_0(src.nativeObj, dst.nativeObj, flags); + + return; + } + + //javadoc: idct(src, dst) + public static void idct(Mat src, Mat dst) + { + + idct_1(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::idft(Mat src, Mat& dst, int flags = 0, int nonzeroRows = 0) + // + + //javadoc: idft(src, dst, flags, nonzeroRows) + public static void idft(Mat src, Mat dst, int flags, int nonzeroRows) + { + + idft_0(src.nativeObj, dst.nativeObj, flags, nonzeroRows); + + return; + } + + //javadoc: idft(src, dst, flags) + public static void idft(Mat src, Mat dst, int flags) + { + + idft_1(src.nativeObj, dst.nativeObj, flags); + + return; + } + + //javadoc: idft(src, dst) + public static void idft(Mat src, Mat dst) + { + + idft_2(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::inRange(Mat src, Scalar lowerb, Scalar upperb, Mat& dst) + // + + //javadoc: inRange(src, lowerb, upperb, dst) + public static void inRange(Mat src, Scalar lowerb, Scalar upperb, Mat dst) + { + + inRange_0(src.nativeObj, lowerb.val[0], lowerb.val[1], lowerb.val[2], lowerb.val[3], upperb.val[0], upperb.val[1], upperb.val[2], upperb.val[3], dst.nativeObj); + + return; + } + + + // + // C++: void cv::insertChannel(Mat src, Mat& dst, int coi) + // + + //javadoc: insertChannel(src, dst, coi) + public static void insertChannel(Mat src, Mat dst, int coi) + { + + insertChannel_0(src.nativeObj, dst.nativeObj, coi); + + return; + } + + + // + // C++: void cv::log(Mat src, Mat& dst) + // + + //javadoc: log(src, dst) + public static void log(Mat src, Mat dst) + { + + log_0(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::magnitude(Mat x, Mat y, Mat& magnitude) + // + + //javadoc: magnitude(x, y, magnitude) + public static void magnitude(Mat x, Mat y, Mat magnitude) + { + + magnitude_0(x.nativeObj, y.nativeObj, magnitude.nativeObj); + + return; + } + + + // + // C++: void cv::max(Mat src1, Mat src2, Mat& dst) + // + + //javadoc: max(src1, src2, dst) + public static void max(Mat src1, Mat src2, Mat dst) + { + + max_0(src1.nativeObj, src2.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::max(Mat src1, Scalar src2, Mat& dst) + // + + //javadoc: max(src1, src2, dst) + public static void max(Mat src1, Scalar src2, Mat dst) + { + + max_1(src1.nativeObj, src2.val[0], src2.val[1], src2.val[2], src2.val[3], dst.nativeObj); + + return; + } + + + // + // C++: void cv::meanStdDev(Mat src, vector_double& mean, vector_double& stddev, Mat mask = Mat()) + // + + //javadoc: meanStdDev(src, mean, stddev, mask) + public static void meanStdDev(Mat src, MatOfDouble mean, MatOfDouble stddev, Mat mask) + { + Mat mean_mat = mean; + Mat stddev_mat = stddev; + meanStdDev_0(src.nativeObj, mean_mat.nativeObj, stddev_mat.nativeObj, mask.nativeObj); + + return; + } + + //javadoc: meanStdDev(src, mean, stddev) + public static void meanStdDev(Mat src, MatOfDouble mean, MatOfDouble stddev) + { + Mat mean_mat = mean; + Mat stddev_mat = stddev; + meanStdDev_1(src.nativeObj, mean_mat.nativeObj, stddev_mat.nativeObj); + + return; + } + + + // + // C++: void cv::merge(vector_Mat mv, Mat& dst) + // + + //javadoc: merge(mv, dst) + public static void merge(List mv, Mat dst) + { + Mat mv_mat = Converters.vector_Mat_to_Mat(mv); + merge_0(mv_mat.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::min(Mat src1, Mat src2, Mat& dst) + // + + //javadoc: min(src1, src2, dst) + public static void min(Mat src1, Mat src2, Mat dst) + { + + min_0(src1.nativeObj, src2.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::min(Mat src1, Scalar src2, Mat& dst) + // + + //javadoc: min(src1, src2, dst) + public static void min(Mat src1, Scalar src2, Mat dst) + { + + min_1(src1.nativeObj, src2.val[0], src2.val[1], src2.val[2], src2.val[3], dst.nativeObj); + + return; + } + + + // + // C++: void cv::mixChannels(vector_Mat src, vector_Mat dst, vector_int fromTo) + // + + //javadoc: mixChannels(src, dst, fromTo) + public static void mixChannels(List src, List dst, MatOfInt fromTo) + { + Mat src_mat = Converters.vector_Mat_to_Mat(src); + Mat dst_mat = Converters.vector_Mat_to_Mat(dst); + Mat fromTo_mat = fromTo; + mixChannels_0(src_mat.nativeObj, dst_mat.nativeObj, fromTo_mat.nativeObj); + + return; + } + + + // + // C++: void cv::mulSpectrums(Mat a, Mat b, Mat& c, int flags, bool conjB = false) + // + + //javadoc: mulSpectrums(a, b, c, flags, conjB) + public static void mulSpectrums(Mat a, Mat b, Mat c, int flags, boolean conjB) + { + + mulSpectrums_0(a.nativeObj, b.nativeObj, c.nativeObj, flags, conjB); + + return; + } + + //javadoc: mulSpectrums(a, b, c, flags) + public static void mulSpectrums(Mat a, Mat b, Mat c, int flags) + { + + mulSpectrums_1(a.nativeObj, b.nativeObj, c.nativeObj, flags); + + return; + } + + + // + // C++: void cv::mulTransposed(Mat src, Mat& dst, bool aTa, Mat delta = Mat(), double scale = 1, int dtype = -1) + // + + //javadoc: mulTransposed(src, dst, aTa, delta, scale, dtype) + public static void mulTransposed(Mat src, Mat dst, boolean aTa, Mat delta, double scale, int dtype) + { + + mulTransposed_0(src.nativeObj, dst.nativeObj, aTa, delta.nativeObj, scale, dtype); + + return; + } + + //javadoc: mulTransposed(src, dst, aTa, delta, scale) + public static void mulTransposed(Mat src, Mat dst, boolean aTa, Mat delta, double scale) + { + + mulTransposed_1(src.nativeObj, dst.nativeObj, aTa, delta.nativeObj, scale); + + return; + } + + //javadoc: mulTransposed(src, dst, aTa, delta) + public static void mulTransposed(Mat src, Mat dst, boolean aTa, Mat delta) + { + + mulTransposed_2(src.nativeObj, dst.nativeObj, aTa, delta.nativeObj); + + return; + } + + //javadoc: mulTransposed(src, dst, aTa) + public static void mulTransposed(Mat src, Mat dst, boolean aTa) + { + + mulTransposed_3(src.nativeObj, dst.nativeObj, aTa); + + return; + } + + + // + // C++: void cv::multiply(Mat src1, Mat src2, Mat& dst, double scale = 1, int dtype = -1) + // + + //javadoc: multiply(src1, src2, dst, scale, dtype) + public static void multiply(Mat src1, Mat src2, Mat dst, double scale, int dtype) + { + + multiply_0(src1.nativeObj, src2.nativeObj, dst.nativeObj, scale, dtype); + + return; + } + + //javadoc: multiply(src1, src2, dst, scale) + public static void multiply(Mat src1, Mat src2, Mat dst, double scale) + { + + multiply_1(src1.nativeObj, src2.nativeObj, dst.nativeObj, scale); + + return; + } + + //javadoc: multiply(src1, src2, dst) + public static void multiply(Mat src1, Mat src2, Mat dst) + { + + multiply_2(src1.nativeObj, src2.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::multiply(Mat src1, Scalar src2, Mat& dst, double scale = 1, int dtype = -1) + // + + //javadoc: multiply(src1, src2, dst, scale, dtype) + public static void multiply(Mat src1, Scalar src2, Mat dst, double scale, int dtype) + { + + multiply_3(src1.nativeObj, src2.val[0], src2.val[1], src2.val[2], src2.val[3], dst.nativeObj, scale, dtype); + + return; + } + + //javadoc: multiply(src1, src2, dst, scale) + public static void multiply(Mat src1, Scalar src2, Mat dst, double scale) + { + + multiply_4(src1.nativeObj, src2.val[0], src2.val[1], src2.val[2], src2.val[3], dst.nativeObj, scale); + + return; + } + + //javadoc: multiply(src1, src2, dst) + public static void multiply(Mat src1, Scalar src2, Mat dst) + { + + multiply_5(src1.nativeObj, src2.val[0], src2.val[1], src2.val[2], src2.val[3], dst.nativeObj); + + return; + } + + + // + // C++: void cv::normalize(Mat src, Mat& dst, double alpha = 1, double beta = 0, int norm_type = NORM_L2, int dtype = -1, Mat mask = Mat()) + // + + //javadoc: normalize(src, dst, alpha, beta, norm_type, dtype, mask) + public static void normalize(Mat src, Mat dst, double alpha, double beta, int norm_type, int dtype, Mat mask) + { + + normalize_0(src.nativeObj, dst.nativeObj, alpha, beta, norm_type, dtype, mask.nativeObj); + + return; + } + + //javadoc: normalize(src, dst, alpha, beta, norm_type, dtype) + public static void normalize(Mat src, Mat dst, double alpha, double beta, int norm_type, int dtype) + { + + normalize_1(src.nativeObj, dst.nativeObj, alpha, beta, norm_type, dtype); + + return; + } + + //javadoc: normalize(src, dst, alpha, beta, norm_type) + public static void normalize(Mat src, Mat dst, double alpha, double beta, int norm_type) + { + + normalize_2(src.nativeObj, dst.nativeObj, alpha, beta, norm_type); + + return; + } + + //javadoc: normalize(src, dst, alpha, beta) + public static void normalize(Mat src, Mat dst, double alpha, double beta) + { + + normalize_3(src.nativeObj, dst.nativeObj, alpha, beta); + + return; + } + + //javadoc: normalize(src, dst, alpha) + public static void normalize(Mat src, Mat dst, double alpha) + { + + normalize_4(src.nativeObj, dst.nativeObj, alpha); + + return; + } + + //javadoc: normalize(src, dst) + public static void normalize(Mat src, Mat dst) + { + + normalize_5(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::patchNaNs(Mat& a, double val = 0) + // + + //javadoc: patchNaNs(a, val) + public static void patchNaNs(Mat a, double val) + { + + patchNaNs_0(a.nativeObj, val); + + return; + } + + //javadoc: patchNaNs(a) + public static void patchNaNs(Mat a) + { + + patchNaNs_1(a.nativeObj); + + return; + } + + + // + // C++: void cv::perspectiveTransform(Mat src, Mat& dst, Mat m) + // + + //javadoc: perspectiveTransform(src, dst, m) + public static void perspectiveTransform(Mat src, Mat dst, Mat m) + { + + perspectiveTransform_0(src.nativeObj, dst.nativeObj, m.nativeObj); + + return; + } + + + // + // C++: void cv::phase(Mat x, Mat y, Mat& angle, bool angleInDegrees = false) + // + + //javadoc: phase(x, y, angle, angleInDegrees) + public static void phase(Mat x, Mat y, Mat angle, boolean angleInDegrees) + { + + phase_0(x.nativeObj, y.nativeObj, angle.nativeObj, angleInDegrees); + + return; + } + + //javadoc: phase(x, y, angle) + public static void phase(Mat x, Mat y, Mat angle) + { + + phase_1(x.nativeObj, y.nativeObj, angle.nativeObj); + + return; + } + + + // + // C++: void cv::polarToCart(Mat magnitude, Mat angle, Mat& x, Mat& y, bool angleInDegrees = false) + // + + //javadoc: polarToCart(magnitude, angle, x, y, angleInDegrees) + public static void polarToCart(Mat magnitude, Mat angle, Mat x, Mat y, boolean angleInDegrees) + { + + polarToCart_0(magnitude.nativeObj, angle.nativeObj, x.nativeObj, y.nativeObj, angleInDegrees); + + return; + } + + //javadoc: polarToCart(magnitude, angle, x, y) + public static void polarToCart(Mat magnitude, Mat angle, Mat x, Mat y) + { + + polarToCart_1(magnitude.nativeObj, angle.nativeObj, x.nativeObj, y.nativeObj); + + return; + } + + + // + // C++: void cv::pow(Mat src, double power, Mat& dst) + // + + //javadoc: pow(src, power, dst) + public static void pow(Mat src, double power, Mat dst) + { + + pow_0(src.nativeObj, power, dst.nativeObj); + + return; + } + + + // + // C++: void cv::randShuffle(Mat& dst, double iterFactor = 1., RNG* rng = 0) + // + + //javadoc: randShuffle(dst, iterFactor) + public static void randShuffle(Mat dst, double iterFactor) + { + + randShuffle_0(dst.nativeObj, iterFactor); + + return; + } + + //javadoc: randShuffle(dst) + public static void randShuffle(Mat dst) + { + + randShuffle_2(dst.nativeObj); + + return; + } + + + // + // C++: void cv::randn(Mat& dst, double mean, double stddev) + // + + //javadoc: randn(dst, mean, stddev) + public static void randn(Mat dst, double mean, double stddev) + { + + randn_0(dst.nativeObj, mean, stddev); + + return; + } + + + // + // C++: void cv::randu(Mat& dst, double low, double high) + // + + //javadoc: randu(dst, low, high) + public static void randu(Mat dst, double low, double high) + { + + randu_0(dst.nativeObj, low, high); + + return; + } + + + // + // C++: void cv::reduce(Mat src, Mat& dst, int dim, int rtype, int dtype = -1) + // + + //javadoc: reduce(src, dst, dim, rtype, dtype) + public static void reduce(Mat src, Mat dst, int dim, int rtype, int dtype) + { + + reduce_0(src.nativeObj, dst.nativeObj, dim, rtype, dtype); + + return; + } + + //javadoc: reduce(src, dst, dim, rtype) + public static void reduce(Mat src, Mat dst, int dim, int rtype) + { + + reduce_1(src.nativeObj, dst.nativeObj, dim, rtype); + + return; + } + + + // + // C++: void cv::repeat(Mat src, int ny, int nx, Mat& dst) + // + + //javadoc: repeat(src, ny, nx, dst) + public static void repeat(Mat src, int ny, int nx, Mat dst) + { + + repeat_0(src.nativeObj, ny, nx, dst.nativeObj); + + return; + } + + + // + // C++: void cv::rotate(Mat src, Mat& dst, int rotateCode) + // + + //javadoc: rotate(src, dst, rotateCode) + public static void rotate(Mat src, Mat dst, int rotateCode) + { + + rotate_0(src.nativeObj, dst.nativeObj, rotateCode); + + return; + } + + + // + // C++: void cv::scaleAdd(Mat src1, double alpha, Mat src2, Mat& dst) + // + + //javadoc: scaleAdd(src1, alpha, src2, dst) + public static void scaleAdd(Mat src1, double alpha, Mat src2, Mat dst) + { + + scaleAdd_0(src1.nativeObj, alpha, src2.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::setErrorVerbosity(bool verbose) + // + + //javadoc: setErrorVerbosity(verbose) + public static void setErrorVerbosity(boolean verbose) + { + + setErrorVerbosity_0(verbose); + + return; + } + + + // + // C++: void cv::setIdentity(Mat& mtx, Scalar s = Scalar(1)) + // + + //javadoc: setIdentity(mtx, s) + public static void setIdentity(Mat mtx, Scalar s) + { + + setIdentity_0(mtx.nativeObj, s.val[0], s.val[1], s.val[2], s.val[3]); + + return; + } + + //javadoc: setIdentity(mtx) + public static void setIdentity(Mat mtx) + { + + setIdentity_1(mtx.nativeObj); + + return; + } + + + // + // C++: void cv::setNumThreads(int nthreads) + // + + //javadoc: setNumThreads(nthreads) + public static void setNumThreads(int nthreads) + { + + setNumThreads_0(nthreads); + + return; + } + + + // + // C++: void cv::setRNGSeed(int seed) + // + + //javadoc: setRNGSeed(seed) + public static void setRNGSeed(int seed) + { + + setRNGSeed_0(seed); + + return; + } + + + // + // C++: void cv::sort(Mat src, Mat& dst, int flags) + // + + //javadoc: sort(src, dst, flags) + public static void sort(Mat src, Mat dst, int flags) + { + + sort_0(src.nativeObj, dst.nativeObj, flags); + + return; + } + + + // + // C++: void cv::sortIdx(Mat src, Mat& dst, int flags) + // + + //javadoc: sortIdx(src, dst, flags) + public static void sortIdx(Mat src, Mat dst, int flags) + { + + sortIdx_0(src.nativeObj, dst.nativeObj, flags); + + return; + } + + + // + // C++: void cv::split(Mat m, vector_Mat& mv) + // + + //javadoc: split(m, mv) + public static void split(Mat m, List mv) + { + Mat mv_mat = new Mat(); + split_0(m.nativeObj, mv_mat.nativeObj); + Converters.Mat_to_vector_Mat(mv_mat, mv); + mv_mat.release(); + return; + } + + + // + // C++: void cv::sqrt(Mat src, Mat& dst) + // + + //javadoc: sqrt(src, dst) + public static void sqrt(Mat src, Mat dst) + { + + sqrt_0(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::subtract(Mat src1, Mat src2, Mat& dst, Mat mask = Mat(), int dtype = -1) + // + + //javadoc: subtract(src1, src2, dst, mask, dtype) + public static void subtract(Mat src1, Mat src2, Mat dst, Mat mask, int dtype) + { + + subtract_0(src1.nativeObj, src2.nativeObj, dst.nativeObj, mask.nativeObj, dtype); + + return; + } + + //javadoc: subtract(src1, src2, dst, mask) + public static void subtract(Mat src1, Mat src2, Mat dst, Mat mask) + { + + subtract_1(src1.nativeObj, src2.nativeObj, dst.nativeObj, mask.nativeObj); + + return; + } + + //javadoc: subtract(src1, src2, dst) + public static void subtract(Mat src1, Mat src2, Mat dst) + { + + subtract_2(src1.nativeObj, src2.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::subtract(Mat src1, Scalar src2, Mat& dst, Mat mask = Mat(), int dtype = -1) + // + + //javadoc: subtract(src1, src2, dst, mask, dtype) + public static void subtract(Mat src1, Scalar src2, Mat dst, Mat mask, int dtype) + { + + subtract_3(src1.nativeObj, src2.val[0], src2.val[1], src2.val[2], src2.val[3], dst.nativeObj, mask.nativeObj, dtype); + + return; + } + + //javadoc: subtract(src1, src2, dst, mask) + public static void subtract(Mat src1, Scalar src2, Mat dst, Mat mask) + { + + subtract_4(src1.nativeObj, src2.val[0], src2.val[1], src2.val[2], src2.val[3], dst.nativeObj, mask.nativeObj); + + return; + } + + //javadoc: subtract(src1, src2, dst) + public static void subtract(Mat src1, Scalar src2, Mat dst) + { + + subtract_5(src1.nativeObj, src2.val[0], src2.val[1], src2.val[2], src2.val[3], dst.nativeObj); + + return; + } + + + // + // C++: void cv::transform(Mat src, Mat& dst, Mat m) + // + + //javadoc: transform(src, dst, m) + public static void transform(Mat src, Mat dst, Mat m) + { + + transform_0(src.nativeObj, dst.nativeObj, m.nativeObj); + + return; + } + + + // + // C++: void cv::transpose(Mat src, Mat& dst) + // + + //javadoc: transpose(src, dst) + public static void transpose(Mat src, Mat dst) + { + + transpose_0(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::vconcat(vector_Mat src, Mat& dst) + // + + //javadoc: vconcat(src, dst) + public static void vconcat(List src, Mat dst) + { + Mat src_mat = Converters.vector_Mat_to_Mat(src); + vconcat_0(src_mat.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::ipp::setUseIPP(bool flag) + // + + //javadoc: setUseIPP(flag) + public static void setUseIPP(boolean flag) + { + + setUseIPP_0(flag); + + return; + } + + + // + // C++: void cv::ipp::setUseIPP_NotExact(bool flag) + // + + //javadoc: setUseIPP_NotExact(flag) + public static void setUseIPP_NotExact(boolean flag) + { + + setUseIPP_NotExact_0(flag); + + return; + } + + + // + // C++: void cv::samples::addSamplesDataSearchPath(String path) + // + + //javadoc: addSamplesDataSearchPath(path) + public static void addSamplesDataSearchPath(String path) + { + + addSamplesDataSearchPath_0(path); + + return; + } + + + // + // C++: void cv::samples::addSamplesDataSearchSubDirectory(String subdir) + // + + //javadoc: addSamplesDataSearchSubDirectory(subdir) + public static void addSamplesDataSearchSubDirectory(String subdir) + { + + addSamplesDataSearchSubDirectory_0(subdir); + + return; + } + +// manual port +public static class MinMaxLocResult { + public double minVal; + public double maxVal; + public Point minLoc; + public Point maxLoc; + + + public MinMaxLocResult() { + minVal=0; maxVal=0; + minLoc=new Point(); + maxLoc=new Point(); + } +} + + +// C++: minMaxLoc(Mat src, double* minVal, double* maxVal=0, Point* minLoc=0, Point* maxLoc=0, InputArray mask=noArray()) + + +//javadoc: minMaxLoc(src, mask) +public static MinMaxLocResult minMaxLoc(Mat src, Mat mask) { + MinMaxLocResult res = new MinMaxLocResult(); + long maskNativeObj=0; + if (mask != null) { + maskNativeObj=mask.nativeObj; + } + double resarr[] = n_minMaxLocManual(src.nativeObj, maskNativeObj); + res.minVal=resarr[0]; + res.maxVal=resarr[1]; + res.minLoc.x=resarr[2]; + res.minLoc.y=resarr[3]; + res.maxLoc.x=resarr[4]; + res.maxLoc.y=resarr[5]; + return res; +} + + +//javadoc: minMaxLoc(src) +public static MinMaxLocResult minMaxLoc(Mat src) { + return minMaxLoc(src, null); +} + + + // C++: Scalar cv::mean(Mat src, Mat mask = Mat()) + private static native double[] mean_0(long src_nativeObj, long mask_nativeObj); + private static native double[] mean_1(long src_nativeObj); + + // C++: Scalar cv::sum(Mat src) + private static native double[] sumElems_0(long src_nativeObj); + + // C++: Scalar cv::trace(Mat mtx) + private static native double[] trace_0(long mtx_nativeObj); + + // C++: String cv::getBuildInformation() + private static native String getBuildInformation_0(); + + // C++: String cv::getHardwareFeatureName(int feature) + private static native String getHardwareFeatureName_0(int feature); + + // C++: String cv::getVersionString() + private static native String getVersionString_0(); + + // C++: String cv::ipp::getIppVersion() + private static native String getIppVersion_0(); + + // C++: String cv::samples::findFile(String relative_path, bool required = true, bool silentMode = false) + private static native String findFile_0(String relative_path, boolean required, boolean silentMode); + private static native String findFile_1(String relative_path, boolean required); + private static native String findFile_2(String relative_path); + + // C++: String cv::samples::findFileOrKeep(String relative_path, bool silentMode = false) + private static native String findFileOrKeep_0(String relative_path, boolean silentMode); + private static native String findFileOrKeep_1(String relative_path); + + // C++: bool cv::checkRange(Mat a, bool quiet = true, _hidden_ * pos = 0, double minVal = -DBL_MAX, double maxVal = DBL_MAX) + private static native boolean checkRange_0(long a_nativeObj, boolean quiet, double minVal, double maxVal); + private static native boolean checkRange_1(long a_nativeObj, boolean quiet, double minVal); + private static native boolean checkRange_2(long a_nativeObj, boolean quiet); + private static native boolean checkRange_4(long a_nativeObj); + + // C++: bool cv::eigen(Mat src, Mat& eigenvalues, Mat& eigenvectors = Mat()) + private static native boolean eigen_0(long src_nativeObj, long eigenvalues_nativeObj, long eigenvectors_nativeObj); + private static native boolean eigen_1(long src_nativeObj, long eigenvalues_nativeObj); + + // C++: bool cv::solve(Mat src1, Mat src2, Mat& dst, int flags = DECOMP_LU) + private static native boolean solve_0(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj, int flags); + private static native boolean solve_1(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj); + + // C++: bool cv::ipp::useIPP() + private static native boolean useIPP_0(); + + // C++: bool cv::ipp::useIPP_NotExact() + private static native boolean useIPP_NotExact_0(); + + // C++: double cv::Mahalanobis(Mat v1, Mat v2, Mat icovar) + private static native double Mahalanobis_0(long v1_nativeObj, long v2_nativeObj, long icovar_nativeObj); + + // C++: double cv::PSNR(Mat src1, Mat src2, double R = 255.) + private static native double PSNR_0(long src1_nativeObj, long src2_nativeObj, double R); + private static native double PSNR_1(long src1_nativeObj, long src2_nativeObj); + + // C++: double cv::determinant(Mat mtx) + private static native double determinant_0(long mtx_nativeObj); + + // C++: double cv::getTickFrequency() + private static native double getTickFrequency_0(); + + // C++: double cv::invert(Mat src, Mat& dst, int flags = DECOMP_LU) + private static native double invert_0(long src_nativeObj, long dst_nativeObj, int flags); + private static native double invert_1(long src_nativeObj, long dst_nativeObj); + + // C++: double cv::kmeans(Mat data, int K, Mat& bestLabels, TermCriteria criteria, int attempts, int flags, Mat& centers = Mat()) + private static native double kmeans_0(long data_nativeObj, int K, long bestLabels_nativeObj, int criteria_type, int criteria_maxCount, double criteria_epsilon, int attempts, int flags, long centers_nativeObj); + private static native double kmeans_1(long data_nativeObj, int K, long bestLabels_nativeObj, int criteria_type, int criteria_maxCount, double criteria_epsilon, int attempts, int flags); + + // C++: double cv::norm(Mat src1, Mat src2, int normType = NORM_L2, Mat mask = Mat()) + private static native double norm_0(long src1_nativeObj, long src2_nativeObj, int normType, long mask_nativeObj); + private static native double norm_1(long src1_nativeObj, long src2_nativeObj, int normType); + private static native double norm_2(long src1_nativeObj, long src2_nativeObj); + + // C++: double cv::norm(Mat src1, int normType = NORM_L2, Mat mask = Mat()) + private static native double norm_3(long src1_nativeObj, int normType, long mask_nativeObj); + private static native double norm_4(long src1_nativeObj, int normType); + private static native double norm_5(long src1_nativeObj); + + // C++: double cv::solvePoly(Mat coeffs, Mat& roots, int maxIters = 300) + private static native double solvePoly_0(long coeffs_nativeObj, long roots_nativeObj, int maxIters); + private static native double solvePoly_1(long coeffs_nativeObj, long roots_nativeObj); + + // C++: float cv::cubeRoot(float val) + private static native float cubeRoot_0(float val); + + // C++: float cv::fastAtan2(float y, float x) + private static native float fastAtan2_0(float y, float x); + + // C++: int cv::borderInterpolate(int p, int len, int borderType) + private static native int borderInterpolate_0(int p, int len, int borderType); + + // C++: int cv::countNonZero(Mat src) + private static native int countNonZero_0(long src_nativeObj); + + // C++: int cv::getNumThreads() + private static native int getNumThreads_0(); + + // C++: int cv::getNumberOfCPUs() + private static native int getNumberOfCPUs_0(); + + // C++: int cv::getOptimalDFTSize(int vecsize) + private static native int getOptimalDFTSize_0(int vecsize); + + // C++: int cv::getThreadNum() + private static native int getThreadNum_0(); + + // C++: int cv::getVersionMajor() + private static native int getVersionMajor_0(); + + // C++: int cv::getVersionMinor() + private static native int getVersionMinor_0(); + + // C++: int cv::getVersionRevision() + private static native int getVersionRevision_0(); + + // C++: int cv::solveCubic(Mat coeffs, Mat& roots) + private static native int solveCubic_0(long coeffs_nativeObj, long roots_nativeObj); + + // C++: int64 cv::getCPUTickCount() + private static native long getCPUTickCount_0(); + + // C++: int64 cv::getTickCount() + private static native long getTickCount_0(); + + // C++: void cv::LUT(Mat src, Mat lut, Mat& dst) + private static native void LUT_0(long src_nativeObj, long lut_nativeObj, long dst_nativeObj); + + // C++: void cv::PCABackProject(Mat data, Mat mean, Mat eigenvectors, Mat& result) + private static native void PCABackProject_0(long data_nativeObj, long mean_nativeObj, long eigenvectors_nativeObj, long result_nativeObj); + + // C++: void cv::PCACompute(Mat data, Mat& mean, Mat& eigenvectors, Mat& eigenvalues, double retainedVariance) + private static native void PCACompute2_0(long data_nativeObj, long mean_nativeObj, long eigenvectors_nativeObj, long eigenvalues_nativeObj, double retainedVariance); + + // C++: void cv::PCACompute(Mat data, Mat& mean, Mat& eigenvectors, Mat& eigenvalues, int maxComponents = 0) + private static native void PCACompute2_1(long data_nativeObj, long mean_nativeObj, long eigenvectors_nativeObj, long eigenvalues_nativeObj, int maxComponents); + private static native void PCACompute2_2(long data_nativeObj, long mean_nativeObj, long eigenvectors_nativeObj, long eigenvalues_nativeObj); + + // C++: void cv::PCACompute(Mat data, Mat& mean, Mat& eigenvectors, double retainedVariance) + private static native void PCACompute_0(long data_nativeObj, long mean_nativeObj, long eigenvectors_nativeObj, double retainedVariance); + + // C++: void cv::PCACompute(Mat data, Mat& mean, Mat& eigenvectors, int maxComponents = 0) + private static native void PCACompute_1(long data_nativeObj, long mean_nativeObj, long eigenvectors_nativeObj, int maxComponents); + private static native void PCACompute_2(long data_nativeObj, long mean_nativeObj, long eigenvectors_nativeObj); + + // C++: void cv::PCAProject(Mat data, Mat mean, Mat eigenvectors, Mat& result) + private static native void PCAProject_0(long data_nativeObj, long mean_nativeObj, long eigenvectors_nativeObj, long result_nativeObj); + + // C++: void cv::SVBackSubst(Mat w, Mat u, Mat vt, Mat rhs, Mat& dst) + private static native void SVBackSubst_0(long w_nativeObj, long u_nativeObj, long vt_nativeObj, long rhs_nativeObj, long dst_nativeObj); + + // C++: void cv::SVDecomp(Mat src, Mat& w, Mat& u, Mat& vt, int flags = 0) + private static native void SVDecomp_0(long src_nativeObj, long w_nativeObj, long u_nativeObj, long vt_nativeObj, int flags); + private static native void SVDecomp_1(long src_nativeObj, long w_nativeObj, long u_nativeObj, long vt_nativeObj); + + // C++: void cv::absdiff(Mat src1, Mat src2, Mat& dst) + private static native void absdiff_0(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj); + + // C++: void cv::absdiff(Mat src1, Scalar src2, Mat& dst) + private static native void absdiff_1(long src1_nativeObj, double src2_val0, double src2_val1, double src2_val2, double src2_val3, long dst_nativeObj); + + // C++: void cv::add(Mat src1, Mat src2, Mat& dst, Mat mask = Mat(), int dtype = -1) + private static native void add_0(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj, long mask_nativeObj, int dtype); + private static native void add_1(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj, long mask_nativeObj); + private static native void add_2(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj); + + // C++: void cv::add(Mat src1, Scalar src2, Mat& dst, Mat mask = Mat(), int dtype = -1) + private static native void add_3(long src1_nativeObj, double src2_val0, double src2_val1, double src2_val2, double src2_val3, long dst_nativeObj, long mask_nativeObj, int dtype); + private static native void add_4(long src1_nativeObj, double src2_val0, double src2_val1, double src2_val2, double src2_val3, long dst_nativeObj, long mask_nativeObj); + private static native void add_5(long src1_nativeObj, double src2_val0, double src2_val1, double src2_val2, double src2_val3, long dst_nativeObj); + + // C++: void cv::addWeighted(Mat src1, double alpha, Mat src2, double beta, double gamma, Mat& dst, int dtype = -1) + private static native void addWeighted_0(long src1_nativeObj, double alpha, long src2_nativeObj, double beta, double gamma, long dst_nativeObj, int dtype); + private static native void addWeighted_1(long src1_nativeObj, double alpha, long src2_nativeObj, double beta, double gamma, long dst_nativeObj); + + // C++: void cv::batchDistance(Mat src1, Mat src2, Mat& dist, int dtype, Mat& nidx, int normType = NORM_L2, int K = 0, Mat mask = Mat(), int update = 0, bool crosscheck = false) + private static native void batchDistance_0(long src1_nativeObj, long src2_nativeObj, long dist_nativeObj, int dtype, long nidx_nativeObj, int normType, int K, long mask_nativeObj, int update, boolean crosscheck); + private static native void batchDistance_1(long src1_nativeObj, long src2_nativeObj, long dist_nativeObj, int dtype, long nidx_nativeObj, int normType, int K, long mask_nativeObj, int update); + private static native void batchDistance_2(long src1_nativeObj, long src2_nativeObj, long dist_nativeObj, int dtype, long nidx_nativeObj, int normType, int K, long mask_nativeObj); + private static native void batchDistance_3(long src1_nativeObj, long src2_nativeObj, long dist_nativeObj, int dtype, long nidx_nativeObj, int normType, int K); + private static native void batchDistance_4(long src1_nativeObj, long src2_nativeObj, long dist_nativeObj, int dtype, long nidx_nativeObj, int normType); + private static native void batchDistance_5(long src1_nativeObj, long src2_nativeObj, long dist_nativeObj, int dtype, long nidx_nativeObj); + + // C++: void cv::bitwise_and(Mat src1, Mat src2, Mat& dst, Mat mask = Mat()) + private static native void bitwise_and_0(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj, long mask_nativeObj); + private static native void bitwise_and_1(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj); + + // C++: void cv::bitwise_not(Mat src, Mat& dst, Mat mask = Mat()) + private static native void bitwise_not_0(long src_nativeObj, long dst_nativeObj, long mask_nativeObj); + private static native void bitwise_not_1(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::bitwise_or(Mat src1, Mat src2, Mat& dst, Mat mask = Mat()) + private static native void bitwise_or_0(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj, long mask_nativeObj); + private static native void bitwise_or_1(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj); + + // C++: void cv::bitwise_xor(Mat src1, Mat src2, Mat& dst, Mat mask = Mat()) + private static native void bitwise_xor_0(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj, long mask_nativeObj); + private static native void bitwise_xor_1(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj); + + // C++: void cv::calcCovarMatrix(Mat samples, Mat& covar, Mat& mean, int flags, int ctype = CV_64F) + private static native void calcCovarMatrix_0(long samples_nativeObj, long covar_nativeObj, long mean_nativeObj, int flags, int ctype); + private static native void calcCovarMatrix_1(long samples_nativeObj, long covar_nativeObj, long mean_nativeObj, int flags); + + // C++: void cv::cartToPolar(Mat x, Mat y, Mat& magnitude, Mat& angle, bool angleInDegrees = false) + private static native void cartToPolar_0(long x_nativeObj, long y_nativeObj, long magnitude_nativeObj, long angle_nativeObj, boolean angleInDegrees); + private static native void cartToPolar_1(long x_nativeObj, long y_nativeObj, long magnitude_nativeObj, long angle_nativeObj); + + // C++: void cv::compare(Mat src1, Mat src2, Mat& dst, int cmpop) + private static native void compare_0(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj, int cmpop); + + // C++: void cv::compare(Mat src1, Scalar src2, Mat& dst, int cmpop) + private static native void compare_1(long src1_nativeObj, double src2_val0, double src2_val1, double src2_val2, double src2_val3, long dst_nativeObj, int cmpop); + + // C++: void cv::completeSymm(Mat& m, bool lowerToUpper = false) + private static native void completeSymm_0(long m_nativeObj, boolean lowerToUpper); + private static native void completeSymm_1(long m_nativeObj); + + // C++: void cv::convertFp16(Mat src, Mat& dst) + private static native void convertFp16_0(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::convertScaleAbs(Mat src, Mat& dst, double alpha = 1, double beta = 0) + private static native void convertScaleAbs_0(long src_nativeObj, long dst_nativeObj, double alpha, double beta); + private static native void convertScaleAbs_1(long src_nativeObj, long dst_nativeObj, double alpha); + private static native void convertScaleAbs_2(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::copyMakeBorder(Mat src, Mat& dst, int top, int bottom, int left, int right, int borderType, Scalar value = Scalar()) + private static native void copyMakeBorder_0(long src_nativeObj, long dst_nativeObj, int top, int bottom, int left, int right, int borderType, double value_val0, double value_val1, double value_val2, double value_val3); + private static native void copyMakeBorder_1(long src_nativeObj, long dst_nativeObj, int top, int bottom, int left, int right, int borderType); + + // C++: void cv::copyTo(Mat src, Mat& dst, Mat mask) + private static native void copyTo_0(long src_nativeObj, long dst_nativeObj, long mask_nativeObj); + + // C++: void cv::dct(Mat src, Mat& dst, int flags = 0) + private static native void dct_0(long src_nativeObj, long dst_nativeObj, int flags); + private static native void dct_1(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::dft(Mat src, Mat& dst, int flags = 0, int nonzeroRows = 0) + private static native void dft_0(long src_nativeObj, long dst_nativeObj, int flags, int nonzeroRows); + private static native void dft_1(long src_nativeObj, long dst_nativeObj, int flags); + private static native void dft_2(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::divide(Mat src1, Mat src2, Mat& dst, double scale = 1, int dtype = -1) + private static native void divide_0(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj, double scale, int dtype); + private static native void divide_1(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj, double scale); + private static native void divide_2(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj); + + // C++: void cv::divide(Mat src1, Scalar src2, Mat& dst, double scale = 1, int dtype = -1) + private static native void divide_3(long src1_nativeObj, double src2_val0, double src2_val1, double src2_val2, double src2_val3, long dst_nativeObj, double scale, int dtype); + private static native void divide_4(long src1_nativeObj, double src2_val0, double src2_val1, double src2_val2, double src2_val3, long dst_nativeObj, double scale); + private static native void divide_5(long src1_nativeObj, double src2_val0, double src2_val1, double src2_val2, double src2_val3, long dst_nativeObj); + + // C++: void cv::divide(double scale, Mat src2, Mat& dst, int dtype = -1) + private static native void divide_6(double scale, long src2_nativeObj, long dst_nativeObj, int dtype); + private static native void divide_7(double scale, long src2_nativeObj, long dst_nativeObj); + + // C++: void cv::eigenNonSymmetric(Mat src, Mat& eigenvalues, Mat& eigenvectors) + private static native void eigenNonSymmetric_0(long src_nativeObj, long eigenvalues_nativeObj, long eigenvectors_nativeObj); + + // C++: void cv::exp(Mat src, Mat& dst) + private static native void exp_0(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::extractChannel(Mat src, Mat& dst, int coi) + private static native void extractChannel_0(long src_nativeObj, long dst_nativeObj, int coi); + + // C++: void cv::findNonZero(Mat src, Mat& idx) + private static native void findNonZero_0(long src_nativeObj, long idx_nativeObj); + + // C++: void cv::flip(Mat src, Mat& dst, int flipCode) + private static native void flip_0(long src_nativeObj, long dst_nativeObj, int flipCode); + + // C++: void cv::gemm(Mat src1, Mat src2, double alpha, Mat src3, double beta, Mat& dst, int flags = 0) + private static native void gemm_0(long src1_nativeObj, long src2_nativeObj, double alpha, long src3_nativeObj, double beta, long dst_nativeObj, int flags); + private static native void gemm_1(long src1_nativeObj, long src2_nativeObj, double alpha, long src3_nativeObj, double beta, long dst_nativeObj); + + // C++: void cv::hconcat(vector_Mat src, Mat& dst) + private static native void hconcat_0(long src_mat_nativeObj, long dst_nativeObj); + + // C++: void cv::idct(Mat src, Mat& dst, int flags = 0) + private static native void idct_0(long src_nativeObj, long dst_nativeObj, int flags); + private static native void idct_1(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::idft(Mat src, Mat& dst, int flags = 0, int nonzeroRows = 0) + private static native void idft_0(long src_nativeObj, long dst_nativeObj, int flags, int nonzeroRows); + private static native void idft_1(long src_nativeObj, long dst_nativeObj, int flags); + private static native void idft_2(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::inRange(Mat src, Scalar lowerb, Scalar upperb, Mat& dst) + private static native void inRange_0(long src_nativeObj, double lowerb_val0, double lowerb_val1, double lowerb_val2, double lowerb_val3, double upperb_val0, double upperb_val1, double upperb_val2, double upperb_val3, long dst_nativeObj); + + // C++: void cv::insertChannel(Mat src, Mat& dst, int coi) + private static native void insertChannel_0(long src_nativeObj, long dst_nativeObj, int coi); + + // C++: void cv::log(Mat src, Mat& dst) + private static native void log_0(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::magnitude(Mat x, Mat y, Mat& magnitude) + private static native void magnitude_0(long x_nativeObj, long y_nativeObj, long magnitude_nativeObj); + + // C++: void cv::max(Mat src1, Mat src2, Mat& dst) + private static native void max_0(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj); + + // C++: void cv::max(Mat src1, Scalar src2, Mat& dst) + private static native void max_1(long src1_nativeObj, double src2_val0, double src2_val1, double src2_val2, double src2_val3, long dst_nativeObj); + + // C++: void cv::meanStdDev(Mat src, vector_double& mean, vector_double& stddev, Mat mask = Mat()) + private static native void meanStdDev_0(long src_nativeObj, long mean_mat_nativeObj, long stddev_mat_nativeObj, long mask_nativeObj); + private static native void meanStdDev_1(long src_nativeObj, long mean_mat_nativeObj, long stddev_mat_nativeObj); + + // C++: void cv::merge(vector_Mat mv, Mat& dst) + private static native void merge_0(long mv_mat_nativeObj, long dst_nativeObj); + + // C++: void cv::min(Mat src1, Mat src2, Mat& dst) + private static native void min_0(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj); + + // C++: void cv::min(Mat src1, Scalar src2, Mat& dst) + private static native void min_1(long src1_nativeObj, double src2_val0, double src2_val1, double src2_val2, double src2_val3, long dst_nativeObj); + + // C++: void cv::mixChannels(vector_Mat src, vector_Mat dst, vector_int fromTo) + private static native void mixChannels_0(long src_mat_nativeObj, long dst_mat_nativeObj, long fromTo_mat_nativeObj); + + // C++: void cv::mulSpectrums(Mat a, Mat b, Mat& c, int flags, bool conjB = false) + private static native void mulSpectrums_0(long a_nativeObj, long b_nativeObj, long c_nativeObj, int flags, boolean conjB); + private static native void mulSpectrums_1(long a_nativeObj, long b_nativeObj, long c_nativeObj, int flags); + + // C++: void cv::mulTransposed(Mat src, Mat& dst, bool aTa, Mat delta = Mat(), double scale = 1, int dtype = -1) + private static native void mulTransposed_0(long src_nativeObj, long dst_nativeObj, boolean aTa, long delta_nativeObj, double scale, int dtype); + private static native void mulTransposed_1(long src_nativeObj, long dst_nativeObj, boolean aTa, long delta_nativeObj, double scale); + private static native void mulTransposed_2(long src_nativeObj, long dst_nativeObj, boolean aTa, long delta_nativeObj); + private static native void mulTransposed_3(long src_nativeObj, long dst_nativeObj, boolean aTa); + + // C++: void cv::multiply(Mat src1, Mat src2, Mat& dst, double scale = 1, int dtype = -1) + private static native void multiply_0(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj, double scale, int dtype); + private static native void multiply_1(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj, double scale); + private static native void multiply_2(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj); + + // C++: void cv::multiply(Mat src1, Scalar src2, Mat& dst, double scale = 1, int dtype = -1) + private static native void multiply_3(long src1_nativeObj, double src2_val0, double src2_val1, double src2_val2, double src2_val3, long dst_nativeObj, double scale, int dtype); + private static native void multiply_4(long src1_nativeObj, double src2_val0, double src2_val1, double src2_val2, double src2_val3, long dst_nativeObj, double scale); + private static native void multiply_5(long src1_nativeObj, double src2_val0, double src2_val1, double src2_val2, double src2_val3, long dst_nativeObj); + + // C++: void cv::normalize(Mat src, Mat& dst, double alpha = 1, double beta = 0, int norm_type = NORM_L2, int dtype = -1, Mat mask = Mat()) + private static native void normalize_0(long src_nativeObj, long dst_nativeObj, double alpha, double beta, int norm_type, int dtype, long mask_nativeObj); + private static native void normalize_1(long src_nativeObj, long dst_nativeObj, double alpha, double beta, int norm_type, int dtype); + private static native void normalize_2(long src_nativeObj, long dst_nativeObj, double alpha, double beta, int norm_type); + private static native void normalize_3(long src_nativeObj, long dst_nativeObj, double alpha, double beta); + private static native void normalize_4(long src_nativeObj, long dst_nativeObj, double alpha); + private static native void normalize_5(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::patchNaNs(Mat& a, double val = 0) + private static native void patchNaNs_0(long a_nativeObj, double val); + private static native void patchNaNs_1(long a_nativeObj); + + // C++: void cv::perspectiveTransform(Mat src, Mat& dst, Mat m) + private static native void perspectiveTransform_0(long src_nativeObj, long dst_nativeObj, long m_nativeObj); + + // C++: void cv::phase(Mat x, Mat y, Mat& angle, bool angleInDegrees = false) + private static native void phase_0(long x_nativeObj, long y_nativeObj, long angle_nativeObj, boolean angleInDegrees); + private static native void phase_1(long x_nativeObj, long y_nativeObj, long angle_nativeObj); + + // C++: void cv::polarToCart(Mat magnitude, Mat angle, Mat& x, Mat& y, bool angleInDegrees = false) + private static native void polarToCart_0(long magnitude_nativeObj, long angle_nativeObj, long x_nativeObj, long y_nativeObj, boolean angleInDegrees); + private static native void polarToCart_1(long magnitude_nativeObj, long angle_nativeObj, long x_nativeObj, long y_nativeObj); + + // C++: void cv::pow(Mat src, double power, Mat& dst) + private static native void pow_0(long src_nativeObj, double power, long dst_nativeObj); + + // C++: void cv::randShuffle(Mat& dst, double iterFactor = 1., RNG* rng = 0) + private static native void randShuffle_0(long dst_nativeObj, double iterFactor); + private static native void randShuffle_2(long dst_nativeObj); + + // C++: void cv::randn(Mat& dst, double mean, double stddev) + private static native void randn_0(long dst_nativeObj, double mean, double stddev); + + // C++: void cv::randu(Mat& dst, double low, double high) + private static native void randu_0(long dst_nativeObj, double low, double high); + + // C++: void cv::reduce(Mat src, Mat& dst, int dim, int rtype, int dtype = -1) + private static native void reduce_0(long src_nativeObj, long dst_nativeObj, int dim, int rtype, int dtype); + private static native void reduce_1(long src_nativeObj, long dst_nativeObj, int dim, int rtype); + + // C++: void cv::repeat(Mat src, int ny, int nx, Mat& dst) + private static native void repeat_0(long src_nativeObj, int ny, int nx, long dst_nativeObj); + + // C++: void cv::rotate(Mat src, Mat& dst, int rotateCode) + private static native void rotate_0(long src_nativeObj, long dst_nativeObj, int rotateCode); + + // C++: void cv::scaleAdd(Mat src1, double alpha, Mat src2, Mat& dst) + private static native void scaleAdd_0(long src1_nativeObj, double alpha, long src2_nativeObj, long dst_nativeObj); + + // C++: void cv::setErrorVerbosity(bool verbose) + private static native void setErrorVerbosity_0(boolean verbose); + + // C++: void cv::setIdentity(Mat& mtx, Scalar s = Scalar(1)) + private static native void setIdentity_0(long mtx_nativeObj, double s_val0, double s_val1, double s_val2, double s_val3); + private static native void setIdentity_1(long mtx_nativeObj); + + // C++: void cv::setNumThreads(int nthreads) + private static native void setNumThreads_0(int nthreads); + + // C++: void cv::setRNGSeed(int seed) + private static native void setRNGSeed_0(int seed); + + // C++: void cv::sort(Mat src, Mat& dst, int flags) + private static native void sort_0(long src_nativeObj, long dst_nativeObj, int flags); + + // C++: void cv::sortIdx(Mat src, Mat& dst, int flags) + private static native void sortIdx_0(long src_nativeObj, long dst_nativeObj, int flags); + + // C++: void cv::split(Mat m, vector_Mat& mv) + private static native void split_0(long m_nativeObj, long mv_mat_nativeObj); + + // C++: void cv::sqrt(Mat src, Mat& dst) + private static native void sqrt_0(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::subtract(Mat src1, Mat src2, Mat& dst, Mat mask = Mat(), int dtype = -1) + private static native void subtract_0(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj, long mask_nativeObj, int dtype); + private static native void subtract_1(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj, long mask_nativeObj); + private static native void subtract_2(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj); + + // C++: void cv::subtract(Mat src1, Scalar src2, Mat& dst, Mat mask = Mat(), int dtype = -1) + private static native void subtract_3(long src1_nativeObj, double src2_val0, double src2_val1, double src2_val2, double src2_val3, long dst_nativeObj, long mask_nativeObj, int dtype); + private static native void subtract_4(long src1_nativeObj, double src2_val0, double src2_val1, double src2_val2, double src2_val3, long dst_nativeObj, long mask_nativeObj); + private static native void subtract_5(long src1_nativeObj, double src2_val0, double src2_val1, double src2_val2, double src2_val3, long dst_nativeObj); + + // C++: void cv::transform(Mat src, Mat& dst, Mat m) + private static native void transform_0(long src_nativeObj, long dst_nativeObj, long m_nativeObj); + + // C++: void cv::transpose(Mat src, Mat& dst) + private static native void transpose_0(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::vconcat(vector_Mat src, Mat& dst) + private static native void vconcat_0(long src_mat_nativeObj, long dst_nativeObj); + + // C++: void cv::ipp::setUseIPP(bool flag) + private static native void setUseIPP_0(boolean flag); + + // C++: void cv::ipp::setUseIPP_NotExact(bool flag) + private static native void setUseIPP_NotExact_0(boolean flag); + + // C++: void cv::samples::addSamplesDataSearchPath(String path) + private static native void addSamplesDataSearchPath_0(String path); + + // C++: void cv::samples::addSamplesDataSearchSubDirectory(String subdir) + private static native void addSamplesDataSearchSubDirectory_0(String subdir); +private static native double[] n_minMaxLocManual(long src_nativeObj, long mask_nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/core/CvException.java b/OpenCV/src/main/java/org/opencv/core/CvException.java new file mode 100644 index 00000000..e9241e68 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/CvException.java @@ -0,0 +1,15 @@ +package org.opencv.core; + +public class CvException extends RuntimeException { + + private static final long serialVersionUID = 1L; + + public CvException(String msg) { + super(msg); + } + + @Override + public String toString() { + return "CvException [" + super.toString() + "]"; + } +} diff --git a/OpenCV/src/main/java/org/opencv/core/CvType.java b/OpenCV/src/main/java/org/opencv/core/CvType.java new file mode 100644 index 00000000..fcf616fe --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/CvType.java @@ -0,0 +1,150 @@ +package org.opencv.core; + +public final class CvType { + + // type depth constants + public static final int + CV_8U = 0, + CV_8S = 1, + CV_16U = 2, + CV_16S = 3, + CV_32S = 4, + CV_32F = 5, + CV_64F = 6, + CV_16F = 7; + + /** + * @deprecated please use {@link #CV_16F} + */ + @Deprecated + public static final int CV_USRTYPE1 = CV_16F; + + // predefined type constants + public static final int + CV_8UC1 = CV_8UC(1), CV_8UC2 = CV_8UC(2), CV_8UC3 = CV_8UC(3), CV_8UC4 = CV_8UC(4), + CV_8SC1 = CV_8SC(1), CV_8SC2 = CV_8SC(2), CV_8SC3 = CV_8SC(3), CV_8SC4 = CV_8SC(4), + CV_16UC1 = CV_16UC(1), CV_16UC2 = CV_16UC(2), CV_16UC3 = CV_16UC(3), CV_16UC4 = CV_16UC(4), + CV_16SC1 = CV_16SC(1), CV_16SC2 = CV_16SC(2), CV_16SC3 = CV_16SC(3), CV_16SC4 = CV_16SC(4), + CV_32SC1 = CV_32SC(1), CV_32SC2 = CV_32SC(2), CV_32SC3 = CV_32SC(3), CV_32SC4 = CV_32SC(4), + CV_32FC1 = CV_32FC(1), CV_32FC2 = CV_32FC(2), CV_32FC3 = CV_32FC(3), CV_32FC4 = CV_32FC(4), + CV_64FC1 = CV_64FC(1), CV_64FC2 = CV_64FC(2), CV_64FC3 = CV_64FC(3), CV_64FC4 = CV_64FC(4), + CV_16FC1 = CV_16FC(1), CV_16FC2 = CV_16FC(2), CV_16FC3 = CV_16FC(3), CV_16FC4 = CV_16FC(4); + + private static final int CV_CN_MAX = 512, CV_CN_SHIFT = 3, CV_DEPTH_MAX = (1 << CV_CN_SHIFT); + + public static final int makeType(int depth, int channels) { + if (channels <= 0 || channels >= CV_CN_MAX) { + throw new UnsupportedOperationException( + "Channels count should be 1.." + (CV_CN_MAX - 1)); + } + if (depth < 0 || depth >= CV_DEPTH_MAX) { + throw new UnsupportedOperationException( + "Data type depth should be 0.." + (CV_DEPTH_MAX - 1)); + } + return (depth & (CV_DEPTH_MAX - 1)) + ((channels - 1) << CV_CN_SHIFT); + } + + public static final int CV_8UC(int ch) { + return makeType(CV_8U, ch); + } + + public static final int CV_8SC(int ch) { + return makeType(CV_8S, ch); + } + + public static final int CV_16UC(int ch) { + return makeType(CV_16U, ch); + } + + public static final int CV_16SC(int ch) { + return makeType(CV_16S, ch); + } + + public static final int CV_32SC(int ch) { + return makeType(CV_32S, ch); + } + + public static final int CV_32FC(int ch) { + return makeType(CV_32F, ch); + } + + public static final int CV_64FC(int ch) { + return makeType(CV_64F, ch); + } + + public static final int CV_16FC(int ch) { + return makeType(CV_16F, ch); + } + + public static final int channels(int type) { + return (type >> CV_CN_SHIFT) + 1; + } + + public static final int depth(int type) { + return type & (CV_DEPTH_MAX - 1); + } + + public static final boolean isInteger(int type) { + return depth(type) < CV_32F; + } + + public static final int ELEM_SIZE(int type) { + switch (depth(type)) { + case CV_8U: + case CV_8S: + return channels(type); + case CV_16U: + case CV_16S: + case CV_16F: + return 2 * channels(type); + case CV_32S: + case CV_32F: + return 4 * channels(type); + case CV_64F: + return 8 * channels(type); + default: + throw new UnsupportedOperationException( + "Unsupported CvType value: " + type); + } + } + + public static final String typeToString(int type) { + String s; + switch (depth(type)) { + case CV_8U: + s = "CV_8U"; + break; + case CV_8S: + s = "CV_8S"; + break; + case CV_16U: + s = "CV_16U"; + break; + case CV_16S: + s = "CV_16S"; + break; + case CV_32S: + s = "CV_32S"; + break; + case CV_32F: + s = "CV_32F"; + break; + case CV_64F: + s = "CV_64F"; + break; + case CV_16F: + s = "CV_16F"; + break; + default: + throw new UnsupportedOperationException( + "Unsupported CvType value: " + type); + } + + int ch = channels(type); + if (ch <= 4) + return s + "C" + ch; + else + return s + "C(" + ch + ")"; + } + +} diff --git a/OpenCV/src/main/java/org/opencv/core/DMatch.java b/OpenCV/src/main/java/org/opencv/core/DMatch.java new file mode 100644 index 00000000..db44d9a0 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/DMatch.java @@ -0,0 +1,58 @@ +package org.opencv.core; + +//C++: class DMatch + +/** + * Structure for matching: query descriptor index, train descriptor index, train + * image index and distance between descriptors. + */ +public class DMatch { + + /** + * Query descriptor index. + */ + public int queryIdx; + /** + * Train descriptor index. + */ + public int trainIdx; + /** + * Train image index. + */ + public int imgIdx; + + // javadoc: DMatch::distance + public float distance; + + // javadoc: DMatch::DMatch() + public DMatch() { + this(-1, -1, Float.MAX_VALUE); + } + + // javadoc: DMatch::DMatch(_queryIdx, _trainIdx, _distance) + public DMatch(int _queryIdx, int _trainIdx, float _distance) { + queryIdx = _queryIdx; + trainIdx = _trainIdx; + imgIdx = -1; + distance = _distance; + } + + // javadoc: DMatch::DMatch(_queryIdx, _trainIdx, _imgIdx, _distance) + public DMatch(int _queryIdx, int _trainIdx, int _imgIdx, float _distance) { + queryIdx = _queryIdx; + trainIdx = _trainIdx; + imgIdx = _imgIdx; + distance = _distance; + } + + public boolean lessThan(DMatch it) { + return distance < it.distance; + } + + @Override + public String toString() { + return "DMatch [queryIdx=" + queryIdx + ", trainIdx=" + trainIdx + + ", imgIdx=" + imgIdx + ", distance=" + distance + "]"; + } + +} diff --git a/OpenCV/src/main/java/org/opencv/core/KeyPoint.java b/OpenCV/src/main/java/org/opencv/core/KeyPoint.java new file mode 100644 index 00000000..de5b2151 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/KeyPoint.java @@ -0,0 +1,83 @@ +package org.opencv.core; + +import org.opencv.core.Point; + +//javadoc: KeyPoint +public class KeyPoint { + + /** + * Coordinates of the keypoint. + */ + public Point pt; + /** + * Diameter of the useful keypoint adjacent area. + */ + public float size; + /** + * Computed orientation of the keypoint (-1 if not applicable). + */ + public float angle; + /** + * The response, by which the strongest keypoints have been selected. Can + * be used for further sorting or subsampling. + */ + public float response; + /** + * Octave (pyramid layer), from which the keypoint has been extracted. + */ + public int octave; + /** + * Object ID, that can be used to cluster keypoints by an object they + * belong to. + */ + public int class_id; + + // javadoc:KeyPoint::KeyPoint(x,y,_size,_angle,_response,_octave,_class_id) + public KeyPoint(float x, float y, float _size, float _angle, float _response, int _octave, int _class_id) + { + pt = new Point(x, y); + size = _size; + angle = _angle; + response = _response; + octave = _octave; + class_id = _class_id; + } + + // javadoc: KeyPoint::KeyPoint() + public KeyPoint() + { + this(0, 0, 0, -1, 0, 0, -1); + } + + // javadoc: KeyPoint::KeyPoint(x, y, _size, _angle, _response, _octave) + public KeyPoint(float x, float y, float _size, float _angle, float _response, int _octave) + { + this(x, y, _size, _angle, _response, _octave, -1); + } + + // javadoc: KeyPoint::KeyPoint(x, y, _size, _angle, _response) + public KeyPoint(float x, float y, float _size, float _angle, float _response) + { + this(x, y, _size, _angle, _response, 0, -1); + } + + // javadoc: KeyPoint::KeyPoint(x, y, _size, _angle) + public KeyPoint(float x, float y, float _size, float _angle) + { + this(x, y, _size, _angle, 0, 0, -1); + } + + // javadoc: KeyPoint::KeyPoint(x, y, _size) + public KeyPoint(float x, float y, float _size) + { + this(x, y, _size, -1, 0, 0, -1); + } + + @Override + public String toString() { + return "KeyPoint [pt=" + pt + ", size=" + size + ", angle=" + angle + + ", response=" + response + ", octave=" + octave + + ", class_id=" + class_id + "]"; + } + +} diff --git a/OpenCV/src/main/java/org/opencv/core/Mat.java b/OpenCV/src/main/java/org/opencv/core/Mat.java new file mode 100644 index 00000000..3bcb1ee9 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/Mat.java @@ -0,0 +1,1723 @@ +package org.opencv.core; + +import java.nio.ByteBuffer; + +// C++: class Mat +//javadoc: Mat +public class Mat { + + public final long nativeObj; + + public Mat(long addr) + { + if (addr == 0) + throw new UnsupportedOperationException("Native object address is NULL"); + nativeObj = addr; + } + + // + // C++: Mat::Mat() + // + + // javadoc: Mat::Mat() + public Mat() + { + + nativeObj = n_Mat(); + + return; + } + + // + // C++: Mat::Mat(int rows, int cols, int type) + // + + // javadoc: Mat::Mat(rows, cols, type) + public Mat(int rows, int cols, int type) + { + + nativeObj = n_Mat(rows, cols, type); + + return; + } + + // + // C++: Mat::Mat(int rows, int cols, int type, void* data) + // + + // javadoc: Mat::Mat(rows, cols, type, data) + public Mat(int rows, int cols, int type, ByteBuffer data) + { + + nativeObj = n_Mat(rows, cols, type, data); + + return; + } + + // + // C++: Mat::Mat(Size size, int type) + // + + // javadoc: Mat::Mat(size, type) + public Mat(Size size, int type) + { + + nativeObj = n_Mat(size.width, size.height, type); + + return; + } + + // + // C++: Mat::Mat(int ndims, const int* sizes, int type) + // + + // javadoc: Mat::Mat(sizes, type) + public Mat(int[] sizes, int type) + { + + nativeObj = n_Mat(sizes.length, sizes, type); + + return; + } + + // + // C++: Mat::Mat(int rows, int cols, int type, Scalar s) + // + + // javadoc: Mat::Mat(rows, cols, type, s) + public Mat(int rows, int cols, int type, Scalar s) + { + + nativeObj = n_Mat(rows, cols, type, s.val[0], s.val[1], s.val[2], s.val[3]); + + return; + } + + // + // C++: Mat::Mat(Size size, int type, Scalar s) + // + + // javadoc: Mat::Mat(size, type, s) + public Mat(Size size, int type, Scalar s) + { + + nativeObj = n_Mat(size.width, size.height, type, s.val[0], s.val[1], s.val[2], s.val[3]); + + return; + } + + // + // C++: Mat::Mat(int ndims, const int* sizes, int type, Scalar s) + // + + // javadoc: Mat::Mat(sizes, type, s) + public Mat(int[] sizes, int type, Scalar s) + { + + nativeObj = n_Mat(sizes.length, sizes, type, s.val[0], s.val[1], s.val[2], s.val[3]); + + return; + } + + // + // C++: Mat::Mat(Mat m, Range rowRange, Range colRange = Range::all()) + // + + // javadoc: Mat::Mat(m, rowRange, colRange) + public Mat(Mat m, Range rowRange, Range colRange) + { + + nativeObj = n_Mat(m.nativeObj, rowRange.start, rowRange.end, colRange.start, colRange.end); + + return; + } + + // javadoc: Mat::Mat(m, rowRange) + public Mat(Mat m, Range rowRange) + { + + nativeObj = n_Mat(m.nativeObj, rowRange.start, rowRange.end); + + return; + } + + // + // C++: Mat::Mat(const Mat& m, const std::vector& ranges) + // + + // javadoc: Mat::Mat(m, ranges) + public Mat(Mat m, Range[] ranges) + { + + nativeObj = n_Mat(m.nativeObj, ranges); + + return; + } + + // + // C++: Mat::Mat(Mat m, Rect roi) + // + + // javadoc: Mat::Mat(m, roi) + public Mat(Mat m, Rect roi) + { + + nativeObj = n_Mat(m.nativeObj, roi.y, roi.y + roi.height, roi.x, roi.x + roi.width); + + return; + } + + // + // C++: Mat Mat::adjustROI(int dtop, int dbottom, int dleft, int dright) + // + + // javadoc: Mat::adjustROI(dtop, dbottom, dleft, dright) + public Mat adjustROI(int dtop, int dbottom, int dleft, int dright) + { + + Mat retVal = new Mat(n_adjustROI(nativeObj, dtop, dbottom, dleft, dright)); + + return retVal; + } + + // + // C++: void Mat::assignTo(Mat m, int type = -1) + // + + // javadoc: Mat::assignTo(m, type) + public void assignTo(Mat m, int type) + { + + n_assignTo(nativeObj, m.nativeObj, type); + + return; + } + + // javadoc: Mat::assignTo(m) + public void assignTo(Mat m) + { + + n_assignTo(nativeObj, m.nativeObj); + + return; + } + + // + // C++: int Mat::channels() + // + + // javadoc: Mat::channels() + public int channels() + { + + int retVal = n_channels(nativeObj); + + return retVal; + } + + // + // C++: int Mat::checkVector(int elemChannels, int depth = -1, bool + // requireContinuous = true) + // + + // javadoc: Mat::checkVector(elemChannels, depth, requireContinuous) + public int checkVector(int elemChannels, int depth, boolean requireContinuous) + { + + int retVal = n_checkVector(nativeObj, elemChannels, depth, requireContinuous); + + return retVal; + } + + // javadoc: Mat::checkVector(elemChannels, depth) + public int checkVector(int elemChannels, int depth) + { + + int retVal = n_checkVector(nativeObj, elemChannels, depth); + + return retVal; + } + + // javadoc: Mat::checkVector(elemChannels) + public int checkVector(int elemChannels) + { + + int retVal = n_checkVector(nativeObj, elemChannels); + + return retVal; + } + + // + // C++: Mat Mat::clone() + // + + // javadoc: Mat::clone() + public Mat clone() + { + + Mat retVal = new Mat(n_clone(nativeObj)); + + return retVal; + } + + // + // C++: Mat Mat::col(int x) + // + + // javadoc: Mat::col(x) + public Mat col(int x) + { + + Mat retVal = new Mat(n_col(nativeObj, x)); + + return retVal; + } + + // + // C++: Mat Mat::colRange(int startcol, int endcol) + // + + // javadoc: Mat::colRange(startcol, endcol) + public Mat colRange(int startcol, int endcol) + { + + Mat retVal = new Mat(n_colRange(nativeObj, startcol, endcol)); + + return retVal; + } + + // + // C++: Mat Mat::colRange(Range r) + // + + // javadoc: Mat::colRange(r) + public Mat colRange(Range r) + { + + Mat retVal = new Mat(n_colRange(nativeObj, r.start, r.end)); + + return retVal; + } + + // + // C++: int Mat::dims() + // + + // javadoc: Mat::dims() + public int dims() + { + + int retVal = n_dims(nativeObj); + + return retVal; + } + + // + // C++: int Mat::cols() + // + + // javadoc: Mat::cols() + public int cols() + { + + int retVal = n_cols(nativeObj); + + return retVal; + } + + // + // C++: void Mat::convertTo(Mat& m, int rtype, double alpha = 1, double beta + // = 0) + // + + // javadoc: Mat::convertTo(m, rtype, alpha, beta) + public void convertTo(Mat m, int rtype, double alpha, double beta) + { + + n_convertTo(nativeObj, m.nativeObj, rtype, alpha, beta); + + return; + } + + // javadoc: Mat::convertTo(m, rtype, alpha) + public void convertTo(Mat m, int rtype, double alpha) + { + + n_convertTo(nativeObj, m.nativeObj, rtype, alpha); + + return; + } + + // javadoc: Mat::convertTo(m, rtype) + public void convertTo(Mat m, int rtype) + { + + n_convertTo(nativeObj, m.nativeObj, rtype); + + return; + } + + // + // C++: void Mat::copyTo(Mat& m) + // + + // javadoc: Mat::copyTo(m) + public void copyTo(Mat m) + { + + n_copyTo(nativeObj, m.nativeObj); + + return; + } + + // + // C++: void Mat::copyTo(Mat& m, Mat mask) + // + + // javadoc: Mat::copyTo(m, mask) + public void copyTo(Mat m, Mat mask) + { + + n_copyTo(nativeObj, m.nativeObj, mask.nativeObj); + + return; + } + + // + // C++: void Mat::create(int rows, int cols, int type) + // + + // javadoc: Mat::create(rows, cols, type) + public void create(int rows, int cols, int type) + { + + n_create(nativeObj, rows, cols, type); + + return; + } + + // + // C++: void Mat::create(Size size, int type) + // + + // javadoc: Mat::create(size, type) + public void create(Size size, int type) + { + + n_create(nativeObj, size.width, size.height, type); + + return; + } + + // + // C++: void Mat::create(int ndims, const int* sizes, int type) + // + + // javadoc: Mat::create(sizes, type) + public void create(int[] sizes, int type) + { + + n_create(nativeObj, sizes.length, sizes, type); + + return; + } + + // + // C++: void Mat::copySize(const Mat& m); + // + + // javadoc: Mat::copySize(m) + public void copySize(Mat m) + { + n_copySize(nativeObj, m.nativeObj); + + return; + } + + // + // C++: Mat Mat::cross(Mat m) + // + + // javadoc: Mat::cross(m) + public Mat cross(Mat m) + { + + Mat retVal = new Mat(n_cross(nativeObj, m.nativeObj)); + + return retVal; + } + + // + // C++: long Mat::dataAddr() + // + + // javadoc: Mat::dataAddr() + public long dataAddr() + { + + long retVal = n_dataAddr(nativeObj); + + return retVal; + } + + // + // C++: int Mat::depth() + // + + // javadoc: Mat::depth() + public int depth() + { + + int retVal = n_depth(nativeObj); + + return retVal; + } + + // + // C++: Mat Mat::diag(int d = 0) + // + + // javadoc: Mat::diag(d) + public Mat diag(int d) + { + + Mat retVal = new Mat(n_diag(nativeObj, d)); + + return retVal; + } + + // javadoc: Mat::diag() + public Mat diag() + { + + Mat retVal = new Mat(n_diag(nativeObj, 0)); + + return retVal; + } + + // + // C++: static Mat Mat::diag(Mat d) + // + + // javadoc: Mat::diag(d) + public static Mat diag(Mat d) + { + + Mat retVal = new Mat(n_diag(d.nativeObj)); + + return retVal; + } + + // + // C++: double Mat::dot(Mat m) + // + + // javadoc: Mat::dot(m) + public double dot(Mat m) + { + + double retVal = n_dot(nativeObj, m.nativeObj); + + return retVal; + } + + // + // C++: size_t Mat::elemSize() + // + + // javadoc: Mat::elemSize() + public long elemSize() + { + + long retVal = n_elemSize(nativeObj); + + return retVal; + } + + // + // C++: size_t Mat::elemSize1() + // + + // javadoc: Mat::elemSize1() + public long elemSize1() + { + + long retVal = n_elemSize1(nativeObj); + + return retVal; + } + + // + // C++: bool Mat::empty() + // + + // javadoc: Mat::empty() + public boolean empty() + { + + boolean retVal = n_empty(nativeObj); + + return retVal; + } + + // + // C++: static Mat Mat::eye(int rows, int cols, int type) + // + + // javadoc: Mat::eye(rows, cols, type) + public static Mat eye(int rows, int cols, int type) + { + + Mat retVal = new Mat(n_eye(rows, cols, type)); + + return retVal; + } + + // + // C++: static Mat Mat::eye(Size size, int type) + // + + // javadoc: Mat::eye(size, type) + public static Mat eye(Size size, int type) + { + + Mat retVal = new Mat(n_eye(size.width, size.height, type)); + + return retVal; + } + + // + // C++: Mat Mat::inv(int method = DECOMP_LU) + // + + // javadoc: Mat::inv(method) + public Mat inv(int method) + { + + Mat retVal = new Mat(n_inv(nativeObj, method)); + + return retVal; + } + + // javadoc: Mat::inv() + public Mat inv() + { + + Mat retVal = new Mat(n_inv(nativeObj)); + + return retVal; + } + + // + // C++: bool Mat::isContinuous() + // + + // javadoc: Mat::isContinuous() + public boolean isContinuous() + { + + boolean retVal = n_isContinuous(nativeObj); + + return retVal; + } + + // + // C++: bool Mat::isSubmatrix() + // + + // javadoc: Mat::isSubmatrix() + public boolean isSubmatrix() + { + + boolean retVal = n_isSubmatrix(nativeObj); + + return retVal; + } + + // + // C++: void Mat::locateROI(Size wholeSize, Point ofs) + // + + // javadoc: Mat::locateROI(wholeSize, ofs) + public void locateROI(Size wholeSize, Point ofs) + { + double[] wholeSize_out = new double[2]; + double[] ofs_out = new double[2]; + locateROI_0(nativeObj, wholeSize_out, ofs_out); + if(wholeSize!=null){ wholeSize.width = wholeSize_out[0]; wholeSize.height = wholeSize_out[1]; } + if(ofs!=null){ ofs.x = ofs_out[0]; ofs.y = ofs_out[1]; } + return; + } + + // + // C++: Mat Mat::mul(Mat m, double scale = 1) + // + + // javadoc: Mat::mul(m, scale) + public Mat mul(Mat m, double scale) + { + + Mat retVal = new Mat(n_mul(nativeObj, m.nativeObj, scale)); + + return retVal; + } + + // javadoc: Mat::mul(m) + public Mat mul(Mat m) + { + + Mat retVal = new Mat(n_mul(nativeObj, m.nativeObj)); + + return retVal; + } + + // + // C++: static Mat Mat::ones(int rows, int cols, int type) + // + + // javadoc: Mat::ones(rows, cols, type) + public static Mat ones(int rows, int cols, int type) + { + + Mat retVal = new Mat(n_ones(rows, cols, type)); + + return retVal; + } + + // + // C++: static Mat Mat::ones(Size size, int type) + // + + // javadoc: Mat::ones(size, type) + public static Mat ones(Size size, int type) + { + + Mat retVal = new Mat(n_ones(size.width, size.height, type)); + + return retVal; + } + + // + // C++: static Mat Mat::ones(int ndims, const int* sizes, int type) + // + + // javadoc: Mat::ones(sizes, type) + public static Mat ones(int[] sizes, int type) + { + + Mat retVal = new Mat(n_ones(sizes.length, sizes, type)); + + return retVal; + } + + // + // C++: void Mat::push_back(Mat m) + // + + // javadoc: Mat::push_back(m) + public void push_back(Mat m) + { + + n_push_back(nativeObj, m.nativeObj); + + return; + } + + // + // C++: void Mat::release() + // + + // javadoc: Mat::release() + public void release() + { + + n_release(nativeObj); + + return; + } + + // + // C++: Mat Mat::reshape(int cn, int rows = 0) + // + + // javadoc: Mat::reshape(cn, rows) + public Mat reshape(int cn, int rows) + { + + Mat retVal = new Mat(n_reshape(nativeObj, cn, rows)); + + return retVal; + } + + // javadoc: Mat::reshape(cn) + public Mat reshape(int cn) + { + + Mat retVal = new Mat(n_reshape(nativeObj, cn)); + + return retVal; + } + + // + // C++: Mat Mat::reshape(int cn, int newndims, const int* newsz) + // + + // javadoc: Mat::reshape(cn, newshape) + public Mat reshape(int cn, int[] newshape) + { + Mat retVal = new Mat(n_reshape_1(nativeObj, cn, newshape.length, newshape)); + + return retVal; + } + + // + // C++: Mat Mat::row(int y) + // + + // javadoc: Mat::row(y) + public Mat row(int y) + { + + Mat retVal = new Mat(n_row(nativeObj, y)); + + return retVal; + } + + // + // C++: Mat Mat::rowRange(int startrow, int endrow) + // + + // javadoc: Mat::rowRange(startrow, endrow) + public Mat rowRange(int startrow, int endrow) + { + + Mat retVal = new Mat(n_rowRange(nativeObj, startrow, endrow)); + + return retVal; + } + + // + // C++: Mat Mat::rowRange(Range r) + // + + // javadoc: Mat::rowRange(r) + public Mat rowRange(Range r) + { + + Mat retVal = new Mat(n_rowRange(nativeObj, r.start, r.end)); + + return retVal; + } + + // + // C++: int Mat::rows() + // + + // javadoc: Mat::rows() + public int rows() + { + + int retVal = n_rows(nativeObj); + + return retVal; + } + + // + // C++: Mat Mat::operator =(Scalar s) + // + + // javadoc: Mat::operator =(s) + public Mat setTo(Scalar s) + { + + Mat retVal = new Mat(n_setTo(nativeObj, s.val[0], s.val[1], s.val[2], s.val[3])); + + return retVal; + } + + // + // C++: Mat Mat::setTo(Scalar value, Mat mask = Mat()) + // + + // javadoc: Mat::setTo(value, mask) + public Mat setTo(Scalar value, Mat mask) + { + + Mat retVal = new Mat(n_setTo(nativeObj, value.val[0], value.val[1], value.val[2], value.val[3], mask.nativeObj)); + + return retVal; + } + + // + // C++: Mat Mat::setTo(Mat value, Mat mask = Mat()) + // + + // javadoc: Mat::setTo(value, mask) + public Mat setTo(Mat value, Mat mask) + { + + Mat retVal = new Mat(n_setTo(nativeObj, value.nativeObj, mask.nativeObj)); + + return retVal; + } + + // javadoc: Mat::setTo(value) + public Mat setTo(Mat value) + { + + Mat retVal = new Mat(n_setTo(nativeObj, value.nativeObj)); + + return retVal; + } + + // + // C++: Size Mat::size() + // + + // javadoc: Mat::size() + public Size size() + { + + Size retVal = new Size(n_size(nativeObj)); + + return retVal; + } + + // + // C++: int Mat::size(int i) + // + + // javadoc: Mat::size(int i) + public int size(int i) + { + int retVal = n_size_i(nativeObj, i); + + return retVal; + } + + // + // C++: size_t Mat::step1(int i = 0) + // + + // javadoc: Mat::step1(i) + public long step1(int i) + { + + long retVal = n_step1(nativeObj, i); + + return retVal; + } + + // javadoc: Mat::step1() + public long step1() + { + + long retVal = n_step1(nativeObj); + + return retVal; + } + + // + // C++: Mat Mat::operator()(int rowStart, int rowEnd, int colStart, int + // colEnd) + // + + // javadoc: Mat::operator()(rowStart, rowEnd, colStart, colEnd) + public Mat submat(int rowStart, int rowEnd, int colStart, int colEnd) + { + + Mat retVal = new Mat(n_submat_rr(nativeObj, rowStart, rowEnd, colStart, colEnd)); + + return retVal; + } + + // + // C++: Mat Mat::operator()(Range rowRange, Range colRange) + // + + // javadoc: Mat::operator()(rowRange, colRange) + public Mat submat(Range rowRange, Range colRange) + { + + Mat retVal = new Mat(n_submat_rr(nativeObj, rowRange.start, rowRange.end, colRange.start, colRange.end)); + + return retVal; + } + + // + // C++: Mat Mat::operator()(const std::vector& ranges) + // + + // javadoc: Mat::operator()(ranges[]) + public Mat submat(Range[] ranges) + { + + Mat retVal = new Mat(n_submat_ranges(nativeObj, ranges)); + + return retVal; + } + + // + // C++: Mat Mat::operator()(Rect roi) + // + + // javadoc: Mat::operator()(roi) + public Mat submat(Rect roi) + { + + Mat retVal = new Mat(n_submat(nativeObj, roi.x, roi.y, roi.width, roi.height)); + + return retVal; + } + + // + // C++: Mat Mat::t() + // + + // javadoc: Mat::t() + public Mat t() + { + + Mat retVal = new Mat(n_t(nativeObj)); + + return retVal; + } + + // + // C++: size_t Mat::total() + // + + // javadoc: Mat::total() + public long total() + { + + long retVal = n_total(nativeObj); + + return retVal; + } + + // + // C++: int Mat::type() + // + + // javadoc: Mat::type() + public int type() + { + + int retVal = n_type(nativeObj); + + return retVal; + } + + // + // C++: static Mat Mat::zeros(int rows, int cols, int type) + // + + // javadoc: Mat::zeros(rows, cols, type) + public static Mat zeros(int rows, int cols, int type) + { + + Mat retVal = new Mat(n_zeros(rows, cols, type)); + + return retVal; + } + + // + // C++: static Mat Mat::zeros(Size size, int type) + // + + // javadoc: Mat::zeros(size, type) + public static Mat zeros(Size size, int type) + { + + Mat retVal = new Mat(n_zeros(size.width, size.height, type)); + + return retVal; + } + + // + // C++: static Mat Mat::zeros(int ndims, const int* sizes, int type) + // + + // javadoc: Mat::zeros(sizes, type) + public static Mat zeros(int[] sizes, int type) + { + + Mat retVal = new Mat(n_zeros(sizes.length, sizes, type)); + + return retVal; + } + + @Override + protected void finalize() throws Throwable { + n_delete(nativeObj); + super.finalize(); + } + + // javadoc:Mat::toString() + @Override + public String toString() { + return "Mat [ " + + rows() + "*" + cols() + "*" + CvType.typeToString(type()) + + ", isCont=" + isContinuous() + ", isSubmat=" + isSubmatrix() + + ", nativeObj=0x" + Long.toHexString(nativeObj) + + ", dataAddr=0x" + Long.toHexString(dataAddr()) + + " ]"; + } + + // javadoc:Mat::dump() + public String dump() { + return nDump(nativeObj); + } + + // javadoc:Mat::put(row,col,data) + public int put(int row, int col, double... data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + return nPutD(nativeObj, row, col, data.length, data); + } + + // javadoc:Mat::put(idx,data) + public int put(int[] idx, double... data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + return nPutDIdx(nativeObj, idx, data.length, data); + } + + // javadoc:Mat::put(row,col,data) + public int put(int row, int col, float[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (CvType.depth(t) == CvType.CV_32F) { + return nPutF(nativeObj, row, col, data.length, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::put(idx,data) + public int put(int[] idx, float[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_32F) { + return nPutFIdx(nativeObj, idx, data.length, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::put(row,col,data) + public int put(int row, int col, int[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (CvType.depth(t) == CvType.CV_32S) { + return nPutI(nativeObj, row, col, data.length, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::put(idx,data) + public int put(int[] idx, int[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_32S) { + return nPutIIdx(nativeObj, idx, data.length, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::put(row,col,data) + public int put(int row, int col, short[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (CvType.depth(t) == CvType.CV_16U || CvType.depth(t) == CvType.CV_16S) { + return nPutS(nativeObj, row, col, data.length, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::put(idx,data) + public int put(int[] idx, short[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_16U || CvType.depth(t) == CvType.CV_16S) { + return nPutSIdx(nativeObj, idx, data.length, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::put(row,col,data) + public int put(int row, int col, byte[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (CvType.depth(t) == CvType.CV_8U || CvType.depth(t) == CvType.CV_8S) { + return nPutB(nativeObj, row, col, data.length, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::put(idx,data) + public int put(int[] idx, byte[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_8U || CvType.depth(t) == CvType.CV_8S) { + return nPutBIdx(nativeObj, idx, data.length, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::put(row,col,data,offset,length) + public int put(int row, int col, byte[] data, int offset, int length) { + int t = type(); + if (data == null || length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (CvType.depth(t) == CvType.CV_8U || CvType.depth(t) == CvType.CV_8S) { + return nPutBwOffset(nativeObj, row, col, length, offset, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::put(idx,data,offset,length) + public int put(int[] idx, byte[] data, int offset, int length) { + int t = type(); + if (data == null || length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_8U || CvType.depth(t) == CvType.CV_8S) { + return nPutBwIdxOffset(nativeObj, idx, length, offset, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::get(row,col,data) + public int get(int row, int col, byte[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (CvType.depth(t) == CvType.CV_8U || CvType.depth(t) == CvType.CV_8S) { + return nGetB(nativeObj, row, col, data.length, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::get(idx,data) + public int get(int[] idx, byte[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_8U || CvType.depth(t) == CvType.CV_8S) { + return nGetBIdx(nativeObj, idx, data.length, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::get(row,col,data) + public int get(int row, int col, short[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (CvType.depth(t) == CvType.CV_16U || CvType.depth(t) == CvType.CV_16S) { + return nGetS(nativeObj, row, col, data.length, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::get(idx,data) + public int get(int[] idx, short[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_16U || CvType.depth(t) == CvType.CV_16S) { + return nGetSIdx(nativeObj, idx, data.length, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::get(row,col,data) + public int get(int row, int col, int[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (CvType.depth(t) == CvType.CV_32S) { + return nGetI(nativeObj, row, col, data.length, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::get(idx,data) + public int get(int[] idx, int[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_32S) { + return nGetIIdx(nativeObj, idx, data.length, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::get(row,col,data) + public int get(int row, int col, float[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (CvType.depth(t) == CvType.CV_32F) { + return nGetF(nativeObj, row, col, data.length, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::get(idx,data) + public int get(int[] idx, float[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_32F) { + return nGetFIdx(nativeObj, idx, data.length, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::get(row,col,data) + public int get(int row, int col, double[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (CvType.depth(t) == CvType.CV_64F) { + return nGetD(nativeObj, row, col, data.length, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::get(idx,data) + public int get(int[] idx, double[] data) { + int t = type(); + if (data == null || data.length % CvType.channels(t) != 0) + throw new UnsupportedOperationException( + "Provided data element number (" + + (data == null ? 0 : data.length) + + ") should be multiple of the Mat channels count (" + + CvType.channels(t) + ")"); + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + if (CvType.depth(t) == CvType.CV_64F) { + return nGetDIdx(nativeObj, idx, data.length, data); + } + throw new UnsupportedOperationException("Mat data type is not compatible: " + t); + } + + // javadoc:Mat::get(row,col) + public double[] get(int row, int col) { + return nGet(nativeObj, row, col); + } + + // javadoc:Mat::get(idx) + public double[] get(int[] idx) { + if (idx.length != dims()) + throw new IllegalArgumentException("Incorrect number of indices"); + return nGetIdx(nativeObj, idx); + } + + // javadoc:Mat::height() + public int height() { + return rows(); + } + + // javadoc:Mat::width() + public int width() { + return cols(); + } + + // javadoc:Mat::getNativeObjAddr() + public long getNativeObjAddr() { + return nativeObj; + } + + // C++: Mat::Mat() + private static native long n_Mat(); + + // C++: Mat::Mat(int rows, int cols, int type) + private static native long n_Mat(int rows, int cols, int type); + + // C++: Mat::Mat(int ndims, const int* sizes, int type) + private static native long n_Mat(int ndims, int[] sizes, int type); + + // C++: Mat::Mat(int rows, int cols, int type, void* data) + private static native long n_Mat(int rows, int cols, int type, ByteBuffer data); + + // C++: Mat::Mat(Size size, int type) + private static native long n_Mat(double size_width, double size_height, int type); + + // C++: Mat::Mat(int rows, int cols, int type, Scalar s) + private static native long n_Mat(int rows, int cols, int type, double s_val0, double s_val1, double s_val2, double s_val3); + + // C++: Mat::Mat(Size size, int type, Scalar s) + private static native long n_Mat(double size_width, double size_height, int type, double s_val0, double s_val1, double s_val2, double s_val3); + + // C++: Mat::Mat(int ndims, const int* sizes, int type, Scalar s) + private static native long n_Mat(int ndims, int[] sizes, int type, double s_val0, double s_val1, double s_val2, double s_val3); + + // C++: Mat::Mat(Mat m, Range rowRange, Range colRange = Range::all()) + private static native long n_Mat(long m_nativeObj, int rowRange_start, int rowRange_end, int colRange_start, int colRange_end); + + private static native long n_Mat(long m_nativeObj, int rowRange_start, int rowRange_end); + + // C++: Mat::Mat(const Mat& m, const std::vector& ranges) + private static native long n_Mat(long m_nativeObj, Range[] ranges); + + // C++: Mat Mat::adjustROI(int dtop, int dbottom, int dleft, int dright) + private static native long n_adjustROI(long nativeObj, int dtop, int dbottom, int dleft, int dright); + + // C++: void Mat::assignTo(Mat m, int type = -1) + private static native void n_assignTo(long nativeObj, long m_nativeObj, int type); + + private static native void n_assignTo(long nativeObj, long m_nativeObj); + + // C++: int Mat::channels() + private static native int n_channels(long nativeObj); + + // C++: int Mat::checkVector(int elemChannels, int depth = -1, bool + // requireContinuous = true) + private static native int n_checkVector(long nativeObj, int elemChannels, int depth, boolean requireContinuous); + + private static native int n_checkVector(long nativeObj, int elemChannels, int depth); + + private static native int n_checkVector(long nativeObj, int elemChannels); + + // C++: Mat Mat::clone() + private static native long n_clone(long nativeObj); + + // C++: Mat Mat::col(int x) + private static native long n_col(long nativeObj, int x); + + // C++: Mat Mat::colRange(int startcol, int endcol) + private static native long n_colRange(long nativeObj, int startcol, int endcol); + + // C++: int Mat::dims() + private static native int n_dims(long nativeObj); + + // C++: int Mat::cols() + private static native int n_cols(long nativeObj); + + // C++: void Mat::convertTo(Mat& m, int rtype, double alpha = 1, double beta + // = 0) + private static native void n_convertTo(long nativeObj, long m_nativeObj, int rtype, double alpha, double beta); + + private static native void n_convertTo(long nativeObj, long m_nativeObj, int rtype, double alpha); + + private static native void n_convertTo(long nativeObj, long m_nativeObj, int rtype); + + // C++: void Mat::copyTo(Mat& m) + private static native void n_copyTo(long nativeObj, long m_nativeObj); + + // C++: void Mat::copyTo(Mat& m, Mat mask) + private static native void n_copyTo(long nativeObj, long m_nativeObj, long mask_nativeObj); + + // C++: void Mat::create(int rows, int cols, int type) + private static native void n_create(long nativeObj, int rows, int cols, int type); + + // C++: void Mat::create(Size size, int type) + private static native void n_create(long nativeObj, double size_width, double size_height, int type); + + // C++: void Mat::create(int ndims, const int* sizes, int type) + private static native void n_create(long nativeObj, int ndims, int[] sizes, int type); + + // C++: void Mat::copySize(const Mat& m) + private static native void n_copySize(long nativeObj, long m_nativeObj); + + // C++: Mat Mat::cross(Mat m) + private static native long n_cross(long nativeObj, long m_nativeObj); + + // C++: long Mat::dataAddr() + private static native long n_dataAddr(long nativeObj); + + // C++: int Mat::depth() + private static native int n_depth(long nativeObj); + + // C++: Mat Mat::diag(int d = 0) + private static native long n_diag(long nativeObj, int d); + + // C++: static Mat Mat::diag(Mat d) + private static native long n_diag(long d_nativeObj); + + // C++: double Mat::dot(Mat m) + private static native double n_dot(long nativeObj, long m_nativeObj); + + // C++: size_t Mat::elemSize() + private static native long n_elemSize(long nativeObj); + + // C++: size_t Mat::elemSize1() + private static native long n_elemSize1(long nativeObj); + + // C++: bool Mat::empty() + private static native boolean n_empty(long nativeObj); + + // C++: static Mat Mat::eye(int rows, int cols, int type) + private static native long n_eye(int rows, int cols, int type); + + // C++: static Mat Mat::eye(Size size, int type) + private static native long n_eye(double size_width, double size_height, int type); + + // C++: Mat Mat::inv(int method = DECOMP_LU) + private static native long n_inv(long nativeObj, int method); + + private static native long n_inv(long nativeObj); + + // C++: bool Mat::isContinuous() + private static native boolean n_isContinuous(long nativeObj); + + // C++: bool Mat::isSubmatrix() + private static native boolean n_isSubmatrix(long nativeObj); + + // C++: void Mat::locateROI(Size wholeSize, Point ofs) + private static native void locateROI_0(long nativeObj, double[] wholeSize_out, double[] ofs_out); + + // C++: Mat Mat::mul(Mat m, double scale = 1) + private static native long n_mul(long nativeObj, long m_nativeObj, double scale); + + private static native long n_mul(long nativeObj, long m_nativeObj); + + // C++: static Mat Mat::ones(int rows, int cols, int type) + private static native long n_ones(int rows, int cols, int type); + + // C++: static Mat Mat::ones(Size size, int type) + private static native long n_ones(double size_width, double size_height, int type); + + // C++: static Mat Mat::ones(int ndims, const int* sizes, int type) + private static native long n_ones(int ndims, int[] sizes, int type); + + // C++: void Mat::push_back(Mat m) + private static native void n_push_back(long nativeObj, long m_nativeObj); + + // C++: void Mat::release() + private static native void n_release(long nativeObj); + + // C++: Mat Mat::reshape(int cn, int rows = 0) + private static native long n_reshape(long nativeObj, int cn, int rows); + + private static native long n_reshape(long nativeObj, int cn); + + // C++: Mat Mat::reshape(int cn, int newndims, const int* newsz) + private static native long n_reshape_1(long nativeObj, int cn, int newndims, int[] newsz); + + // C++: Mat Mat::row(int y) + private static native long n_row(long nativeObj, int y); + + // C++: Mat Mat::rowRange(int startrow, int endrow) + private static native long n_rowRange(long nativeObj, int startrow, int endrow); + + // C++: int Mat::rows() + private static native int n_rows(long nativeObj); + + // C++: Mat Mat::operator =(Scalar s) + private static native long n_setTo(long nativeObj, double s_val0, double s_val1, double s_val2, double s_val3); + + // C++: Mat Mat::setTo(Scalar value, Mat mask = Mat()) + private static native long n_setTo(long nativeObj, double s_val0, double s_val1, double s_val2, double s_val3, long mask_nativeObj); + + // C++: Mat Mat::setTo(Mat value, Mat mask = Mat()) + private static native long n_setTo(long nativeObj, long value_nativeObj, long mask_nativeObj); + + private static native long n_setTo(long nativeObj, long value_nativeObj); + + // C++: Size Mat::size() + private static native double[] n_size(long nativeObj); + + // C++: int Mat::size(int i) + private static native int n_size_i(long nativeObj, int i); + + // C++: size_t Mat::step1(int i = 0) + private static native long n_step1(long nativeObj, int i); + + private static native long n_step1(long nativeObj); + + // C++: Mat Mat::operator()(Range rowRange, Range colRange) + private static native long n_submat_rr(long nativeObj, int rowRange_start, int rowRange_end, int colRange_start, int colRange_end); + + // C++: Mat Mat::operator()(const std::vector& ranges) + private static native long n_submat_ranges(long nativeObj, Range[] ranges); + + // C++: Mat Mat::operator()(Rect roi) + private static native long n_submat(long nativeObj, int roi_x, int roi_y, int roi_width, int roi_height); + + // C++: Mat Mat::t() + private static native long n_t(long nativeObj); + + // C++: size_t Mat::total() + private static native long n_total(long nativeObj); + + // C++: int Mat::type() + private static native int n_type(long nativeObj); + + // C++: static Mat Mat::zeros(int rows, int cols, int type) + private static native long n_zeros(int rows, int cols, int type); + + // C++: static Mat Mat::zeros(Size size, int type) + private static native long n_zeros(double size_width, double size_height, int type); + + // C++: static Mat Mat::zeros(int ndims, const int* sizes, int type) + private static native long n_zeros(int ndims, int[] sizes, int type); + + // native support for java finalize() + private static native void n_delete(long nativeObj); + + private static native int nPutD(long self, int row, int col, int count, double[] data); + + private static native int nPutDIdx(long self, int[] idx, int count, double[] data); + + private static native int nPutF(long self, int row, int col, int count, float[] data); + + private static native int nPutFIdx(long self, int[] idx, int count, float[] data); + + private static native int nPutI(long self, int row, int col, int count, int[] data); + + private static native int nPutIIdx(long self, int[] idx, int count, int[] data); + + private static native int nPutS(long self, int row, int col, int count, short[] data); + + private static native int nPutSIdx(long self, int[] idx, int count, short[] data); + + private static native int nPutB(long self, int row, int col, int count, byte[] data); + + private static native int nPutBIdx(long self, int[] idx, int count, byte[] data); + + private static native int nPutBwOffset(long self, int row, int col, int count, int offset, byte[] data); + + private static native int nPutBwIdxOffset(long self, int[] idx, int count, int offset, byte[] data); + + private static native int nGetB(long self, int row, int col, int count, byte[] vals); + + private static native int nGetBIdx(long self, int[] idx, int count, byte[] vals); + + private static native int nGetS(long self, int row, int col, int count, short[] vals); + + private static native int nGetSIdx(long self, int[] idx, int count, short[] vals); + + private static native int nGetI(long self, int row, int col, int count, int[] vals); + + private static native int nGetIIdx(long self, int[] idx, int count, int[] vals); + + private static native int nGetF(long self, int row, int col, int count, float[] vals); + + private static native int nGetFIdx(long self, int[] idx, int count, float[] vals); + + private static native int nGetD(long self, int row, int col, int count, double[] vals); + + private static native int nGetDIdx(long self, int[] idx, int count, double[] vals); + + private static native double[] nGet(long self, int row, int col); + + private static native double[] nGetIdx(long self, int[] idx); + + private static native String nDump(long self); +} diff --git a/OpenCV/src/main/java/org/opencv/core/MatOfByte.java b/OpenCV/src/main/java/org/opencv/core/MatOfByte.java new file mode 100644 index 00000000..eb928fb0 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/MatOfByte.java @@ -0,0 +1,98 @@ +package org.opencv.core; + +import java.util.Arrays; +import java.util.List; + +public class MatOfByte extends Mat { + // 8UC(x) + private static final int _depth = CvType.CV_8U; + private static final int _channels = 1; + + public MatOfByte() { + super(); + } + + protected MatOfByte(long addr) { + super(addr); + if( !empty() && checkVector(_channels, _depth) < 0 ) + throw new IllegalArgumentException("Incompatible Mat"); + //FIXME: do we need release() here? + } + + public static MatOfByte fromNativeAddr(long addr) { + return new MatOfByte(addr); + } + + public MatOfByte(Mat m) { + super(m, Range.all()); + if( !empty() && checkVector(_channels, _depth) < 0 ) + throw new IllegalArgumentException("Incompatible Mat"); + //FIXME: do we need release() here? + } + + public MatOfByte(byte...a) { + super(); + fromArray(a); + } + + public MatOfByte(int offset, int length, byte...a) { + super(); + fromArray(offset, length, a); + } + + public void alloc(int elemNumber) { + if(elemNumber>0) + super.create(elemNumber, 1, CvType.makeType(_depth, _channels)); + } + + public void fromArray(byte...a) { + if(a==null || a.length==0) + return; + int num = a.length / _channels; + alloc(num); + put(0, 0, a); //TODO: check ret val! + } + + public void fromArray(int offset, int length, byte...a) { + if (offset < 0) + throw new IllegalArgumentException("offset < 0"); + if (a == null) + throw new NullPointerException(); + if (length < 0 || length + offset > a.length) + throw new IllegalArgumentException("invalid 'length' parameter: " + Integer.toString(length)); + if (a.length == 0) + return; + int num = length / _channels; + alloc(num); + put(0, 0, a, offset, length); //TODO: check ret val! + } + + public byte[] toArray() { + int num = checkVector(_channels, _depth); + if(num < 0) + throw new RuntimeException("Native Mat has unexpected type or size: " + toString()); + byte[] a = new byte[num * _channels]; + if(num == 0) + return a; + get(0, 0, a); //TODO: check ret val! + return a; + } + + public void fromList(List lb) { + if(lb==null || lb.size()==0) + return; + Byte ab[] = lb.toArray(new Byte[0]); + byte a[] = new byte[ab.length]; + for(int i=0; i toList() { + byte[] a = toArray(); + Byte ab[] = new Byte[a.length]; + for(int i=0; i0) + super.create(elemNumber, 1, CvType.makeType(_depth, _channels)); + } + + + public void fromArray(DMatch...a) { + if(a==null || a.length==0) + return; + int num = a.length; + alloc(num); + float buff[] = new float[num * _channels]; + for(int i=0; i ldm) { + DMatch adm[] = ldm.toArray(new DMatch[0]); + fromArray(adm); + } + + public List toList() { + DMatch[] adm = toArray(); + return Arrays.asList(adm); + } +} diff --git a/OpenCV/src/main/java/org/opencv/core/MatOfDouble.java b/OpenCV/src/main/java/org/opencv/core/MatOfDouble.java new file mode 100644 index 00000000..1a8e23ca --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/MatOfDouble.java @@ -0,0 +1,79 @@ +package org.opencv.core; + +import java.util.Arrays; +import java.util.List; + +public class MatOfDouble extends Mat { + // 64FC(x) + private static final int _depth = CvType.CV_64F; + private static final int _channels = 1; + + public MatOfDouble() { + super(); + } + + protected MatOfDouble(long addr) { + super(addr); + if( !empty() && checkVector(_channels, _depth) < 0 ) + throw new IllegalArgumentException("Incompatible Mat"); + //FIXME: do we need release() here? + } + + public static MatOfDouble fromNativeAddr(long addr) { + return new MatOfDouble(addr); + } + + public MatOfDouble(Mat m) { + super(m, Range.all()); + if( !empty() && checkVector(_channels, _depth) < 0 ) + throw new IllegalArgumentException("Incompatible Mat"); + //FIXME: do we need release() here? + } + + public MatOfDouble(double...a) { + super(); + fromArray(a); + } + + public void alloc(int elemNumber) { + if(elemNumber>0) + super.create(elemNumber, 1, CvType.makeType(_depth, _channels)); + } + + public void fromArray(double...a) { + if(a==null || a.length==0) + return; + int num = a.length / _channels; + alloc(num); + put(0, 0, a); //TODO: check ret val! + } + + public double[] toArray() { + int num = checkVector(_channels, _depth); + if(num < 0) + throw new RuntimeException("Native Mat has unexpected type or size: " + toString()); + double[] a = new double[num * _channels]; + if(num == 0) + return a; + get(0, 0, a); //TODO: check ret val! + return a; + } + + public void fromList(List lb) { + if(lb==null || lb.size()==0) + return; + Double ab[] = lb.toArray(new Double[0]); + double a[] = new double[ab.length]; + for(int i=0; i toList() { + double[] a = toArray(); + Double ab[] = new Double[a.length]; + for(int i=0; i0) + super.create(elemNumber, 1, CvType.makeType(_depth, _channels)); + } + + public void fromArray(float...a) { + if(a==null || a.length==0) + return; + int num = a.length / _channels; + alloc(num); + put(0, 0, a); //TODO: check ret val! + } + + public float[] toArray() { + int num = checkVector(_channels, _depth); + if(num < 0) + throw new RuntimeException("Native Mat has unexpected type or size: " + toString()); + float[] a = new float[num * _channels]; + if(num == 0) + return a; + get(0, 0, a); //TODO: check ret val! + return a; + } + + public void fromList(List lb) { + if(lb==null || lb.size()==0) + return; + Float ab[] = lb.toArray(new Float[0]); + float a[] = new float[ab.length]; + for(int i=0; i toList() { + float[] a = toArray(); + Float ab[] = new Float[a.length]; + for(int i=0; i0) + super.create(elemNumber, 1, CvType.makeType(_depth, _channels)); + } + + public void fromArray(float...a) { + if(a==null || a.length==0) + return; + int num = a.length / _channels; + alloc(num); + put(0, 0, a); //TODO: check ret val! + } + + public float[] toArray() { + int num = checkVector(_channels, _depth); + if(num < 0) + throw new RuntimeException("Native Mat has unexpected type or size: " + toString()); + float[] a = new float[num * _channels]; + if(num == 0) + return a; + get(0, 0, a); //TODO: check ret val! + return a; + } + + public void fromList(List lb) { + if(lb==null || lb.size()==0) + return; + Float ab[] = lb.toArray(new Float[0]); + float a[] = new float[ab.length]; + for(int i=0; i toList() { + float[] a = toArray(); + Float ab[] = new Float[a.length]; + for(int i=0; i0) + super.create(elemNumber, 1, CvType.makeType(_depth, _channels)); + } + + public void fromArray(float...a) { + if(a==null || a.length==0) + return; + int num = a.length / _channels; + alloc(num); + put(0, 0, a); //TODO: check ret val! + } + + public float[] toArray() { + int num = checkVector(_channels, _depth); + if(num < 0) + throw new RuntimeException("Native Mat has unexpected type or size: " + toString()); + float[] a = new float[num * _channels]; + if(num == 0) + return a; + get(0, 0, a); //TODO: check ret val! + return a; + } + + public void fromList(List lb) { + if(lb==null || lb.size()==0) + return; + Float ab[] = lb.toArray(new Float[0]); + float a[] = new float[ab.length]; + for(int i=0; i toList() { + float[] a = toArray(); + Float ab[] = new Float[a.length]; + for(int i=0; i0) + super.create(elemNumber, 1, CvType.makeType(_depth, _channels)); + } + + public void fromArray(int...a) { + if(a==null || a.length==0) + return; + int num = a.length / _channels; + alloc(num); + put(0, 0, a); //TODO: check ret val! + } + + public int[] toArray() { + int num = checkVector(_channels, _depth); + if(num < 0) + throw new RuntimeException("Native Mat has unexpected type or size: " + toString()); + int[] a = new int[num * _channels]; + if(num == 0) + return a; + get(0, 0, a); //TODO: check ret val! + return a; + } + + public void fromList(List lb) { + if(lb==null || lb.size()==0) + return; + Integer ab[] = lb.toArray(new Integer[0]); + int a[] = new int[ab.length]; + for(int i=0; i toList() { + int[] a = toArray(); + Integer ab[] = new Integer[a.length]; + for(int i=0; i0) + super.create(elemNumber, 1, CvType.makeType(_depth, _channels)); + } + + public void fromArray(int...a) { + if(a==null || a.length==0) + return; + int num = a.length / _channels; + alloc(num); + put(0, 0, a); //TODO: check ret val! + } + + public int[] toArray() { + int num = checkVector(_channels, _depth); + if(num < 0) + throw new RuntimeException("Native Mat has unexpected type or size: " + toString()); + int[] a = new int[num * _channels]; + if(num == 0) + return a; + get(0, 0, a); //TODO: check ret val! + return a; + } + + public void fromList(List lb) { + if(lb==null || lb.size()==0) + return; + Integer ab[] = lb.toArray(new Integer[0]); + int a[] = new int[ab.length]; + for(int i=0; i toList() { + int[] a = toArray(); + Integer ab[] = new Integer[a.length]; + for(int i=0; i0) + super.create(elemNumber, 1, CvType.makeType(_depth, _channels)); + } + + public void fromArray(KeyPoint...a) { + if(a==null || a.length==0) + return; + int num = a.length; + alloc(num); + float buff[] = new float[num * _channels]; + for(int i=0; i lkp) { + KeyPoint akp[] = lkp.toArray(new KeyPoint[0]); + fromArray(akp); + } + + public List toList() { + KeyPoint[] akp = toArray(); + return Arrays.asList(akp); + } +} diff --git a/OpenCV/src/main/java/org/opencv/core/MatOfPoint.java b/OpenCV/src/main/java/org/opencv/core/MatOfPoint.java new file mode 100644 index 00000000..f4d573bb --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/MatOfPoint.java @@ -0,0 +1,78 @@ +package org.opencv.core; + +import java.util.Arrays; +import java.util.List; + +public class MatOfPoint extends Mat { + // 32SC2 + private static final int _depth = CvType.CV_32S; + private static final int _channels = 2; + + public MatOfPoint() { + super(); + } + + protected MatOfPoint(long addr) { + super(addr); + if( !empty() && checkVector(_channels, _depth) < 0 ) + throw new IllegalArgumentException("Incompatible Mat"); + //FIXME: do we need release() here? + } + + public static MatOfPoint fromNativeAddr(long addr) { + return new MatOfPoint(addr); + } + + public MatOfPoint(Mat m) { + super(m, Range.all()); + if( !empty() && checkVector(_channels, _depth) < 0 ) + throw new IllegalArgumentException("Incompatible Mat"); + //FIXME: do we need release() here? + } + + public MatOfPoint(Point...a) { + super(); + fromArray(a); + } + + public void alloc(int elemNumber) { + if(elemNumber>0) + super.create(elemNumber, 1, CvType.makeType(_depth, _channels)); + } + + public void fromArray(Point...a) { + if(a==null || a.length==0) + return; + int num = a.length; + alloc(num); + int buff[] = new int[num * _channels]; + for(int i=0; i lp) { + Point ap[] = lp.toArray(new Point[0]); + fromArray(ap); + } + + public List toList() { + Point[] ap = toArray(); + return Arrays.asList(ap); + } +} diff --git a/OpenCV/src/main/java/org/opencv/core/MatOfPoint2f.java b/OpenCV/src/main/java/org/opencv/core/MatOfPoint2f.java new file mode 100644 index 00000000..4b8c926f --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/MatOfPoint2f.java @@ -0,0 +1,78 @@ +package org.opencv.core; + +import java.util.Arrays; +import java.util.List; + +public class MatOfPoint2f extends Mat { + // 32FC2 + private static final int _depth = CvType.CV_32F; + private static final int _channels = 2; + + public MatOfPoint2f() { + super(); + } + + protected MatOfPoint2f(long addr) { + super(addr); + if( !empty() && checkVector(_channels, _depth) < 0 ) + throw new IllegalArgumentException("Incompatible Mat"); + //FIXME: do we need release() here? + } + + public static MatOfPoint2f fromNativeAddr(long addr) { + return new MatOfPoint2f(addr); + } + + public MatOfPoint2f(Mat m) { + super(m, Range.all()); + if( !empty() && checkVector(_channels, _depth) < 0 ) + throw new IllegalArgumentException("Incompatible Mat"); + //FIXME: do we need release() here? + } + + public MatOfPoint2f(Point...a) { + super(); + fromArray(a); + } + + public void alloc(int elemNumber) { + if(elemNumber>0) + super.create(elemNumber, 1, CvType.makeType(_depth, _channels)); + } + + public void fromArray(Point...a) { + if(a==null || a.length==0) + return; + int num = a.length; + alloc(num); + float buff[] = new float[num * _channels]; + for(int i=0; i lp) { + Point ap[] = lp.toArray(new Point[0]); + fromArray(ap); + } + + public List toList() { + Point[] ap = toArray(); + return Arrays.asList(ap); + } +} diff --git a/OpenCV/src/main/java/org/opencv/core/MatOfPoint3.java b/OpenCV/src/main/java/org/opencv/core/MatOfPoint3.java new file mode 100644 index 00000000..3b50561e --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/MatOfPoint3.java @@ -0,0 +1,79 @@ +package org.opencv.core; + +import java.util.Arrays; +import java.util.List; + +public class MatOfPoint3 extends Mat { + // 32SC3 + private static final int _depth = CvType.CV_32S; + private static final int _channels = 3; + + public MatOfPoint3() { + super(); + } + + protected MatOfPoint3(long addr) { + super(addr); + if( !empty() && checkVector(_channels, _depth) < 0 ) + throw new IllegalArgumentException("Incompatible Mat"); + //FIXME: do we need release() here? + } + + public static MatOfPoint3 fromNativeAddr(long addr) { + return new MatOfPoint3(addr); + } + + public MatOfPoint3(Mat m) { + super(m, Range.all()); + if( !empty() && checkVector(_channels, _depth) < 0 ) + throw new IllegalArgumentException("Incompatible Mat"); + //FIXME: do we need release() here? + } + + public MatOfPoint3(Point3...a) { + super(); + fromArray(a); + } + + public void alloc(int elemNumber) { + if(elemNumber>0) + super.create(elemNumber, 1, CvType.makeType(_depth, _channels)); + } + + public void fromArray(Point3...a) { + if(a==null || a.length==0) + return; + int num = a.length; + alloc(num); + int buff[] = new int[num * _channels]; + for(int i=0; i lp) { + Point3 ap[] = lp.toArray(new Point3[0]); + fromArray(ap); + } + + public List toList() { + Point3[] ap = toArray(); + return Arrays.asList(ap); + } +} diff --git a/OpenCV/src/main/java/org/opencv/core/MatOfPoint3f.java b/OpenCV/src/main/java/org/opencv/core/MatOfPoint3f.java new file mode 100644 index 00000000..fc5fee43 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/MatOfPoint3f.java @@ -0,0 +1,79 @@ +package org.opencv.core; + +import java.util.Arrays; +import java.util.List; + +public class MatOfPoint3f extends Mat { + // 32FC3 + private static final int _depth = CvType.CV_32F; + private static final int _channels = 3; + + public MatOfPoint3f() { + super(); + } + + protected MatOfPoint3f(long addr) { + super(addr); + if( !empty() && checkVector(_channels, _depth) < 0 ) + throw new IllegalArgumentException("Incompatible Mat"); + //FIXME: do we need release() here? + } + + public static MatOfPoint3f fromNativeAddr(long addr) { + return new MatOfPoint3f(addr); + } + + public MatOfPoint3f(Mat m) { + super(m, Range.all()); + if( !empty() && checkVector(_channels, _depth) < 0 ) + throw new IllegalArgumentException("Incompatible Mat"); + //FIXME: do we need release() here? + } + + public MatOfPoint3f(Point3...a) { + super(); + fromArray(a); + } + + public void alloc(int elemNumber) { + if(elemNumber>0) + super.create(elemNumber, 1, CvType.makeType(_depth, _channels)); + } + + public void fromArray(Point3...a) { + if(a==null || a.length==0) + return; + int num = a.length; + alloc(num); + float buff[] = new float[num * _channels]; + for(int i=0; i lp) { + Point3 ap[] = lp.toArray(new Point3[0]); + fromArray(ap); + } + + public List toList() { + Point3[] ap = toArray(); + return Arrays.asList(ap); + } +} diff --git a/OpenCV/src/main/java/org/opencv/core/MatOfRect.java b/OpenCV/src/main/java/org/opencv/core/MatOfRect.java new file mode 100644 index 00000000..ec0fb01e --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/MatOfRect.java @@ -0,0 +1,81 @@ +package org.opencv.core; + +import java.util.Arrays; +import java.util.List; + + +public class MatOfRect extends Mat { + // 32SC4 + private static final int _depth = CvType.CV_32S; + private static final int _channels = 4; + + public MatOfRect() { + super(); + } + + protected MatOfRect(long addr) { + super(addr); + if( !empty() && checkVector(_channels, _depth) < 0 ) + throw new IllegalArgumentException("Incompatible Mat"); + //FIXME: do we need release() here? + } + + public static MatOfRect fromNativeAddr(long addr) { + return new MatOfRect(addr); + } + + public MatOfRect(Mat m) { + super(m, Range.all()); + if( !empty() && checkVector(_channels, _depth) < 0 ) + throw new IllegalArgumentException("Incompatible Mat"); + //FIXME: do we need release() here? + } + + public MatOfRect(Rect...a) { + super(); + fromArray(a); + } + + public void alloc(int elemNumber) { + if(elemNumber>0) + super.create(elemNumber, 1, CvType.makeType(_depth, _channels)); + } + + public void fromArray(Rect...a) { + if(a==null || a.length==0) + return; + int num = a.length; + alloc(num); + int buff[] = new int[num * _channels]; + for(int i=0; i lr) { + Rect ap[] = lr.toArray(new Rect[0]); + fromArray(ap); + } + + public List toList() { + Rect[] ar = toArray(); + return Arrays.asList(ar); + } +} diff --git a/OpenCV/src/main/java/org/opencv/core/MatOfRect2d.java b/OpenCV/src/main/java/org/opencv/core/MatOfRect2d.java new file mode 100644 index 00000000..71c4b1ae --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/MatOfRect2d.java @@ -0,0 +1,81 @@ +package org.opencv.core; + +import java.util.Arrays; +import java.util.List; + + +public class MatOfRect2d extends Mat { + // 64FC4 + private static final int _depth = CvType.CV_64F; + private static final int _channels = 4; + + public MatOfRect2d() { + super(); + } + + protected MatOfRect2d(long addr) { + super(addr); + if( !empty() && checkVector(_channels, _depth) < 0 ) + throw new IllegalArgumentException("Incompatible Mat"); + //FIXME: do we need release() here? + } + + public static MatOfRect2d fromNativeAddr(long addr) { + return new MatOfRect2d(addr); + } + + public MatOfRect2d(Mat m) { + super(m, Range.all()); + if( !empty() && checkVector(_channels, _depth) < 0 ) + throw new IllegalArgumentException("Incompatible Mat"); + //FIXME: do we need release() here? + } + + public MatOfRect2d(Rect2d...a) { + super(); + fromArray(a); + } + + public void alloc(int elemNumber) { + if(elemNumber>0) + super.create(elemNumber, 1, CvType.makeType(_depth, _channels)); + } + + public void fromArray(Rect2d...a) { + if(a==null || a.length==0) + return; + int num = a.length; + alloc(num); + double buff[] = new double[num * _channels]; + for(int i=0; i lr) { + Rect2d ap[] = lr.toArray(new Rect2d[0]); + fromArray(ap); + } + + public List toList() { + Rect2d[] ar = toArray(); + return Arrays.asList(ar); + } +} diff --git a/OpenCV/src/main/java/org/opencv/core/MatOfRotatedRect.java b/OpenCV/src/main/java/org/opencv/core/MatOfRotatedRect.java new file mode 100644 index 00000000..6f36e6ca --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/MatOfRotatedRect.java @@ -0,0 +1,86 @@ +package org.opencv.core; + +import java.util.Arrays; +import java.util.List; + +import org.opencv.core.RotatedRect; + + + +public class MatOfRotatedRect extends Mat { + // 32FC5 + private static final int _depth = CvType.CV_32F; + private static final int _channels = 5; + + public MatOfRotatedRect() { + super(); + } + + protected MatOfRotatedRect(long addr) { + super(addr); + if( !empty() && checkVector(_channels, _depth) < 0 ) + throw new IllegalArgumentException("Incompatible Mat"); + //FIXME: do we need release() here? + } + + public static MatOfRotatedRect fromNativeAddr(long addr) { + return new MatOfRotatedRect(addr); + } + + public MatOfRotatedRect(Mat m) { + super(m, Range.all()); + if( !empty() && checkVector(_channels, _depth) < 0 ) + throw new IllegalArgumentException("Incompatible Mat"); + //FIXME: do we need release() here? + } + + public MatOfRotatedRect(RotatedRect...a) { + super(); + fromArray(a); + } + + public void alloc(int elemNumber) { + if(elemNumber>0) + super.create(elemNumber, 1, CvType.makeType(_depth, _channels)); + } + + public void fromArray(RotatedRect...a) { + if(a==null || a.length==0) + return; + int num = a.length; + alloc(num); + float buff[] = new float[num * _channels]; + for(int i=0; i lr) { + RotatedRect ap[] = lr.toArray(new RotatedRect[0]); + fromArray(ap); + } + + public List toList() { + RotatedRect[] ar = toArray(); + return Arrays.asList(ar); + } +} diff --git a/OpenCV/src/main/java/org/opencv/core/Point.java b/OpenCV/src/main/java/org/opencv/core/Point.java new file mode 100644 index 00000000..ce493d74 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/Point.java @@ -0,0 +1,68 @@ +package org.opencv.core; + +//javadoc:Point_ +public class Point { + + public double x, y; + + public Point(double x, double y) { + this.x = x; + this.y = y; + } + + public Point() { + this(0, 0); + } + + public Point(double[] vals) { + this(); + set(vals); + } + + public void set(double[] vals) { + if (vals != null) { + x = vals.length > 0 ? vals[0] : 0; + y = vals.length > 1 ? vals[1] : 0; + } else { + x = 0; + y = 0; + } + } + + public Point clone() { + return new Point(x, y); + } + + public double dot(Point p) { + return x * p.x + y * p.y; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(x); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(y); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof Point)) return false; + Point it = (Point) obj; + return x == it.x && y == it.y; + } + + public boolean inside(Rect r) { + return r.contains(this); + } + + @Override + public String toString() { + return "{" + x + ", " + y + "}"; + } +} diff --git a/OpenCV/src/main/java/org/opencv/core/Point3.java b/OpenCV/src/main/java/org/opencv/core/Point3.java new file mode 100644 index 00000000..14b91c6b --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/Point3.java @@ -0,0 +1,79 @@ +package org.opencv.core; + +//javadoc:Point3_ +public class Point3 { + + public double x, y, z; + + public Point3(double x, double y, double z) { + this.x = x; + this.y = y; + this.z = z; + } + + public Point3() { + this(0, 0, 0); + } + + public Point3(Point p) { + x = p.x; + y = p.y; + z = 0; + } + + public Point3(double[] vals) { + this(); + set(vals); + } + + public void set(double[] vals) { + if (vals != null) { + x = vals.length > 0 ? vals[0] : 0; + y = vals.length > 1 ? vals[1] : 0; + z = vals.length > 2 ? vals[2] : 0; + } else { + x = 0; + y = 0; + z = 0; + } + } + + public Point3 clone() { + return new Point3(x, y, z); + } + + public double dot(Point3 p) { + return x * p.x + y * p.y + z * p.z; + } + + public Point3 cross(Point3 p) { + return new Point3(y * p.z - z * p.y, z * p.x - x * p.z, x * p.y - y * p.x); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(x); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(y); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(z); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof Point3)) return false; + Point3 it = (Point3) obj; + return x == it.x && y == it.y && z == it.z; + } + + @Override + public String toString() { + return "{" + x + ", " + y + ", " + z + "}"; + } +} diff --git a/OpenCV/src/main/java/org/opencv/core/Range.java b/OpenCV/src/main/java/org/opencv/core/Range.java new file mode 100644 index 00000000..f7eee4dd --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/Range.java @@ -0,0 +1,82 @@ +package org.opencv.core; + +//javadoc:Range +public class Range { + + public int start, end; + + public Range(int s, int e) { + this.start = s; + this.end = e; + } + + public Range() { + this(0, 0); + } + + public Range(double[] vals) { + set(vals); + } + + public void set(double[] vals) { + if (vals != null) { + start = vals.length > 0 ? (int) vals[0] : 0; + end = vals.length > 1 ? (int) vals[1] : 0; + } else { + start = 0; + end = 0; + } + + } + + public int size() { + return empty() ? 0 : end - start; + } + + public boolean empty() { + return end <= start; + } + + public static Range all() { + return new Range(Integer.MIN_VALUE, Integer.MAX_VALUE); + } + + public Range intersection(Range r1) { + Range r = new Range(Math.max(r1.start, this.start), Math.min(r1.end, this.end)); + r.end = Math.max(r.end, r.start); + return r; + } + + public Range shift(int delta) { + return new Range(start + delta, end + delta); + } + + public Range clone() { + return new Range(start, end); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(start); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(end); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof Range)) return false; + Range it = (Range) obj; + return start == it.start && end == it.end; + } + + @Override + public String toString() { + return "[" + start + ", " + end + ")"; + } +} diff --git a/OpenCV/src/main/java/org/opencv/core/Rect.java b/OpenCV/src/main/java/org/opencv/core/Rect.java new file mode 100644 index 00000000..c68e818e --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/Rect.java @@ -0,0 +1,104 @@ +package org.opencv.core; + +//javadoc:Rect_ +public class Rect { + + public int x, y, width, height; + + public Rect(int x, int y, int width, int height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + public Rect() { + this(0, 0, 0, 0); + } + + public Rect(Point p1, Point p2) { + x = (int) (p1.x < p2.x ? p1.x : p2.x); + y = (int) (p1.y < p2.y ? p1.y : p2.y); + width = (int) (p1.x > p2.x ? p1.x : p2.x) - x; + height = (int) (p1.y > p2.y ? p1.y : p2.y) - y; + } + + public Rect(Point p, Size s) { + this((int) p.x, (int) p.y, (int) s.width, (int) s.height); + } + + public Rect(double[] vals) { + set(vals); + } + + public void set(double[] vals) { + if (vals != null) { + x = vals.length > 0 ? (int) vals[0] : 0; + y = vals.length > 1 ? (int) vals[1] : 0; + width = vals.length > 2 ? (int) vals[2] : 0; + height = vals.length > 3 ? (int) vals[3] : 0; + } else { + x = 0; + y = 0; + width = 0; + height = 0; + } + } + + public Rect clone() { + return new Rect(x, y, width, height); + } + + public Point tl() { + return new Point(x, y); + } + + public Point br() { + return new Point(x + width, y + height); + } + + public Size size() { + return new Size(width, height); + } + + public double area() { + return width * height; + } + + public boolean empty() { + return width <= 0 || height <= 0; + } + + public boolean contains(Point p) { + return x <= p.x && p.x < x + width && y <= p.y && p.y < y + height; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(height); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(width); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(x); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(y); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof Rect)) return false; + Rect it = (Rect) obj; + return x == it.x && y == it.y && width == it.width && height == it.height; + } + + @Override + public String toString() { + return "{" + x + ", " + y + ", " + width + "x" + height + "}"; + } +} diff --git a/OpenCV/src/main/java/org/opencv/core/Rect2d.java b/OpenCV/src/main/java/org/opencv/core/Rect2d.java new file mode 100644 index 00000000..4c278696 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/Rect2d.java @@ -0,0 +1,104 @@ +package org.opencv.core; + +//javadoc:Rect2d_ +public class Rect2d { + + public double x, y, width, height; + + public Rect2d(double x, double y, double width, double height) { + this.x = x; + this.y = y; + this.width = width; + this.height = height; + } + + public Rect2d() { + this(0, 0, 0, 0); + } + + public Rect2d(Point p1, Point p2) { + x = (double) (p1.x < p2.x ? p1.x : p2.x); + y = (double) (p1.y < p2.y ? p1.y : p2.y); + width = (double) (p1.x > p2.x ? p1.x : p2.x) - x; + height = (double) (p1.y > p2.y ? p1.y : p2.y) - y; + } + + public Rect2d(Point p, Size s) { + this((double) p.x, (double) p.y, (double) s.width, (double) s.height); + } + + public Rect2d(double[] vals) { + set(vals); + } + + public void set(double[] vals) { + if (vals != null) { + x = vals.length > 0 ? (double) vals[0] : 0; + y = vals.length > 1 ? (double) vals[1] : 0; + width = vals.length > 2 ? (double) vals[2] : 0; + height = vals.length > 3 ? (double) vals[3] : 0; + } else { + x = 0; + y = 0; + width = 0; + height = 0; + } + } + + public Rect2d clone() { + return new Rect2d(x, y, width, height); + } + + public Point tl() { + return new Point(x, y); + } + + public Point br() { + return new Point(x + width, y + height); + } + + public Size size() { + return new Size(width, height); + } + + public double area() { + return width * height; + } + + public boolean empty() { + return width <= 0 || height <= 0; + } + + public boolean contains(Point p) { + return x <= p.x && p.x < x + width && y <= p.y && p.y < y + height; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(height); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(width); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(x); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(y); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof Rect2d)) return false; + Rect2d it = (Rect2d) obj; + return x == it.x && y == it.y && width == it.width && height == it.height; + } + + @Override + public String toString() { + return "{" + x + ", " + y + ", " + width + "x" + height + "}"; + } +} diff --git a/OpenCV/src/main/java/org/opencv/core/RotatedRect.java b/OpenCV/src/main/java/org/opencv/core/RotatedRect.java new file mode 100644 index 00000000..05ee3811 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/RotatedRect.java @@ -0,0 +1,113 @@ +package org.opencv.core; + +//javadoc:RotatedRect_ +public class RotatedRect { + + public Point center; + public Size size; + public double angle; + + public RotatedRect() { + this.center = new Point(); + this.size = new Size(); + this.angle = 0; + } + + public RotatedRect(Point c, Size s, double a) { + this.center = c.clone(); + this.size = s.clone(); + this.angle = a; + } + + public RotatedRect(double[] vals) { + this(); + set(vals); + } + + public void set(double[] vals) { + if (vals != null) { + center.x = vals.length > 0 ? (double) vals[0] : 0; + center.y = vals.length > 1 ? (double) vals[1] : 0; + size.width = vals.length > 2 ? (double) vals[2] : 0; + size.height = vals.length > 3 ? (double) vals[3] : 0; + angle = vals.length > 4 ? (double) vals[4] : 0; + } else { + center.x = 0; + center.y = 0; + size.width = 0; + size.height = 0; + angle = 0; + } + } + + public void points(Point pt[]) + { + double _angle = angle * Math.PI / 180.0; + double b = (double) Math.cos(_angle) * 0.5f; + double a = (double) Math.sin(_angle) * 0.5f; + + pt[0] = new Point( + center.x - a * size.height - b * size.width, + center.y + b * size.height - a * size.width); + + pt[1] = new Point( + center.x + a * size.height - b * size.width, + center.y - b * size.height - a * size.width); + + pt[2] = new Point( + 2 * center.x - pt[0].x, + 2 * center.y - pt[0].y); + + pt[3] = new Point( + 2 * center.x - pt[1].x, + 2 * center.y - pt[1].y); + } + + public Rect boundingRect() + { + Point pt[] = new Point[4]; + points(pt); + Rect r = new Rect((int) Math.floor(Math.min(Math.min(Math.min(pt[0].x, pt[1].x), pt[2].x), pt[3].x)), + (int) Math.floor(Math.min(Math.min(Math.min(pt[0].y, pt[1].y), pt[2].y), pt[3].y)), + (int) Math.ceil(Math.max(Math.max(Math.max(pt[0].x, pt[1].x), pt[2].x), pt[3].x)), + (int) Math.ceil(Math.max(Math.max(Math.max(pt[0].y, pt[1].y), pt[2].y), pt[3].y))); + r.width -= r.x - 1; + r.height -= r.y - 1; + return r; + } + + public RotatedRect clone() { + return new RotatedRect(center, size, angle); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(center.x); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(center.y); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(size.width); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(size.height); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(angle); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof RotatedRect)) return false; + RotatedRect it = (RotatedRect) obj; + return center.equals(it.center) && size.equals(it.size) && angle == it.angle; + } + + @Override + public String toString() { + return "{ " + center + " " + size + " * " + angle + " }"; + } +} diff --git a/OpenCV/src/main/java/org/opencv/core/Scalar.java b/OpenCV/src/main/java/org/opencv/core/Scalar.java new file mode 100644 index 00000000..01676e4c --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/Scalar.java @@ -0,0 +1,90 @@ +package org.opencv.core; + +//javadoc:Scalar_ +public class Scalar { + + public double val[]; + + public Scalar(double v0, double v1, double v2, double v3) { + val = new double[] { v0, v1, v2, v3 }; + } + + public Scalar(double v0, double v1, double v2) { + val = new double[] { v0, v1, v2, 0 }; + } + + public Scalar(double v0, double v1) { + val = new double[] { v0, v1, 0, 0 }; + } + + public Scalar(double v0) { + val = new double[] { v0, 0, 0, 0 }; + } + + public Scalar(double[] vals) { + if (vals != null && vals.length == 4) + val = vals.clone(); + else { + val = new double[4]; + set(vals); + } + } + + public void set(double[] vals) { + if (vals != null) { + val[0] = vals.length > 0 ? vals[0] : 0; + val[1] = vals.length > 1 ? vals[1] : 0; + val[2] = vals.length > 2 ? vals[2] : 0; + val[3] = vals.length > 3 ? vals[3] : 0; + } else + val[0] = val[1] = val[2] = val[3] = 0; + } + + public static Scalar all(double v) { + return new Scalar(v, v, v, v); + } + + public Scalar clone() { + return new Scalar(val); + } + + public Scalar mul(Scalar it, double scale) { + return new Scalar(val[0] * it.val[0] * scale, val[1] * it.val[1] * scale, + val[2] * it.val[2] * scale, val[3] * it.val[3] * scale); + } + + public Scalar mul(Scalar it) { + return mul(it, 1); + } + + public Scalar conj() { + return new Scalar(val[0], -val[1], -val[2], -val[3]); + } + + public boolean isReal() { + return val[1] == 0 && val[2] == 0 && val[3] == 0; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + java.util.Arrays.hashCode(val); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof Scalar)) return false; + Scalar it = (Scalar) obj; + if (!java.util.Arrays.equals(val, it.val)) return false; + return true; + } + + @Override + public String toString() { + return "[" + val[0] + ", " + val[1] + ", " + val[2] + ", " + val[3] + "]"; + } + +} diff --git a/OpenCV/src/main/java/org/opencv/core/Size.java b/OpenCV/src/main/java/org/opencv/core/Size.java new file mode 100644 index 00000000..f7d69f37 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/Size.java @@ -0,0 +1,73 @@ +package org.opencv.core; + +//javadoc:Size_ +public class Size { + + public double width, height; + + public Size(double width, double height) { + this.width = width; + this.height = height; + } + + public Size() { + this(0, 0); + } + + public Size(Point p) { + width = p.x; + height = p.y; + } + + public Size(double[] vals) { + set(vals); + } + + public void set(double[] vals) { + if (vals != null) { + width = vals.length > 0 ? vals[0] : 0; + height = vals.length > 1 ? vals[1] : 0; + } else { + width = 0; + height = 0; + } + } + + public double area() { + return width * height; + } + + public boolean empty() { + return width <= 0 || height <= 0; + } + + public Size clone() { + return new Size(width, height); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(height); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(width); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof Size)) return false; + Size it = (Size) obj; + return width == it.width && height == it.height; + } + + @Override + public String toString() { + return (int)width + "x" + (int)height; + } + +} diff --git a/OpenCV/src/main/java/org/opencv/core/TermCriteria.java b/OpenCV/src/main/java/org/opencv/core/TermCriteria.java new file mode 100644 index 00000000..c67e51ea --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/TermCriteria.java @@ -0,0 +1,92 @@ +package org.opencv.core; + +//javadoc:TermCriteria +public class TermCriteria { + + /** + * The maximum number of iterations or elements to compute + */ + public static final int COUNT = 1; + /** + * The maximum number of iterations or elements to compute + */ + public static final int MAX_ITER = COUNT; + /** + * The desired accuracy threshold or change in parameters at which the iterative algorithm is terminated. + */ + public static final int EPS = 2; + + public int type; + public int maxCount; + public double epsilon; + + /** + * Termination criteria for iterative algorithms. + * + * @param type + * the type of termination criteria: COUNT, EPS or COUNT + EPS. + * @param maxCount + * the maximum number of iterations/elements. + * @param epsilon + * the desired accuracy. + */ + public TermCriteria(int type, int maxCount, double epsilon) { + this.type = type; + this.maxCount = maxCount; + this.epsilon = epsilon; + } + + /** + * Termination criteria for iterative algorithms. + */ + public TermCriteria() { + this(0, 0, 0.0); + } + + public TermCriteria(double[] vals) { + set(vals); + } + + public void set(double[] vals) { + if (vals != null) { + type = vals.length > 0 ? (int) vals[0] : 0; + maxCount = vals.length > 1 ? (int) vals[1] : 0; + epsilon = vals.length > 2 ? (double) vals[2] : 0; + } else { + type = 0; + maxCount = 0; + epsilon = 0; + } + } + + public TermCriteria clone() { + return new TermCriteria(type, maxCount, epsilon); + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + long temp; + temp = Double.doubleToLongBits(type); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(maxCount); + result = prime * result + (int) (temp ^ (temp >>> 32)); + temp = Double.doubleToLongBits(epsilon); + result = prime * result + (int) (temp ^ (temp >>> 32)); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof TermCriteria)) return false; + TermCriteria it = (TermCriteria) obj; + return type == it.type && maxCount == it.maxCount && epsilon == it.epsilon; + } + + @Override + public String toString() { + return "{ type: " + type + ", maxCount: " + maxCount + ", epsilon: " + epsilon + "}"; + } +} diff --git a/OpenCV/src/main/java/org/opencv/core/TickMeter.java b/OpenCV/src/main/java/org/opencv/core/TickMeter.java new file mode 100644 index 00000000..1ad728d9 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/core/TickMeter.java @@ -0,0 +1,184 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.core; + + + +// C++: class TickMeter +//javadoc: TickMeter + +public class TickMeter { + + protected final long nativeObj; + protected TickMeter(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static TickMeter __fromPtr__(long addr) { return new TickMeter(addr); } + + // + // C++: cv::TickMeter::TickMeter() + // + + //javadoc: TickMeter::TickMeter() + public TickMeter() + { + + nativeObj = TickMeter_0(); + + return; + } + + + // + // C++: double cv::TickMeter::getTimeMicro() + // + + //javadoc: TickMeter::getTimeMicro() + public double getTimeMicro() + { + + double retVal = getTimeMicro_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::TickMeter::getTimeMilli() + // + + //javadoc: TickMeter::getTimeMilli() + public double getTimeMilli() + { + + double retVal = getTimeMilli_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::TickMeter::getTimeSec() + // + + //javadoc: TickMeter::getTimeSec() + public double getTimeSec() + { + + double retVal = getTimeSec_0(nativeObj); + + return retVal; + } + + + // + // C++: int64 cv::TickMeter::getCounter() + // + + //javadoc: TickMeter::getCounter() + public long getCounter() + { + + long retVal = getCounter_0(nativeObj); + + return retVal; + } + + + // + // C++: int64 cv::TickMeter::getTimeTicks() + // + + //javadoc: TickMeter::getTimeTicks() + public long getTimeTicks() + { + + long retVal = getTimeTicks_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::TickMeter::reset() + // + + //javadoc: TickMeter::reset() + public void reset() + { + + reset_0(nativeObj); + + return; + } + + + // + // C++: void cv::TickMeter::start() + // + + //javadoc: TickMeter::start() + public void start() + { + + start_0(nativeObj); + + return; + } + + + // + // C++: void cv::TickMeter::stop() + // + + //javadoc: TickMeter::stop() + public void stop() + { + + stop_0(nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: cv::TickMeter::TickMeter() + private static native long TickMeter_0(); + + // C++: double cv::TickMeter::getTimeMicro() + private static native double getTimeMicro_0(long nativeObj); + + // C++: double cv::TickMeter::getTimeMilli() + private static native double getTimeMilli_0(long nativeObj); + + // C++: double cv::TickMeter::getTimeSec() + private static native double getTimeSec_0(long nativeObj); + + // C++: int64 cv::TickMeter::getCounter() + private static native long getCounter_0(long nativeObj); + + // C++: int64 cv::TickMeter::getTimeTicks() + private static native long getTimeTicks_0(long nativeObj); + + // C++: void cv::TickMeter::reset() + private static native void reset_0(long nativeObj); + + // C++: void cv::TickMeter::start() + private static native void start_0(long nativeObj); + + // C++: void cv::TickMeter::stop() + private static native void stop_0(long nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/dnn/DictValue.java b/OpenCV/src/main/java/org/opencv/dnn/DictValue.java new file mode 100644 index 00000000..194429ad --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/dnn/DictValue.java @@ -0,0 +1,214 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.dnn; + +import java.lang.String; + +// C++: class DictValue +//javadoc: DictValue + +public class DictValue { + + protected final long nativeObj; + protected DictValue(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static DictValue __fromPtr__(long addr) { return new DictValue(addr); } + + // + // C++: cv::dnn::DictValue::DictValue(String s) + // + + //javadoc: DictValue::DictValue(s) + public DictValue(String s) + { + + nativeObj = DictValue_0(s); + + return; + } + + + // + // C++: cv::dnn::DictValue::DictValue(double p) + // + + //javadoc: DictValue::DictValue(p) + public DictValue(double p) + { + + nativeObj = DictValue_1(p); + + return; + } + + + // + // C++: cv::dnn::DictValue::DictValue(int i) + // + + //javadoc: DictValue::DictValue(i) + public DictValue(int i) + { + + nativeObj = DictValue_2(i); + + return; + } + + + // + // C++: String cv::dnn::DictValue::getStringValue(int idx = -1) + // + + //javadoc: DictValue::getStringValue(idx) + public String getStringValue(int idx) + { + + String retVal = getStringValue_0(nativeObj, idx); + + return retVal; + } + + //javadoc: DictValue::getStringValue() + public String getStringValue() + { + + String retVal = getStringValue_1(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::dnn::DictValue::isInt() + // + + //javadoc: DictValue::isInt() + public boolean isInt() + { + + boolean retVal = isInt_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::dnn::DictValue::isReal() + // + + //javadoc: DictValue::isReal() + public boolean isReal() + { + + boolean retVal = isReal_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::dnn::DictValue::isString() + // + + //javadoc: DictValue::isString() + public boolean isString() + { + + boolean retVal = isString_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::dnn::DictValue::getRealValue(int idx = -1) + // + + //javadoc: DictValue::getRealValue(idx) + public double getRealValue(int idx) + { + + double retVal = getRealValue_0(nativeObj, idx); + + return retVal; + } + + //javadoc: DictValue::getRealValue() + public double getRealValue() + { + + double retVal = getRealValue_1(nativeObj); + + return retVal; + } + + + // + // C++: int cv::dnn::DictValue::getIntValue(int idx = -1) + // + + //javadoc: DictValue::getIntValue(idx) + public int getIntValue(int idx) + { + + int retVal = getIntValue_0(nativeObj, idx); + + return retVal; + } + + //javadoc: DictValue::getIntValue() + public int getIntValue() + { + + int retVal = getIntValue_1(nativeObj); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: cv::dnn::DictValue::DictValue(String s) + private static native long DictValue_0(String s); + + // C++: cv::dnn::DictValue::DictValue(double p) + private static native long DictValue_1(double p); + + // C++: cv::dnn::DictValue::DictValue(int i) + private static native long DictValue_2(int i); + + // C++: String cv::dnn::DictValue::getStringValue(int idx = -1) + private static native String getStringValue_0(long nativeObj, int idx); + private static native String getStringValue_1(long nativeObj); + + // C++: bool cv::dnn::DictValue::isInt() + private static native boolean isInt_0(long nativeObj); + + // C++: bool cv::dnn::DictValue::isReal() + private static native boolean isReal_0(long nativeObj); + + // C++: bool cv::dnn::DictValue::isString() + private static native boolean isString_0(long nativeObj); + + // C++: double cv::dnn::DictValue::getRealValue(int idx = -1) + private static native double getRealValue_0(long nativeObj, int idx); + private static native double getRealValue_1(long nativeObj); + + // C++: int cv::dnn::DictValue::getIntValue(int idx = -1) + private static native int getIntValue_0(long nativeObj, int idx); + private static native int getIntValue_1(long nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/dnn/Dnn.java b/OpenCV/src/main/java/org/opencv/dnn/Dnn.java new file mode 100644 index 00000000..65106d19 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/dnn/Dnn.java @@ -0,0 +1,788 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.dnn; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfByte; +import org.opencv.core.MatOfFloat; +import org.opencv.core.MatOfInt; +import org.opencv.core.MatOfRect; +import org.opencv.core.MatOfRect2d; +import org.opencv.core.MatOfRotatedRect; +import org.opencv.core.Scalar; +import org.opencv.core.Size; +import org.opencv.dnn.Net; +import org.opencv.utils.Converters; + +// C++: class Dnn +//javadoc: Dnn + +public class Dnn { + + // C++: enum Backend + public static final int + DNN_BACKEND_DEFAULT = 0, + DNN_BACKEND_HALIDE = 1, + DNN_BACKEND_INFERENCE_ENGINE = 2, + DNN_BACKEND_OPENCV = 3, + DNN_BACKEND_VKCOM = 4; + + + // C++: enum Target + public static final int + DNN_TARGET_CPU = 0, + DNN_TARGET_OPENCL = 1, + DNN_TARGET_OPENCL_FP16 = 2, + DNN_TARGET_MYRIAD = 3, + DNN_TARGET_VULKAN = 4, + DNN_TARGET_FPGA = 5; + + + // + // C++: Mat cv::dnn::blobFromImage(Mat image, double scalefactor = 1.0, Size size = Size(), Scalar mean = Scalar(), bool swapRB = false, bool crop = false, int ddepth = CV_32F) + // + + //javadoc: blobFromImage(image, scalefactor, size, mean, swapRB, crop, ddepth) + public static Mat blobFromImage(Mat image, double scalefactor, Size size, Scalar mean, boolean swapRB, boolean crop, int ddepth) + { + + Mat retVal = new Mat(blobFromImage_0(image.nativeObj, scalefactor, size.width, size.height, mean.val[0], mean.val[1], mean.val[2], mean.val[3], swapRB, crop, ddepth)); + + return retVal; + } + + //javadoc: blobFromImage(image, scalefactor, size, mean, swapRB, crop) + public static Mat blobFromImage(Mat image, double scalefactor, Size size, Scalar mean, boolean swapRB, boolean crop) + { + + Mat retVal = new Mat(blobFromImage_1(image.nativeObj, scalefactor, size.width, size.height, mean.val[0], mean.val[1], mean.val[2], mean.val[3], swapRB, crop)); + + return retVal; + } + + //javadoc: blobFromImage(image, scalefactor, size, mean, swapRB) + public static Mat blobFromImage(Mat image, double scalefactor, Size size, Scalar mean, boolean swapRB) + { + + Mat retVal = new Mat(blobFromImage_2(image.nativeObj, scalefactor, size.width, size.height, mean.val[0], mean.val[1], mean.val[2], mean.val[3], swapRB)); + + return retVal; + } + + //javadoc: blobFromImage(image, scalefactor, size, mean) + public static Mat blobFromImage(Mat image, double scalefactor, Size size, Scalar mean) + { + + Mat retVal = new Mat(blobFromImage_3(image.nativeObj, scalefactor, size.width, size.height, mean.val[0], mean.val[1], mean.val[2], mean.val[3])); + + return retVal; + } + + //javadoc: blobFromImage(image, scalefactor, size) + public static Mat blobFromImage(Mat image, double scalefactor, Size size) + { + + Mat retVal = new Mat(blobFromImage_4(image.nativeObj, scalefactor, size.width, size.height)); + + return retVal; + } + + //javadoc: blobFromImage(image, scalefactor) + public static Mat blobFromImage(Mat image, double scalefactor) + { + + Mat retVal = new Mat(blobFromImage_5(image.nativeObj, scalefactor)); + + return retVal; + } + + //javadoc: blobFromImage(image) + public static Mat blobFromImage(Mat image) + { + + Mat retVal = new Mat(blobFromImage_6(image.nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::dnn::blobFromImages(vector_Mat images, double scalefactor = 1.0, Size size = Size(), Scalar mean = Scalar(), bool swapRB = false, bool crop = false, int ddepth = CV_32F) + // + + //javadoc: blobFromImages(images, scalefactor, size, mean, swapRB, crop, ddepth) + public static Mat blobFromImages(List images, double scalefactor, Size size, Scalar mean, boolean swapRB, boolean crop, int ddepth) + { + Mat images_mat = Converters.vector_Mat_to_Mat(images); + Mat retVal = new Mat(blobFromImages_0(images_mat.nativeObj, scalefactor, size.width, size.height, mean.val[0], mean.val[1], mean.val[2], mean.val[3], swapRB, crop, ddepth)); + + return retVal; + } + + //javadoc: blobFromImages(images, scalefactor, size, mean, swapRB, crop) + public static Mat blobFromImages(List images, double scalefactor, Size size, Scalar mean, boolean swapRB, boolean crop) + { + Mat images_mat = Converters.vector_Mat_to_Mat(images); + Mat retVal = new Mat(blobFromImages_1(images_mat.nativeObj, scalefactor, size.width, size.height, mean.val[0], mean.val[1], mean.val[2], mean.val[3], swapRB, crop)); + + return retVal; + } + + //javadoc: blobFromImages(images, scalefactor, size, mean, swapRB) + public static Mat blobFromImages(List images, double scalefactor, Size size, Scalar mean, boolean swapRB) + { + Mat images_mat = Converters.vector_Mat_to_Mat(images); + Mat retVal = new Mat(blobFromImages_2(images_mat.nativeObj, scalefactor, size.width, size.height, mean.val[0], mean.val[1], mean.val[2], mean.val[3], swapRB)); + + return retVal; + } + + //javadoc: blobFromImages(images, scalefactor, size, mean) + public static Mat blobFromImages(List images, double scalefactor, Size size, Scalar mean) + { + Mat images_mat = Converters.vector_Mat_to_Mat(images); + Mat retVal = new Mat(blobFromImages_3(images_mat.nativeObj, scalefactor, size.width, size.height, mean.val[0], mean.val[1], mean.val[2], mean.val[3])); + + return retVal; + } + + //javadoc: blobFromImages(images, scalefactor, size) + public static Mat blobFromImages(List images, double scalefactor, Size size) + { + Mat images_mat = Converters.vector_Mat_to_Mat(images); + Mat retVal = new Mat(blobFromImages_4(images_mat.nativeObj, scalefactor, size.width, size.height)); + + return retVal; + } + + //javadoc: blobFromImages(images, scalefactor) + public static Mat blobFromImages(List images, double scalefactor) + { + Mat images_mat = Converters.vector_Mat_to_Mat(images); + Mat retVal = new Mat(blobFromImages_5(images_mat.nativeObj, scalefactor)); + + return retVal; + } + + //javadoc: blobFromImages(images) + public static Mat blobFromImages(List images) + { + Mat images_mat = Converters.vector_Mat_to_Mat(images); + Mat retVal = new Mat(blobFromImages_6(images_mat.nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::dnn::readTensorFromONNX(String path) + // + + //javadoc: readTensorFromONNX(path) + public static Mat readTensorFromONNX(String path) + { + + Mat retVal = new Mat(readTensorFromONNX_0(path)); + + return retVal; + } + + + // + // C++: Mat cv::dnn::readTorchBlob(String filename, bool isBinary = true) + // + + //javadoc: readTorchBlob(filename, isBinary) + public static Mat readTorchBlob(String filename, boolean isBinary) + { + + Mat retVal = new Mat(readTorchBlob_0(filename, isBinary)); + + return retVal; + } + + //javadoc: readTorchBlob(filename) + public static Mat readTorchBlob(String filename) + { + + Mat retVal = new Mat(readTorchBlob_1(filename)); + + return retVal; + } + + + // + // C++: Net cv::dnn::readNet(String framework, vector_uchar bufferModel, vector_uchar bufferConfig = std::vector()) + // + + //javadoc: readNet(framework, bufferModel, bufferConfig) + public static Net readNet(String framework, MatOfByte bufferModel, MatOfByte bufferConfig) + { + Mat bufferModel_mat = bufferModel; + Mat bufferConfig_mat = bufferConfig; + Net retVal = new Net(readNet_0(framework, bufferModel_mat.nativeObj, bufferConfig_mat.nativeObj)); + + return retVal; + } + + //javadoc: readNet(framework, bufferModel) + public static Net readNet(String framework, MatOfByte bufferModel) + { + Mat bufferModel_mat = bufferModel; + Net retVal = new Net(readNet_1(framework, bufferModel_mat.nativeObj)); + + return retVal; + } + + + // + // C++: Net cv::dnn::readNet(String model, String config = "", String framework = "") + // + + //javadoc: readNet(model, config, framework) + public static Net readNet(String model, String config, String framework) + { + + Net retVal = new Net(readNet_2(model, config, framework)); + + return retVal; + } + + //javadoc: readNet(model, config) + public static Net readNet(String model, String config) + { + + Net retVal = new Net(readNet_3(model, config)); + + return retVal; + } + + //javadoc: readNet(model) + public static Net readNet(String model) + { + + Net retVal = new Net(readNet_4(model)); + + return retVal; + } + + + // + // C++: Net cv::dnn::readNetFromCaffe(String prototxt, String caffeModel = String()) + // + + //javadoc: readNetFromCaffe(prototxt, caffeModel) + public static Net readNetFromCaffe(String prototxt, String caffeModel) + { + + Net retVal = new Net(readNetFromCaffe_0(prototxt, caffeModel)); + + return retVal; + } + + //javadoc: readNetFromCaffe(prototxt) + public static Net readNetFromCaffe(String prototxt) + { + + Net retVal = new Net(readNetFromCaffe_1(prototxt)); + + return retVal; + } + + + // + // C++: Net cv::dnn::readNetFromCaffe(vector_uchar bufferProto, vector_uchar bufferModel = std::vector()) + // + + //javadoc: readNetFromCaffe(bufferProto, bufferModel) + public static Net readNetFromCaffe(MatOfByte bufferProto, MatOfByte bufferModel) + { + Mat bufferProto_mat = bufferProto; + Mat bufferModel_mat = bufferModel; + Net retVal = new Net(readNetFromCaffe_2(bufferProto_mat.nativeObj, bufferModel_mat.nativeObj)); + + return retVal; + } + + //javadoc: readNetFromCaffe(bufferProto) + public static Net readNetFromCaffe(MatOfByte bufferProto) + { + Mat bufferProto_mat = bufferProto; + Net retVal = new Net(readNetFromCaffe_3(bufferProto_mat.nativeObj)); + + return retVal; + } + + + // + // C++: Net cv::dnn::readNetFromDarknet(String cfgFile, String darknetModel = String()) + // + + //javadoc: readNetFromDarknet(cfgFile, darknetModel) + public static Net readNetFromDarknet(String cfgFile, String darknetModel) + { + + Net retVal = new Net(readNetFromDarknet_0(cfgFile, darknetModel)); + + return retVal; + } + + //javadoc: readNetFromDarknet(cfgFile) + public static Net readNetFromDarknet(String cfgFile) + { + + Net retVal = new Net(readNetFromDarknet_1(cfgFile)); + + return retVal; + } + + + // + // C++: Net cv::dnn::readNetFromDarknet(vector_uchar bufferCfg, vector_uchar bufferModel = std::vector()) + // + + //javadoc: readNetFromDarknet(bufferCfg, bufferModel) + public static Net readNetFromDarknet(MatOfByte bufferCfg, MatOfByte bufferModel) + { + Mat bufferCfg_mat = bufferCfg; + Mat bufferModel_mat = bufferModel; + Net retVal = new Net(readNetFromDarknet_2(bufferCfg_mat.nativeObj, bufferModel_mat.nativeObj)); + + return retVal; + } + + //javadoc: readNetFromDarknet(bufferCfg) + public static Net readNetFromDarknet(MatOfByte bufferCfg) + { + Mat bufferCfg_mat = bufferCfg; + Net retVal = new Net(readNetFromDarknet_3(bufferCfg_mat.nativeObj)); + + return retVal; + } + + + // + // C++: Net cv::dnn::readNetFromModelOptimizer(String xml, String bin) + // + + //javadoc: readNetFromModelOptimizer(xml, bin) + public static Net readNetFromModelOptimizer(String xml, String bin) + { + + Net retVal = new Net(readNetFromModelOptimizer_0(xml, bin)); + + return retVal; + } + + + // + // C++: Net cv::dnn::readNetFromONNX(String onnxFile) + // + + //javadoc: readNetFromONNX(onnxFile) + public static Net readNetFromONNX(String onnxFile) + { + + Net retVal = new Net(readNetFromONNX_0(onnxFile)); + + return retVal; + } + + + // + // C++: Net cv::dnn::readNetFromONNX(vector_uchar buffer) + // + + //javadoc: readNetFromONNX(buffer) + public static Net readNetFromONNX(MatOfByte buffer) + { + Mat buffer_mat = buffer; + Net retVal = new Net(readNetFromONNX_1(buffer_mat.nativeObj)); + + return retVal; + } + + + // + // C++: Net cv::dnn::readNetFromTensorflow(String model, String config = String()) + // + + //javadoc: readNetFromTensorflow(model, config) + public static Net readNetFromTensorflow(String model, String config) + { + + Net retVal = new Net(readNetFromTensorflow_0(model, config)); + + return retVal; + } + + //javadoc: readNetFromTensorflow(model) + public static Net readNetFromTensorflow(String model) + { + + Net retVal = new Net(readNetFromTensorflow_1(model)); + + return retVal; + } + + + // + // C++: Net cv::dnn::readNetFromTensorflow(vector_uchar bufferModel, vector_uchar bufferConfig = std::vector()) + // + + //javadoc: readNetFromTensorflow(bufferModel, bufferConfig) + public static Net readNetFromTensorflow(MatOfByte bufferModel, MatOfByte bufferConfig) + { + Mat bufferModel_mat = bufferModel; + Mat bufferConfig_mat = bufferConfig; + Net retVal = new Net(readNetFromTensorflow_2(bufferModel_mat.nativeObj, bufferConfig_mat.nativeObj)); + + return retVal; + } + + //javadoc: readNetFromTensorflow(bufferModel) + public static Net readNetFromTensorflow(MatOfByte bufferModel) + { + Mat bufferModel_mat = bufferModel; + Net retVal = new Net(readNetFromTensorflow_3(bufferModel_mat.nativeObj)); + + return retVal; + } + + + // + // C++: Net cv::dnn::readNetFromTorch(String model, bool isBinary = true, bool evaluate = true) + // + + //javadoc: readNetFromTorch(model, isBinary, evaluate) + public static Net readNetFromTorch(String model, boolean isBinary, boolean evaluate) + { + + Net retVal = new Net(readNetFromTorch_0(model, isBinary, evaluate)); + + return retVal; + } + + //javadoc: readNetFromTorch(model, isBinary) + public static Net readNetFromTorch(String model, boolean isBinary) + { + + Net retVal = new Net(readNetFromTorch_1(model, isBinary)); + + return retVal; + } + + //javadoc: readNetFromTorch(model) + public static Net readNetFromTorch(String model) + { + + Net retVal = new Net(readNetFromTorch_2(model)); + + return retVal; + } + + + // + // C++: String cv::dnn::getInferenceEngineVPUType() + // + + //javadoc: getInferenceEngineVPUType() + public static String getInferenceEngineVPUType() + { + + String retVal = getInferenceEngineVPUType_0(); + + return retVal; + } + + + // + // C++: void cv::dnn::NMSBoxes(vector_Rect bboxes, vector_float scores, float score_threshold, float nms_threshold, vector_int& indices, float eta = 1.f, int top_k = 0) + // + + //javadoc: NMSBoxes(bboxes, scores, score_threshold, nms_threshold, indices, eta, top_k) + public static void NMSBoxes(MatOfRect bboxes, MatOfFloat scores, float score_threshold, float nms_threshold, MatOfInt indices, float eta, int top_k) + { + Mat bboxes_mat = bboxes; + Mat scores_mat = scores; + Mat indices_mat = indices; + NMSBoxes_0(bboxes_mat.nativeObj, scores_mat.nativeObj, score_threshold, nms_threshold, indices_mat.nativeObj, eta, top_k); + + return; + } + + //javadoc: NMSBoxes(bboxes, scores, score_threshold, nms_threshold, indices, eta) + public static void NMSBoxes(MatOfRect bboxes, MatOfFloat scores, float score_threshold, float nms_threshold, MatOfInt indices, float eta) + { + Mat bboxes_mat = bboxes; + Mat scores_mat = scores; + Mat indices_mat = indices; + NMSBoxes_1(bboxes_mat.nativeObj, scores_mat.nativeObj, score_threshold, nms_threshold, indices_mat.nativeObj, eta); + + return; + } + + //javadoc: NMSBoxes(bboxes, scores, score_threshold, nms_threshold, indices) + public static void NMSBoxes(MatOfRect bboxes, MatOfFloat scores, float score_threshold, float nms_threshold, MatOfInt indices) + { + Mat bboxes_mat = bboxes; + Mat scores_mat = scores; + Mat indices_mat = indices; + NMSBoxes_2(bboxes_mat.nativeObj, scores_mat.nativeObj, score_threshold, nms_threshold, indices_mat.nativeObj); + + return; + } + + + // + // C++: void cv::dnn::NMSBoxes(vector_Rect2d bboxes, vector_float scores, float score_threshold, float nms_threshold, vector_int& indices, float eta = 1.f, int top_k = 0) + // + + //javadoc: NMSBoxes(bboxes, scores, score_threshold, nms_threshold, indices, eta, top_k) + public static void NMSBoxes(MatOfRect2d bboxes, MatOfFloat scores, float score_threshold, float nms_threshold, MatOfInt indices, float eta, int top_k) + { + Mat bboxes_mat = bboxes; + Mat scores_mat = scores; + Mat indices_mat = indices; + NMSBoxes_3(bboxes_mat.nativeObj, scores_mat.nativeObj, score_threshold, nms_threshold, indices_mat.nativeObj, eta, top_k); + + return; + } + + //javadoc: NMSBoxes(bboxes, scores, score_threshold, nms_threshold, indices, eta) + public static void NMSBoxes(MatOfRect2d bboxes, MatOfFloat scores, float score_threshold, float nms_threshold, MatOfInt indices, float eta) + { + Mat bboxes_mat = bboxes; + Mat scores_mat = scores; + Mat indices_mat = indices; + NMSBoxes_4(bboxes_mat.nativeObj, scores_mat.nativeObj, score_threshold, nms_threshold, indices_mat.nativeObj, eta); + + return; + } + + //javadoc: NMSBoxes(bboxes, scores, score_threshold, nms_threshold, indices) + public static void NMSBoxes(MatOfRect2d bboxes, MatOfFloat scores, float score_threshold, float nms_threshold, MatOfInt indices) + { + Mat bboxes_mat = bboxes; + Mat scores_mat = scores; + Mat indices_mat = indices; + NMSBoxes_5(bboxes_mat.nativeObj, scores_mat.nativeObj, score_threshold, nms_threshold, indices_mat.nativeObj); + + return; + } + + + // + // C++: void cv::dnn::NMSBoxes(vector_RotatedRect bboxes, vector_float scores, float score_threshold, float nms_threshold, vector_int& indices, float eta = 1.f, int top_k = 0) + // + + //javadoc: NMSBoxesRotated(bboxes, scores, score_threshold, nms_threshold, indices, eta, top_k) + public static void NMSBoxesRotated(MatOfRotatedRect bboxes, MatOfFloat scores, float score_threshold, float nms_threshold, MatOfInt indices, float eta, int top_k) + { + Mat bboxes_mat = bboxes; + Mat scores_mat = scores; + Mat indices_mat = indices; + NMSBoxesRotated_0(bboxes_mat.nativeObj, scores_mat.nativeObj, score_threshold, nms_threshold, indices_mat.nativeObj, eta, top_k); + + return; + } + + //javadoc: NMSBoxesRotated(bboxes, scores, score_threshold, nms_threshold, indices, eta) + public static void NMSBoxesRotated(MatOfRotatedRect bboxes, MatOfFloat scores, float score_threshold, float nms_threshold, MatOfInt indices, float eta) + { + Mat bboxes_mat = bboxes; + Mat scores_mat = scores; + Mat indices_mat = indices; + NMSBoxesRotated_1(bboxes_mat.nativeObj, scores_mat.nativeObj, score_threshold, nms_threshold, indices_mat.nativeObj, eta); + + return; + } + + //javadoc: NMSBoxesRotated(bboxes, scores, score_threshold, nms_threshold, indices) + public static void NMSBoxesRotated(MatOfRotatedRect bboxes, MatOfFloat scores, float score_threshold, float nms_threshold, MatOfInt indices) + { + Mat bboxes_mat = bboxes; + Mat scores_mat = scores; + Mat indices_mat = indices; + NMSBoxesRotated_2(bboxes_mat.nativeObj, scores_mat.nativeObj, score_threshold, nms_threshold, indices_mat.nativeObj); + + return; + } + + + // + // C++: void cv::dnn::imagesFromBlob(Mat blob_, vector_Mat& images_) + // + + //javadoc: imagesFromBlob(blob_, images_) + public static void imagesFromBlob(Mat blob_, List images_) + { + Mat images__mat = new Mat(); + imagesFromBlob_0(blob_.nativeObj, images__mat.nativeObj); + Converters.Mat_to_vector_Mat(images__mat, images_); + images__mat.release(); + return; + } + + + // + // C++: void cv::dnn::resetMyriadDevice() + // + + //javadoc: resetMyriadDevice() + public static void resetMyriadDevice() + { + + resetMyriadDevice_0(); + + return; + } + + + // + // C++: void cv::dnn::shrinkCaffeModel(String src, String dst, vector_String layersTypes = std::vector()) + // + + //javadoc: shrinkCaffeModel(src, dst, layersTypes) + public static void shrinkCaffeModel(String src, String dst, List layersTypes) + { + + shrinkCaffeModel_0(src, dst, layersTypes); + + return; + } + + //javadoc: shrinkCaffeModel(src, dst) + public static void shrinkCaffeModel(String src, String dst) + { + + shrinkCaffeModel_1(src, dst); + + return; + } + + + // + // C++: void cv::dnn::writeTextGraph(String model, String output) + // + + //javadoc: writeTextGraph(model, output) + public static void writeTextGraph(String model, String output) + { + + writeTextGraph_0(model, output); + + return; + } + + + + + // C++: Mat cv::dnn::blobFromImage(Mat image, double scalefactor = 1.0, Size size = Size(), Scalar mean = Scalar(), bool swapRB = false, bool crop = false, int ddepth = CV_32F) + private static native long blobFromImage_0(long image_nativeObj, double scalefactor, double size_width, double size_height, double mean_val0, double mean_val1, double mean_val2, double mean_val3, boolean swapRB, boolean crop, int ddepth); + private static native long blobFromImage_1(long image_nativeObj, double scalefactor, double size_width, double size_height, double mean_val0, double mean_val1, double mean_val2, double mean_val3, boolean swapRB, boolean crop); + private static native long blobFromImage_2(long image_nativeObj, double scalefactor, double size_width, double size_height, double mean_val0, double mean_val1, double mean_val2, double mean_val3, boolean swapRB); + private static native long blobFromImage_3(long image_nativeObj, double scalefactor, double size_width, double size_height, double mean_val0, double mean_val1, double mean_val2, double mean_val3); + private static native long blobFromImage_4(long image_nativeObj, double scalefactor, double size_width, double size_height); + private static native long blobFromImage_5(long image_nativeObj, double scalefactor); + private static native long blobFromImage_6(long image_nativeObj); + + // C++: Mat cv::dnn::blobFromImages(vector_Mat images, double scalefactor = 1.0, Size size = Size(), Scalar mean = Scalar(), bool swapRB = false, bool crop = false, int ddepth = CV_32F) + private static native long blobFromImages_0(long images_mat_nativeObj, double scalefactor, double size_width, double size_height, double mean_val0, double mean_val1, double mean_val2, double mean_val3, boolean swapRB, boolean crop, int ddepth); + private static native long blobFromImages_1(long images_mat_nativeObj, double scalefactor, double size_width, double size_height, double mean_val0, double mean_val1, double mean_val2, double mean_val3, boolean swapRB, boolean crop); + private static native long blobFromImages_2(long images_mat_nativeObj, double scalefactor, double size_width, double size_height, double mean_val0, double mean_val1, double mean_val2, double mean_val3, boolean swapRB); + private static native long blobFromImages_3(long images_mat_nativeObj, double scalefactor, double size_width, double size_height, double mean_val0, double mean_val1, double mean_val2, double mean_val3); + private static native long blobFromImages_4(long images_mat_nativeObj, double scalefactor, double size_width, double size_height); + private static native long blobFromImages_5(long images_mat_nativeObj, double scalefactor); + private static native long blobFromImages_6(long images_mat_nativeObj); + + // C++: Mat cv::dnn::readTensorFromONNX(String path) + private static native long readTensorFromONNX_0(String path); + + // C++: Mat cv::dnn::readTorchBlob(String filename, bool isBinary = true) + private static native long readTorchBlob_0(String filename, boolean isBinary); + private static native long readTorchBlob_1(String filename); + + // C++: Net cv::dnn::readNet(String framework, vector_uchar bufferModel, vector_uchar bufferConfig = std::vector()) + private static native long readNet_0(String framework, long bufferModel_mat_nativeObj, long bufferConfig_mat_nativeObj); + private static native long readNet_1(String framework, long bufferModel_mat_nativeObj); + + // C++: Net cv::dnn::readNet(String model, String config = "", String framework = "") + private static native long readNet_2(String model, String config, String framework); + private static native long readNet_3(String model, String config); + private static native long readNet_4(String model); + + // C++: Net cv::dnn::readNetFromCaffe(String prototxt, String caffeModel = String()) + private static native long readNetFromCaffe_0(String prototxt, String caffeModel); + private static native long readNetFromCaffe_1(String prototxt); + + // C++: Net cv::dnn::readNetFromCaffe(vector_uchar bufferProto, vector_uchar bufferModel = std::vector()) + private static native long readNetFromCaffe_2(long bufferProto_mat_nativeObj, long bufferModel_mat_nativeObj); + private static native long readNetFromCaffe_3(long bufferProto_mat_nativeObj); + + // C++: Net cv::dnn::readNetFromDarknet(String cfgFile, String darknetModel = String()) + private static native long readNetFromDarknet_0(String cfgFile, String darknetModel); + private static native long readNetFromDarknet_1(String cfgFile); + + // C++: Net cv::dnn::readNetFromDarknet(vector_uchar bufferCfg, vector_uchar bufferModel = std::vector()) + private static native long readNetFromDarknet_2(long bufferCfg_mat_nativeObj, long bufferModel_mat_nativeObj); + private static native long readNetFromDarknet_3(long bufferCfg_mat_nativeObj); + + // C++: Net cv::dnn::readNetFromModelOptimizer(String xml, String bin) + private static native long readNetFromModelOptimizer_0(String xml, String bin); + + // C++: Net cv::dnn::readNetFromONNX(String onnxFile) + private static native long readNetFromONNX_0(String onnxFile); + + // C++: Net cv::dnn::readNetFromONNX(vector_uchar buffer) + private static native long readNetFromONNX_1(long buffer_mat_nativeObj); + + // C++: Net cv::dnn::readNetFromTensorflow(String model, String config = String()) + private static native long readNetFromTensorflow_0(String model, String config); + private static native long readNetFromTensorflow_1(String model); + + // C++: Net cv::dnn::readNetFromTensorflow(vector_uchar bufferModel, vector_uchar bufferConfig = std::vector()) + private static native long readNetFromTensorflow_2(long bufferModel_mat_nativeObj, long bufferConfig_mat_nativeObj); + private static native long readNetFromTensorflow_3(long bufferModel_mat_nativeObj); + + // C++: Net cv::dnn::readNetFromTorch(String model, bool isBinary = true, bool evaluate = true) + private static native long readNetFromTorch_0(String model, boolean isBinary, boolean evaluate); + private static native long readNetFromTorch_1(String model, boolean isBinary); + private static native long readNetFromTorch_2(String model); + + // C++: String cv::dnn::getInferenceEngineVPUType() + private static native String getInferenceEngineVPUType_0(); + + // C++: void cv::dnn::NMSBoxes(vector_Rect bboxes, vector_float scores, float score_threshold, float nms_threshold, vector_int& indices, float eta = 1.f, int top_k = 0) + private static native void NMSBoxes_0(long bboxes_mat_nativeObj, long scores_mat_nativeObj, float score_threshold, float nms_threshold, long indices_mat_nativeObj, float eta, int top_k); + private static native void NMSBoxes_1(long bboxes_mat_nativeObj, long scores_mat_nativeObj, float score_threshold, float nms_threshold, long indices_mat_nativeObj, float eta); + private static native void NMSBoxes_2(long bboxes_mat_nativeObj, long scores_mat_nativeObj, float score_threshold, float nms_threshold, long indices_mat_nativeObj); + + // C++: void cv::dnn::NMSBoxes(vector_Rect2d bboxes, vector_float scores, float score_threshold, float nms_threshold, vector_int& indices, float eta = 1.f, int top_k = 0) + private static native void NMSBoxes_3(long bboxes_mat_nativeObj, long scores_mat_nativeObj, float score_threshold, float nms_threshold, long indices_mat_nativeObj, float eta, int top_k); + private static native void NMSBoxes_4(long bboxes_mat_nativeObj, long scores_mat_nativeObj, float score_threshold, float nms_threshold, long indices_mat_nativeObj, float eta); + private static native void NMSBoxes_5(long bboxes_mat_nativeObj, long scores_mat_nativeObj, float score_threshold, float nms_threshold, long indices_mat_nativeObj); + + // C++: void cv::dnn::NMSBoxes(vector_RotatedRect bboxes, vector_float scores, float score_threshold, float nms_threshold, vector_int& indices, float eta = 1.f, int top_k = 0) + private static native void NMSBoxesRotated_0(long bboxes_mat_nativeObj, long scores_mat_nativeObj, float score_threshold, float nms_threshold, long indices_mat_nativeObj, float eta, int top_k); + private static native void NMSBoxesRotated_1(long bboxes_mat_nativeObj, long scores_mat_nativeObj, float score_threshold, float nms_threshold, long indices_mat_nativeObj, float eta); + private static native void NMSBoxesRotated_2(long bboxes_mat_nativeObj, long scores_mat_nativeObj, float score_threshold, float nms_threshold, long indices_mat_nativeObj); + + // C++: void cv::dnn::imagesFromBlob(Mat blob_, vector_Mat& images_) + private static native void imagesFromBlob_0(long blob__nativeObj, long images__mat_nativeObj); + + // C++: void cv::dnn::resetMyriadDevice() + private static native void resetMyriadDevice_0(); + + // C++: void cv::dnn::shrinkCaffeModel(String src, String dst, vector_String layersTypes = std::vector()) + private static native void shrinkCaffeModel_0(String src, String dst, List layersTypes); + private static native void shrinkCaffeModel_1(String src, String dst); + + // C++: void cv::dnn::writeTextGraph(String model, String output) + private static native void writeTextGraph_0(String model, String output); + +} diff --git a/OpenCV/src/main/java/org/opencv/dnn/Layer.java b/OpenCV/src/main/java/org/opencv/dnn/Layer.java new file mode 100644 index 00000000..e1384c68 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/dnn/Layer.java @@ -0,0 +1,177 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.dnn; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.utils.Converters; + +// C++: class Layer +//javadoc: Layer + +public class Layer extends Algorithm { + + protected Layer(long addr) { super(addr); } + + // internal usage only + public static Layer __fromPtr__(long addr) { return new Layer(addr); } + + // + // C++: int cv::dnn::Layer::outputNameToIndex(String outputName) + // + + //javadoc: Layer::outputNameToIndex(outputName) + public int outputNameToIndex(String outputName) + { + + int retVal = outputNameToIndex_0(nativeObj, outputName); + + return retVal; + } + + + // + // C++: void cv::dnn::Layer::finalize(vector_Mat inputs, vector_Mat& outputs) + // + + //javadoc: Layer::finalize(inputs, outputs) + public void finalize(List inputs, List outputs) + { + Mat inputs_mat = Converters.vector_Mat_to_Mat(inputs); + Mat outputs_mat = new Mat(); + finalize_0(nativeObj, inputs_mat.nativeObj, outputs_mat.nativeObj); + Converters.Mat_to_vector_Mat(outputs_mat, outputs); + outputs_mat.release(); + return; + } + + + // + // C++: void cv::dnn::Layer::run(vector_Mat inputs, vector_Mat& outputs, vector_Mat& internals) + // + + //javadoc: Layer::run(inputs, outputs, internals) + @Deprecated + public void run(List inputs, List outputs, List internals) + { + Mat inputs_mat = Converters.vector_Mat_to_Mat(inputs); + Mat outputs_mat = new Mat(); + Mat internals_mat = Converters.vector_Mat_to_Mat(internals); + run_0(nativeObj, inputs_mat.nativeObj, outputs_mat.nativeObj, internals_mat.nativeObj); + Converters.Mat_to_vector_Mat(outputs_mat, outputs); + outputs_mat.release(); + Converters.Mat_to_vector_Mat(internals_mat, internals); + internals_mat.release(); + return; + } + + + // + // C++: vector_Mat Layer::blobs + // + + //javadoc: Layer::get_blobs() + public List get_blobs() + { + List retVal = new ArrayList(); + Mat retValMat = new Mat(get_blobs_0(nativeObj)); + Converters.Mat_to_vector_Mat(retValMat, retVal); + return retVal; + } + + + // + // C++: void Layer::blobs + // + + //javadoc: Layer::set_blobs(blobs) + public void set_blobs(List blobs) + { + Mat blobs_mat = Converters.vector_Mat_to_Mat(blobs); + set_blobs_0(nativeObj, blobs_mat.nativeObj); + + return; + } + + + // + // C++: String Layer::name + // + + //javadoc: Layer::get_name() + public String get_name() + { + + String retVal = get_name_0(nativeObj); + + return retVal; + } + + + // + // C++: String Layer::type + // + + //javadoc: Layer::get_type() + public String get_type() + { + + String retVal = get_type_0(nativeObj); + + return retVal; + } + + + // + // C++: int Layer::preferableTarget + // + + //javadoc: Layer::get_preferableTarget() + public int get_preferableTarget() + { + + int retVal = get_preferableTarget_0(nativeObj); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: int cv::dnn::Layer::outputNameToIndex(String outputName) + private static native int outputNameToIndex_0(long nativeObj, String outputName); + + // C++: void cv::dnn::Layer::finalize(vector_Mat inputs, vector_Mat& outputs) + private static native void finalize_0(long nativeObj, long inputs_mat_nativeObj, long outputs_mat_nativeObj); + + // C++: void cv::dnn::Layer::run(vector_Mat inputs, vector_Mat& outputs, vector_Mat& internals) + private static native void run_0(long nativeObj, long inputs_mat_nativeObj, long outputs_mat_nativeObj, long internals_mat_nativeObj); + + // C++: vector_Mat Layer::blobs + private static native long get_blobs_0(long nativeObj); + + // C++: void Layer::blobs + private static native void set_blobs_0(long nativeObj, long blobs_mat_nativeObj); + + // C++: String Layer::name + private static native String get_name_0(long nativeObj); + + // C++: String Layer::type + private static native String get_type_0(long nativeObj); + + // C++: int Layer::preferableTarget + private static native int get_preferableTarget_0(long nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/dnn/Net.java b/OpenCV/src/main/java/org/opencv/dnn/Net.java new file mode 100644 index 00000000..e9f69801 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/dnn/Net.java @@ -0,0 +1,684 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.dnn; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfDouble; +import org.opencv.core.MatOfInt; +import org.opencv.core.Scalar; +import org.opencv.dnn.DictValue; +import org.opencv.dnn.Layer; +import org.opencv.dnn.Net; +import org.opencv.utils.Converters; + +// C++: class Net +//javadoc: Net + +public class Net { + + protected final long nativeObj; + protected Net(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static Net __fromPtr__(long addr) { return new Net(addr); } + + // + // C++: cv::dnn::Net::Net() + // + + //javadoc: Net::Net() + public Net() + { + + nativeObj = Net_0(); + + return; + } + + + // + // C++: AsyncMat cv::dnn::Net::forwardAsync(String outputName = String()) + // + + // Return type 'AsyncMat' is not supported, skipping the function + + + // + // C++: Mat cv::dnn::Net::forward(String outputName = String()) + // + + //javadoc: Net::forward(outputName) + public Mat forward(String outputName) + { + + Mat retVal = new Mat(forward_0(nativeObj, outputName)); + + return retVal; + } + + //javadoc: Net::forward() + public Mat forward() + { + + Mat retVal = new Mat(forward_1(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::dnn::Net::getParam(LayerId layer, int numParam = 0) + // + + //javadoc: Net::getParam(layer, numParam) + public Mat getParam(DictValue layer, int numParam) + { + + Mat retVal = new Mat(getParam_0(nativeObj, layer.getNativeObjAddr(), numParam)); + + return retVal; + } + + //javadoc: Net::getParam(layer) + public Mat getParam(DictValue layer) + { + + Mat retVal = new Mat(getParam_1(nativeObj, layer.getNativeObjAddr())); + + return retVal; + } + + + // + // C++: static Net cv::dnn::Net::readFromModelOptimizer(String xml, String bin) + // + + //javadoc: Net::readFromModelOptimizer(xml, bin) + public static Net readFromModelOptimizer(String xml, String bin) + { + + Net retVal = new Net(readFromModelOptimizer_0(xml, bin)); + + return retVal; + } + + + // + // C++: Ptr_Layer cv::dnn::Net::getLayer(LayerId layerId) + // + + //javadoc: Net::getLayer(layerId) + public Layer getLayer(DictValue layerId) + { + + Layer retVal = Layer.__fromPtr__(getLayer_0(nativeObj, layerId.getNativeObjAddr())); + + return retVal; + } + + + // + // C++: String cv::dnn::Net::dump() + // + + //javadoc: Net::dump() + public String dump() + { + + String retVal = dump_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::dnn::Net::empty() + // + + //javadoc: Net::empty() + public boolean empty() + { + + boolean retVal = empty_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::dnn::Net::getLayerId(String layer) + // + + //javadoc: Net::getLayerId(layer) + public int getLayerId(String layer) + { + + int retVal = getLayerId_0(nativeObj, layer); + + return retVal; + } + + + // + // C++: int cv::dnn::Net::getLayersCount(String layerType) + // + + //javadoc: Net::getLayersCount(layerType) + public int getLayersCount(String layerType) + { + + int retVal = getLayersCount_0(nativeObj, layerType); + + return retVal; + } + + + // + // C++: int64 cv::dnn::Net::getFLOPS(MatShape netInputShape) + // + + //javadoc: Net::getFLOPS(netInputShape) + public long getFLOPS(MatOfInt netInputShape) + { + Mat netInputShape_mat = netInputShape; + long retVal = getFLOPS_0(nativeObj, netInputShape_mat.nativeObj); + + return retVal; + } + + + // + // C++: int64 cv::dnn::Net::getFLOPS(int layerId, MatShape netInputShape) + // + + //javadoc: Net::getFLOPS(layerId, netInputShape) + public long getFLOPS(int layerId, MatOfInt netInputShape) + { + Mat netInputShape_mat = netInputShape; + long retVal = getFLOPS_1(nativeObj, layerId, netInputShape_mat.nativeObj); + + return retVal; + } + + + // + // C++: int64 cv::dnn::Net::getFLOPS(int layerId, vector_MatShape netInputShapes) + // + + //javadoc: Net::getFLOPS(layerId, netInputShapes) + public long getFLOPS(int layerId, List netInputShapes) + { + + long retVal = getFLOPS_2(nativeObj, layerId, netInputShapes); + + return retVal; + } + + + // + // C++: int64 cv::dnn::Net::getFLOPS(vector_MatShape netInputShapes) + // + + //javadoc: Net::getFLOPS(netInputShapes) + public long getFLOPS(List netInputShapes) + { + + long retVal = getFLOPS_3(nativeObj, netInputShapes); + + return retVal; + } + + + // + // C++: int64 cv::dnn::Net::getPerfProfile(vector_double& timings) + // + + //javadoc: Net::getPerfProfile(timings) + public long getPerfProfile(MatOfDouble timings) + { + Mat timings_mat = timings; + long retVal = getPerfProfile_0(nativeObj, timings_mat.nativeObj); + + return retVal; + } + + + // + // C++: vector_String cv::dnn::Net::getLayerNames() + // + + //javadoc: Net::getLayerNames() + public List getLayerNames() + { + + List retVal = getLayerNames_0(nativeObj); + + return retVal; + } + + + // + // C++: vector_String cv::dnn::Net::getUnconnectedOutLayersNames() + // + + //javadoc: Net::getUnconnectedOutLayersNames() + public List getUnconnectedOutLayersNames() + { + + List retVal = getUnconnectedOutLayersNames_0(nativeObj); + + return retVal; + } + + + // + // C++: vector_int cv::dnn::Net::getUnconnectedOutLayers() + // + + //javadoc: Net::getUnconnectedOutLayers() + public MatOfInt getUnconnectedOutLayers() + { + + MatOfInt retVal = MatOfInt.fromNativeAddr(getUnconnectedOutLayers_0(nativeObj)); + + return retVal; + } + + + // + // C++: void cv::dnn::Net::connect(String outPin, String inpPin) + // + + //javadoc: Net::connect(outPin, inpPin) + public void connect(String outPin, String inpPin) + { + + connect_0(nativeObj, outPin, inpPin); + + return; + } + + + // + // C++: void cv::dnn::Net::dumpToFile(String path) + // + + //javadoc: Net::dumpToFile(path) + public void dumpToFile(String path) + { + + dumpToFile_0(nativeObj, path); + + return; + } + + + // + // C++: void cv::dnn::Net::enableFusion(bool fusion) + // + + //javadoc: Net::enableFusion(fusion) + public void enableFusion(boolean fusion) + { + + enableFusion_0(nativeObj, fusion); + + return; + } + + + // + // C++: void cv::dnn::Net::forward(vector_Mat& outputBlobs, String outputName = String()) + // + + //javadoc: Net::forward(outputBlobs, outputName) + public void forward(List outputBlobs, String outputName) + { + Mat outputBlobs_mat = new Mat(); + forward_2(nativeObj, outputBlobs_mat.nativeObj, outputName); + Converters.Mat_to_vector_Mat(outputBlobs_mat, outputBlobs); + outputBlobs_mat.release(); + return; + } + + //javadoc: Net::forward(outputBlobs) + public void forward(List outputBlobs) + { + Mat outputBlobs_mat = new Mat(); + forward_3(nativeObj, outputBlobs_mat.nativeObj); + Converters.Mat_to_vector_Mat(outputBlobs_mat, outputBlobs); + outputBlobs_mat.release(); + return; + } + + + // + // C++: void cv::dnn::Net::forward(vector_Mat& outputBlobs, vector_String outBlobNames) + // + + //javadoc: Net::forward(outputBlobs, outBlobNames) + public void forward(List outputBlobs, List outBlobNames) + { + Mat outputBlobs_mat = new Mat(); + forward_4(nativeObj, outputBlobs_mat.nativeObj, outBlobNames); + Converters.Mat_to_vector_Mat(outputBlobs_mat, outputBlobs); + outputBlobs_mat.release(); + return; + } + + + // + // C++: void cv::dnn::Net::forward(vector_vector_Mat& outputBlobs, vector_String outBlobNames) + // + + // Unknown type 'vector_vector_Mat' (O), skipping the function + + + // + // C++: void cv::dnn::Net::getLayerTypes(vector_String& layersTypes) + // + + //javadoc: Net::getLayerTypes(layersTypes) + public void getLayerTypes(List layersTypes) + { + + getLayerTypes_0(nativeObj, layersTypes); + + return; + } + + + // + // C++: void cv::dnn::Net::getLayersShapes(MatShape netInputShape, vector_int& layersIds, vector_vector_MatShape& inLayersShapes, vector_vector_MatShape& outLayersShapes) + // + + // Unknown type 'vector_vector_MatShape' (O), skipping the function + + + // + // C++: void cv::dnn::Net::getLayersShapes(vector_MatShape netInputShapes, vector_int& layersIds, vector_vector_MatShape& inLayersShapes, vector_vector_MatShape& outLayersShapes) + // + + // Unknown type 'vector_vector_MatShape' (O), skipping the function + + + // + // C++: void cv::dnn::Net::getMemoryConsumption(MatShape netInputShape, size_t& weights, size_t& blobs) + // + + //javadoc: Net::getMemoryConsumption(netInputShape, weights, blobs) + public void getMemoryConsumption(MatOfInt netInputShape, long[] weights, long[] blobs) + { + Mat netInputShape_mat = netInputShape; + double[] weights_out = new double[1]; + double[] blobs_out = new double[1]; + getMemoryConsumption_0(nativeObj, netInputShape_mat.nativeObj, weights_out, blobs_out); + if(weights!=null) weights[0] = (long)weights_out[0]; + if(blobs!=null) blobs[0] = (long)blobs_out[0]; + return; + } + + + // + // C++: void cv::dnn::Net::getMemoryConsumption(int layerId, MatShape netInputShape, size_t& weights, size_t& blobs) + // + + //javadoc: Net::getMemoryConsumption(layerId, netInputShape, weights, blobs) + public void getMemoryConsumption(int layerId, MatOfInt netInputShape, long[] weights, long[] blobs) + { + Mat netInputShape_mat = netInputShape; + double[] weights_out = new double[1]; + double[] blobs_out = new double[1]; + getMemoryConsumption_1(nativeObj, layerId, netInputShape_mat.nativeObj, weights_out, blobs_out); + if(weights!=null) weights[0] = (long)weights_out[0]; + if(blobs!=null) blobs[0] = (long)blobs_out[0]; + return; + } + + + // + // C++: void cv::dnn::Net::getMemoryConsumption(int layerId, vector_MatShape netInputShapes, size_t& weights, size_t& blobs) + // + + //javadoc: Net::getMemoryConsumption(layerId, netInputShapes, weights, blobs) + public void getMemoryConsumption(int layerId, List netInputShapes, long[] weights, long[] blobs) + { + double[] weights_out = new double[1]; + double[] blobs_out = new double[1]; + getMemoryConsumption_2(nativeObj, layerId, netInputShapes, weights_out, blobs_out); + if(weights!=null) weights[0] = (long)weights_out[0]; + if(blobs!=null) blobs[0] = (long)blobs_out[0]; + return; + } + + + // + // C++: void cv::dnn::Net::setHalideScheduler(String scheduler) + // + + //javadoc: Net::setHalideScheduler(scheduler) + public void setHalideScheduler(String scheduler) + { + + setHalideScheduler_0(nativeObj, scheduler); + + return; + } + + + // + // C++: void cv::dnn::Net::setInput(Mat blob, String name = "", double scalefactor = 1.0, Scalar mean = Scalar()) + // + + //javadoc: Net::setInput(blob, name, scalefactor, mean) + public void setInput(Mat blob, String name, double scalefactor, Scalar mean) + { + + setInput_0(nativeObj, blob.nativeObj, name, scalefactor, mean.val[0], mean.val[1], mean.val[2], mean.val[3]); + + return; + } + + //javadoc: Net::setInput(blob, name, scalefactor) + public void setInput(Mat blob, String name, double scalefactor) + { + + setInput_1(nativeObj, blob.nativeObj, name, scalefactor); + + return; + } + + //javadoc: Net::setInput(blob, name) + public void setInput(Mat blob, String name) + { + + setInput_2(nativeObj, blob.nativeObj, name); + + return; + } + + //javadoc: Net::setInput(blob) + public void setInput(Mat blob) + { + + setInput_3(nativeObj, blob.nativeObj); + + return; + } + + + // + // C++: void cv::dnn::Net::setInputsNames(vector_String inputBlobNames) + // + + //javadoc: Net::setInputsNames(inputBlobNames) + public void setInputsNames(List inputBlobNames) + { + + setInputsNames_0(nativeObj, inputBlobNames); + + return; + } + + + // + // C++: void cv::dnn::Net::setParam(LayerId layer, int numParam, Mat blob) + // + + //javadoc: Net::setParam(layer, numParam, blob) + public void setParam(DictValue layer, int numParam, Mat blob) + { + + setParam_0(nativeObj, layer.getNativeObjAddr(), numParam, blob.nativeObj); + + return; + } + + + // + // C++: void cv::dnn::Net::setPreferableBackend(int backendId) + // + + //javadoc: Net::setPreferableBackend(backendId) + public void setPreferableBackend(int backendId) + { + + setPreferableBackend_0(nativeObj, backendId); + + return; + } + + + // + // C++: void cv::dnn::Net::setPreferableTarget(int targetId) + // + + //javadoc: Net::setPreferableTarget(targetId) + public void setPreferableTarget(int targetId) + { + + setPreferableTarget_0(nativeObj, targetId); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: cv::dnn::Net::Net() + private static native long Net_0(); + + // C++: Mat cv::dnn::Net::forward(String outputName = String()) + private static native long forward_0(long nativeObj, String outputName); + private static native long forward_1(long nativeObj); + + // C++: Mat cv::dnn::Net::getParam(LayerId layer, int numParam = 0) + private static native long getParam_0(long nativeObj, long layer_nativeObj, int numParam); + private static native long getParam_1(long nativeObj, long layer_nativeObj); + + // C++: static Net cv::dnn::Net::readFromModelOptimizer(String xml, String bin) + private static native long readFromModelOptimizer_0(String xml, String bin); + + // C++: Ptr_Layer cv::dnn::Net::getLayer(LayerId layerId) + private static native long getLayer_0(long nativeObj, long layerId_nativeObj); + + // C++: String cv::dnn::Net::dump() + private static native String dump_0(long nativeObj); + + // C++: bool cv::dnn::Net::empty() + private static native boolean empty_0(long nativeObj); + + // C++: int cv::dnn::Net::getLayerId(String layer) + private static native int getLayerId_0(long nativeObj, String layer); + + // C++: int cv::dnn::Net::getLayersCount(String layerType) + private static native int getLayersCount_0(long nativeObj, String layerType); + + // C++: int64 cv::dnn::Net::getFLOPS(MatShape netInputShape) + private static native long getFLOPS_0(long nativeObj, long netInputShape_mat_nativeObj); + + // C++: int64 cv::dnn::Net::getFLOPS(int layerId, MatShape netInputShape) + private static native long getFLOPS_1(long nativeObj, int layerId, long netInputShape_mat_nativeObj); + + // C++: int64 cv::dnn::Net::getFLOPS(int layerId, vector_MatShape netInputShapes) + private static native long getFLOPS_2(long nativeObj, int layerId, List netInputShapes); + + // C++: int64 cv::dnn::Net::getFLOPS(vector_MatShape netInputShapes) + private static native long getFLOPS_3(long nativeObj, List netInputShapes); + + // C++: int64 cv::dnn::Net::getPerfProfile(vector_double& timings) + private static native long getPerfProfile_0(long nativeObj, long timings_mat_nativeObj); + + // C++: vector_String cv::dnn::Net::getLayerNames() + private static native List getLayerNames_0(long nativeObj); + + // C++: vector_String cv::dnn::Net::getUnconnectedOutLayersNames() + private static native List getUnconnectedOutLayersNames_0(long nativeObj); + + // C++: vector_int cv::dnn::Net::getUnconnectedOutLayers() + private static native long getUnconnectedOutLayers_0(long nativeObj); + + // C++: void cv::dnn::Net::connect(String outPin, String inpPin) + private static native void connect_0(long nativeObj, String outPin, String inpPin); + + // C++: void cv::dnn::Net::dumpToFile(String path) + private static native void dumpToFile_0(long nativeObj, String path); + + // C++: void cv::dnn::Net::enableFusion(bool fusion) + private static native void enableFusion_0(long nativeObj, boolean fusion); + + // C++: void cv::dnn::Net::forward(vector_Mat& outputBlobs, String outputName = String()) + private static native void forward_2(long nativeObj, long outputBlobs_mat_nativeObj, String outputName); + private static native void forward_3(long nativeObj, long outputBlobs_mat_nativeObj); + + // C++: void cv::dnn::Net::forward(vector_Mat& outputBlobs, vector_String outBlobNames) + private static native void forward_4(long nativeObj, long outputBlobs_mat_nativeObj, List outBlobNames); + + // C++: void cv::dnn::Net::getLayerTypes(vector_String& layersTypes) + private static native void getLayerTypes_0(long nativeObj, List layersTypes); + + // C++: void cv::dnn::Net::getMemoryConsumption(MatShape netInputShape, size_t& weights, size_t& blobs) + private static native void getMemoryConsumption_0(long nativeObj, long netInputShape_mat_nativeObj, double[] weights_out, double[] blobs_out); + + // C++: void cv::dnn::Net::getMemoryConsumption(int layerId, MatShape netInputShape, size_t& weights, size_t& blobs) + private static native void getMemoryConsumption_1(long nativeObj, int layerId, long netInputShape_mat_nativeObj, double[] weights_out, double[] blobs_out); + + // C++: void cv::dnn::Net::getMemoryConsumption(int layerId, vector_MatShape netInputShapes, size_t& weights, size_t& blobs) + private static native void getMemoryConsumption_2(long nativeObj, int layerId, List netInputShapes, double[] weights_out, double[] blobs_out); + + // C++: void cv::dnn::Net::setHalideScheduler(String scheduler) + private static native void setHalideScheduler_0(long nativeObj, String scheduler); + + // C++: void cv::dnn::Net::setInput(Mat blob, String name = "", double scalefactor = 1.0, Scalar mean = Scalar()) + private static native void setInput_0(long nativeObj, long blob_nativeObj, String name, double scalefactor, double mean_val0, double mean_val1, double mean_val2, double mean_val3); + private static native void setInput_1(long nativeObj, long blob_nativeObj, String name, double scalefactor); + private static native void setInput_2(long nativeObj, long blob_nativeObj, String name); + private static native void setInput_3(long nativeObj, long blob_nativeObj); + + // C++: void cv::dnn::Net::setInputsNames(vector_String inputBlobNames) + private static native void setInputsNames_0(long nativeObj, List inputBlobNames); + + // C++: void cv::dnn::Net::setParam(LayerId layer, int numParam, Mat blob) + private static native void setParam_0(long nativeObj, long layer_nativeObj, int numParam, long blob_nativeObj); + + // C++: void cv::dnn::Net::setPreferableBackend(int backendId) + private static native void setPreferableBackend_0(long nativeObj, int backendId); + + // C++: void cv::dnn::Net::setPreferableTarget(int targetId) + private static native void setPreferableTarget_0(long nativeObj, int targetId); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/face/BIF.java b/OpenCV/src/main/java/org/opencv/face/BIF.java new file mode 100644 index 00000000..31ee6ee5 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/face/BIF.java @@ -0,0 +1,118 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.face; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.face.BIF; + +// C++: class BIF +//javadoc: BIF + +public class BIF extends Algorithm { + + protected BIF(long addr) { super(addr); } + + // internal usage only + public static BIF __fromPtr__(long addr) { return new BIF(addr); } + + // + // C++: static Ptr_BIF cv::face::BIF::create(int num_bands = 8, int num_rotations = 12) + // + + //javadoc: BIF::create(num_bands, num_rotations) + public static BIF create(int num_bands, int num_rotations) + { + + BIF retVal = BIF.__fromPtr__(create_0(num_bands, num_rotations)); + + return retVal; + } + + //javadoc: BIF::create(num_bands) + public static BIF create(int num_bands) + { + + BIF retVal = BIF.__fromPtr__(create_1(num_bands)); + + return retVal; + } + + //javadoc: BIF::create() + public static BIF create() + { + + BIF retVal = BIF.__fromPtr__(create_2()); + + return retVal; + } + + + // + // C++: int cv::face::BIF::getNumBands() + // + + //javadoc: BIF::getNumBands() + public int getNumBands() + { + + int retVal = getNumBands_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::face::BIF::getNumRotations() + // + + //javadoc: BIF::getNumRotations() + public int getNumRotations() + { + + int retVal = getNumRotations_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::face::BIF::compute(Mat image, Mat& features) + // + + //javadoc: BIF::compute(image, features) + public void compute(Mat image, Mat features) + { + + compute_0(nativeObj, image.nativeObj, features.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_BIF cv::face::BIF::create(int num_bands = 8, int num_rotations = 12) + private static native long create_0(int num_bands, int num_rotations); + private static native long create_1(int num_bands); + private static native long create_2(); + + // C++: int cv::face::BIF::getNumBands() + private static native int getNumBands_0(long nativeObj); + + // C++: int cv::face::BIF::getNumRotations() + private static native int getNumRotations_0(long nativeObj); + + // C++: void cv::face::BIF::compute(Mat image, Mat& features) + private static native void compute_0(long nativeObj, long image_nativeObj, long features_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/face/BasicFaceRecognizer.java b/OpenCV/src/main/java/org/opencv/face/BasicFaceRecognizer.java new file mode 100644 index 00000000..d196b5b5 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/face/BasicFaceRecognizer.java @@ -0,0 +1,185 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.face; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.face.FaceRecognizer; +import org.opencv.utils.Converters; + +// C++: class BasicFaceRecognizer +//javadoc: BasicFaceRecognizer + +public class BasicFaceRecognizer extends FaceRecognizer { + + protected BasicFaceRecognizer(long addr) { super(addr); } + + // internal usage only + public static BasicFaceRecognizer __fromPtr__(long addr) { return new BasicFaceRecognizer(addr); } + + // + // C++: Mat cv::face::BasicFaceRecognizer::getEigenValues() + // + + //javadoc: BasicFaceRecognizer::getEigenValues() + public Mat getEigenValues() + { + + Mat retVal = new Mat(getEigenValues_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::face::BasicFaceRecognizer::getEigenVectors() + // + + //javadoc: BasicFaceRecognizer::getEigenVectors() + public Mat getEigenVectors() + { + + Mat retVal = new Mat(getEigenVectors_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::face::BasicFaceRecognizer::getLabels() + // + + //javadoc: BasicFaceRecognizer::getLabels() + public Mat getLabels() + { + + Mat retVal = new Mat(getLabels_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::face::BasicFaceRecognizer::getMean() + // + + //javadoc: BasicFaceRecognizer::getMean() + public Mat getMean() + { + + Mat retVal = new Mat(getMean_0(nativeObj)); + + return retVal; + } + + + // + // C++: double cv::face::BasicFaceRecognizer::getThreshold() + // + + //javadoc: BasicFaceRecognizer::getThreshold() + public double getThreshold() + { + + double retVal = getThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::face::BasicFaceRecognizer::getNumComponents() + // + + //javadoc: BasicFaceRecognizer::getNumComponents() + public int getNumComponents() + { + + int retVal = getNumComponents_0(nativeObj); + + return retVal; + } + + + // + // C++: vector_Mat cv::face::BasicFaceRecognizer::getProjections() + // + + //javadoc: BasicFaceRecognizer::getProjections() + public List getProjections() + { + List retVal = new ArrayList(); + Mat retValMat = new Mat(getProjections_0(nativeObj)); + Converters.Mat_to_vector_Mat(retValMat, retVal); + return retVal; + } + + + // + // C++: void cv::face::BasicFaceRecognizer::setNumComponents(int val) + // + + //javadoc: BasicFaceRecognizer::setNumComponents(val) + public void setNumComponents(int val) + { + + setNumComponents_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::face::BasicFaceRecognizer::setThreshold(double val) + // + + //javadoc: BasicFaceRecognizer::setThreshold(val) + public void setThreshold(double val) + { + + setThreshold_0(nativeObj, val); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: Mat cv::face::BasicFaceRecognizer::getEigenValues() + private static native long getEigenValues_0(long nativeObj); + + // C++: Mat cv::face::BasicFaceRecognizer::getEigenVectors() + private static native long getEigenVectors_0(long nativeObj); + + // C++: Mat cv::face::BasicFaceRecognizer::getLabels() + private static native long getLabels_0(long nativeObj); + + // C++: Mat cv::face::BasicFaceRecognizer::getMean() + private static native long getMean_0(long nativeObj); + + // C++: double cv::face::BasicFaceRecognizer::getThreshold() + private static native double getThreshold_0(long nativeObj); + + // C++: int cv::face::BasicFaceRecognizer::getNumComponents() + private static native int getNumComponents_0(long nativeObj); + + // C++: vector_Mat cv::face::BasicFaceRecognizer::getProjections() + private static native long getProjections_0(long nativeObj); + + // C++: void cv::face::BasicFaceRecognizer::setNumComponents(int val) + private static native void setNumComponents_0(long nativeObj, int val); + + // C++: void cv::face::BasicFaceRecognizer::setThreshold(double val) + private static native void setThreshold_0(long nativeObj, double val); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/face/EigenFaceRecognizer.java b/OpenCV/src/main/java/org/opencv/face/EigenFaceRecognizer.java new file mode 100644 index 00000000..03546cd8 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/face/EigenFaceRecognizer.java @@ -0,0 +1,66 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.face; + +import org.opencv.face.BasicFaceRecognizer; +import org.opencv.face.EigenFaceRecognizer; + +// C++: class EigenFaceRecognizer +//javadoc: EigenFaceRecognizer + +public class EigenFaceRecognizer extends BasicFaceRecognizer { + + protected EigenFaceRecognizer(long addr) { super(addr); } + + // internal usage only + public static EigenFaceRecognizer __fromPtr__(long addr) { return new EigenFaceRecognizer(addr); } + + // + // C++: static Ptr_EigenFaceRecognizer cv::face::EigenFaceRecognizer::create(int num_components = 0, double threshold = DBL_MAX) + // + + //javadoc: EigenFaceRecognizer::create(num_components, threshold) + public static EigenFaceRecognizer create(int num_components, double threshold) + { + + EigenFaceRecognizer retVal = EigenFaceRecognizer.__fromPtr__(create_0(num_components, threshold)); + + return retVal; + } + + //javadoc: EigenFaceRecognizer::create(num_components) + public static EigenFaceRecognizer create(int num_components) + { + + EigenFaceRecognizer retVal = EigenFaceRecognizer.__fromPtr__(create_1(num_components)); + + return retVal; + } + + //javadoc: EigenFaceRecognizer::create() + public static EigenFaceRecognizer create() + { + + EigenFaceRecognizer retVal = EigenFaceRecognizer.__fromPtr__(create_2()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_EigenFaceRecognizer cv::face::EigenFaceRecognizer::create(int num_components = 0, double threshold = DBL_MAX) + private static native long create_0(int num_components, double threshold); + private static native long create_1(int num_components); + private static native long create_2(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/face/Face.java b/OpenCV/src/main/java/org/opencv/face/Face.java new file mode 100644 index 00000000..3c26fc73 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/face/Face.java @@ -0,0 +1,243 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.face; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfPoint2f; +import org.opencv.core.Scalar; +import org.opencv.face.Facemark; +import org.opencv.utils.Converters; + +// C++: class Face +//javadoc: Face + +public class Face { + + // + // C++: Ptr_Facemark cv::face::createFacemarkAAM() + // + + //javadoc: createFacemarkAAM() + public static Facemark createFacemarkAAM() + { + + Facemark retVal = Facemark.__fromPtr__(createFacemarkAAM_0()); + + return retVal; + } + + + // + // C++: Ptr_Facemark cv::face::createFacemarkKazemi() + // + + //javadoc: createFacemarkKazemi() + public static Facemark createFacemarkKazemi() + { + + Facemark retVal = Facemark.__fromPtr__(createFacemarkKazemi_0()); + + return retVal; + } + + + // + // C++: Ptr_Facemark cv::face::createFacemarkLBF() + // + + //javadoc: createFacemarkLBF() + public static Facemark createFacemarkLBF() + { + + Facemark retVal = Facemark.__fromPtr__(createFacemarkLBF_0()); + + return retVal; + } + + + // + // C++: bool cv::face::getFacesHAAR(Mat image, Mat& faces, String face_cascade_name) + // + + //javadoc: getFacesHAAR(image, faces, face_cascade_name) + public static boolean getFacesHAAR(Mat image, Mat faces, String face_cascade_name) + { + + boolean retVal = getFacesHAAR_0(image.nativeObj, faces.nativeObj, face_cascade_name); + + return retVal; + } + + + // + // C++: bool cv::face::loadDatasetList(String imageList, String annotationList, vector_String images, vector_String annotations) + // + + //javadoc: loadDatasetList(imageList, annotationList, images, annotations) + public static boolean loadDatasetList(String imageList, String annotationList, List images, List annotations) + { + + boolean retVal = loadDatasetList_0(imageList, annotationList, images, annotations); + + return retVal; + } + + + // + // C++: bool cv::face::loadFacePoints(String filename, Mat& points, float offset = 0.0f) + // + + //javadoc: loadFacePoints(filename, points, offset) + public static boolean loadFacePoints(String filename, Mat points, float offset) + { + + boolean retVal = loadFacePoints_0(filename, points.nativeObj, offset); + + return retVal; + } + + //javadoc: loadFacePoints(filename, points) + public static boolean loadFacePoints(String filename, Mat points) + { + + boolean retVal = loadFacePoints_1(filename, points.nativeObj); + + return retVal; + } + + + // + // C++: bool cv::face::loadTrainingData(String filename, vector_String images, Mat& facePoints, char delim = ' ', float offset = 0.0f) + // + + //javadoc: loadTrainingData(filename, images, facePoints, delim, offset) + public static boolean loadTrainingData(String filename, List images, Mat facePoints, char delim, float offset) + { + + boolean retVal = loadTrainingData_0(filename, images, facePoints.nativeObj, delim, offset); + + return retVal; + } + + //javadoc: loadTrainingData(filename, images, facePoints, delim) + public static boolean loadTrainingData(String filename, List images, Mat facePoints, char delim) + { + + boolean retVal = loadTrainingData_1(filename, images, facePoints.nativeObj, delim); + + return retVal; + } + + //javadoc: loadTrainingData(filename, images, facePoints) + public static boolean loadTrainingData(String filename, List images, Mat facePoints) + { + + boolean retVal = loadTrainingData_2(filename, images, facePoints.nativeObj); + + return retVal; + } + + + // + // C++: bool cv::face::loadTrainingData(String imageList, String groundTruth, vector_String images, Mat& facePoints, float offset = 0.0f) + // + + //javadoc: loadTrainingData(imageList, groundTruth, images, facePoints, offset) + public static boolean loadTrainingData(String imageList, String groundTruth, List images, Mat facePoints, float offset) + { + + boolean retVal = loadTrainingData_3(imageList, groundTruth, images, facePoints.nativeObj, offset); + + return retVal; + } + + //javadoc: loadTrainingData(imageList, groundTruth, images, facePoints) + public static boolean loadTrainingData(String imageList, String groundTruth, List images, Mat facePoints) + { + + boolean retVal = loadTrainingData_4(imageList, groundTruth, images, facePoints.nativeObj); + + return retVal; + } + + + // + // C++: bool cv::face::loadTrainingData(vector_String filename, vector_vector_Point2f trainlandmarks, vector_String trainimages) + // + + //javadoc: loadTrainingData(filename, trainlandmarks, trainimages) + public static boolean loadTrainingData(List filename, List trainlandmarks, List trainimages) + { + List trainlandmarks_tmplm = new ArrayList((trainlandmarks != null) ? trainlandmarks.size() : 0); + Mat trainlandmarks_mat = Converters.vector_vector_Point2f_to_Mat(trainlandmarks, trainlandmarks_tmplm); + boolean retVal = loadTrainingData_5(filename, trainlandmarks_mat.nativeObj, trainimages); + + return retVal; + } + + + // + // C++: void cv::face::drawFacemarks(Mat& image, Mat points, Scalar color = Scalar(255,0,0)) + // + + //javadoc: drawFacemarks(image, points, color) + public static void drawFacemarks(Mat image, Mat points, Scalar color) + { + + drawFacemarks_0(image.nativeObj, points.nativeObj, color.val[0], color.val[1], color.val[2], color.val[3]); + + return; + } + + //javadoc: drawFacemarks(image, points) + public static void drawFacemarks(Mat image, Mat points) + { + + drawFacemarks_1(image.nativeObj, points.nativeObj); + + return; + } + + + + + // C++: Ptr_Facemark cv::face::createFacemarkAAM() + private static native long createFacemarkAAM_0(); + + // C++: Ptr_Facemark cv::face::createFacemarkKazemi() + private static native long createFacemarkKazemi_0(); + + // C++: Ptr_Facemark cv::face::createFacemarkLBF() + private static native long createFacemarkLBF_0(); + + // C++: bool cv::face::getFacesHAAR(Mat image, Mat& faces, String face_cascade_name) + private static native boolean getFacesHAAR_0(long image_nativeObj, long faces_nativeObj, String face_cascade_name); + + // C++: bool cv::face::loadDatasetList(String imageList, String annotationList, vector_String images, vector_String annotations) + private static native boolean loadDatasetList_0(String imageList, String annotationList, List images, List annotations); + + // C++: bool cv::face::loadFacePoints(String filename, Mat& points, float offset = 0.0f) + private static native boolean loadFacePoints_0(String filename, long points_nativeObj, float offset); + private static native boolean loadFacePoints_1(String filename, long points_nativeObj); + + // C++: bool cv::face::loadTrainingData(String filename, vector_String images, Mat& facePoints, char delim = ' ', float offset = 0.0f) + private static native boolean loadTrainingData_0(String filename, List images, long facePoints_nativeObj, char delim, float offset); + private static native boolean loadTrainingData_1(String filename, List images, long facePoints_nativeObj, char delim); + private static native boolean loadTrainingData_2(String filename, List images, long facePoints_nativeObj); + + // C++: bool cv::face::loadTrainingData(String imageList, String groundTruth, vector_String images, Mat& facePoints, float offset = 0.0f) + private static native boolean loadTrainingData_3(String imageList, String groundTruth, List images, long facePoints_nativeObj, float offset); + private static native boolean loadTrainingData_4(String imageList, String groundTruth, List images, long facePoints_nativeObj); + + // C++: bool cv::face::loadTrainingData(vector_String filename, vector_vector_Point2f trainlandmarks, vector_String trainimages) + private static native boolean loadTrainingData_5(List filename, long trainlandmarks_mat_nativeObj, List trainimages); + + // C++: void cv::face::drawFacemarks(Mat& image, Mat points, Scalar color = Scalar(255,0,0)) + private static native void drawFacemarks_0(long image_nativeObj, long points_nativeObj, double color_val0, double color_val1, double color_val2, double color_val3); + private static native void drawFacemarks_1(long image_nativeObj, long points_nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/face/FaceRecognizer.java b/OpenCV/src/main/java/org/opencv/face/FaceRecognizer.java new file mode 100644 index 00000000..5a2471eb --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/face/FaceRecognizer.java @@ -0,0 +1,207 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.face; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.core.MatOfInt; +import org.opencv.face.PredictCollector; +import org.opencv.utils.Converters; + +// C++: class FaceRecognizer +//javadoc: FaceRecognizer + +public class FaceRecognizer extends Algorithm { + + protected FaceRecognizer(long addr) { super(addr); } + + // internal usage only + public static FaceRecognizer __fromPtr__(long addr) { return new FaceRecognizer(addr); } + + // + // C++: String cv::face::FaceRecognizer::getLabelInfo(int label) + // + + //javadoc: FaceRecognizer::getLabelInfo(label) + public String getLabelInfo(int label) + { + + String retVal = getLabelInfo_0(nativeObj, label); + + return retVal; + } + + + // + // C++: int cv::face::FaceRecognizer::predict(Mat src) + // + + //javadoc: FaceRecognizer::predict_label(src) + public int predict_label(Mat src) + { + + int retVal = predict_label_0(nativeObj, src.nativeObj); + + return retVal; + } + + + // + // C++: vector_int cv::face::FaceRecognizer::getLabelsByString(String str) + // + + //javadoc: FaceRecognizer::getLabelsByString(str) + public MatOfInt getLabelsByString(String str) + { + + MatOfInt retVal = MatOfInt.fromNativeAddr(getLabelsByString_0(nativeObj, str)); + + return retVal; + } + + + // + // C++: void cv::face::FaceRecognizer::predict(Mat src, Ptr_PredictCollector collector) + // + + //javadoc: FaceRecognizer::predict_collect(src, collector) + public void predict_collect(Mat src, PredictCollector collector) + { + + predict_collect_0(nativeObj, src.nativeObj, collector.getNativeObjAddr()); + + return; + } + + + // + // C++: void cv::face::FaceRecognizer::predict(Mat src, int& label, double& confidence) + // + + //javadoc: FaceRecognizer::predict(src, label, confidence) + public void predict(Mat src, int[] label, double[] confidence) + { + double[] label_out = new double[1]; + double[] confidence_out = new double[1]; + predict_0(nativeObj, src.nativeObj, label_out, confidence_out); + if(label!=null) label[0] = (int)label_out[0]; + if(confidence!=null) confidence[0] = (double)confidence_out[0]; + return; + } + + + // + // C++: void cv::face::FaceRecognizer::read(String filename) + // + + //javadoc: FaceRecognizer::read(filename) + public void read(String filename) + { + + read_0(nativeObj, filename); + + return; + } + + + // + // C++: void cv::face::FaceRecognizer::setLabelInfo(int label, String strInfo) + // + + //javadoc: FaceRecognizer::setLabelInfo(label, strInfo) + public void setLabelInfo(int label, String strInfo) + { + + setLabelInfo_0(nativeObj, label, strInfo); + + return; + } + + + // + // C++: void cv::face::FaceRecognizer::train(vector_Mat src, Mat labels) + // + + //javadoc: FaceRecognizer::train(src, labels) + public void train(List src, Mat labels) + { + Mat src_mat = Converters.vector_Mat_to_Mat(src); + train_0(nativeObj, src_mat.nativeObj, labels.nativeObj); + + return; + } + + + // + // C++: void cv::face::FaceRecognizer::update(vector_Mat src, Mat labels) + // + + //javadoc: FaceRecognizer::update(src, labels) + public void update(List src, Mat labels) + { + Mat src_mat = Converters.vector_Mat_to_Mat(src); + update_0(nativeObj, src_mat.nativeObj, labels.nativeObj); + + return; + } + + + // + // C++: void cv::face::FaceRecognizer::write(String filename) + // + + //javadoc: FaceRecognizer::write(filename) + public void write(String filename) + { + + write_0(nativeObj, filename); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: String cv::face::FaceRecognizer::getLabelInfo(int label) + private static native String getLabelInfo_0(long nativeObj, int label); + + // C++: int cv::face::FaceRecognizer::predict(Mat src) + private static native int predict_label_0(long nativeObj, long src_nativeObj); + + // C++: vector_int cv::face::FaceRecognizer::getLabelsByString(String str) + private static native long getLabelsByString_0(long nativeObj, String str); + + // C++: void cv::face::FaceRecognizer::predict(Mat src, Ptr_PredictCollector collector) + private static native void predict_collect_0(long nativeObj, long src_nativeObj, long collector_nativeObj); + + // C++: void cv::face::FaceRecognizer::predict(Mat src, int& label, double& confidence) + private static native void predict_0(long nativeObj, long src_nativeObj, double[] label_out, double[] confidence_out); + + // C++: void cv::face::FaceRecognizer::read(String filename) + private static native void read_0(long nativeObj, String filename); + + // C++: void cv::face::FaceRecognizer::setLabelInfo(int label, String strInfo) + private static native void setLabelInfo_0(long nativeObj, int label, String strInfo); + + // C++: void cv::face::FaceRecognizer::train(vector_Mat src, Mat labels) + private static native void train_0(long nativeObj, long src_mat_nativeObj, long labels_nativeObj); + + // C++: void cv::face::FaceRecognizer::update(vector_Mat src, Mat labels) + private static native void update_0(long nativeObj, long src_mat_nativeObj, long labels_nativeObj); + + // C++: void cv::face::FaceRecognizer::write(String filename) + private static native void write_0(long nativeObj, String filename); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/face/Facemark.java b/OpenCV/src/main/java/org/opencv/face/Facemark.java new file mode 100644 index 00000000..dcc633c5 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/face/Facemark.java @@ -0,0 +1,71 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.face; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.core.MatOfPoint2f; +import org.opencv.core.MatOfRect; +import org.opencv.utils.Converters; + +// C++: class Facemark +//javadoc: Facemark + +public class Facemark extends Algorithm { + + protected Facemark(long addr) { super(addr); } + + // internal usage only + public static Facemark __fromPtr__(long addr) { return new Facemark(addr); } + + // + // C++: bool cv::face::Facemark::fit(Mat image, vector_Rect faces, vector_vector_Point2f& landmarks) + // + + //javadoc: Facemark::fit(image, faces, landmarks) + public boolean fit(Mat image, MatOfRect faces, List landmarks) + { + Mat faces_mat = faces; + Mat landmarks_mat = new Mat(); + boolean retVal = fit_0(nativeObj, image.nativeObj, faces_mat.nativeObj, landmarks_mat.nativeObj); + Converters.Mat_to_vector_vector_Point2f(landmarks_mat, landmarks); + landmarks_mat.release(); + return retVal; + } + + + // + // C++: void cv::face::Facemark::loadModel(String model) + // + + //javadoc: Facemark::loadModel(model) + public void loadModel(String model) + { + + loadModel_0(nativeObj, model); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: bool cv::face::Facemark::fit(Mat image, vector_Rect faces, vector_vector_Point2f& landmarks) + private static native boolean fit_0(long nativeObj, long image_nativeObj, long faces_mat_nativeObj, long landmarks_mat_nativeObj); + + // C++: void cv::face::Facemark::loadModel(String model) + private static native void loadModel_0(long nativeObj, String model); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/face/FacemarkAAM.java b/OpenCV/src/main/java/org/opencv/face/FacemarkAAM.java new file mode 100644 index 00000000..f04e2a32 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/face/FacemarkAAM.java @@ -0,0 +1,28 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.face; + + + +// C++: class FacemarkAAM +//javadoc: FacemarkAAM + +public class FacemarkAAM extends FacemarkTrain { + + protected FacemarkAAM(long addr) { super(addr); } + + // internal usage only + public static FacemarkAAM __fromPtr__(long addr) { return new FacemarkAAM(addr); } + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/face/FacemarkKazemi.java b/OpenCV/src/main/java/org/opencv/face/FacemarkKazemi.java new file mode 100644 index 00000000..d46c486f --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/face/FacemarkKazemi.java @@ -0,0 +1,28 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.face; + + + +// C++: class FacemarkKazemi +//javadoc: FacemarkKazemi + +public class FacemarkKazemi extends Facemark { + + protected FacemarkKazemi(long addr) { super(addr); } + + // internal usage only + public static FacemarkKazemi __fromPtr__(long addr) { return new FacemarkKazemi(addr); } + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/face/FacemarkLBF.java b/OpenCV/src/main/java/org/opencv/face/FacemarkLBF.java new file mode 100644 index 00000000..48cb8645 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/face/FacemarkLBF.java @@ -0,0 +1,28 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.face; + + + +// C++: class FacemarkLBF +//javadoc: FacemarkLBF + +public class FacemarkLBF extends FacemarkTrain { + + protected FacemarkLBF(long addr) { super(addr); } + + // internal usage only + public static FacemarkLBF __fromPtr__(long addr) { return new FacemarkLBF(addr); } + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/face/FacemarkTrain.java b/OpenCV/src/main/java/org/opencv/face/FacemarkTrain.java new file mode 100644 index 00000000..5a9be687 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/face/FacemarkTrain.java @@ -0,0 +1,28 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.face; + +import org.opencv.face.Facemark; + +// C++: class FacemarkTrain +//javadoc: FacemarkTrain + +public class FacemarkTrain extends Facemark { + + protected FacemarkTrain(long addr) { super(addr); } + + // internal usage only + public static FacemarkTrain __fromPtr__(long addr) { return new FacemarkTrain(addr); } + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/face/FisherFaceRecognizer.java b/OpenCV/src/main/java/org/opencv/face/FisherFaceRecognizer.java new file mode 100644 index 00000000..c49d1112 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/face/FisherFaceRecognizer.java @@ -0,0 +1,66 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.face; + +import org.opencv.face.BasicFaceRecognizer; +import org.opencv.face.FisherFaceRecognizer; + +// C++: class FisherFaceRecognizer +//javadoc: FisherFaceRecognizer + +public class FisherFaceRecognizer extends BasicFaceRecognizer { + + protected FisherFaceRecognizer(long addr) { super(addr); } + + // internal usage only + public static FisherFaceRecognizer __fromPtr__(long addr) { return new FisherFaceRecognizer(addr); } + + // + // C++: static Ptr_FisherFaceRecognizer cv::face::FisherFaceRecognizer::create(int num_components = 0, double threshold = DBL_MAX) + // + + //javadoc: FisherFaceRecognizer::create(num_components, threshold) + public static FisherFaceRecognizer create(int num_components, double threshold) + { + + FisherFaceRecognizer retVal = FisherFaceRecognizer.__fromPtr__(create_0(num_components, threshold)); + + return retVal; + } + + //javadoc: FisherFaceRecognizer::create(num_components) + public static FisherFaceRecognizer create(int num_components) + { + + FisherFaceRecognizer retVal = FisherFaceRecognizer.__fromPtr__(create_1(num_components)); + + return retVal; + } + + //javadoc: FisherFaceRecognizer::create() + public static FisherFaceRecognizer create() + { + + FisherFaceRecognizer retVal = FisherFaceRecognizer.__fromPtr__(create_2()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_FisherFaceRecognizer cv::face::FisherFaceRecognizer::create(int num_components = 0, double threshold = DBL_MAX) + private static native long create_0(int num_components, double threshold); + private static native long create_1(int num_components); + private static native long create_2(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/face/LBPHFaceRecognizer.java b/OpenCV/src/main/java/org/opencv/face/LBPHFaceRecognizer.java new file mode 100644 index 00000000..0a91d3cd --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/face/LBPHFaceRecognizer.java @@ -0,0 +1,304 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.face; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.face.FaceRecognizer; +import org.opencv.face.LBPHFaceRecognizer; +import org.opencv.utils.Converters; + +// C++: class LBPHFaceRecognizer +//javadoc: LBPHFaceRecognizer + +public class LBPHFaceRecognizer extends FaceRecognizer { + + protected LBPHFaceRecognizer(long addr) { super(addr); } + + // internal usage only + public static LBPHFaceRecognizer __fromPtr__(long addr) { return new LBPHFaceRecognizer(addr); } + + // + // C++: Mat cv::face::LBPHFaceRecognizer::getLabels() + // + + //javadoc: LBPHFaceRecognizer::getLabels() + public Mat getLabels() + { + + Mat retVal = new Mat(getLabels_0(nativeObj)); + + return retVal; + } + + + // + // C++: static Ptr_LBPHFaceRecognizer cv::face::LBPHFaceRecognizer::create(int radius = 1, int neighbors = 8, int grid_x = 8, int grid_y = 8, double threshold = DBL_MAX) + // + + //javadoc: LBPHFaceRecognizer::create(radius, neighbors, grid_x, grid_y, threshold) + public static LBPHFaceRecognizer create(int radius, int neighbors, int grid_x, int grid_y, double threshold) + { + + LBPHFaceRecognizer retVal = LBPHFaceRecognizer.__fromPtr__(create_0(radius, neighbors, grid_x, grid_y, threshold)); + + return retVal; + } + + //javadoc: LBPHFaceRecognizer::create(radius, neighbors, grid_x, grid_y) + public static LBPHFaceRecognizer create(int radius, int neighbors, int grid_x, int grid_y) + { + + LBPHFaceRecognizer retVal = LBPHFaceRecognizer.__fromPtr__(create_1(radius, neighbors, grid_x, grid_y)); + + return retVal; + } + + //javadoc: LBPHFaceRecognizer::create(radius, neighbors, grid_x) + public static LBPHFaceRecognizer create(int radius, int neighbors, int grid_x) + { + + LBPHFaceRecognizer retVal = LBPHFaceRecognizer.__fromPtr__(create_2(radius, neighbors, grid_x)); + + return retVal; + } + + //javadoc: LBPHFaceRecognizer::create(radius, neighbors) + public static LBPHFaceRecognizer create(int radius, int neighbors) + { + + LBPHFaceRecognizer retVal = LBPHFaceRecognizer.__fromPtr__(create_3(radius, neighbors)); + + return retVal; + } + + //javadoc: LBPHFaceRecognizer::create(radius) + public static LBPHFaceRecognizer create(int radius) + { + + LBPHFaceRecognizer retVal = LBPHFaceRecognizer.__fromPtr__(create_4(radius)); + + return retVal; + } + + //javadoc: LBPHFaceRecognizer::create() + public static LBPHFaceRecognizer create() + { + + LBPHFaceRecognizer retVal = LBPHFaceRecognizer.__fromPtr__(create_5()); + + return retVal; + } + + + // + // C++: double cv::face::LBPHFaceRecognizer::getThreshold() + // + + //javadoc: LBPHFaceRecognizer::getThreshold() + public double getThreshold() + { + + double retVal = getThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::face::LBPHFaceRecognizer::getGridX() + // + + //javadoc: LBPHFaceRecognizer::getGridX() + public int getGridX() + { + + int retVal = getGridX_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::face::LBPHFaceRecognizer::getGridY() + // + + //javadoc: LBPHFaceRecognizer::getGridY() + public int getGridY() + { + + int retVal = getGridY_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::face::LBPHFaceRecognizer::getNeighbors() + // + + //javadoc: LBPHFaceRecognizer::getNeighbors() + public int getNeighbors() + { + + int retVal = getNeighbors_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::face::LBPHFaceRecognizer::getRadius() + // + + //javadoc: LBPHFaceRecognizer::getRadius() + public int getRadius() + { + + int retVal = getRadius_0(nativeObj); + + return retVal; + } + + + // + // C++: vector_Mat cv::face::LBPHFaceRecognizer::getHistograms() + // + + //javadoc: LBPHFaceRecognizer::getHistograms() + public List getHistograms() + { + List retVal = new ArrayList(); + Mat retValMat = new Mat(getHistograms_0(nativeObj)); + Converters.Mat_to_vector_Mat(retValMat, retVal); + return retVal; + } + + + // + // C++: void cv::face::LBPHFaceRecognizer::setGridX(int val) + // + + //javadoc: LBPHFaceRecognizer::setGridX(val) + public void setGridX(int val) + { + + setGridX_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::face::LBPHFaceRecognizer::setGridY(int val) + // + + //javadoc: LBPHFaceRecognizer::setGridY(val) + public void setGridY(int val) + { + + setGridY_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::face::LBPHFaceRecognizer::setNeighbors(int val) + // + + //javadoc: LBPHFaceRecognizer::setNeighbors(val) + public void setNeighbors(int val) + { + + setNeighbors_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::face::LBPHFaceRecognizer::setRadius(int val) + // + + //javadoc: LBPHFaceRecognizer::setRadius(val) + public void setRadius(int val) + { + + setRadius_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::face::LBPHFaceRecognizer::setThreshold(double val) + // + + //javadoc: LBPHFaceRecognizer::setThreshold(val) + public void setThreshold(double val) + { + + setThreshold_0(nativeObj, val); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: Mat cv::face::LBPHFaceRecognizer::getLabels() + private static native long getLabels_0(long nativeObj); + + // C++: static Ptr_LBPHFaceRecognizer cv::face::LBPHFaceRecognizer::create(int radius = 1, int neighbors = 8, int grid_x = 8, int grid_y = 8, double threshold = DBL_MAX) + private static native long create_0(int radius, int neighbors, int grid_x, int grid_y, double threshold); + private static native long create_1(int radius, int neighbors, int grid_x, int grid_y); + private static native long create_2(int radius, int neighbors, int grid_x); + private static native long create_3(int radius, int neighbors); + private static native long create_4(int radius); + private static native long create_5(); + + // C++: double cv::face::LBPHFaceRecognizer::getThreshold() + private static native double getThreshold_0(long nativeObj); + + // C++: int cv::face::LBPHFaceRecognizer::getGridX() + private static native int getGridX_0(long nativeObj); + + // C++: int cv::face::LBPHFaceRecognizer::getGridY() + private static native int getGridY_0(long nativeObj); + + // C++: int cv::face::LBPHFaceRecognizer::getNeighbors() + private static native int getNeighbors_0(long nativeObj); + + // C++: int cv::face::LBPHFaceRecognizer::getRadius() + private static native int getRadius_0(long nativeObj); + + // C++: vector_Mat cv::face::LBPHFaceRecognizer::getHistograms() + private static native long getHistograms_0(long nativeObj); + + // C++: void cv::face::LBPHFaceRecognizer::setGridX(int val) + private static native void setGridX_0(long nativeObj, int val); + + // C++: void cv::face::LBPHFaceRecognizer::setGridY(int val) + private static native void setGridY_0(long nativeObj, int val); + + // C++: void cv::face::LBPHFaceRecognizer::setNeighbors(int val) + private static native void setNeighbors_0(long nativeObj, int val); + + // C++: void cv::face::LBPHFaceRecognizer::setRadius(int val) + private static native void setRadius_0(long nativeObj, int val); + + // C++: void cv::face::LBPHFaceRecognizer::setThreshold(double val) + private static native void setThreshold_0(long nativeObj, double val); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/face/MACE.java b/OpenCV/src/main/java/org/opencv/face/MACE.java new file mode 100644 index 00000000..9154d8bc --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/face/MACE.java @@ -0,0 +1,139 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.face; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.face.MACE; +import org.opencv.utils.Converters; + +// C++: class MACE +//javadoc: MACE + +public class MACE extends Algorithm { + + protected MACE(long addr) { super(addr); } + + // internal usage only + public static MACE __fromPtr__(long addr) { return new MACE(addr); } + + // + // C++: static Ptr_MACE cv::face::MACE::create(int IMGSIZE = 64) + // + + //javadoc: MACE::create(IMGSIZE) + public static MACE create(int IMGSIZE) + { + + MACE retVal = MACE.__fromPtr__(create_0(IMGSIZE)); + + return retVal; + } + + //javadoc: MACE::create() + public static MACE create() + { + + MACE retVal = MACE.__fromPtr__(create_1()); + + return retVal; + } + + + // + // C++: static Ptr_MACE cv::face::MACE::load(String filename, String objname = String()) + // + + //javadoc: MACE::load(filename, objname) + public static MACE load(String filename, String objname) + { + + MACE retVal = MACE.__fromPtr__(load_0(filename, objname)); + + return retVal; + } + + //javadoc: MACE::load(filename) + public static MACE load(String filename) + { + + MACE retVal = MACE.__fromPtr__(load_1(filename)); + + return retVal; + } + + + // + // C++: bool cv::face::MACE::same(Mat query) + // + + //javadoc: MACE::same(query) + public boolean same(Mat query) + { + + boolean retVal = same_0(nativeObj, query.nativeObj); + + return retVal; + } + + + // + // C++: void cv::face::MACE::salt(String passphrase) + // + + //javadoc: MACE::salt(passphrase) + public void salt(String passphrase) + { + + salt_0(nativeObj, passphrase); + + return; + } + + + // + // C++: void cv::face::MACE::train(vector_Mat images) + // + + //javadoc: MACE::train(images) + public void train(List images) + { + Mat images_mat = Converters.vector_Mat_to_Mat(images); + train_0(nativeObj, images_mat.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_MACE cv::face::MACE::create(int IMGSIZE = 64) + private static native long create_0(int IMGSIZE); + private static native long create_1(); + + // C++: static Ptr_MACE cv::face::MACE::load(String filename, String objname = String()) + private static native long load_0(String filename, String objname); + private static native long load_1(String filename); + + // C++: bool cv::face::MACE::same(Mat query) + private static native boolean same_0(long nativeObj, long query_nativeObj); + + // C++: void cv::face::MACE::salt(String passphrase) + private static native void salt_0(long nativeObj, String passphrase); + + // C++: void cv::face::MACE::train(vector_Mat images) + private static native void train_0(long nativeObj, long images_mat_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/face/PredictCollector.java b/OpenCV/src/main/java/org/opencv/face/PredictCollector.java new file mode 100644 index 00000000..70be98da --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/face/PredictCollector.java @@ -0,0 +1,31 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.face; + + + +// C++: class PredictCollector +//javadoc: PredictCollector + +public class PredictCollector { + + protected final long nativeObj; + protected PredictCollector(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static PredictCollector __fromPtr__(long addr) { return new PredictCollector(addr); } + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/face/StandardCollector.java b/OpenCV/src/main/java/org/opencv/face/StandardCollector.java new file mode 100644 index 00000000..83f23614 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/face/StandardCollector.java @@ -0,0 +1,97 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.face; + +import org.opencv.face.PredictCollector; +import org.opencv.face.StandardCollector; + +// C++: class StandardCollector +//javadoc: StandardCollector + +public class StandardCollector extends PredictCollector { + + protected StandardCollector(long addr) { super(addr); } + + // internal usage only + public static StandardCollector __fromPtr__(long addr) { return new StandardCollector(addr); } + + // + // C++: static Ptr_StandardCollector cv::face::StandardCollector::create(double threshold = DBL_MAX) + // + + //javadoc: StandardCollector::create(threshold) + public static StandardCollector create(double threshold) + { + + StandardCollector retVal = StandardCollector.__fromPtr__(create_0(threshold)); + + return retVal; + } + + //javadoc: StandardCollector::create() + public static StandardCollector create() + { + + StandardCollector retVal = StandardCollector.__fromPtr__(create_1()); + + return retVal; + } + + + // + // C++: double cv::face::StandardCollector::getMinDist() + // + + //javadoc: StandardCollector::getMinDist() + public double getMinDist() + { + + double retVal = getMinDist_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::face::StandardCollector::getMinLabel() + // + + //javadoc: StandardCollector::getMinLabel() + public int getMinLabel() + { + + int retVal = getMinLabel_0(nativeObj); + + return retVal; + } + + + // + // C++: vector_pair_int_and_double cv::face::StandardCollector::getResults(bool sorted = false) + // + + // Return type 'vector_pair_int_and_double' is not supported, skipping the function + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_StandardCollector cv::face::StandardCollector::create(double threshold = DBL_MAX) + private static native long create_0(double threshold); + private static native long create_1(); + + // C++: double cv::face::StandardCollector::getMinDist() + private static native double getMinDist_0(long nativeObj); + + // C++: int cv::face::StandardCollector::getMinLabel() + private static native int getMinLabel_0(long nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/features2d/AKAZE.java b/OpenCV/src/main/java/org/opencv/features2d/AKAZE.java new file mode 100644 index 00000000..016968a0 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/features2d/AKAZE.java @@ -0,0 +1,380 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.features2d; + +import java.lang.String; +import org.opencv.features2d.AKAZE; +import org.opencv.features2d.Feature2D; + +// C++: class AKAZE +//javadoc: AKAZE + +public class AKAZE extends Feature2D { + + protected AKAZE(long addr) { super(addr); } + + // internal usage only + public static AKAZE __fromPtr__(long addr) { return new AKAZE(addr); } + + // C++: enum DescriptorType + public static final int + DESCRIPTOR_KAZE_UPRIGHT = 2, + DESCRIPTOR_KAZE = 3, + DESCRIPTOR_MLDB_UPRIGHT = 4, + DESCRIPTOR_MLDB = 5; + + + // + // C++: AKAZE_DescriptorType cv::AKAZE::getDescriptorType() + // + + //javadoc: AKAZE::getDescriptorType() + public int getDescriptorType() + { + + int retVal = getDescriptorType_0(nativeObj); + + return retVal; + } + + + // + // C++: KAZE_DiffusivityType cv::AKAZE::getDiffusivity() + // + + //javadoc: AKAZE::getDiffusivity() + public int getDiffusivity() + { + + int retVal = getDiffusivity_0(nativeObj); + + return retVal; + } + + + // + // C++: static Ptr_AKAZE cv::AKAZE::create(AKAZE_DescriptorType descriptor_type = AKAZE::DESCRIPTOR_MLDB, int descriptor_size = 0, int descriptor_channels = 3, float threshold = 0.001f, int nOctaves = 4, int nOctaveLayers = 4, KAZE_DiffusivityType diffusivity = KAZE::DIFF_PM_G2) + // + + //javadoc: AKAZE::create(descriptor_type, descriptor_size, descriptor_channels, threshold, nOctaves, nOctaveLayers, diffusivity) + public static AKAZE create(int descriptor_type, int descriptor_size, int descriptor_channels, float threshold, int nOctaves, int nOctaveLayers, int diffusivity) + { + + AKAZE retVal = AKAZE.__fromPtr__(create_0(descriptor_type, descriptor_size, descriptor_channels, threshold, nOctaves, nOctaveLayers, diffusivity)); + + return retVal; + } + + //javadoc: AKAZE::create(descriptor_type, descriptor_size, descriptor_channels, threshold, nOctaves, nOctaveLayers) + public static AKAZE create(int descriptor_type, int descriptor_size, int descriptor_channels, float threshold, int nOctaves, int nOctaveLayers) + { + + AKAZE retVal = AKAZE.__fromPtr__(create_1(descriptor_type, descriptor_size, descriptor_channels, threshold, nOctaves, nOctaveLayers)); + + return retVal; + } + + //javadoc: AKAZE::create(descriptor_type, descriptor_size, descriptor_channels, threshold, nOctaves) + public static AKAZE create(int descriptor_type, int descriptor_size, int descriptor_channels, float threshold, int nOctaves) + { + + AKAZE retVal = AKAZE.__fromPtr__(create_2(descriptor_type, descriptor_size, descriptor_channels, threshold, nOctaves)); + + return retVal; + } + + //javadoc: AKAZE::create(descriptor_type, descriptor_size, descriptor_channels, threshold) + public static AKAZE create(int descriptor_type, int descriptor_size, int descriptor_channels, float threshold) + { + + AKAZE retVal = AKAZE.__fromPtr__(create_3(descriptor_type, descriptor_size, descriptor_channels, threshold)); + + return retVal; + } + + //javadoc: AKAZE::create(descriptor_type, descriptor_size, descriptor_channels) + public static AKAZE create(int descriptor_type, int descriptor_size, int descriptor_channels) + { + + AKAZE retVal = AKAZE.__fromPtr__(create_4(descriptor_type, descriptor_size, descriptor_channels)); + + return retVal; + } + + //javadoc: AKAZE::create(descriptor_type, descriptor_size) + public static AKAZE create(int descriptor_type, int descriptor_size) + { + + AKAZE retVal = AKAZE.__fromPtr__(create_5(descriptor_type, descriptor_size)); + + return retVal; + } + + //javadoc: AKAZE::create(descriptor_type) + public static AKAZE create(int descriptor_type) + { + + AKAZE retVal = AKAZE.__fromPtr__(create_6(descriptor_type)); + + return retVal; + } + + //javadoc: AKAZE::create() + public static AKAZE create() + { + + AKAZE retVal = AKAZE.__fromPtr__(create_7()); + + return retVal; + } + + + // + // C++: String cv::AKAZE::getDefaultName() + // + + //javadoc: AKAZE::getDefaultName() + public String getDefaultName() + { + + String retVal = getDefaultName_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::AKAZE::getThreshold() + // + + //javadoc: AKAZE::getThreshold() + public double getThreshold() + { + + double retVal = getThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::AKAZE::getDescriptorChannels() + // + + //javadoc: AKAZE::getDescriptorChannels() + public int getDescriptorChannels() + { + + int retVal = getDescriptorChannels_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::AKAZE::getDescriptorSize() + // + + //javadoc: AKAZE::getDescriptorSize() + public int getDescriptorSize() + { + + int retVal = getDescriptorSize_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::AKAZE::getNOctaveLayers() + // + + //javadoc: AKAZE::getNOctaveLayers() + public int getNOctaveLayers() + { + + int retVal = getNOctaveLayers_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::AKAZE::getNOctaves() + // + + //javadoc: AKAZE::getNOctaves() + public int getNOctaves() + { + + int retVal = getNOctaves_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::AKAZE::setDescriptorChannels(int dch) + // + + //javadoc: AKAZE::setDescriptorChannels(dch) + public void setDescriptorChannels(int dch) + { + + setDescriptorChannels_0(nativeObj, dch); + + return; + } + + + // + // C++: void cv::AKAZE::setDescriptorSize(int dsize) + // + + //javadoc: AKAZE::setDescriptorSize(dsize) + public void setDescriptorSize(int dsize) + { + + setDescriptorSize_0(nativeObj, dsize); + + return; + } + + + // + // C++: void cv::AKAZE::setDescriptorType(AKAZE_DescriptorType dtype) + // + + //javadoc: AKAZE::setDescriptorType(dtype) + public void setDescriptorType(int dtype) + { + + setDescriptorType_0(nativeObj, dtype); + + return; + } + + + // + // C++: void cv::AKAZE::setDiffusivity(KAZE_DiffusivityType diff) + // + + //javadoc: AKAZE::setDiffusivity(diff) + public void setDiffusivity(int diff) + { + + setDiffusivity_0(nativeObj, diff); + + return; + } + + + // + // C++: void cv::AKAZE::setNOctaveLayers(int octaveLayers) + // + + //javadoc: AKAZE::setNOctaveLayers(octaveLayers) + public void setNOctaveLayers(int octaveLayers) + { + + setNOctaveLayers_0(nativeObj, octaveLayers); + + return; + } + + + // + // C++: void cv::AKAZE::setNOctaves(int octaves) + // + + //javadoc: AKAZE::setNOctaves(octaves) + public void setNOctaves(int octaves) + { + + setNOctaves_0(nativeObj, octaves); + + return; + } + + + // + // C++: void cv::AKAZE::setThreshold(double threshold) + // + + //javadoc: AKAZE::setThreshold(threshold) + public void setThreshold(double threshold) + { + + setThreshold_0(nativeObj, threshold); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: AKAZE_DescriptorType cv::AKAZE::getDescriptorType() + private static native int getDescriptorType_0(long nativeObj); + + // C++: KAZE_DiffusivityType cv::AKAZE::getDiffusivity() + private static native int getDiffusivity_0(long nativeObj); + + // C++: static Ptr_AKAZE cv::AKAZE::create(AKAZE_DescriptorType descriptor_type = AKAZE::DESCRIPTOR_MLDB, int descriptor_size = 0, int descriptor_channels = 3, float threshold = 0.001f, int nOctaves = 4, int nOctaveLayers = 4, KAZE_DiffusivityType diffusivity = KAZE::DIFF_PM_G2) + private static native long create_0(int descriptor_type, int descriptor_size, int descriptor_channels, float threshold, int nOctaves, int nOctaveLayers, int diffusivity); + private static native long create_1(int descriptor_type, int descriptor_size, int descriptor_channels, float threshold, int nOctaves, int nOctaveLayers); + private static native long create_2(int descriptor_type, int descriptor_size, int descriptor_channels, float threshold, int nOctaves); + private static native long create_3(int descriptor_type, int descriptor_size, int descriptor_channels, float threshold); + private static native long create_4(int descriptor_type, int descriptor_size, int descriptor_channels); + private static native long create_5(int descriptor_type, int descriptor_size); + private static native long create_6(int descriptor_type); + private static native long create_7(); + + // C++: String cv::AKAZE::getDefaultName() + private static native String getDefaultName_0(long nativeObj); + + // C++: double cv::AKAZE::getThreshold() + private static native double getThreshold_0(long nativeObj); + + // C++: int cv::AKAZE::getDescriptorChannels() + private static native int getDescriptorChannels_0(long nativeObj); + + // C++: int cv::AKAZE::getDescriptorSize() + private static native int getDescriptorSize_0(long nativeObj); + + // C++: int cv::AKAZE::getNOctaveLayers() + private static native int getNOctaveLayers_0(long nativeObj); + + // C++: int cv::AKAZE::getNOctaves() + private static native int getNOctaves_0(long nativeObj); + + // C++: void cv::AKAZE::setDescriptorChannels(int dch) + private static native void setDescriptorChannels_0(long nativeObj, int dch); + + // C++: void cv::AKAZE::setDescriptorSize(int dsize) + private static native void setDescriptorSize_0(long nativeObj, int dsize); + + // C++: void cv::AKAZE::setDescriptorType(AKAZE_DescriptorType dtype) + private static native void setDescriptorType_0(long nativeObj, int dtype); + + // C++: void cv::AKAZE::setDiffusivity(KAZE_DiffusivityType diff) + private static native void setDiffusivity_0(long nativeObj, int diff); + + // C++: void cv::AKAZE::setNOctaveLayers(int octaveLayers) + private static native void setNOctaveLayers_0(long nativeObj, int octaveLayers); + + // C++: void cv::AKAZE::setNOctaves(int octaves) + private static native void setNOctaves_0(long nativeObj, int octaves); + + // C++: void cv::AKAZE::setThreshold(double threshold) + private static native void setThreshold_0(long nativeObj, double threshold); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/features2d/AgastFeatureDetector.java b/OpenCV/src/main/java/org/opencv/features2d/AgastFeatureDetector.java new file mode 100644 index 00000000..71e039f0 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/features2d/AgastFeatureDetector.java @@ -0,0 +1,210 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.features2d; + +import java.lang.String; +import org.opencv.features2d.AgastFeatureDetector; +import org.opencv.features2d.Feature2D; + +// C++: class AgastFeatureDetector +//javadoc: AgastFeatureDetector + +public class AgastFeatureDetector extends Feature2D { + + protected AgastFeatureDetector(long addr) { super(addr); } + + // internal usage only + public static AgastFeatureDetector __fromPtr__(long addr) { return new AgastFeatureDetector(addr); } + + // C++: enum + public static final int + THRESHOLD = 10000, + NONMAX_SUPPRESSION = 10001; + + + // C++: enum DetectorType + public static final int + AGAST_5_8 = 0, + AGAST_7_12d = 1, + AGAST_7_12s = 2, + OAST_9_16 = 3; + + + // + // C++: AgastFeatureDetector_DetectorType cv::AgastFeatureDetector::getType() + // + + //javadoc: AgastFeatureDetector::getType() + public int getType() + { + + int retVal = getType_0(nativeObj); + + return retVal; + } + + + // + // C++: static Ptr_AgastFeatureDetector cv::AgastFeatureDetector::create(int threshold = 10, bool nonmaxSuppression = true, AgastFeatureDetector_DetectorType type = AgastFeatureDetector::OAST_9_16) + // + + //javadoc: AgastFeatureDetector::create(threshold, nonmaxSuppression, type) + public static AgastFeatureDetector create(int threshold, boolean nonmaxSuppression, int type) + { + + AgastFeatureDetector retVal = AgastFeatureDetector.__fromPtr__(create_0(threshold, nonmaxSuppression, type)); + + return retVal; + } + + //javadoc: AgastFeatureDetector::create(threshold, nonmaxSuppression) + public static AgastFeatureDetector create(int threshold, boolean nonmaxSuppression) + { + + AgastFeatureDetector retVal = AgastFeatureDetector.__fromPtr__(create_1(threshold, nonmaxSuppression)); + + return retVal; + } + + //javadoc: AgastFeatureDetector::create(threshold) + public static AgastFeatureDetector create(int threshold) + { + + AgastFeatureDetector retVal = AgastFeatureDetector.__fromPtr__(create_2(threshold)); + + return retVal; + } + + //javadoc: AgastFeatureDetector::create() + public static AgastFeatureDetector create() + { + + AgastFeatureDetector retVal = AgastFeatureDetector.__fromPtr__(create_3()); + + return retVal; + } + + + // + // C++: String cv::AgastFeatureDetector::getDefaultName() + // + + //javadoc: AgastFeatureDetector::getDefaultName() + public String getDefaultName() + { + + String retVal = getDefaultName_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::AgastFeatureDetector::getNonmaxSuppression() + // + + //javadoc: AgastFeatureDetector::getNonmaxSuppression() + public boolean getNonmaxSuppression() + { + + boolean retVal = getNonmaxSuppression_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::AgastFeatureDetector::getThreshold() + // + + //javadoc: AgastFeatureDetector::getThreshold() + public int getThreshold() + { + + int retVal = getThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::AgastFeatureDetector::setNonmaxSuppression(bool f) + // + + //javadoc: AgastFeatureDetector::setNonmaxSuppression(f) + public void setNonmaxSuppression(boolean f) + { + + setNonmaxSuppression_0(nativeObj, f); + + return; + } + + + // + // C++: void cv::AgastFeatureDetector::setThreshold(int threshold) + // + + //javadoc: AgastFeatureDetector::setThreshold(threshold) + public void setThreshold(int threshold) + { + + setThreshold_0(nativeObj, threshold); + + return; + } + + + // + // C++: void cv::AgastFeatureDetector::setType(AgastFeatureDetector_DetectorType type) + // + + //javadoc: AgastFeatureDetector::setType(type) + public void setType(int type) + { + + setType_0(nativeObj, type); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: AgastFeatureDetector_DetectorType cv::AgastFeatureDetector::getType() + private static native int getType_0(long nativeObj); + + // C++: static Ptr_AgastFeatureDetector cv::AgastFeatureDetector::create(int threshold = 10, bool nonmaxSuppression = true, AgastFeatureDetector_DetectorType type = AgastFeatureDetector::OAST_9_16) + private static native long create_0(int threshold, boolean nonmaxSuppression, int type); + private static native long create_1(int threshold, boolean nonmaxSuppression); + private static native long create_2(int threshold); + private static native long create_3(); + + // C++: String cv::AgastFeatureDetector::getDefaultName() + private static native String getDefaultName_0(long nativeObj); + + // C++: bool cv::AgastFeatureDetector::getNonmaxSuppression() + private static native boolean getNonmaxSuppression_0(long nativeObj); + + // C++: int cv::AgastFeatureDetector::getThreshold() + private static native int getThreshold_0(long nativeObj); + + // C++: void cv::AgastFeatureDetector::setNonmaxSuppression(bool f) + private static native void setNonmaxSuppression_0(long nativeObj, boolean f); + + // C++: void cv::AgastFeatureDetector::setThreshold(int threshold) + private static native void setThreshold_0(long nativeObj, int threshold); + + // C++: void cv::AgastFeatureDetector::setType(AgastFeatureDetector_DetectorType type) + private static native void setType_0(long nativeObj, int type); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/features2d/BFMatcher.java b/OpenCV/src/main/java/org/opencv/features2d/BFMatcher.java new file mode 100644 index 00000000..15a1ffa7 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/features2d/BFMatcher.java @@ -0,0 +1,103 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.features2d; + +import org.opencv.features2d.BFMatcher; +import org.opencv.features2d.DescriptorMatcher; + +// C++: class BFMatcher +//javadoc: BFMatcher + +public class BFMatcher extends DescriptorMatcher { + + protected BFMatcher(long addr) { super(addr); } + + // internal usage only + public static BFMatcher __fromPtr__(long addr) { return new BFMatcher(addr); } + + // + // C++: cv::BFMatcher::BFMatcher(int normType = NORM_L2, bool crossCheck = false) + // + + //javadoc: BFMatcher::BFMatcher(normType, crossCheck) + public BFMatcher(int normType, boolean crossCheck) + { + + super( BFMatcher_0(normType, crossCheck) ); + + return; + } + + //javadoc: BFMatcher::BFMatcher(normType) + public BFMatcher(int normType) + { + + super( BFMatcher_1(normType) ); + + return; + } + + //javadoc: BFMatcher::BFMatcher() + public BFMatcher() + { + + super( BFMatcher_2() ); + + return; + } + + + // + // C++: static Ptr_BFMatcher cv::BFMatcher::create(int normType = NORM_L2, bool crossCheck = false) + // + + //javadoc: BFMatcher::create(normType, crossCheck) + public static BFMatcher create(int normType, boolean crossCheck) + { + + BFMatcher retVal = BFMatcher.__fromPtr__(create_0(normType, crossCheck)); + + return retVal; + } + + //javadoc: BFMatcher::create(normType) + public static BFMatcher create(int normType) + { + + BFMatcher retVal = BFMatcher.__fromPtr__(create_1(normType)); + + return retVal; + } + + //javadoc: BFMatcher::create() + public static BFMatcher create() + { + + BFMatcher retVal = BFMatcher.__fromPtr__(create_2()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: cv::BFMatcher::BFMatcher(int normType = NORM_L2, bool crossCheck = false) + private static native long BFMatcher_0(int normType, boolean crossCheck); + private static native long BFMatcher_1(int normType); + private static native long BFMatcher_2(); + + // C++: static Ptr_BFMatcher cv::BFMatcher::create(int normType = NORM_L2, bool crossCheck = false) + private static native long create_0(int normType, boolean crossCheck); + private static native long create_1(int normType); + private static native long create_2(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/features2d/BOWImgDescriptorExtractor.java b/OpenCV/src/main/java/org/opencv/features2d/BOWImgDescriptorExtractor.java new file mode 100644 index 00000000..6de2cb67 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/features2d/BOWImgDescriptorExtractor.java @@ -0,0 +1,127 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.features2d; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfKeyPoint; +import org.opencv.utils.Converters; + +// C++: class BOWImgDescriptorExtractor +//javadoc: BOWImgDescriptorExtractor + +public class BOWImgDescriptorExtractor { + + protected final long nativeObj; + protected BOWImgDescriptorExtractor(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static BOWImgDescriptorExtractor __fromPtr__(long addr) { return new BOWImgDescriptorExtractor(addr); } + + // + // C++: cv::BOWImgDescriptorExtractor::BOWImgDescriptorExtractor(Ptr_DescriptorExtractor dextractor, Ptr_DescriptorMatcher dmatcher) + // + + // Unknown type 'Ptr_DescriptorExtractor' (I), skipping the function + + + // + // C++: Mat cv::BOWImgDescriptorExtractor::getVocabulary() + // + + //javadoc: BOWImgDescriptorExtractor::getVocabulary() + public Mat getVocabulary() + { + + Mat retVal = new Mat(getVocabulary_0(nativeObj)); + + return retVal; + } + + + // + // C++: int cv::BOWImgDescriptorExtractor::descriptorSize() + // + + //javadoc: BOWImgDescriptorExtractor::descriptorSize() + public int descriptorSize() + { + + int retVal = descriptorSize_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::BOWImgDescriptorExtractor::descriptorType() + // + + //javadoc: BOWImgDescriptorExtractor::descriptorType() + public int descriptorType() + { + + int retVal = descriptorType_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::BOWImgDescriptorExtractor::compute2(Mat image, vector_KeyPoint keypoints, Mat& imgDescriptor) + // + + //javadoc: BOWImgDescriptorExtractor::compute(image, keypoints, imgDescriptor) + public void compute(Mat image, MatOfKeyPoint keypoints, Mat imgDescriptor) + { + Mat keypoints_mat = keypoints; + compute_0(nativeObj, image.nativeObj, keypoints_mat.nativeObj, imgDescriptor.nativeObj); + + return; + } + + + // + // C++: void cv::BOWImgDescriptorExtractor::setVocabulary(Mat vocabulary) + // + + //javadoc: BOWImgDescriptorExtractor::setVocabulary(vocabulary) + public void setVocabulary(Mat vocabulary) + { + + setVocabulary_0(nativeObj, vocabulary.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: Mat cv::BOWImgDescriptorExtractor::getVocabulary() + private static native long getVocabulary_0(long nativeObj); + + // C++: int cv::BOWImgDescriptorExtractor::descriptorSize() + private static native int descriptorSize_0(long nativeObj); + + // C++: int cv::BOWImgDescriptorExtractor::descriptorType() + private static native int descriptorType_0(long nativeObj); + + // C++: void cv::BOWImgDescriptorExtractor::compute2(Mat image, vector_KeyPoint keypoints, Mat& imgDescriptor) + private static native void compute_0(long nativeObj, long image_nativeObj, long keypoints_mat_nativeObj, long imgDescriptor_nativeObj); + + // C++: void cv::BOWImgDescriptorExtractor::setVocabulary(Mat vocabulary) + private static native void setVocabulary_0(long nativeObj, long vocabulary_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/features2d/BOWKMeansTrainer.java b/OpenCV/src/main/java/org/opencv/features2d/BOWKMeansTrainer.java new file mode 100644 index 00000000..c578aba6 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/features2d/BOWKMeansTrainer.java @@ -0,0 +1,111 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.features2d; + +import org.opencv.core.Mat; +import org.opencv.core.TermCriteria; +import org.opencv.features2d.BOWTrainer; + +// C++: class BOWKMeansTrainer +//javadoc: BOWKMeansTrainer + +public class BOWKMeansTrainer extends BOWTrainer { + + protected BOWKMeansTrainer(long addr) { super(addr); } + + // internal usage only + public static BOWKMeansTrainer __fromPtr__(long addr) { return new BOWKMeansTrainer(addr); } + + // + // C++: cv::BOWKMeansTrainer::BOWKMeansTrainer(int clusterCount, TermCriteria termcrit = TermCriteria(), int attempts = 3, int flags = KMEANS_PP_CENTERS) + // + + //javadoc: BOWKMeansTrainer::BOWKMeansTrainer(clusterCount, termcrit, attempts, flags) + public BOWKMeansTrainer(int clusterCount, TermCriteria termcrit, int attempts, int flags) + { + + super( BOWKMeansTrainer_0(clusterCount, termcrit.type, termcrit.maxCount, termcrit.epsilon, attempts, flags) ); + + return; + } + + //javadoc: BOWKMeansTrainer::BOWKMeansTrainer(clusterCount, termcrit, attempts) + public BOWKMeansTrainer(int clusterCount, TermCriteria termcrit, int attempts) + { + + super( BOWKMeansTrainer_1(clusterCount, termcrit.type, termcrit.maxCount, termcrit.epsilon, attempts) ); + + return; + } + + //javadoc: BOWKMeansTrainer::BOWKMeansTrainer(clusterCount, termcrit) + public BOWKMeansTrainer(int clusterCount, TermCriteria termcrit) + { + + super( BOWKMeansTrainer_2(clusterCount, termcrit.type, termcrit.maxCount, termcrit.epsilon) ); + + return; + } + + //javadoc: BOWKMeansTrainer::BOWKMeansTrainer(clusterCount) + public BOWKMeansTrainer(int clusterCount) + { + + super( BOWKMeansTrainer_3(clusterCount) ); + + return; + } + + + // + // C++: Mat cv::BOWKMeansTrainer::cluster(Mat descriptors) + // + + //javadoc: BOWKMeansTrainer::cluster(descriptors) + public Mat cluster(Mat descriptors) + { + + Mat retVal = new Mat(cluster_0(nativeObj, descriptors.nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::BOWKMeansTrainer::cluster() + // + + //javadoc: BOWKMeansTrainer::cluster() + public Mat cluster() + { + + Mat retVal = new Mat(cluster_1(nativeObj)); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: cv::BOWKMeansTrainer::BOWKMeansTrainer(int clusterCount, TermCriteria termcrit = TermCriteria(), int attempts = 3, int flags = KMEANS_PP_CENTERS) + private static native long BOWKMeansTrainer_0(int clusterCount, int termcrit_type, int termcrit_maxCount, double termcrit_epsilon, int attempts, int flags); + private static native long BOWKMeansTrainer_1(int clusterCount, int termcrit_type, int termcrit_maxCount, double termcrit_epsilon, int attempts); + private static native long BOWKMeansTrainer_2(int clusterCount, int termcrit_type, int termcrit_maxCount, double termcrit_epsilon); + private static native long BOWKMeansTrainer_3(int clusterCount); + + // C++: Mat cv::BOWKMeansTrainer::cluster(Mat descriptors) + private static native long cluster_0(long nativeObj, long descriptors_nativeObj); + + // C++: Mat cv::BOWKMeansTrainer::cluster() + private static native long cluster_1(long nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/features2d/BOWTrainer.java b/OpenCV/src/main/java/org/opencv/features2d/BOWTrainer.java new file mode 100644 index 00000000..80b2497c --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/features2d/BOWTrainer.java @@ -0,0 +1,136 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.features2d; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.utils.Converters; + +// C++: class BOWTrainer +//javadoc: BOWTrainer + +public class BOWTrainer { + + protected final long nativeObj; + protected BOWTrainer(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static BOWTrainer __fromPtr__(long addr) { return new BOWTrainer(addr); } + + // + // C++: Mat cv::BOWTrainer::cluster(Mat descriptors) + // + + //javadoc: BOWTrainer::cluster(descriptors) + public Mat cluster(Mat descriptors) + { + + Mat retVal = new Mat(cluster_0(nativeObj, descriptors.nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::BOWTrainer::cluster() + // + + //javadoc: BOWTrainer::cluster() + public Mat cluster() + { + + Mat retVal = new Mat(cluster_1(nativeObj)); + + return retVal; + } + + + // + // C++: int cv::BOWTrainer::descriptorsCount() + // + + //javadoc: BOWTrainer::descriptorsCount() + public int descriptorsCount() + { + + int retVal = descriptorsCount_0(nativeObj); + + return retVal; + } + + + // + // C++: vector_Mat cv::BOWTrainer::getDescriptors() + // + + //javadoc: BOWTrainer::getDescriptors() + public List getDescriptors() + { + List retVal = new ArrayList(); + Mat retValMat = new Mat(getDescriptors_0(nativeObj)); + Converters.Mat_to_vector_Mat(retValMat, retVal); + return retVal; + } + + + // + // C++: void cv::BOWTrainer::add(Mat descriptors) + // + + //javadoc: BOWTrainer::add(descriptors) + public void add(Mat descriptors) + { + + add_0(nativeObj, descriptors.nativeObj); + + return; + } + + + // + // C++: void cv::BOWTrainer::clear() + // + + //javadoc: BOWTrainer::clear() + public void clear() + { + + clear_0(nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: Mat cv::BOWTrainer::cluster(Mat descriptors) + private static native long cluster_0(long nativeObj, long descriptors_nativeObj); + + // C++: Mat cv::BOWTrainer::cluster() + private static native long cluster_1(long nativeObj); + + // C++: int cv::BOWTrainer::descriptorsCount() + private static native int descriptorsCount_0(long nativeObj); + + // C++: vector_Mat cv::BOWTrainer::getDescriptors() + private static native long getDescriptors_0(long nativeObj); + + // C++: void cv::BOWTrainer::add(Mat descriptors) + private static native void add_0(long nativeObj, long descriptors_nativeObj); + + // C++: void cv::BOWTrainer::clear() + private static native void clear_0(long nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/features2d/BRISK.java b/OpenCV/src/main/java/org/opencv/features2d/BRISK.java new file mode 100644 index 00000000..58247da9 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/features2d/BRISK.java @@ -0,0 +1,272 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.features2d; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfFloat; +import org.opencv.core.MatOfInt; +import org.opencv.features2d.BRISK; +import org.opencv.features2d.Feature2D; +import org.opencv.utils.Converters; + +// C++: class BRISK +//javadoc: BRISK + +public class BRISK extends Feature2D { + + protected BRISK(long addr) { super(addr); } + + // internal usage only + public static BRISK __fromPtr__(long addr) { return new BRISK(addr); } + + // + // C++: static Ptr_BRISK cv::BRISK::create(int thresh, int octaves, vector_float radiusList, vector_int numberList, float dMax = 5.85f, float dMin = 8.2f, vector_int indexChange = std::vector()) + // + + //javadoc: BRISK::create(thresh, octaves, radiusList, numberList, dMax, dMin, indexChange) + public static BRISK create(int thresh, int octaves, MatOfFloat radiusList, MatOfInt numberList, float dMax, float dMin, MatOfInt indexChange) + { + Mat radiusList_mat = radiusList; + Mat numberList_mat = numberList; + Mat indexChange_mat = indexChange; + BRISK retVal = BRISK.__fromPtr__(create_0(thresh, octaves, radiusList_mat.nativeObj, numberList_mat.nativeObj, dMax, dMin, indexChange_mat.nativeObj)); + + return retVal; + } + + //javadoc: BRISK::create(thresh, octaves, radiusList, numberList, dMax, dMin) + public static BRISK create(int thresh, int octaves, MatOfFloat radiusList, MatOfInt numberList, float dMax, float dMin) + { + Mat radiusList_mat = radiusList; + Mat numberList_mat = numberList; + BRISK retVal = BRISK.__fromPtr__(create_1(thresh, octaves, radiusList_mat.nativeObj, numberList_mat.nativeObj, dMax, dMin)); + + return retVal; + } + + //javadoc: BRISK::create(thresh, octaves, radiusList, numberList, dMax) + public static BRISK create(int thresh, int octaves, MatOfFloat radiusList, MatOfInt numberList, float dMax) + { + Mat radiusList_mat = radiusList; + Mat numberList_mat = numberList; + BRISK retVal = BRISK.__fromPtr__(create_2(thresh, octaves, radiusList_mat.nativeObj, numberList_mat.nativeObj, dMax)); + + return retVal; + } + + //javadoc: BRISK::create(thresh, octaves, radiusList, numberList) + public static BRISK create(int thresh, int octaves, MatOfFloat radiusList, MatOfInt numberList) + { + Mat radiusList_mat = radiusList; + Mat numberList_mat = numberList; + BRISK retVal = BRISK.__fromPtr__(create_3(thresh, octaves, radiusList_mat.nativeObj, numberList_mat.nativeObj)); + + return retVal; + } + + + // + // C++: static Ptr_BRISK cv::BRISK::create(int thresh = 30, int octaves = 3, float patternScale = 1.0f) + // + + //javadoc: BRISK::create(thresh, octaves, patternScale) + public static BRISK create(int thresh, int octaves, float patternScale) + { + + BRISK retVal = BRISK.__fromPtr__(create_4(thresh, octaves, patternScale)); + + return retVal; + } + + //javadoc: BRISK::create(thresh, octaves) + public static BRISK create(int thresh, int octaves) + { + + BRISK retVal = BRISK.__fromPtr__(create_5(thresh, octaves)); + + return retVal; + } + + //javadoc: BRISK::create(thresh) + public static BRISK create(int thresh) + { + + BRISK retVal = BRISK.__fromPtr__(create_6(thresh)); + + return retVal; + } + + //javadoc: BRISK::create() + public static BRISK create() + { + + BRISK retVal = BRISK.__fromPtr__(create_7()); + + return retVal; + } + + + // + // C++: static Ptr_BRISK cv::BRISK::create(vector_float radiusList, vector_int numberList, float dMax = 5.85f, float dMin = 8.2f, vector_int indexChange = std::vector()) + // + + //javadoc: BRISK::create(radiusList, numberList, dMax, dMin, indexChange) + public static BRISK create(MatOfFloat radiusList, MatOfInt numberList, float dMax, float dMin, MatOfInt indexChange) + { + Mat radiusList_mat = radiusList; + Mat numberList_mat = numberList; + Mat indexChange_mat = indexChange; + BRISK retVal = BRISK.__fromPtr__(create_8(radiusList_mat.nativeObj, numberList_mat.nativeObj, dMax, dMin, indexChange_mat.nativeObj)); + + return retVal; + } + + //javadoc: BRISK::create(radiusList, numberList, dMax, dMin) + public static BRISK create(MatOfFloat radiusList, MatOfInt numberList, float dMax, float dMin) + { + Mat radiusList_mat = radiusList; + Mat numberList_mat = numberList; + BRISK retVal = BRISK.__fromPtr__(create_9(radiusList_mat.nativeObj, numberList_mat.nativeObj, dMax, dMin)); + + return retVal; + } + + //javadoc: BRISK::create(radiusList, numberList, dMax) + public static BRISK create(MatOfFloat radiusList, MatOfInt numberList, float dMax) + { + Mat radiusList_mat = radiusList; + Mat numberList_mat = numberList; + BRISK retVal = BRISK.__fromPtr__(create_10(radiusList_mat.nativeObj, numberList_mat.nativeObj, dMax)); + + return retVal; + } + + //javadoc: BRISK::create(radiusList, numberList) + public static BRISK create(MatOfFloat radiusList, MatOfInt numberList) + { + Mat radiusList_mat = radiusList; + Mat numberList_mat = numberList; + BRISK retVal = BRISK.__fromPtr__(create_11(radiusList_mat.nativeObj, numberList_mat.nativeObj)); + + return retVal; + } + + + // + // C++: String cv::BRISK::getDefaultName() + // + + //javadoc: BRISK::getDefaultName() + public String getDefaultName() + { + + String retVal = getDefaultName_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::BRISK::getOctaves() + // + + //javadoc: BRISK::getOctaves() + public int getOctaves() + { + + int retVal = getOctaves_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::BRISK::getThreshold() + // + + //javadoc: BRISK::getThreshold() + public int getThreshold() + { + + int retVal = getThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::BRISK::setOctaves(int octaves) + // + + //javadoc: BRISK::setOctaves(octaves) + public void setOctaves(int octaves) + { + + setOctaves_0(nativeObj, octaves); + + return; + } + + + // + // C++: void cv::BRISK::setThreshold(int threshold) + // + + //javadoc: BRISK::setThreshold(threshold) + public void setThreshold(int threshold) + { + + setThreshold_0(nativeObj, threshold); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_BRISK cv::BRISK::create(int thresh, int octaves, vector_float radiusList, vector_int numberList, float dMax = 5.85f, float dMin = 8.2f, vector_int indexChange = std::vector()) + private static native long create_0(int thresh, int octaves, long radiusList_mat_nativeObj, long numberList_mat_nativeObj, float dMax, float dMin, long indexChange_mat_nativeObj); + private static native long create_1(int thresh, int octaves, long radiusList_mat_nativeObj, long numberList_mat_nativeObj, float dMax, float dMin); + private static native long create_2(int thresh, int octaves, long radiusList_mat_nativeObj, long numberList_mat_nativeObj, float dMax); + private static native long create_3(int thresh, int octaves, long radiusList_mat_nativeObj, long numberList_mat_nativeObj); + + // C++: static Ptr_BRISK cv::BRISK::create(int thresh = 30, int octaves = 3, float patternScale = 1.0f) + private static native long create_4(int thresh, int octaves, float patternScale); + private static native long create_5(int thresh, int octaves); + private static native long create_6(int thresh); + private static native long create_7(); + + // C++: static Ptr_BRISK cv::BRISK::create(vector_float radiusList, vector_int numberList, float dMax = 5.85f, float dMin = 8.2f, vector_int indexChange = std::vector()) + private static native long create_8(long radiusList_mat_nativeObj, long numberList_mat_nativeObj, float dMax, float dMin, long indexChange_mat_nativeObj); + private static native long create_9(long radiusList_mat_nativeObj, long numberList_mat_nativeObj, float dMax, float dMin); + private static native long create_10(long radiusList_mat_nativeObj, long numberList_mat_nativeObj, float dMax); + private static native long create_11(long radiusList_mat_nativeObj, long numberList_mat_nativeObj); + + // C++: String cv::BRISK::getDefaultName() + private static native String getDefaultName_0(long nativeObj); + + // C++: int cv::BRISK::getOctaves() + private static native int getOctaves_0(long nativeObj); + + // C++: int cv::BRISK::getThreshold() + private static native int getThreshold_0(long nativeObj); + + // C++: void cv::BRISK::setOctaves(int octaves) + private static native void setOctaves_0(long nativeObj, int octaves); + + // C++: void cv::BRISK::setThreshold(int threshold) + private static native void setThreshold_0(long nativeObj, int threshold); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/features2d/DescriptorMatcher.java b/OpenCV/src/main/java/org/opencv/features2d/DescriptorMatcher.java new file mode 100644 index 00000000..b36595b2 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/features2d/DescriptorMatcher.java @@ -0,0 +1,475 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.features2d; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.core.MatOfDMatch; +import org.opencv.features2d.DescriptorMatcher; +import org.opencv.utils.Converters; + +// C++: class DescriptorMatcher +//javadoc: DescriptorMatcher + +public class DescriptorMatcher extends Algorithm { + + protected DescriptorMatcher(long addr) { super(addr); } + + // internal usage only + public static DescriptorMatcher __fromPtr__(long addr) { return new DescriptorMatcher(addr); } + + // C++: enum MatcherType + public static final int + FLANNBASED = 1, + BRUTEFORCE = 2, + BRUTEFORCE_L1 = 3, + BRUTEFORCE_HAMMING = 4, + BRUTEFORCE_HAMMINGLUT = 5, + BRUTEFORCE_SL2 = 6; + + + // + // C++: Ptr_DescriptorMatcher cv::DescriptorMatcher::clone(bool emptyTrainData = false) + // + + //javadoc: DescriptorMatcher::clone(emptyTrainData) + public DescriptorMatcher clone(boolean emptyTrainData) + { + + DescriptorMatcher retVal = DescriptorMatcher.__fromPtr__(clone_0(nativeObj, emptyTrainData)); + + return retVal; + } + + //javadoc: DescriptorMatcher::clone() + public DescriptorMatcher clone() + { + + DescriptorMatcher retVal = DescriptorMatcher.__fromPtr__(clone_1(nativeObj)); + + return retVal; + } + + + // + // C++: static Ptr_DescriptorMatcher cv::DescriptorMatcher::create(DescriptorMatcher_MatcherType matcherType) + // + + //javadoc: DescriptorMatcher::create(matcherType) + public static DescriptorMatcher create(int matcherType) + { + + DescriptorMatcher retVal = DescriptorMatcher.__fromPtr__(create_0(matcherType)); + + return retVal; + } + + + // + // C++: static Ptr_DescriptorMatcher cv::DescriptorMatcher::create(String descriptorMatcherType) + // + + //javadoc: DescriptorMatcher::create(descriptorMatcherType) + public static DescriptorMatcher create(String descriptorMatcherType) + { + + DescriptorMatcher retVal = DescriptorMatcher.__fromPtr__(create_1(descriptorMatcherType)); + + return retVal; + } + + + // + // C++: bool cv::DescriptorMatcher::empty() + // + + //javadoc: DescriptorMatcher::empty() + public boolean empty() + { + + boolean retVal = empty_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::DescriptorMatcher::isMaskSupported() + // + + //javadoc: DescriptorMatcher::isMaskSupported() + public boolean isMaskSupported() + { + + boolean retVal = isMaskSupported_0(nativeObj); + + return retVal; + } + + + // + // C++: vector_Mat cv::DescriptorMatcher::getTrainDescriptors() + // + + //javadoc: DescriptorMatcher::getTrainDescriptors() + public List getTrainDescriptors() + { + List retVal = new ArrayList(); + Mat retValMat = new Mat(getTrainDescriptors_0(nativeObj)); + Converters.Mat_to_vector_Mat(retValMat, retVal); + return retVal; + } + + + // + // C++: void cv::DescriptorMatcher::add(vector_Mat descriptors) + // + + //javadoc: DescriptorMatcher::add(descriptors) + public void add(List descriptors) + { + Mat descriptors_mat = Converters.vector_Mat_to_Mat(descriptors); + add_0(nativeObj, descriptors_mat.nativeObj); + + return; + } + + + // + // C++: void cv::DescriptorMatcher::clear() + // + + //javadoc: DescriptorMatcher::clear() + public void clear() + { + + clear_0(nativeObj); + + return; + } + + + // + // C++: void cv::DescriptorMatcher::knnMatch(Mat queryDescriptors, Mat trainDescriptors, vector_vector_DMatch& matches, int k, Mat mask = Mat(), bool compactResult = false) + // + + //javadoc: DescriptorMatcher::knnMatch(queryDescriptors, trainDescriptors, matches, k, mask, compactResult) + public void knnMatch(Mat queryDescriptors, Mat trainDescriptors, List matches, int k, Mat mask, boolean compactResult) + { + Mat matches_mat = new Mat(); + knnMatch_0(nativeObj, queryDescriptors.nativeObj, trainDescriptors.nativeObj, matches_mat.nativeObj, k, mask.nativeObj, compactResult); + Converters.Mat_to_vector_vector_DMatch(matches_mat, matches); + matches_mat.release(); + return; + } + + //javadoc: DescriptorMatcher::knnMatch(queryDescriptors, trainDescriptors, matches, k, mask) + public void knnMatch(Mat queryDescriptors, Mat trainDescriptors, List matches, int k, Mat mask) + { + Mat matches_mat = new Mat(); + knnMatch_1(nativeObj, queryDescriptors.nativeObj, trainDescriptors.nativeObj, matches_mat.nativeObj, k, mask.nativeObj); + Converters.Mat_to_vector_vector_DMatch(matches_mat, matches); + matches_mat.release(); + return; + } + + //javadoc: DescriptorMatcher::knnMatch(queryDescriptors, trainDescriptors, matches, k) + public void knnMatch(Mat queryDescriptors, Mat trainDescriptors, List matches, int k) + { + Mat matches_mat = new Mat(); + knnMatch_2(nativeObj, queryDescriptors.nativeObj, trainDescriptors.nativeObj, matches_mat.nativeObj, k); + Converters.Mat_to_vector_vector_DMatch(matches_mat, matches); + matches_mat.release(); + return; + } + + + // + // C++: void cv::DescriptorMatcher::knnMatch(Mat queryDescriptors, vector_vector_DMatch& matches, int k, vector_Mat masks = vector_Mat(), bool compactResult = false) + // + + //javadoc: DescriptorMatcher::knnMatch(queryDescriptors, matches, k, masks, compactResult) + public void knnMatch(Mat queryDescriptors, List matches, int k, List masks, boolean compactResult) + { + Mat matches_mat = new Mat(); + Mat masks_mat = Converters.vector_Mat_to_Mat(masks); + knnMatch_3(nativeObj, queryDescriptors.nativeObj, matches_mat.nativeObj, k, masks_mat.nativeObj, compactResult); + Converters.Mat_to_vector_vector_DMatch(matches_mat, matches); + matches_mat.release(); + return; + } + + //javadoc: DescriptorMatcher::knnMatch(queryDescriptors, matches, k, masks) + public void knnMatch(Mat queryDescriptors, List matches, int k, List masks) + { + Mat matches_mat = new Mat(); + Mat masks_mat = Converters.vector_Mat_to_Mat(masks); + knnMatch_4(nativeObj, queryDescriptors.nativeObj, matches_mat.nativeObj, k, masks_mat.nativeObj); + Converters.Mat_to_vector_vector_DMatch(matches_mat, matches); + matches_mat.release(); + return; + } + + //javadoc: DescriptorMatcher::knnMatch(queryDescriptors, matches, k) + public void knnMatch(Mat queryDescriptors, List matches, int k) + { + Mat matches_mat = new Mat(); + knnMatch_5(nativeObj, queryDescriptors.nativeObj, matches_mat.nativeObj, k); + Converters.Mat_to_vector_vector_DMatch(matches_mat, matches); + matches_mat.release(); + return; + } + + + // + // C++: void cv::DescriptorMatcher::match(Mat queryDescriptors, Mat trainDescriptors, vector_DMatch& matches, Mat mask = Mat()) + // + + //javadoc: DescriptorMatcher::match(queryDescriptors, trainDescriptors, matches, mask) + public void match(Mat queryDescriptors, Mat trainDescriptors, MatOfDMatch matches, Mat mask) + { + Mat matches_mat = matches; + match_0(nativeObj, queryDescriptors.nativeObj, trainDescriptors.nativeObj, matches_mat.nativeObj, mask.nativeObj); + + return; + } + + //javadoc: DescriptorMatcher::match(queryDescriptors, trainDescriptors, matches) + public void match(Mat queryDescriptors, Mat trainDescriptors, MatOfDMatch matches) + { + Mat matches_mat = matches; + match_1(nativeObj, queryDescriptors.nativeObj, trainDescriptors.nativeObj, matches_mat.nativeObj); + + return; + } + + + // + // C++: void cv::DescriptorMatcher::match(Mat queryDescriptors, vector_DMatch& matches, vector_Mat masks = vector_Mat()) + // + + //javadoc: DescriptorMatcher::match(queryDescriptors, matches, masks) + public void match(Mat queryDescriptors, MatOfDMatch matches, List masks) + { + Mat matches_mat = matches; + Mat masks_mat = Converters.vector_Mat_to_Mat(masks); + match_2(nativeObj, queryDescriptors.nativeObj, matches_mat.nativeObj, masks_mat.nativeObj); + + return; + } + + //javadoc: DescriptorMatcher::match(queryDescriptors, matches) + public void match(Mat queryDescriptors, MatOfDMatch matches) + { + Mat matches_mat = matches; + match_3(nativeObj, queryDescriptors.nativeObj, matches_mat.nativeObj); + + return; + } + + + // + // C++: void cv::DescriptorMatcher::radiusMatch(Mat queryDescriptors, Mat trainDescriptors, vector_vector_DMatch& matches, float maxDistance, Mat mask = Mat(), bool compactResult = false) + // + + //javadoc: DescriptorMatcher::radiusMatch(queryDescriptors, trainDescriptors, matches, maxDistance, mask, compactResult) + public void radiusMatch(Mat queryDescriptors, Mat trainDescriptors, List matches, float maxDistance, Mat mask, boolean compactResult) + { + Mat matches_mat = new Mat(); + radiusMatch_0(nativeObj, queryDescriptors.nativeObj, trainDescriptors.nativeObj, matches_mat.nativeObj, maxDistance, mask.nativeObj, compactResult); + Converters.Mat_to_vector_vector_DMatch(matches_mat, matches); + matches_mat.release(); + return; + } + + //javadoc: DescriptorMatcher::radiusMatch(queryDescriptors, trainDescriptors, matches, maxDistance, mask) + public void radiusMatch(Mat queryDescriptors, Mat trainDescriptors, List matches, float maxDistance, Mat mask) + { + Mat matches_mat = new Mat(); + radiusMatch_1(nativeObj, queryDescriptors.nativeObj, trainDescriptors.nativeObj, matches_mat.nativeObj, maxDistance, mask.nativeObj); + Converters.Mat_to_vector_vector_DMatch(matches_mat, matches); + matches_mat.release(); + return; + } + + //javadoc: DescriptorMatcher::radiusMatch(queryDescriptors, trainDescriptors, matches, maxDistance) + public void radiusMatch(Mat queryDescriptors, Mat trainDescriptors, List matches, float maxDistance) + { + Mat matches_mat = new Mat(); + radiusMatch_2(nativeObj, queryDescriptors.nativeObj, trainDescriptors.nativeObj, matches_mat.nativeObj, maxDistance); + Converters.Mat_to_vector_vector_DMatch(matches_mat, matches); + matches_mat.release(); + return; + } + + + // + // C++: void cv::DescriptorMatcher::radiusMatch(Mat queryDescriptors, vector_vector_DMatch& matches, float maxDistance, vector_Mat masks = vector_Mat(), bool compactResult = false) + // + + //javadoc: DescriptorMatcher::radiusMatch(queryDescriptors, matches, maxDistance, masks, compactResult) + public void radiusMatch(Mat queryDescriptors, List matches, float maxDistance, List masks, boolean compactResult) + { + Mat matches_mat = new Mat(); + Mat masks_mat = Converters.vector_Mat_to_Mat(masks); + radiusMatch_3(nativeObj, queryDescriptors.nativeObj, matches_mat.nativeObj, maxDistance, masks_mat.nativeObj, compactResult); + Converters.Mat_to_vector_vector_DMatch(matches_mat, matches); + matches_mat.release(); + return; + } + + //javadoc: DescriptorMatcher::radiusMatch(queryDescriptors, matches, maxDistance, masks) + public void radiusMatch(Mat queryDescriptors, List matches, float maxDistance, List masks) + { + Mat matches_mat = new Mat(); + Mat masks_mat = Converters.vector_Mat_to_Mat(masks); + radiusMatch_4(nativeObj, queryDescriptors.nativeObj, matches_mat.nativeObj, maxDistance, masks_mat.nativeObj); + Converters.Mat_to_vector_vector_DMatch(matches_mat, matches); + matches_mat.release(); + return; + } + + //javadoc: DescriptorMatcher::radiusMatch(queryDescriptors, matches, maxDistance) + public void radiusMatch(Mat queryDescriptors, List matches, float maxDistance) + { + Mat matches_mat = new Mat(); + radiusMatch_5(nativeObj, queryDescriptors.nativeObj, matches_mat.nativeObj, maxDistance); + Converters.Mat_to_vector_vector_DMatch(matches_mat, matches); + matches_mat.release(); + return; + } + + + // + // C++: void cv::DescriptorMatcher::read(FileNode arg1) + // + + // Unknown type 'FileNode' (I), skipping the function + + + // + // C++: void cv::DescriptorMatcher::read(String fileName) + // + + //javadoc: DescriptorMatcher::read(fileName) + public void read(String fileName) + { + + read_0(nativeObj, fileName); + + return; + } + + + // + // C++: void cv::DescriptorMatcher::train() + // + + //javadoc: DescriptorMatcher::train() + public void train() + { + + train_0(nativeObj); + + return; + } + + + // + // C++: void cv::DescriptorMatcher::write(Ptr_FileStorage fs, String name = String()) + // + + // Unknown type 'Ptr_FileStorage' (I), skipping the function + + + // + // C++: void cv::DescriptorMatcher::write(String fileName) + // + + //javadoc: DescriptorMatcher::write(fileName) + public void write(String fileName) + { + + write_0(nativeObj, fileName); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: Ptr_DescriptorMatcher cv::DescriptorMatcher::clone(bool emptyTrainData = false) + private static native long clone_0(long nativeObj, boolean emptyTrainData); + private static native long clone_1(long nativeObj); + + // C++: static Ptr_DescriptorMatcher cv::DescriptorMatcher::create(DescriptorMatcher_MatcherType matcherType) + private static native long create_0(int matcherType); + + // C++: static Ptr_DescriptorMatcher cv::DescriptorMatcher::create(String descriptorMatcherType) + private static native long create_1(String descriptorMatcherType); + + // C++: bool cv::DescriptorMatcher::empty() + private static native boolean empty_0(long nativeObj); + + // C++: bool cv::DescriptorMatcher::isMaskSupported() + private static native boolean isMaskSupported_0(long nativeObj); + + // C++: vector_Mat cv::DescriptorMatcher::getTrainDescriptors() + private static native long getTrainDescriptors_0(long nativeObj); + + // C++: void cv::DescriptorMatcher::add(vector_Mat descriptors) + private static native void add_0(long nativeObj, long descriptors_mat_nativeObj); + + // C++: void cv::DescriptorMatcher::clear() + private static native void clear_0(long nativeObj); + + // C++: void cv::DescriptorMatcher::knnMatch(Mat queryDescriptors, Mat trainDescriptors, vector_vector_DMatch& matches, int k, Mat mask = Mat(), bool compactResult = false) + private static native void knnMatch_0(long nativeObj, long queryDescriptors_nativeObj, long trainDescriptors_nativeObj, long matches_mat_nativeObj, int k, long mask_nativeObj, boolean compactResult); + private static native void knnMatch_1(long nativeObj, long queryDescriptors_nativeObj, long trainDescriptors_nativeObj, long matches_mat_nativeObj, int k, long mask_nativeObj); + private static native void knnMatch_2(long nativeObj, long queryDescriptors_nativeObj, long trainDescriptors_nativeObj, long matches_mat_nativeObj, int k); + + // C++: void cv::DescriptorMatcher::knnMatch(Mat queryDescriptors, vector_vector_DMatch& matches, int k, vector_Mat masks = vector_Mat(), bool compactResult = false) + private static native void knnMatch_3(long nativeObj, long queryDescriptors_nativeObj, long matches_mat_nativeObj, int k, long masks_mat_nativeObj, boolean compactResult); + private static native void knnMatch_4(long nativeObj, long queryDescriptors_nativeObj, long matches_mat_nativeObj, int k, long masks_mat_nativeObj); + private static native void knnMatch_5(long nativeObj, long queryDescriptors_nativeObj, long matches_mat_nativeObj, int k); + + // C++: void cv::DescriptorMatcher::match(Mat queryDescriptors, Mat trainDescriptors, vector_DMatch& matches, Mat mask = Mat()) + private static native void match_0(long nativeObj, long queryDescriptors_nativeObj, long trainDescriptors_nativeObj, long matches_mat_nativeObj, long mask_nativeObj); + private static native void match_1(long nativeObj, long queryDescriptors_nativeObj, long trainDescriptors_nativeObj, long matches_mat_nativeObj); + + // C++: void cv::DescriptorMatcher::match(Mat queryDescriptors, vector_DMatch& matches, vector_Mat masks = vector_Mat()) + private static native void match_2(long nativeObj, long queryDescriptors_nativeObj, long matches_mat_nativeObj, long masks_mat_nativeObj); + private static native void match_3(long nativeObj, long queryDescriptors_nativeObj, long matches_mat_nativeObj); + + // C++: void cv::DescriptorMatcher::radiusMatch(Mat queryDescriptors, Mat trainDescriptors, vector_vector_DMatch& matches, float maxDistance, Mat mask = Mat(), bool compactResult = false) + private static native void radiusMatch_0(long nativeObj, long queryDescriptors_nativeObj, long trainDescriptors_nativeObj, long matches_mat_nativeObj, float maxDistance, long mask_nativeObj, boolean compactResult); + private static native void radiusMatch_1(long nativeObj, long queryDescriptors_nativeObj, long trainDescriptors_nativeObj, long matches_mat_nativeObj, float maxDistance, long mask_nativeObj); + private static native void radiusMatch_2(long nativeObj, long queryDescriptors_nativeObj, long trainDescriptors_nativeObj, long matches_mat_nativeObj, float maxDistance); + + // C++: void cv::DescriptorMatcher::radiusMatch(Mat queryDescriptors, vector_vector_DMatch& matches, float maxDistance, vector_Mat masks = vector_Mat(), bool compactResult = false) + private static native void radiusMatch_3(long nativeObj, long queryDescriptors_nativeObj, long matches_mat_nativeObj, float maxDistance, long masks_mat_nativeObj, boolean compactResult); + private static native void radiusMatch_4(long nativeObj, long queryDescriptors_nativeObj, long matches_mat_nativeObj, float maxDistance, long masks_mat_nativeObj); + private static native void radiusMatch_5(long nativeObj, long queryDescriptors_nativeObj, long matches_mat_nativeObj, float maxDistance); + + // C++: void cv::DescriptorMatcher::read(String fileName) + private static native void read_0(long nativeObj, String fileName); + + // C++: void cv::DescriptorMatcher::train() + private static native void train_0(long nativeObj); + + // C++: void cv::DescriptorMatcher::write(String fileName) + private static native void write_0(long nativeObj, String fileName); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/features2d/FastFeatureDetector.java b/OpenCV/src/main/java/org/opencv/features2d/FastFeatureDetector.java new file mode 100644 index 00000000..3b78b34c --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/features2d/FastFeatureDetector.java @@ -0,0 +1,210 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.features2d; + +import java.lang.String; +import org.opencv.features2d.FastFeatureDetector; +import org.opencv.features2d.Feature2D; + +// C++: class FastFeatureDetector +//javadoc: FastFeatureDetector + +public class FastFeatureDetector extends Feature2D { + + protected FastFeatureDetector(long addr) { super(addr); } + + // internal usage only + public static FastFeatureDetector __fromPtr__(long addr) { return new FastFeatureDetector(addr); } + + // C++: enum DetectorType + public static final int + TYPE_5_8 = 0, + TYPE_7_12 = 1, + TYPE_9_16 = 2; + + + // C++: enum + public static final int + THRESHOLD = 10000, + NONMAX_SUPPRESSION = 10001, + FAST_N = 10002; + + + // + // C++: FastFeatureDetector_DetectorType cv::FastFeatureDetector::getType() + // + + //javadoc: FastFeatureDetector::getType() + public int getType() + { + + int retVal = getType_0(nativeObj); + + return retVal; + } + + + // + // C++: static Ptr_FastFeatureDetector cv::FastFeatureDetector::create(int threshold = 10, bool nonmaxSuppression = true, FastFeatureDetector_DetectorType type = FastFeatureDetector::TYPE_9_16) + // + + //javadoc: FastFeatureDetector::create(threshold, nonmaxSuppression, type) + public static FastFeatureDetector create(int threshold, boolean nonmaxSuppression, int type) + { + + FastFeatureDetector retVal = FastFeatureDetector.__fromPtr__(create_0(threshold, nonmaxSuppression, type)); + + return retVal; + } + + //javadoc: FastFeatureDetector::create(threshold, nonmaxSuppression) + public static FastFeatureDetector create(int threshold, boolean nonmaxSuppression) + { + + FastFeatureDetector retVal = FastFeatureDetector.__fromPtr__(create_1(threshold, nonmaxSuppression)); + + return retVal; + } + + //javadoc: FastFeatureDetector::create(threshold) + public static FastFeatureDetector create(int threshold) + { + + FastFeatureDetector retVal = FastFeatureDetector.__fromPtr__(create_2(threshold)); + + return retVal; + } + + //javadoc: FastFeatureDetector::create() + public static FastFeatureDetector create() + { + + FastFeatureDetector retVal = FastFeatureDetector.__fromPtr__(create_3()); + + return retVal; + } + + + // + // C++: String cv::FastFeatureDetector::getDefaultName() + // + + //javadoc: FastFeatureDetector::getDefaultName() + public String getDefaultName() + { + + String retVal = getDefaultName_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::FastFeatureDetector::getNonmaxSuppression() + // + + //javadoc: FastFeatureDetector::getNonmaxSuppression() + public boolean getNonmaxSuppression() + { + + boolean retVal = getNonmaxSuppression_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::FastFeatureDetector::getThreshold() + // + + //javadoc: FastFeatureDetector::getThreshold() + public int getThreshold() + { + + int retVal = getThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::FastFeatureDetector::setNonmaxSuppression(bool f) + // + + //javadoc: FastFeatureDetector::setNonmaxSuppression(f) + public void setNonmaxSuppression(boolean f) + { + + setNonmaxSuppression_0(nativeObj, f); + + return; + } + + + // + // C++: void cv::FastFeatureDetector::setThreshold(int threshold) + // + + //javadoc: FastFeatureDetector::setThreshold(threshold) + public void setThreshold(int threshold) + { + + setThreshold_0(nativeObj, threshold); + + return; + } + + + // + // C++: void cv::FastFeatureDetector::setType(FastFeatureDetector_DetectorType type) + // + + //javadoc: FastFeatureDetector::setType(type) + public void setType(int type) + { + + setType_0(nativeObj, type); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: FastFeatureDetector_DetectorType cv::FastFeatureDetector::getType() + private static native int getType_0(long nativeObj); + + // C++: static Ptr_FastFeatureDetector cv::FastFeatureDetector::create(int threshold = 10, bool nonmaxSuppression = true, FastFeatureDetector_DetectorType type = FastFeatureDetector::TYPE_9_16) + private static native long create_0(int threshold, boolean nonmaxSuppression, int type); + private static native long create_1(int threshold, boolean nonmaxSuppression); + private static native long create_2(int threshold); + private static native long create_3(); + + // C++: String cv::FastFeatureDetector::getDefaultName() + private static native String getDefaultName_0(long nativeObj); + + // C++: bool cv::FastFeatureDetector::getNonmaxSuppression() + private static native boolean getNonmaxSuppression_0(long nativeObj); + + // C++: int cv::FastFeatureDetector::getThreshold() + private static native int getThreshold_0(long nativeObj); + + // C++: void cv::FastFeatureDetector::setNonmaxSuppression(bool f) + private static native void setNonmaxSuppression_0(long nativeObj, boolean f); + + // C++: void cv::FastFeatureDetector::setThreshold(int threshold) + private static native void setThreshold_0(long nativeObj, int threshold); + + // C++: void cv::FastFeatureDetector::setType(FastFeatureDetector_DetectorType type) + private static native void setType_0(long nativeObj, int type); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/features2d/Feature2D.java b/OpenCV/src/main/java/org/opencv/features2d/Feature2D.java new file mode 100644 index 00000000..07100341 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/features2d/Feature2D.java @@ -0,0 +1,293 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.features2d; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.core.MatOfKeyPoint; +import org.opencv.utils.Converters; + +// C++: class Feature2D +//javadoc: Feature2D + +public class Feature2D extends Algorithm { + + protected Feature2D(long addr) { super(addr); } + + // internal usage only + public static Feature2D __fromPtr__(long addr) { return new Feature2D(addr); } + + // + // C++: String cv::Feature2D::getDefaultName() + // + + //javadoc: Feature2D::getDefaultName() + public String getDefaultName() + { + + String retVal = getDefaultName_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::Feature2D::empty() + // + + //javadoc: Feature2D::empty() + public boolean empty() + { + + boolean retVal = empty_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::Feature2D::defaultNorm() + // + + //javadoc: Feature2D::defaultNorm() + public int defaultNorm() + { + + int retVal = defaultNorm_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::Feature2D::descriptorSize() + // + + //javadoc: Feature2D::descriptorSize() + public int descriptorSize() + { + + int retVal = descriptorSize_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::Feature2D::descriptorType() + // + + //javadoc: Feature2D::descriptorType() + public int descriptorType() + { + + int retVal = descriptorType_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::Feature2D::compute(Mat image, vector_KeyPoint& keypoints, Mat& descriptors) + // + + //javadoc: Feature2D::compute(image, keypoints, descriptors) + public void compute(Mat image, MatOfKeyPoint keypoints, Mat descriptors) + { + Mat keypoints_mat = keypoints; + compute_0(nativeObj, image.nativeObj, keypoints_mat.nativeObj, descriptors.nativeObj); + + return; + } + + + // + // C++: void cv::Feature2D::compute(vector_Mat images, vector_vector_KeyPoint& keypoints, vector_Mat& descriptors) + // + + //javadoc: Feature2D::compute(images, keypoints, descriptors) + public void compute(List images, List keypoints, List descriptors) + { + Mat images_mat = Converters.vector_Mat_to_Mat(images); + List keypoints_tmplm = new ArrayList((keypoints != null) ? keypoints.size() : 0); + Mat keypoints_mat = Converters.vector_vector_KeyPoint_to_Mat(keypoints, keypoints_tmplm); + Mat descriptors_mat = new Mat(); + compute_1(nativeObj, images_mat.nativeObj, keypoints_mat.nativeObj, descriptors_mat.nativeObj); + Converters.Mat_to_vector_vector_KeyPoint(keypoints_mat, keypoints); + keypoints_mat.release(); + Converters.Mat_to_vector_Mat(descriptors_mat, descriptors); + descriptors_mat.release(); + return; + } + + + // + // C++: void cv::Feature2D::detect(Mat image, vector_KeyPoint& keypoints, Mat mask = Mat()) + // + + //javadoc: Feature2D::detect(image, keypoints, mask) + public void detect(Mat image, MatOfKeyPoint keypoints, Mat mask) + { + Mat keypoints_mat = keypoints; + detect_0(nativeObj, image.nativeObj, keypoints_mat.nativeObj, mask.nativeObj); + + return; + } + + //javadoc: Feature2D::detect(image, keypoints) + public void detect(Mat image, MatOfKeyPoint keypoints) + { + Mat keypoints_mat = keypoints; + detect_1(nativeObj, image.nativeObj, keypoints_mat.nativeObj); + + return; + } + + + // + // C++: void cv::Feature2D::detect(vector_Mat images, vector_vector_KeyPoint& keypoints, vector_Mat masks = vector_Mat()) + // + + //javadoc: Feature2D::detect(images, keypoints, masks) + public void detect(List images, List keypoints, List masks) + { + Mat images_mat = Converters.vector_Mat_to_Mat(images); + Mat keypoints_mat = new Mat(); + Mat masks_mat = Converters.vector_Mat_to_Mat(masks); + detect_2(nativeObj, images_mat.nativeObj, keypoints_mat.nativeObj, masks_mat.nativeObj); + Converters.Mat_to_vector_vector_KeyPoint(keypoints_mat, keypoints); + keypoints_mat.release(); + return; + } + + //javadoc: Feature2D::detect(images, keypoints) + public void detect(List images, List keypoints) + { + Mat images_mat = Converters.vector_Mat_to_Mat(images); + Mat keypoints_mat = new Mat(); + detect_3(nativeObj, images_mat.nativeObj, keypoints_mat.nativeObj); + Converters.Mat_to_vector_vector_KeyPoint(keypoints_mat, keypoints); + keypoints_mat.release(); + return; + } + + + // + // C++: void cv::Feature2D::detectAndCompute(Mat image, Mat mask, vector_KeyPoint& keypoints, Mat& descriptors, bool useProvidedKeypoints = false) + // + + //javadoc: Feature2D::detectAndCompute(image, mask, keypoints, descriptors, useProvidedKeypoints) + public void detectAndCompute(Mat image, Mat mask, MatOfKeyPoint keypoints, Mat descriptors, boolean useProvidedKeypoints) + { + Mat keypoints_mat = keypoints; + detectAndCompute_0(nativeObj, image.nativeObj, mask.nativeObj, keypoints_mat.nativeObj, descriptors.nativeObj, useProvidedKeypoints); + + return; + } + + //javadoc: Feature2D::detectAndCompute(image, mask, keypoints, descriptors) + public void detectAndCompute(Mat image, Mat mask, MatOfKeyPoint keypoints, Mat descriptors) + { + Mat keypoints_mat = keypoints; + detectAndCompute_1(nativeObj, image.nativeObj, mask.nativeObj, keypoints_mat.nativeObj, descriptors.nativeObj); + + return; + } + + + // + // C++: void cv::Feature2D::read(FileNode arg1) + // + + // Unknown type 'FileNode' (I), skipping the function + + + // + // C++: void cv::Feature2D::read(String fileName) + // + + //javadoc: Feature2D::read(fileName) + public void read(String fileName) + { + + read_0(nativeObj, fileName); + + return; + } + + + // + // C++: void cv::Feature2D::write(Ptr_FileStorage fs, String name = String()) + // + + // Unknown type 'Ptr_FileStorage' (I), skipping the function + + + // + // C++: void cv::Feature2D::write(String fileName) + // + + //javadoc: Feature2D::write(fileName) + public void write(String fileName) + { + + write_0(nativeObj, fileName); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: String cv::Feature2D::getDefaultName() + private static native String getDefaultName_0(long nativeObj); + + // C++: bool cv::Feature2D::empty() + private static native boolean empty_0(long nativeObj); + + // C++: int cv::Feature2D::defaultNorm() + private static native int defaultNorm_0(long nativeObj); + + // C++: int cv::Feature2D::descriptorSize() + private static native int descriptorSize_0(long nativeObj); + + // C++: int cv::Feature2D::descriptorType() + private static native int descriptorType_0(long nativeObj); + + // C++: void cv::Feature2D::compute(Mat image, vector_KeyPoint& keypoints, Mat& descriptors) + private static native void compute_0(long nativeObj, long image_nativeObj, long keypoints_mat_nativeObj, long descriptors_nativeObj); + + // C++: void cv::Feature2D::compute(vector_Mat images, vector_vector_KeyPoint& keypoints, vector_Mat& descriptors) + private static native void compute_1(long nativeObj, long images_mat_nativeObj, long keypoints_mat_nativeObj, long descriptors_mat_nativeObj); + + // C++: void cv::Feature2D::detect(Mat image, vector_KeyPoint& keypoints, Mat mask = Mat()) + private static native void detect_0(long nativeObj, long image_nativeObj, long keypoints_mat_nativeObj, long mask_nativeObj); + private static native void detect_1(long nativeObj, long image_nativeObj, long keypoints_mat_nativeObj); + + // C++: void cv::Feature2D::detect(vector_Mat images, vector_vector_KeyPoint& keypoints, vector_Mat masks = vector_Mat()) + private static native void detect_2(long nativeObj, long images_mat_nativeObj, long keypoints_mat_nativeObj, long masks_mat_nativeObj); + private static native void detect_3(long nativeObj, long images_mat_nativeObj, long keypoints_mat_nativeObj); + + // C++: void cv::Feature2D::detectAndCompute(Mat image, Mat mask, vector_KeyPoint& keypoints, Mat& descriptors, bool useProvidedKeypoints = false) + private static native void detectAndCompute_0(long nativeObj, long image_nativeObj, long mask_nativeObj, long keypoints_mat_nativeObj, long descriptors_nativeObj, boolean useProvidedKeypoints); + private static native void detectAndCompute_1(long nativeObj, long image_nativeObj, long mask_nativeObj, long keypoints_mat_nativeObj, long descriptors_nativeObj); + + // C++: void cv::Feature2D::read(String fileName) + private static native void read_0(long nativeObj, String fileName); + + // C++: void cv::Feature2D::write(String fileName) + private static native void write_0(long nativeObj, String fileName); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/features2d/Features2d.java b/OpenCV/src/main/java/org/opencv/features2d/Features2d.java new file mode 100644 index 00000000..6bb2db1d --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/features2d/Features2d.java @@ -0,0 +1,212 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.features2d; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfByte; +import org.opencv.core.MatOfDMatch; +import org.opencv.core.MatOfKeyPoint; +import org.opencv.core.Scalar; +import org.opencv.utils.Converters; + +// C++: class Features2d +//javadoc: Features2d + +public class Features2d { + + // C++: enum DrawMatchesFlags + public static final int + DrawMatchesFlags_DEFAULT = 0, + DrawMatchesFlags_DRAW_OVER_OUTIMG = 1, + DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS = 2, + DrawMatchesFlags_DRAW_RICH_KEYPOINTS = 4; + + + // + // C++: void cv::drawKeypoints(Mat image, vector_KeyPoint keypoints, Mat& outImage, Scalar color = Scalar::all(-1), DrawMatchesFlags flags = DrawMatchesFlags::DEFAULT) + // + + //javadoc: drawKeypoints(image, keypoints, outImage, color, flags) + public static void drawKeypoints(Mat image, MatOfKeyPoint keypoints, Mat outImage, Scalar color, int flags) + { + Mat keypoints_mat = keypoints; + drawKeypoints_0(image.nativeObj, keypoints_mat.nativeObj, outImage.nativeObj, color.val[0], color.val[1], color.val[2], color.val[3], flags); + + return; + } + + //javadoc: drawKeypoints(image, keypoints, outImage, color) + public static void drawKeypoints(Mat image, MatOfKeyPoint keypoints, Mat outImage, Scalar color) + { + Mat keypoints_mat = keypoints; + drawKeypoints_1(image.nativeObj, keypoints_mat.nativeObj, outImage.nativeObj, color.val[0], color.val[1], color.val[2], color.val[3]); + + return; + } + + //javadoc: drawKeypoints(image, keypoints, outImage) + public static void drawKeypoints(Mat image, MatOfKeyPoint keypoints, Mat outImage) + { + Mat keypoints_mat = keypoints; + drawKeypoints_2(image.nativeObj, keypoints_mat.nativeObj, outImage.nativeObj); + + return; + } + + + // + // C++: void cv::drawMatches(Mat img1, vector_KeyPoint keypoints1, Mat img2, vector_KeyPoint keypoints2, vector_DMatch matches1to2, Mat& outImg, Scalar matchColor = Scalar::all(-1), Scalar singlePointColor = Scalar::all(-1), vector_char matchesMask = std::vector(), DrawMatchesFlags flags = DrawMatchesFlags::DEFAULT) + // + + //javadoc: drawMatches(img1, keypoints1, img2, keypoints2, matches1to2, outImg, matchColor, singlePointColor, matchesMask, flags) + public static void drawMatches(Mat img1, MatOfKeyPoint keypoints1, Mat img2, MatOfKeyPoint keypoints2, MatOfDMatch matches1to2, Mat outImg, Scalar matchColor, Scalar singlePointColor, MatOfByte matchesMask, int flags) + { + Mat keypoints1_mat = keypoints1; + Mat keypoints2_mat = keypoints2; + Mat matches1to2_mat = matches1to2; + Mat matchesMask_mat = matchesMask; + drawMatches_0(img1.nativeObj, keypoints1_mat.nativeObj, img2.nativeObj, keypoints2_mat.nativeObj, matches1to2_mat.nativeObj, outImg.nativeObj, matchColor.val[0], matchColor.val[1], matchColor.val[2], matchColor.val[3], singlePointColor.val[0], singlePointColor.val[1], singlePointColor.val[2], singlePointColor.val[3], matchesMask_mat.nativeObj, flags); + + return; + } + + //javadoc: drawMatches(img1, keypoints1, img2, keypoints2, matches1to2, outImg, matchColor, singlePointColor, matchesMask) + public static void drawMatches(Mat img1, MatOfKeyPoint keypoints1, Mat img2, MatOfKeyPoint keypoints2, MatOfDMatch matches1to2, Mat outImg, Scalar matchColor, Scalar singlePointColor, MatOfByte matchesMask) + { + Mat keypoints1_mat = keypoints1; + Mat keypoints2_mat = keypoints2; + Mat matches1to2_mat = matches1to2; + Mat matchesMask_mat = matchesMask; + drawMatches_1(img1.nativeObj, keypoints1_mat.nativeObj, img2.nativeObj, keypoints2_mat.nativeObj, matches1to2_mat.nativeObj, outImg.nativeObj, matchColor.val[0], matchColor.val[1], matchColor.val[2], matchColor.val[3], singlePointColor.val[0], singlePointColor.val[1], singlePointColor.val[2], singlePointColor.val[3], matchesMask_mat.nativeObj); + + return; + } + + //javadoc: drawMatches(img1, keypoints1, img2, keypoints2, matches1to2, outImg, matchColor, singlePointColor) + public static void drawMatches(Mat img1, MatOfKeyPoint keypoints1, Mat img2, MatOfKeyPoint keypoints2, MatOfDMatch matches1to2, Mat outImg, Scalar matchColor, Scalar singlePointColor) + { + Mat keypoints1_mat = keypoints1; + Mat keypoints2_mat = keypoints2; + Mat matches1to2_mat = matches1to2; + drawMatches_2(img1.nativeObj, keypoints1_mat.nativeObj, img2.nativeObj, keypoints2_mat.nativeObj, matches1to2_mat.nativeObj, outImg.nativeObj, matchColor.val[0], matchColor.val[1], matchColor.val[2], matchColor.val[3], singlePointColor.val[0], singlePointColor.val[1], singlePointColor.val[2], singlePointColor.val[3]); + + return; + } + + //javadoc: drawMatches(img1, keypoints1, img2, keypoints2, matches1to2, outImg, matchColor) + public static void drawMatches(Mat img1, MatOfKeyPoint keypoints1, Mat img2, MatOfKeyPoint keypoints2, MatOfDMatch matches1to2, Mat outImg, Scalar matchColor) + { + Mat keypoints1_mat = keypoints1; + Mat keypoints2_mat = keypoints2; + Mat matches1to2_mat = matches1to2; + drawMatches_3(img1.nativeObj, keypoints1_mat.nativeObj, img2.nativeObj, keypoints2_mat.nativeObj, matches1to2_mat.nativeObj, outImg.nativeObj, matchColor.val[0], matchColor.val[1], matchColor.val[2], matchColor.val[3]); + + return; + } + + //javadoc: drawMatches(img1, keypoints1, img2, keypoints2, matches1to2, outImg) + public static void drawMatches(Mat img1, MatOfKeyPoint keypoints1, Mat img2, MatOfKeyPoint keypoints2, MatOfDMatch matches1to2, Mat outImg) + { + Mat keypoints1_mat = keypoints1; + Mat keypoints2_mat = keypoints2; + Mat matches1to2_mat = matches1to2; + drawMatches_4(img1.nativeObj, keypoints1_mat.nativeObj, img2.nativeObj, keypoints2_mat.nativeObj, matches1to2_mat.nativeObj, outImg.nativeObj); + + return; + } + + + // + // C++: void cv::drawMatches(Mat img1, vector_KeyPoint keypoints1, Mat img2, vector_KeyPoint keypoints2, vector_vector_DMatch matches1to2, Mat& outImg, Scalar matchColor = Scalar::all(-1), Scalar singlePointColor = Scalar::all(-1), vector_vector_char matchesMask = std::vector >(), DrawMatchesFlags flags = DrawMatchesFlags::DEFAULT) + // + + //javadoc: drawMatchesKnn(img1, keypoints1, img2, keypoints2, matches1to2, outImg, matchColor, singlePointColor, matchesMask, flags) + public static void drawMatchesKnn(Mat img1, MatOfKeyPoint keypoints1, Mat img2, MatOfKeyPoint keypoints2, List matches1to2, Mat outImg, Scalar matchColor, Scalar singlePointColor, List matchesMask, int flags) + { + Mat keypoints1_mat = keypoints1; + Mat keypoints2_mat = keypoints2; + List matches1to2_tmplm = new ArrayList((matches1to2 != null) ? matches1to2.size() : 0); + Mat matches1to2_mat = Converters.vector_vector_DMatch_to_Mat(matches1to2, matches1to2_tmplm); + List matchesMask_tmplm = new ArrayList((matchesMask != null) ? matchesMask.size() : 0); + Mat matchesMask_mat = Converters.vector_vector_char_to_Mat(matchesMask, matchesMask_tmplm); + drawMatchesKnn_0(img1.nativeObj, keypoints1_mat.nativeObj, img2.nativeObj, keypoints2_mat.nativeObj, matches1to2_mat.nativeObj, outImg.nativeObj, matchColor.val[0], matchColor.val[1], matchColor.val[2], matchColor.val[3], singlePointColor.val[0], singlePointColor.val[1], singlePointColor.val[2], singlePointColor.val[3], matchesMask_mat.nativeObj, flags); + + return; + } + + //javadoc: drawMatchesKnn(img1, keypoints1, img2, keypoints2, matches1to2, outImg, matchColor, singlePointColor, matchesMask) + public static void drawMatchesKnn(Mat img1, MatOfKeyPoint keypoints1, Mat img2, MatOfKeyPoint keypoints2, List matches1to2, Mat outImg, Scalar matchColor, Scalar singlePointColor, List matchesMask) + { + Mat keypoints1_mat = keypoints1; + Mat keypoints2_mat = keypoints2; + List matches1to2_tmplm = new ArrayList((matches1to2 != null) ? matches1to2.size() : 0); + Mat matches1to2_mat = Converters.vector_vector_DMatch_to_Mat(matches1to2, matches1to2_tmplm); + List matchesMask_tmplm = new ArrayList((matchesMask != null) ? matchesMask.size() : 0); + Mat matchesMask_mat = Converters.vector_vector_char_to_Mat(matchesMask, matchesMask_tmplm); + drawMatchesKnn_1(img1.nativeObj, keypoints1_mat.nativeObj, img2.nativeObj, keypoints2_mat.nativeObj, matches1to2_mat.nativeObj, outImg.nativeObj, matchColor.val[0], matchColor.val[1], matchColor.val[2], matchColor.val[3], singlePointColor.val[0], singlePointColor.val[1], singlePointColor.val[2], singlePointColor.val[3], matchesMask_mat.nativeObj); + + return; + } + + //javadoc: drawMatchesKnn(img1, keypoints1, img2, keypoints2, matches1to2, outImg, matchColor, singlePointColor) + public static void drawMatchesKnn(Mat img1, MatOfKeyPoint keypoints1, Mat img2, MatOfKeyPoint keypoints2, List matches1to2, Mat outImg, Scalar matchColor, Scalar singlePointColor) + { + Mat keypoints1_mat = keypoints1; + Mat keypoints2_mat = keypoints2; + List matches1to2_tmplm = new ArrayList((matches1to2 != null) ? matches1to2.size() : 0); + Mat matches1to2_mat = Converters.vector_vector_DMatch_to_Mat(matches1to2, matches1to2_tmplm); + drawMatchesKnn_2(img1.nativeObj, keypoints1_mat.nativeObj, img2.nativeObj, keypoints2_mat.nativeObj, matches1to2_mat.nativeObj, outImg.nativeObj, matchColor.val[0], matchColor.val[1], matchColor.val[2], matchColor.val[3], singlePointColor.val[0], singlePointColor.val[1], singlePointColor.val[2], singlePointColor.val[3]); + + return; + } + + //javadoc: drawMatchesKnn(img1, keypoints1, img2, keypoints2, matches1to2, outImg, matchColor) + public static void drawMatchesKnn(Mat img1, MatOfKeyPoint keypoints1, Mat img2, MatOfKeyPoint keypoints2, List matches1to2, Mat outImg, Scalar matchColor) + { + Mat keypoints1_mat = keypoints1; + Mat keypoints2_mat = keypoints2; + List matches1to2_tmplm = new ArrayList((matches1to2 != null) ? matches1to2.size() : 0); + Mat matches1to2_mat = Converters.vector_vector_DMatch_to_Mat(matches1to2, matches1to2_tmplm); + drawMatchesKnn_3(img1.nativeObj, keypoints1_mat.nativeObj, img2.nativeObj, keypoints2_mat.nativeObj, matches1to2_mat.nativeObj, outImg.nativeObj, matchColor.val[0], matchColor.val[1], matchColor.val[2], matchColor.val[3]); + + return; + } + + //javadoc: drawMatchesKnn(img1, keypoints1, img2, keypoints2, matches1to2, outImg) + public static void drawMatchesKnn(Mat img1, MatOfKeyPoint keypoints1, Mat img2, MatOfKeyPoint keypoints2, List matches1to2, Mat outImg) + { + Mat keypoints1_mat = keypoints1; + Mat keypoints2_mat = keypoints2; + List matches1to2_tmplm = new ArrayList((matches1to2 != null) ? matches1to2.size() : 0); + Mat matches1to2_mat = Converters.vector_vector_DMatch_to_Mat(matches1to2, matches1to2_tmplm); + drawMatchesKnn_4(img1.nativeObj, keypoints1_mat.nativeObj, img2.nativeObj, keypoints2_mat.nativeObj, matches1to2_mat.nativeObj, outImg.nativeObj); + + return; + } + + + + + // C++: void cv::drawKeypoints(Mat image, vector_KeyPoint keypoints, Mat& outImage, Scalar color = Scalar::all(-1), DrawMatchesFlags flags = DrawMatchesFlags::DEFAULT) + private static native void drawKeypoints_0(long image_nativeObj, long keypoints_mat_nativeObj, long outImage_nativeObj, double color_val0, double color_val1, double color_val2, double color_val3, int flags); + private static native void drawKeypoints_1(long image_nativeObj, long keypoints_mat_nativeObj, long outImage_nativeObj, double color_val0, double color_val1, double color_val2, double color_val3); + private static native void drawKeypoints_2(long image_nativeObj, long keypoints_mat_nativeObj, long outImage_nativeObj); + + // C++: void cv::drawMatches(Mat img1, vector_KeyPoint keypoints1, Mat img2, vector_KeyPoint keypoints2, vector_DMatch matches1to2, Mat& outImg, Scalar matchColor = Scalar::all(-1), Scalar singlePointColor = Scalar::all(-1), vector_char matchesMask = std::vector(), DrawMatchesFlags flags = DrawMatchesFlags::DEFAULT) + private static native void drawMatches_0(long img1_nativeObj, long keypoints1_mat_nativeObj, long img2_nativeObj, long keypoints2_mat_nativeObj, long matches1to2_mat_nativeObj, long outImg_nativeObj, double matchColor_val0, double matchColor_val1, double matchColor_val2, double matchColor_val3, double singlePointColor_val0, double singlePointColor_val1, double singlePointColor_val2, double singlePointColor_val3, long matchesMask_mat_nativeObj, int flags); + private static native void drawMatches_1(long img1_nativeObj, long keypoints1_mat_nativeObj, long img2_nativeObj, long keypoints2_mat_nativeObj, long matches1to2_mat_nativeObj, long outImg_nativeObj, double matchColor_val0, double matchColor_val1, double matchColor_val2, double matchColor_val3, double singlePointColor_val0, double singlePointColor_val1, double singlePointColor_val2, double singlePointColor_val3, long matchesMask_mat_nativeObj); + private static native void drawMatches_2(long img1_nativeObj, long keypoints1_mat_nativeObj, long img2_nativeObj, long keypoints2_mat_nativeObj, long matches1to2_mat_nativeObj, long outImg_nativeObj, double matchColor_val0, double matchColor_val1, double matchColor_val2, double matchColor_val3, double singlePointColor_val0, double singlePointColor_val1, double singlePointColor_val2, double singlePointColor_val3); + private static native void drawMatches_3(long img1_nativeObj, long keypoints1_mat_nativeObj, long img2_nativeObj, long keypoints2_mat_nativeObj, long matches1to2_mat_nativeObj, long outImg_nativeObj, double matchColor_val0, double matchColor_val1, double matchColor_val2, double matchColor_val3); + private static native void drawMatches_4(long img1_nativeObj, long keypoints1_mat_nativeObj, long img2_nativeObj, long keypoints2_mat_nativeObj, long matches1to2_mat_nativeObj, long outImg_nativeObj); + + // C++: void cv::drawMatches(Mat img1, vector_KeyPoint keypoints1, Mat img2, vector_KeyPoint keypoints2, vector_vector_DMatch matches1to2, Mat& outImg, Scalar matchColor = Scalar::all(-1), Scalar singlePointColor = Scalar::all(-1), vector_vector_char matchesMask = std::vector >(), DrawMatchesFlags flags = DrawMatchesFlags::DEFAULT) + private static native void drawMatchesKnn_0(long img1_nativeObj, long keypoints1_mat_nativeObj, long img2_nativeObj, long keypoints2_mat_nativeObj, long matches1to2_mat_nativeObj, long outImg_nativeObj, double matchColor_val0, double matchColor_val1, double matchColor_val2, double matchColor_val3, double singlePointColor_val0, double singlePointColor_val1, double singlePointColor_val2, double singlePointColor_val3, long matchesMask_mat_nativeObj, int flags); + private static native void drawMatchesKnn_1(long img1_nativeObj, long keypoints1_mat_nativeObj, long img2_nativeObj, long keypoints2_mat_nativeObj, long matches1to2_mat_nativeObj, long outImg_nativeObj, double matchColor_val0, double matchColor_val1, double matchColor_val2, double matchColor_val3, double singlePointColor_val0, double singlePointColor_val1, double singlePointColor_val2, double singlePointColor_val3, long matchesMask_mat_nativeObj); + private static native void drawMatchesKnn_2(long img1_nativeObj, long keypoints1_mat_nativeObj, long img2_nativeObj, long keypoints2_mat_nativeObj, long matches1to2_mat_nativeObj, long outImg_nativeObj, double matchColor_val0, double matchColor_val1, double matchColor_val2, double matchColor_val3, double singlePointColor_val0, double singlePointColor_val1, double singlePointColor_val2, double singlePointColor_val3); + private static native void drawMatchesKnn_3(long img1_nativeObj, long keypoints1_mat_nativeObj, long img2_nativeObj, long keypoints2_mat_nativeObj, long matches1to2_mat_nativeObj, long outImg_nativeObj, double matchColor_val0, double matchColor_val1, double matchColor_val2, double matchColor_val3); + private static native void drawMatchesKnn_4(long img1_nativeObj, long keypoints1_mat_nativeObj, long img2_nativeObj, long keypoints2_mat_nativeObj, long matches1to2_mat_nativeObj, long outImg_nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/features2d/FlannBasedMatcher.java b/OpenCV/src/main/java/org/opencv/features2d/FlannBasedMatcher.java new file mode 100644 index 00000000..1de9318b --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/features2d/FlannBasedMatcher.java @@ -0,0 +1,63 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.features2d; + +import org.opencv.features2d.DescriptorMatcher; +import org.opencv.features2d.FlannBasedMatcher; + +// C++: class FlannBasedMatcher +//javadoc: FlannBasedMatcher + +public class FlannBasedMatcher extends DescriptorMatcher { + + protected FlannBasedMatcher(long addr) { super(addr); } + + // internal usage only + public static FlannBasedMatcher __fromPtr__(long addr) { return new FlannBasedMatcher(addr); } + + // + // C++: cv::FlannBasedMatcher::FlannBasedMatcher(Ptr_flann_IndexParams indexParams = makePtr(), Ptr_flann_SearchParams searchParams = makePtr()) + // + + //javadoc: FlannBasedMatcher::FlannBasedMatcher() + public FlannBasedMatcher() + { + + super( FlannBasedMatcher_0() ); + + return; + } + + + // + // C++: static Ptr_FlannBasedMatcher cv::FlannBasedMatcher::create() + // + + //javadoc: FlannBasedMatcher::create() + public static FlannBasedMatcher create() + { + + FlannBasedMatcher retVal = FlannBasedMatcher.__fromPtr__(create_0()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: cv::FlannBasedMatcher::FlannBasedMatcher(Ptr_flann_IndexParams indexParams = makePtr(), Ptr_flann_SearchParams searchParams = makePtr()) + private static native long FlannBasedMatcher_0(); + + // C++: static Ptr_FlannBasedMatcher cv::FlannBasedMatcher::create() + private static native long create_0(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/features2d/GFTTDetector.java b/OpenCV/src/main/java/org/opencv/features2d/GFTTDetector.java new file mode 100644 index 00000000..e1609df1 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/features2d/GFTTDetector.java @@ -0,0 +1,365 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.features2d; + +import java.lang.String; +import org.opencv.features2d.Feature2D; +import org.opencv.features2d.GFTTDetector; + +// C++: class GFTTDetector +//javadoc: GFTTDetector + +public class GFTTDetector extends Feature2D { + + protected GFTTDetector(long addr) { super(addr); } + + // internal usage only + public static GFTTDetector __fromPtr__(long addr) { return new GFTTDetector(addr); } + + // + // C++: static Ptr_GFTTDetector cv::GFTTDetector::create(int maxCorners, double qualityLevel, double minDistance, int blockSize, int gradiantSize, bool useHarrisDetector = false, double k = 0.04) + // + + //javadoc: GFTTDetector::create(maxCorners, qualityLevel, minDistance, blockSize, gradiantSize, useHarrisDetector, k) + public static GFTTDetector create(int maxCorners, double qualityLevel, double minDistance, int blockSize, int gradiantSize, boolean useHarrisDetector, double k) + { + + GFTTDetector retVal = GFTTDetector.__fromPtr__(create_0(maxCorners, qualityLevel, minDistance, blockSize, gradiantSize, useHarrisDetector, k)); + + return retVal; + } + + //javadoc: GFTTDetector::create(maxCorners, qualityLevel, minDistance, blockSize, gradiantSize, useHarrisDetector) + public static GFTTDetector create(int maxCorners, double qualityLevel, double minDistance, int blockSize, int gradiantSize, boolean useHarrisDetector) + { + + GFTTDetector retVal = GFTTDetector.__fromPtr__(create_1(maxCorners, qualityLevel, minDistance, blockSize, gradiantSize, useHarrisDetector)); + + return retVal; + } + + //javadoc: GFTTDetector::create(maxCorners, qualityLevel, minDistance, blockSize, gradiantSize) + public static GFTTDetector create(int maxCorners, double qualityLevel, double minDistance, int blockSize, int gradiantSize) + { + + GFTTDetector retVal = GFTTDetector.__fromPtr__(create_2(maxCorners, qualityLevel, minDistance, blockSize, gradiantSize)); + + return retVal; + } + + + // + // C++: static Ptr_GFTTDetector cv::GFTTDetector::create(int maxCorners = 1000, double qualityLevel = 0.01, double minDistance = 1, int blockSize = 3, bool useHarrisDetector = false, double k = 0.04) + // + + //javadoc: GFTTDetector::create(maxCorners, qualityLevel, minDistance, blockSize, useHarrisDetector, k) + public static GFTTDetector create(int maxCorners, double qualityLevel, double minDistance, int blockSize, boolean useHarrisDetector, double k) + { + + GFTTDetector retVal = GFTTDetector.__fromPtr__(create_3(maxCorners, qualityLevel, minDistance, blockSize, useHarrisDetector, k)); + + return retVal; + } + + //javadoc: GFTTDetector::create(maxCorners, qualityLevel, minDistance, blockSize, useHarrisDetector) + public static GFTTDetector create(int maxCorners, double qualityLevel, double minDistance, int blockSize, boolean useHarrisDetector) + { + + GFTTDetector retVal = GFTTDetector.__fromPtr__(create_4(maxCorners, qualityLevel, minDistance, blockSize, useHarrisDetector)); + + return retVal; + } + + //javadoc: GFTTDetector::create(maxCorners, qualityLevel, minDistance, blockSize) + public static GFTTDetector create(int maxCorners, double qualityLevel, double minDistance, int blockSize) + { + + GFTTDetector retVal = GFTTDetector.__fromPtr__(create_5(maxCorners, qualityLevel, minDistance, blockSize)); + + return retVal; + } + + //javadoc: GFTTDetector::create(maxCorners, qualityLevel, minDistance) + public static GFTTDetector create(int maxCorners, double qualityLevel, double minDistance) + { + + GFTTDetector retVal = GFTTDetector.__fromPtr__(create_6(maxCorners, qualityLevel, minDistance)); + + return retVal; + } + + //javadoc: GFTTDetector::create(maxCorners, qualityLevel) + public static GFTTDetector create(int maxCorners, double qualityLevel) + { + + GFTTDetector retVal = GFTTDetector.__fromPtr__(create_7(maxCorners, qualityLevel)); + + return retVal; + } + + //javadoc: GFTTDetector::create(maxCorners) + public static GFTTDetector create(int maxCorners) + { + + GFTTDetector retVal = GFTTDetector.__fromPtr__(create_8(maxCorners)); + + return retVal; + } + + //javadoc: GFTTDetector::create() + public static GFTTDetector create() + { + + GFTTDetector retVal = GFTTDetector.__fromPtr__(create_9()); + + return retVal; + } + + + // + // C++: String cv::GFTTDetector::getDefaultName() + // + + //javadoc: GFTTDetector::getDefaultName() + public String getDefaultName() + { + + String retVal = getDefaultName_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::GFTTDetector::getHarrisDetector() + // + + //javadoc: GFTTDetector::getHarrisDetector() + public boolean getHarrisDetector() + { + + boolean retVal = getHarrisDetector_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::GFTTDetector::getK() + // + + //javadoc: GFTTDetector::getK() + public double getK() + { + + double retVal = getK_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::GFTTDetector::getMinDistance() + // + + //javadoc: GFTTDetector::getMinDistance() + public double getMinDistance() + { + + double retVal = getMinDistance_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::GFTTDetector::getQualityLevel() + // + + //javadoc: GFTTDetector::getQualityLevel() + public double getQualityLevel() + { + + double retVal = getQualityLevel_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::GFTTDetector::getBlockSize() + // + + //javadoc: GFTTDetector::getBlockSize() + public int getBlockSize() + { + + int retVal = getBlockSize_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::GFTTDetector::getMaxFeatures() + // + + //javadoc: GFTTDetector::getMaxFeatures() + public int getMaxFeatures() + { + + int retVal = getMaxFeatures_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::GFTTDetector::setBlockSize(int blockSize) + // + + //javadoc: GFTTDetector::setBlockSize(blockSize) + public void setBlockSize(int blockSize) + { + + setBlockSize_0(nativeObj, blockSize); + + return; + } + + + // + // C++: void cv::GFTTDetector::setHarrisDetector(bool val) + // + + //javadoc: GFTTDetector::setHarrisDetector(val) + public void setHarrisDetector(boolean val) + { + + setHarrisDetector_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::GFTTDetector::setK(double k) + // + + //javadoc: GFTTDetector::setK(k) + public void setK(double k) + { + + setK_0(nativeObj, k); + + return; + } + + + // + // C++: void cv::GFTTDetector::setMaxFeatures(int maxFeatures) + // + + //javadoc: GFTTDetector::setMaxFeatures(maxFeatures) + public void setMaxFeatures(int maxFeatures) + { + + setMaxFeatures_0(nativeObj, maxFeatures); + + return; + } + + + // + // C++: void cv::GFTTDetector::setMinDistance(double minDistance) + // + + //javadoc: GFTTDetector::setMinDistance(minDistance) + public void setMinDistance(double minDistance) + { + + setMinDistance_0(nativeObj, minDistance); + + return; + } + + + // + // C++: void cv::GFTTDetector::setQualityLevel(double qlevel) + // + + //javadoc: GFTTDetector::setQualityLevel(qlevel) + public void setQualityLevel(double qlevel) + { + + setQualityLevel_0(nativeObj, qlevel); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_GFTTDetector cv::GFTTDetector::create(int maxCorners, double qualityLevel, double minDistance, int blockSize, int gradiantSize, bool useHarrisDetector = false, double k = 0.04) + private static native long create_0(int maxCorners, double qualityLevel, double minDistance, int blockSize, int gradiantSize, boolean useHarrisDetector, double k); + private static native long create_1(int maxCorners, double qualityLevel, double minDistance, int blockSize, int gradiantSize, boolean useHarrisDetector); + private static native long create_2(int maxCorners, double qualityLevel, double minDistance, int blockSize, int gradiantSize); + + // C++: static Ptr_GFTTDetector cv::GFTTDetector::create(int maxCorners = 1000, double qualityLevel = 0.01, double minDistance = 1, int blockSize = 3, bool useHarrisDetector = false, double k = 0.04) + private static native long create_3(int maxCorners, double qualityLevel, double minDistance, int blockSize, boolean useHarrisDetector, double k); + private static native long create_4(int maxCorners, double qualityLevel, double minDistance, int blockSize, boolean useHarrisDetector); + private static native long create_5(int maxCorners, double qualityLevel, double minDistance, int blockSize); + private static native long create_6(int maxCorners, double qualityLevel, double minDistance); + private static native long create_7(int maxCorners, double qualityLevel); + private static native long create_8(int maxCorners); + private static native long create_9(); + + // C++: String cv::GFTTDetector::getDefaultName() + private static native String getDefaultName_0(long nativeObj); + + // C++: bool cv::GFTTDetector::getHarrisDetector() + private static native boolean getHarrisDetector_0(long nativeObj); + + // C++: double cv::GFTTDetector::getK() + private static native double getK_0(long nativeObj); + + // C++: double cv::GFTTDetector::getMinDistance() + private static native double getMinDistance_0(long nativeObj); + + // C++: double cv::GFTTDetector::getQualityLevel() + private static native double getQualityLevel_0(long nativeObj); + + // C++: int cv::GFTTDetector::getBlockSize() + private static native int getBlockSize_0(long nativeObj); + + // C++: int cv::GFTTDetector::getMaxFeatures() + private static native int getMaxFeatures_0(long nativeObj); + + // C++: void cv::GFTTDetector::setBlockSize(int blockSize) + private static native void setBlockSize_0(long nativeObj, int blockSize); + + // C++: void cv::GFTTDetector::setHarrisDetector(bool val) + private static native void setHarrisDetector_0(long nativeObj, boolean val); + + // C++: void cv::GFTTDetector::setK(double k) + private static native void setK_0(long nativeObj, double k); + + // C++: void cv::GFTTDetector::setMaxFeatures(int maxFeatures) + private static native void setMaxFeatures_0(long nativeObj, int maxFeatures); + + // C++: void cv::GFTTDetector::setMinDistance(double minDistance) + private static native void setMinDistance_0(long nativeObj, double minDistance); + + // C++: void cv::GFTTDetector::setQualityLevel(double qlevel) + private static native void setQualityLevel_0(long nativeObj, double qlevel); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/features2d/KAZE.java b/OpenCV/src/main/java/org/opencv/features2d/KAZE.java new file mode 100644 index 00000000..7a69b03a --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/features2d/KAZE.java @@ -0,0 +1,336 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.features2d; + +import java.lang.String; +import org.opencv.features2d.Feature2D; +import org.opencv.features2d.KAZE; + +// C++: class KAZE +//javadoc: KAZE + +public class KAZE extends Feature2D { + + protected KAZE(long addr) { super(addr); } + + // internal usage only + public static KAZE __fromPtr__(long addr) { return new KAZE(addr); } + + // C++: enum DiffusivityType + public static final int + DIFF_PM_G1 = 0, + DIFF_PM_G2 = 1, + DIFF_WEICKERT = 2, + DIFF_CHARBONNIER = 3; + + + // + // C++: KAZE_DiffusivityType cv::KAZE::getDiffusivity() + // + + //javadoc: KAZE::getDiffusivity() + public int getDiffusivity() + { + + int retVal = getDiffusivity_0(nativeObj); + + return retVal; + } + + + // + // C++: static Ptr_KAZE cv::KAZE::create(bool extended = false, bool upright = false, float threshold = 0.001f, int nOctaves = 4, int nOctaveLayers = 4, KAZE_DiffusivityType diffusivity = KAZE::DIFF_PM_G2) + // + + //javadoc: KAZE::create(extended, upright, threshold, nOctaves, nOctaveLayers, diffusivity) + public static KAZE create(boolean extended, boolean upright, float threshold, int nOctaves, int nOctaveLayers, int diffusivity) + { + + KAZE retVal = KAZE.__fromPtr__(create_0(extended, upright, threshold, nOctaves, nOctaveLayers, diffusivity)); + + return retVal; + } + + //javadoc: KAZE::create(extended, upright, threshold, nOctaves, nOctaveLayers) + public static KAZE create(boolean extended, boolean upright, float threshold, int nOctaves, int nOctaveLayers) + { + + KAZE retVal = KAZE.__fromPtr__(create_1(extended, upright, threshold, nOctaves, nOctaveLayers)); + + return retVal; + } + + //javadoc: KAZE::create(extended, upright, threshold, nOctaves) + public static KAZE create(boolean extended, boolean upright, float threshold, int nOctaves) + { + + KAZE retVal = KAZE.__fromPtr__(create_2(extended, upright, threshold, nOctaves)); + + return retVal; + } + + //javadoc: KAZE::create(extended, upright, threshold) + public static KAZE create(boolean extended, boolean upright, float threshold) + { + + KAZE retVal = KAZE.__fromPtr__(create_3(extended, upright, threshold)); + + return retVal; + } + + //javadoc: KAZE::create(extended, upright) + public static KAZE create(boolean extended, boolean upright) + { + + KAZE retVal = KAZE.__fromPtr__(create_4(extended, upright)); + + return retVal; + } + + //javadoc: KAZE::create(extended) + public static KAZE create(boolean extended) + { + + KAZE retVal = KAZE.__fromPtr__(create_5(extended)); + + return retVal; + } + + //javadoc: KAZE::create() + public static KAZE create() + { + + KAZE retVal = KAZE.__fromPtr__(create_6()); + + return retVal; + } + + + // + // C++: String cv::KAZE::getDefaultName() + // + + //javadoc: KAZE::getDefaultName() + public String getDefaultName() + { + + String retVal = getDefaultName_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::KAZE::getExtended() + // + + //javadoc: KAZE::getExtended() + public boolean getExtended() + { + + boolean retVal = getExtended_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::KAZE::getUpright() + // + + //javadoc: KAZE::getUpright() + public boolean getUpright() + { + + boolean retVal = getUpright_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::KAZE::getThreshold() + // + + //javadoc: KAZE::getThreshold() + public double getThreshold() + { + + double retVal = getThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::KAZE::getNOctaveLayers() + // + + //javadoc: KAZE::getNOctaveLayers() + public int getNOctaveLayers() + { + + int retVal = getNOctaveLayers_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::KAZE::getNOctaves() + // + + //javadoc: KAZE::getNOctaves() + public int getNOctaves() + { + + int retVal = getNOctaves_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::KAZE::setDiffusivity(KAZE_DiffusivityType diff) + // + + //javadoc: KAZE::setDiffusivity(diff) + public void setDiffusivity(int diff) + { + + setDiffusivity_0(nativeObj, diff); + + return; + } + + + // + // C++: void cv::KAZE::setExtended(bool extended) + // + + //javadoc: KAZE::setExtended(extended) + public void setExtended(boolean extended) + { + + setExtended_0(nativeObj, extended); + + return; + } + + + // + // C++: void cv::KAZE::setNOctaveLayers(int octaveLayers) + // + + //javadoc: KAZE::setNOctaveLayers(octaveLayers) + public void setNOctaveLayers(int octaveLayers) + { + + setNOctaveLayers_0(nativeObj, octaveLayers); + + return; + } + + + // + // C++: void cv::KAZE::setNOctaves(int octaves) + // + + //javadoc: KAZE::setNOctaves(octaves) + public void setNOctaves(int octaves) + { + + setNOctaves_0(nativeObj, octaves); + + return; + } + + + // + // C++: void cv::KAZE::setThreshold(double threshold) + // + + //javadoc: KAZE::setThreshold(threshold) + public void setThreshold(double threshold) + { + + setThreshold_0(nativeObj, threshold); + + return; + } + + + // + // C++: void cv::KAZE::setUpright(bool upright) + // + + //javadoc: KAZE::setUpright(upright) + public void setUpright(boolean upright) + { + + setUpright_0(nativeObj, upright); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: KAZE_DiffusivityType cv::KAZE::getDiffusivity() + private static native int getDiffusivity_0(long nativeObj); + + // C++: static Ptr_KAZE cv::KAZE::create(bool extended = false, bool upright = false, float threshold = 0.001f, int nOctaves = 4, int nOctaveLayers = 4, KAZE_DiffusivityType diffusivity = KAZE::DIFF_PM_G2) + private static native long create_0(boolean extended, boolean upright, float threshold, int nOctaves, int nOctaveLayers, int diffusivity); + private static native long create_1(boolean extended, boolean upright, float threshold, int nOctaves, int nOctaveLayers); + private static native long create_2(boolean extended, boolean upright, float threshold, int nOctaves); + private static native long create_3(boolean extended, boolean upright, float threshold); + private static native long create_4(boolean extended, boolean upright); + private static native long create_5(boolean extended); + private static native long create_6(); + + // C++: String cv::KAZE::getDefaultName() + private static native String getDefaultName_0(long nativeObj); + + // C++: bool cv::KAZE::getExtended() + private static native boolean getExtended_0(long nativeObj); + + // C++: bool cv::KAZE::getUpright() + private static native boolean getUpright_0(long nativeObj); + + // C++: double cv::KAZE::getThreshold() + private static native double getThreshold_0(long nativeObj); + + // C++: int cv::KAZE::getNOctaveLayers() + private static native int getNOctaveLayers_0(long nativeObj); + + // C++: int cv::KAZE::getNOctaves() + private static native int getNOctaves_0(long nativeObj); + + // C++: void cv::KAZE::setDiffusivity(KAZE_DiffusivityType diff) + private static native void setDiffusivity_0(long nativeObj, int diff); + + // C++: void cv::KAZE::setExtended(bool extended) + private static native void setExtended_0(long nativeObj, boolean extended); + + // C++: void cv::KAZE::setNOctaveLayers(int octaveLayers) + private static native void setNOctaveLayers_0(long nativeObj, int octaveLayers); + + // C++: void cv::KAZE::setNOctaves(int octaves) + private static native void setNOctaves_0(long nativeObj, int octaves); + + // C++: void cv::KAZE::setThreshold(double threshold) + private static native void setThreshold_0(long nativeObj, double threshold); + + // C++: void cv::KAZE::setUpright(bool upright) + private static native void setUpright_0(long nativeObj, boolean upright); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/features2d/MSER.java b/OpenCV/src/main/java/org/opencv/features2d/MSER.java new file mode 100644 index 00000000..ac78cc0d --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/features2d/MSER.java @@ -0,0 +1,315 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.features2d; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfPoint; +import org.opencv.core.MatOfRect; +import org.opencv.features2d.Feature2D; +import org.opencv.features2d.MSER; +import org.opencv.utils.Converters; + +// C++: class MSER +//javadoc: MSER + +public class MSER extends Feature2D { + + protected MSER(long addr) { super(addr); } + + // internal usage only + public static MSER __fromPtr__(long addr) { return new MSER(addr); } + + // + // C++: static Ptr_MSER cv::MSER::create(int _delta = 5, int _min_area = 60, int _max_area = 14400, double _max_variation = 0.25, double _min_diversity = .2, int _max_evolution = 200, double _area_threshold = 1.01, double _min_margin = 0.003, int _edge_blur_size = 5) + // + + //javadoc: MSER::create(_delta, _min_area, _max_area, _max_variation, _min_diversity, _max_evolution, _area_threshold, _min_margin, _edge_blur_size) + public static MSER create(int _delta, int _min_area, int _max_area, double _max_variation, double _min_diversity, int _max_evolution, double _area_threshold, double _min_margin, int _edge_blur_size) + { + + MSER retVal = MSER.__fromPtr__(create_0(_delta, _min_area, _max_area, _max_variation, _min_diversity, _max_evolution, _area_threshold, _min_margin, _edge_blur_size)); + + return retVal; + } + + //javadoc: MSER::create(_delta, _min_area, _max_area, _max_variation, _min_diversity, _max_evolution, _area_threshold, _min_margin) + public static MSER create(int _delta, int _min_area, int _max_area, double _max_variation, double _min_diversity, int _max_evolution, double _area_threshold, double _min_margin) + { + + MSER retVal = MSER.__fromPtr__(create_1(_delta, _min_area, _max_area, _max_variation, _min_diversity, _max_evolution, _area_threshold, _min_margin)); + + return retVal; + } + + //javadoc: MSER::create(_delta, _min_area, _max_area, _max_variation, _min_diversity, _max_evolution, _area_threshold) + public static MSER create(int _delta, int _min_area, int _max_area, double _max_variation, double _min_diversity, int _max_evolution, double _area_threshold) + { + + MSER retVal = MSER.__fromPtr__(create_2(_delta, _min_area, _max_area, _max_variation, _min_diversity, _max_evolution, _area_threshold)); + + return retVal; + } + + //javadoc: MSER::create(_delta, _min_area, _max_area, _max_variation, _min_diversity, _max_evolution) + public static MSER create(int _delta, int _min_area, int _max_area, double _max_variation, double _min_diversity, int _max_evolution) + { + + MSER retVal = MSER.__fromPtr__(create_3(_delta, _min_area, _max_area, _max_variation, _min_diversity, _max_evolution)); + + return retVal; + } + + //javadoc: MSER::create(_delta, _min_area, _max_area, _max_variation, _min_diversity) + public static MSER create(int _delta, int _min_area, int _max_area, double _max_variation, double _min_diversity) + { + + MSER retVal = MSER.__fromPtr__(create_4(_delta, _min_area, _max_area, _max_variation, _min_diversity)); + + return retVal; + } + + //javadoc: MSER::create(_delta, _min_area, _max_area, _max_variation) + public static MSER create(int _delta, int _min_area, int _max_area, double _max_variation) + { + + MSER retVal = MSER.__fromPtr__(create_5(_delta, _min_area, _max_area, _max_variation)); + + return retVal; + } + + //javadoc: MSER::create(_delta, _min_area, _max_area) + public static MSER create(int _delta, int _min_area, int _max_area) + { + + MSER retVal = MSER.__fromPtr__(create_6(_delta, _min_area, _max_area)); + + return retVal; + } + + //javadoc: MSER::create(_delta, _min_area) + public static MSER create(int _delta, int _min_area) + { + + MSER retVal = MSER.__fromPtr__(create_7(_delta, _min_area)); + + return retVal; + } + + //javadoc: MSER::create(_delta) + public static MSER create(int _delta) + { + + MSER retVal = MSER.__fromPtr__(create_8(_delta)); + + return retVal; + } + + //javadoc: MSER::create() + public static MSER create() + { + + MSER retVal = MSER.__fromPtr__(create_9()); + + return retVal; + } + + + // + // C++: String cv::MSER::getDefaultName() + // + + //javadoc: MSER::getDefaultName() + public String getDefaultName() + { + + String retVal = getDefaultName_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::MSER::getPass2Only() + // + + //javadoc: MSER::getPass2Only() + public boolean getPass2Only() + { + + boolean retVal = getPass2Only_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::MSER::getDelta() + // + + //javadoc: MSER::getDelta() + public int getDelta() + { + + int retVal = getDelta_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::MSER::getMaxArea() + // + + //javadoc: MSER::getMaxArea() + public int getMaxArea() + { + + int retVal = getMaxArea_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::MSER::getMinArea() + // + + //javadoc: MSER::getMinArea() + public int getMinArea() + { + + int retVal = getMinArea_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::MSER::detectRegions(Mat image, vector_vector_Point& msers, vector_Rect& bboxes) + // + + //javadoc: MSER::detectRegions(image, msers, bboxes) + public void detectRegions(Mat image, List msers, MatOfRect bboxes) + { + Mat msers_mat = new Mat(); + Mat bboxes_mat = bboxes; + detectRegions_0(nativeObj, image.nativeObj, msers_mat.nativeObj, bboxes_mat.nativeObj); + Converters.Mat_to_vector_vector_Point(msers_mat, msers); + msers_mat.release(); + return; + } + + + // + // C++: void cv::MSER::setDelta(int delta) + // + + //javadoc: MSER::setDelta(delta) + public void setDelta(int delta) + { + + setDelta_0(nativeObj, delta); + + return; + } + + + // + // C++: void cv::MSER::setMaxArea(int maxArea) + // + + //javadoc: MSER::setMaxArea(maxArea) + public void setMaxArea(int maxArea) + { + + setMaxArea_0(nativeObj, maxArea); + + return; + } + + + // + // C++: void cv::MSER::setMinArea(int minArea) + // + + //javadoc: MSER::setMinArea(minArea) + public void setMinArea(int minArea) + { + + setMinArea_0(nativeObj, minArea); + + return; + } + + + // + // C++: void cv::MSER::setPass2Only(bool f) + // + + //javadoc: MSER::setPass2Only(f) + public void setPass2Only(boolean f) + { + + setPass2Only_0(nativeObj, f); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_MSER cv::MSER::create(int _delta = 5, int _min_area = 60, int _max_area = 14400, double _max_variation = 0.25, double _min_diversity = .2, int _max_evolution = 200, double _area_threshold = 1.01, double _min_margin = 0.003, int _edge_blur_size = 5) + private static native long create_0(int _delta, int _min_area, int _max_area, double _max_variation, double _min_diversity, int _max_evolution, double _area_threshold, double _min_margin, int _edge_blur_size); + private static native long create_1(int _delta, int _min_area, int _max_area, double _max_variation, double _min_diversity, int _max_evolution, double _area_threshold, double _min_margin); + private static native long create_2(int _delta, int _min_area, int _max_area, double _max_variation, double _min_diversity, int _max_evolution, double _area_threshold); + private static native long create_3(int _delta, int _min_area, int _max_area, double _max_variation, double _min_diversity, int _max_evolution); + private static native long create_4(int _delta, int _min_area, int _max_area, double _max_variation, double _min_diversity); + private static native long create_5(int _delta, int _min_area, int _max_area, double _max_variation); + private static native long create_6(int _delta, int _min_area, int _max_area); + private static native long create_7(int _delta, int _min_area); + private static native long create_8(int _delta); + private static native long create_9(); + + // C++: String cv::MSER::getDefaultName() + private static native String getDefaultName_0(long nativeObj); + + // C++: bool cv::MSER::getPass2Only() + private static native boolean getPass2Only_0(long nativeObj); + + // C++: int cv::MSER::getDelta() + private static native int getDelta_0(long nativeObj); + + // C++: int cv::MSER::getMaxArea() + private static native int getMaxArea_0(long nativeObj); + + // C++: int cv::MSER::getMinArea() + private static native int getMinArea_0(long nativeObj); + + // C++: void cv::MSER::detectRegions(Mat image, vector_vector_Point& msers, vector_Rect& bboxes) + private static native void detectRegions_0(long nativeObj, long image_nativeObj, long msers_mat_nativeObj, long bboxes_mat_nativeObj); + + // C++: void cv::MSER::setDelta(int delta) + private static native void setDelta_0(long nativeObj, int delta); + + // C++: void cv::MSER::setMaxArea(int maxArea) + private static native void setMaxArea_0(long nativeObj, int maxArea); + + // C++: void cv::MSER::setMinArea(int minArea) + private static native void setMinArea_0(long nativeObj, int minArea); + + // C++: void cv::MSER::setPass2Only(bool f) + private static native void setPass2Only_0(long nativeObj, boolean f); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/features2d/ORB.java b/OpenCV/src/main/java/org/opencv/features2d/ORB.java new file mode 100644 index 00000000..e46d31c7 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/features2d/ORB.java @@ -0,0 +1,466 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.features2d; + +import java.lang.String; +import org.opencv.features2d.Feature2D; +import org.opencv.features2d.ORB; + +// C++: class ORB +//javadoc: ORB + +public class ORB extends Feature2D { + + protected ORB(long addr) { super(addr); } + + // internal usage only + public static ORB __fromPtr__(long addr) { return new ORB(addr); } + + // C++: enum ScoreType + public static final int + HARRIS_SCORE = 0, + FAST_SCORE = 1; + + + // + // C++: ORB_ScoreType cv::ORB::getScoreType() + // + + //javadoc: ORB::getScoreType() + public int getScoreType() + { + + int retVal = getScoreType_0(nativeObj); + + return retVal; + } + + + // + // C++: static Ptr_ORB cv::ORB::create(int nfeatures = 500, float scaleFactor = 1.2f, int nlevels = 8, int edgeThreshold = 31, int firstLevel = 0, int WTA_K = 2, ORB_ScoreType scoreType = ORB::HARRIS_SCORE, int patchSize = 31, int fastThreshold = 20) + // + + //javadoc: ORB::create(nfeatures, scaleFactor, nlevels, edgeThreshold, firstLevel, WTA_K, scoreType, patchSize, fastThreshold) + public static ORB create(int nfeatures, float scaleFactor, int nlevels, int edgeThreshold, int firstLevel, int WTA_K, int scoreType, int patchSize, int fastThreshold) + { + + ORB retVal = ORB.__fromPtr__(create_0(nfeatures, scaleFactor, nlevels, edgeThreshold, firstLevel, WTA_K, scoreType, patchSize, fastThreshold)); + + return retVal; + } + + //javadoc: ORB::create(nfeatures, scaleFactor, nlevels, edgeThreshold, firstLevel, WTA_K, scoreType, patchSize) + public static ORB create(int nfeatures, float scaleFactor, int nlevels, int edgeThreshold, int firstLevel, int WTA_K, int scoreType, int patchSize) + { + + ORB retVal = ORB.__fromPtr__(create_1(nfeatures, scaleFactor, nlevels, edgeThreshold, firstLevel, WTA_K, scoreType, patchSize)); + + return retVal; + } + + //javadoc: ORB::create(nfeatures, scaleFactor, nlevels, edgeThreshold, firstLevel, WTA_K, scoreType) + public static ORB create(int nfeatures, float scaleFactor, int nlevels, int edgeThreshold, int firstLevel, int WTA_K, int scoreType) + { + + ORB retVal = ORB.__fromPtr__(create_2(nfeatures, scaleFactor, nlevels, edgeThreshold, firstLevel, WTA_K, scoreType)); + + return retVal; + } + + //javadoc: ORB::create(nfeatures, scaleFactor, nlevels, edgeThreshold, firstLevel, WTA_K) + public static ORB create(int nfeatures, float scaleFactor, int nlevels, int edgeThreshold, int firstLevel, int WTA_K) + { + + ORB retVal = ORB.__fromPtr__(create_3(nfeatures, scaleFactor, nlevels, edgeThreshold, firstLevel, WTA_K)); + + return retVal; + } + + //javadoc: ORB::create(nfeatures, scaleFactor, nlevels, edgeThreshold, firstLevel) + public static ORB create(int nfeatures, float scaleFactor, int nlevels, int edgeThreshold, int firstLevel) + { + + ORB retVal = ORB.__fromPtr__(create_4(nfeatures, scaleFactor, nlevels, edgeThreshold, firstLevel)); + + return retVal; + } + + //javadoc: ORB::create(nfeatures, scaleFactor, nlevels, edgeThreshold) + public static ORB create(int nfeatures, float scaleFactor, int nlevels, int edgeThreshold) + { + + ORB retVal = ORB.__fromPtr__(create_5(nfeatures, scaleFactor, nlevels, edgeThreshold)); + + return retVal; + } + + //javadoc: ORB::create(nfeatures, scaleFactor, nlevels) + public static ORB create(int nfeatures, float scaleFactor, int nlevels) + { + + ORB retVal = ORB.__fromPtr__(create_6(nfeatures, scaleFactor, nlevels)); + + return retVal; + } + + //javadoc: ORB::create(nfeatures, scaleFactor) + public static ORB create(int nfeatures, float scaleFactor) + { + + ORB retVal = ORB.__fromPtr__(create_7(nfeatures, scaleFactor)); + + return retVal; + } + + //javadoc: ORB::create(nfeatures) + public static ORB create(int nfeatures) + { + + ORB retVal = ORB.__fromPtr__(create_8(nfeatures)); + + return retVal; + } + + //javadoc: ORB::create() + public static ORB create() + { + + ORB retVal = ORB.__fromPtr__(create_9()); + + return retVal; + } + + + // + // C++: String cv::ORB::getDefaultName() + // + + //javadoc: ORB::getDefaultName() + public String getDefaultName() + { + + String retVal = getDefaultName_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::ORB::getScaleFactor() + // + + //javadoc: ORB::getScaleFactor() + public double getScaleFactor() + { + + double retVal = getScaleFactor_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ORB::getEdgeThreshold() + // + + //javadoc: ORB::getEdgeThreshold() + public int getEdgeThreshold() + { + + int retVal = getEdgeThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ORB::getFastThreshold() + // + + //javadoc: ORB::getFastThreshold() + public int getFastThreshold() + { + + int retVal = getFastThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ORB::getFirstLevel() + // + + //javadoc: ORB::getFirstLevel() + public int getFirstLevel() + { + + int retVal = getFirstLevel_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ORB::getMaxFeatures() + // + + //javadoc: ORB::getMaxFeatures() + public int getMaxFeatures() + { + + int retVal = getMaxFeatures_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ORB::getNLevels() + // + + //javadoc: ORB::getNLevels() + public int getNLevels() + { + + int retVal = getNLevels_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ORB::getPatchSize() + // + + //javadoc: ORB::getPatchSize() + public int getPatchSize() + { + + int retVal = getPatchSize_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ORB::getWTA_K() + // + + //javadoc: ORB::getWTA_K() + public int getWTA_K() + { + + int retVal = getWTA_K_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::ORB::setEdgeThreshold(int edgeThreshold) + // + + //javadoc: ORB::setEdgeThreshold(edgeThreshold) + public void setEdgeThreshold(int edgeThreshold) + { + + setEdgeThreshold_0(nativeObj, edgeThreshold); + + return; + } + + + // + // C++: void cv::ORB::setFastThreshold(int fastThreshold) + // + + //javadoc: ORB::setFastThreshold(fastThreshold) + public void setFastThreshold(int fastThreshold) + { + + setFastThreshold_0(nativeObj, fastThreshold); + + return; + } + + + // + // C++: void cv::ORB::setFirstLevel(int firstLevel) + // + + //javadoc: ORB::setFirstLevel(firstLevel) + public void setFirstLevel(int firstLevel) + { + + setFirstLevel_0(nativeObj, firstLevel); + + return; + } + + + // + // C++: void cv::ORB::setMaxFeatures(int maxFeatures) + // + + //javadoc: ORB::setMaxFeatures(maxFeatures) + public void setMaxFeatures(int maxFeatures) + { + + setMaxFeatures_0(nativeObj, maxFeatures); + + return; + } + + + // + // C++: void cv::ORB::setNLevels(int nlevels) + // + + //javadoc: ORB::setNLevels(nlevels) + public void setNLevels(int nlevels) + { + + setNLevels_0(nativeObj, nlevels); + + return; + } + + + // + // C++: void cv::ORB::setPatchSize(int patchSize) + // + + //javadoc: ORB::setPatchSize(patchSize) + public void setPatchSize(int patchSize) + { + + setPatchSize_0(nativeObj, patchSize); + + return; + } + + + // + // C++: void cv::ORB::setScaleFactor(double scaleFactor) + // + + //javadoc: ORB::setScaleFactor(scaleFactor) + public void setScaleFactor(double scaleFactor) + { + + setScaleFactor_0(nativeObj, scaleFactor); + + return; + } + + + // + // C++: void cv::ORB::setScoreType(ORB_ScoreType scoreType) + // + + //javadoc: ORB::setScoreType(scoreType) + public void setScoreType(int scoreType) + { + + setScoreType_0(nativeObj, scoreType); + + return; + } + + + // + // C++: void cv::ORB::setWTA_K(int wta_k) + // + + //javadoc: ORB::setWTA_K(wta_k) + public void setWTA_K(int wta_k) + { + + setWTA_K_0(nativeObj, wta_k); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: ORB_ScoreType cv::ORB::getScoreType() + private static native int getScoreType_0(long nativeObj); + + // C++: static Ptr_ORB cv::ORB::create(int nfeatures = 500, float scaleFactor = 1.2f, int nlevels = 8, int edgeThreshold = 31, int firstLevel = 0, int WTA_K = 2, ORB_ScoreType scoreType = ORB::HARRIS_SCORE, int patchSize = 31, int fastThreshold = 20) + private static native long create_0(int nfeatures, float scaleFactor, int nlevels, int edgeThreshold, int firstLevel, int WTA_K, int scoreType, int patchSize, int fastThreshold); + private static native long create_1(int nfeatures, float scaleFactor, int nlevels, int edgeThreshold, int firstLevel, int WTA_K, int scoreType, int patchSize); + private static native long create_2(int nfeatures, float scaleFactor, int nlevels, int edgeThreshold, int firstLevel, int WTA_K, int scoreType); + private static native long create_3(int nfeatures, float scaleFactor, int nlevels, int edgeThreshold, int firstLevel, int WTA_K); + private static native long create_4(int nfeatures, float scaleFactor, int nlevels, int edgeThreshold, int firstLevel); + private static native long create_5(int nfeatures, float scaleFactor, int nlevels, int edgeThreshold); + private static native long create_6(int nfeatures, float scaleFactor, int nlevels); + private static native long create_7(int nfeatures, float scaleFactor); + private static native long create_8(int nfeatures); + private static native long create_9(); + + // C++: String cv::ORB::getDefaultName() + private static native String getDefaultName_0(long nativeObj); + + // C++: double cv::ORB::getScaleFactor() + private static native double getScaleFactor_0(long nativeObj); + + // C++: int cv::ORB::getEdgeThreshold() + private static native int getEdgeThreshold_0(long nativeObj); + + // C++: int cv::ORB::getFastThreshold() + private static native int getFastThreshold_0(long nativeObj); + + // C++: int cv::ORB::getFirstLevel() + private static native int getFirstLevel_0(long nativeObj); + + // C++: int cv::ORB::getMaxFeatures() + private static native int getMaxFeatures_0(long nativeObj); + + // C++: int cv::ORB::getNLevels() + private static native int getNLevels_0(long nativeObj); + + // C++: int cv::ORB::getPatchSize() + private static native int getPatchSize_0(long nativeObj); + + // C++: int cv::ORB::getWTA_K() + private static native int getWTA_K_0(long nativeObj); + + // C++: void cv::ORB::setEdgeThreshold(int edgeThreshold) + private static native void setEdgeThreshold_0(long nativeObj, int edgeThreshold); + + // C++: void cv::ORB::setFastThreshold(int fastThreshold) + private static native void setFastThreshold_0(long nativeObj, int fastThreshold); + + // C++: void cv::ORB::setFirstLevel(int firstLevel) + private static native void setFirstLevel_0(long nativeObj, int firstLevel); + + // C++: void cv::ORB::setMaxFeatures(int maxFeatures) + private static native void setMaxFeatures_0(long nativeObj, int maxFeatures); + + // C++: void cv::ORB::setNLevels(int nlevels) + private static native void setNLevels_0(long nativeObj, int nlevels); + + // C++: void cv::ORB::setPatchSize(int patchSize) + private static native void setPatchSize_0(long nativeObj, int patchSize); + + // C++: void cv::ORB::setScaleFactor(double scaleFactor) + private static native void setScaleFactor_0(long nativeObj, double scaleFactor); + + // C++: void cv::ORB::setScoreType(ORB_ScoreType scoreType) + private static native void setScoreType_0(long nativeObj, int scoreType); + + // C++: void cv::ORB::setWTA_K(int wta_k) + private static native void setWTA_K_0(long nativeObj, int wta_k); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/features2d/Params.java b/OpenCV/src/main/java/org/opencv/features2d/Params.java new file mode 100644 index 00000000..3323facc --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/features2d/Params.java @@ -0,0 +1,674 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.features2d; + + + +// C++: class Params +//javadoc: Params + +public class Params { + + protected final long nativeObj; + protected Params(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static Params __fromPtr__(long addr) { return new Params(addr); } + + // + // C++: cv::SimpleBlobDetector::Params::Params() + // + + //javadoc: Params::Params() + public Params() + { + + nativeObj = Params_0(); + + return; + } + + + // + // C++: float Params::thresholdStep + // + + //javadoc: Params::get_thresholdStep() + public float get_thresholdStep() + { + + float retVal = get_thresholdStep_0(nativeObj); + + return retVal; + } + + + // + // C++: void Params::thresholdStep + // + + //javadoc: Params::set_thresholdStep(thresholdStep) + public void set_thresholdStep(float thresholdStep) + { + + set_thresholdStep_0(nativeObj, thresholdStep); + + return; + } + + + // + // C++: float Params::minThreshold + // + + //javadoc: Params::get_minThreshold() + public float get_minThreshold() + { + + float retVal = get_minThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: void Params::minThreshold + // + + //javadoc: Params::set_minThreshold(minThreshold) + public void set_minThreshold(float minThreshold) + { + + set_minThreshold_0(nativeObj, minThreshold); + + return; + } + + + // + // C++: float Params::maxThreshold + // + + //javadoc: Params::get_maxThreshold() + public float get_maxThreshold() + { + + float retVal = get_maxThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: void Params::maxThreshold + // + + //javadoc: Params::set_maxThreshold(maxThreshold) + public void set_maxThreshold(float maxThreshold) + { + + set_maxThreshold_0(nativeObj, maxThreshold); + + return; + } + + + // + // C++: size_t Params::minRepeatability + // + + //javadoc: Params::get_minRepeatability() + public long get_minRepeatability() + { + + long retVal = get_minRepeatability_0(nativeObj); + + return retVal; + } + + + // + // C++: void Params::minRepeatability + // + + //javadoc: Params::set_minRepeatability(minRepeatability) + public void set_minRepeatability(long minRepeatability) + { + + set_minRepeatability_0(nativeObj, minRepeatability); + + return; + } + + + // + // C++: float Params::minDistBetweenBlobs + // + + //javadoc: Params::get_minDistBetweenBlobs() + public float get_minDistBetweenBlobs() + { + + float retVal = get_minDistBetweenBlobs_0(nativeObj); + + return retVal; + } + + + // + // C++: void Params::minDistBetweenBlobs + // + + //javadoc: Params::set_minDistBetweenBlobs(minDistBetweenBlobs) + public void set_minDistBetweenBlobs(float minDistBetweenBlobs) + { + + set_minDistBetweenBlobs_0(nativeObj, minDistBetweenBlobs); + + return; + } + + + // + // C++: bool Params::filterByColor + // + + //javadoc: Params::get_filterByColor() + public boolean get_filterByColor() + { + + boolean retVal = get_filterByColor_0(nativeObj); + + return retVal; + } + + + // + // C++: void Params::filterByColor + // + + //javadoc: Params::set_filterByColor(filterByColor) + public void set_filterByColor(boolean filterByColor) + { + + set_filterByColor_0(nativeObj, filterByColor); + + return; + } + + + // + // C++: uchar Params::blobColor + // + + // Return type 'uchar' is not supported, skipping the function + + + // + // C++: void Params::blobColor + // + + // Unknown type 'uchar' (I), skipping the function + + + // + // C++: bool Params::filterByArea + // + + //javadoc: Params::get_filterByArea() + public boolean get_filterByArea() + { + + boolean retVal = get_filterByArea_0(nativeObj); + + return retVal; + } + + + // + // C++: void Params::filterByArea + // + + //javadoc: Params::set_filterByArea(filterByArea) + public void set_filterByArea(boolean filterByArea) + { + + set_filterByArea_0(nativeObj, filterByArea); + + return; + } + + + // + // C++: float Params::minArea + // + + //javadoc: Params::get_minArea() + public float get_minArea() + { + + float retVal = get_minArea_0(nativeObj); + + return retVal; + } + + + // + // C++: void Params::minArea + // + + //javadoc: Params::set_minArea(minArea) + public void set_minArea(float minArea) + { + + set_minArea_0(nativeObj, minArea); + + return; + } + + + // + // C++: float Params::maxArea + // + + //javadoc: Params::get_maxArea() + public float get_maxArea() + { + + float retVal = get_maxArea_0(nativeObj); + + return retVal; + } + + + // + // C++: void Params::maxArea + // + + //javadoc: Params::set_maxArea(maxArea) + public void set_maxArea(float maxArea) + { + + set_maxArea_0(nativeObj, maxArea); + + return; + } + + + // + // C++: bool Params::filterByCircularity + // + + //javadoc: Params::get_filterByCircularity() + public boolean get_filterByCircularity() + { + + boolean retVal = get_filterByCircularity_0(nativeObj); + + return retVal; + } + + + // + // C++: void Params::filterByCircularity + // + + //javadoc: Params::set_filterByCircularity(filterByCircularity) + public void set_filterByCircularity(boolean filterByCircularity) + { + + set_filterByCircularity_0(nativeObj, filterByCircularity); + + return; + } + + + // + // C++: float Params::minCircularity + // + + //javadoc: Params::get_minCircularity() + public float get_minCircularity() + { + + float retVal = get_minCircularity_0(nativeObj); + + return retVal; + } + + + // + // C++: void Params::minCircularity + // + + //javadoc: Params::set_minCircularity(minCircularity) + public void set_minCircularity(float minCircularity) + { + + set_minCircularity_0(nativeObj, minCircularity); + + return; + } + + + // + // C++: float Params::maxCircularity + // + + //javadoc: Params::get_maxCircularity() + public float get_maxCircularity() + { + + float retVal = get_maxCircularity_0(nativeObj); + + return retVal; + } + + + // + // C++: void Params::maxCircularity + // + + //javadoc: Params::set_maxCircularity(maxCircularity) + public void set_maxCircularity(float maxCircularity) + { + + set_maxCircularity_0(nativeObj, maxCircularity); + + return; + } + + + // + // C++: bool Params::filterByInertia + // + + //javadoc: Params::get_filterByInertia() + public boolean get_filterByInertia() + { + + boolean retVal = get_filterByInertia_0(nativeObj); + + return retVal; + } + + + // + // C++: void Params::filterByInertia + // + + //javadoc: Params::set_filterByInertia(filterByInertia) + public void set_filterByInertia(boolean filterByInertia) + { + + set_filterByInertia_0(nativeObj, filterByInertia); + + return; + } + + + // + // C++: float Params::minInertiaRatio + // + + //javadoc: Params::get_minInertiaRatio() + public float get_minInertiaRatio() + { + + float retVal = get_minInertiaRatio_0(nativeObj); + + return retVal; + } + + + // + // C++: void Params::minInertiaRatio + // + + //javadoc: Params::set_minInertiaRatio(minInertiaRatio) + public void set_minInertiaRatio(float minInertiaRatio) + { + + set_minInertiaRatio_0(nativeObj, minInertiaRatio); + + return; + } + + + // + // C++: float Params::maxInertiaRatio + // + + //javadoc: Params::get_maxInertiaRatio() + public float get_maxInertiaRatio() + { + + float retVal = get_maxInertiaRatio_0(nativeObj); + + return retVal; + } + + + // + // C++: void Params::maxInertiaRatio + // + + //javadoc: Params::set_maxInertiaRatio(maxInertiaRatio) + public void set_maxInertiaRatio(float maxInertiaRatio) + { + + set_maxInertiaRatio_0(nativeObj, maxInertiaRatio); + + return; + } + + + // + // C++: bool Params::filterByConvexity + // + + //javadoc: Params::get_filterByConvexity() + public boolean get_filterByConvexity() + { + + boolean retVal = get_filterByConvexity_0(nativeObj); + + return retVal; + } + + + // + // C++: void Params::filterByConvexity + // + + //javadoc: Params::set_filterByConvexity(filterByConvexity) + public void set_filterByConvexity(boolean filterByConvexity) + { + + set_filterByConvexity_0(nativeObj, filterByConvexity); + + return; + } + + + // + // C++: float Params::minConvexity + // + + //javadoc: Params::get_minConvexity() + public float get_minConvexity() + { + + float retVal = get_minConvexity_0(nativeObj); + + return retVal; + } + + + // + // C++: void Params::minConvexity + // + + //javadoc: Params::set_minConvexity(minConvexity) + public void set_minConvexity(float minConvexity) + { + + set_minConvexity_0(nativeObj, minConvexity); + + return; + } + + + // + // C++: float Params::maxConvexity + // + + //javadoc: Params::get_maxConvexity() + public float get_maxConvexity() + { + + float retVal = get_maxConvexity_0(nativeObj); + + return retVal; + } + + + // + // C++: void Params::maxConvexity + // + + //javadoc: Params::set_maxConvexity(maxConvexity) + public void set_maxConvexity(float maxConvexity) + { + + set_maxConvexity_0(nativeObj, maxConvexity); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: cv::SimpleBlobDetector::Params::Params() + private static native long Params_0(); + + // C++: float Params::thresholdStep + private static native float get_thresholdStep_0(long nativeObj); + + // C++: void Params::thresholdStep + private static native void set_thresholdStep_0(long nativeObj, float thresholdStep); + + // C++: float Params::minThreshold + private static native float get_minThreshold_0(long nativeObj); + + // C++: void Params::minThreshold + private static native void set_minThreshold_0(long nativeObj, float minThreshold); + + // C++: float Params::maxThreshold + private static native float get_maxThreshold_0(long nativeObj); + + // C++: void Params::maxThreshold + private static native void set_maxThreshold_0(long nativeObj, float maxThreshold); + + // C++: size_t Params::minRepeatability + private static native long get_minRepeatability_0(long nativeObj); + + // C++: void Params::minRepeatability + private static native void set_minRepeatability_0(long nativeObj, long minRepeatability); + + // C++: float Params::minDistBetweenBlobs + private static native float get_minDistBetweenBlobs_0(long nativeObj); + + // C++: void Params::minDistBetweenBlobs + private static native void set_minDistBetweenBlobs_0(long nativeObj, float minDistBetweenBlobs); + + // C++: bool Params::filterByColor + private static native boolean get_filterByColor_0(long nativeObj); + + // C++: void Params::filterByColor + private static native void set_filterByColor_0(long nativeObj, boolean filterByColor); + + // C++: bool Params::filterByArea + private static native boolean get_filterByArea_0(long nativeObj); + + // C++: void Params::filterByArea + private static native void set_filterByArea_0(long nativeObj, boolean filterByArea); + + // C++: float Params::minArea + private static native float get_minArea_0(long nativeObj); + + // C++: void Params::minArea + private static native void set_minArea_0(long nativeObj, float minArea); + + // C++: float Params::maxArea + private static native float get_maxArea_0(long nativeObj); + + // C++: void Params::maxArea + private static native void set_maxArea_0(long nativeObj, float maxArea); + + // C++: bool Params::filterByCircularity + private static native boolean get_filterByCircularity_0(long nativeObj); + + // C++: void Params::filterByCircularity + private static native void set_filterByCircularity_0(long nativeObj, boolean filterByCircularity); + + // C++: float Params::minCircularity + private static native float get_minCircularity_0(long nativeObj); + + // C++: void Params::minCircularity + private static native void set_minCircularity_0(long nativeObj, float minCircularity); + + // C++: float Params::maxCircularity + private static native float get_maxCircularity_0(long nativeObj); + + // C++: void Params::maxCircularity + private static native void set_maxCircularity_0(long nativeObj, float maxCircularity); + + // C++: bool Params::filterByInertia + private static native boolean get_filterByInertia_0(long nativeObj); + + // C++: void Params::filterByInertia + private static native void set_filterByInertia_0(long nativeObj, boolean filterByInertia); + + // C++: float Params::minInertiaRatio + private static native float get_minInertiaRatio_0(long nativeObj); + + // C++: void Params::minInertiaRatio + private static native void set_minInertiaRatio_0(long nativeObj, float minInertiaRatio); + + // C++: float Params::maxInertiaRatio + private static native float get_maxInertiaRatio_0(long nativeObj); + + // C++: void Params::maxInertiaRatio + private static native void set_maxInertiaRatio_0(long nativeObj, float maxInertiaRatio); + + // C++: bool Params::filterByConvexity + private static native boolean get_filterByConvexity_0(long nativeObj); + + // C++: void Params::filterByConvexity + private static native void set_filterByConvexity_0(long nativeObj, boolean filterByConvexity); + + // C++: float Params::minConvexity + private static native float get_minConvexity_0(long nativeObj); + + // C++: void Params::minConvexity + private static native void set_minConvexity_0(long nativeObj, float minConvexity); + + // C++: float Params::maxConvexity + private static native float get_maxConvexity_0(long nativeObj); + + // C++: void Params::maxConvexity + private static native void set_maxConvexity_0(long nativeObj, float maxConvexity); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/img_hash/AverageHash.java b/OpenCV/src/main/java/org/opencv/img_hash/AverageHash.java new file mode 100644 index 00000000..6fff8f69 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/img_hash/AverageHash.java @@ -0,0 +1,45 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.img_hash; + +import org.opencv.img_hash.AverageHash; + +// C++: class AverageHash +//javadoc: AverageHash + +public class AverageHash extends ImgHashBase { + + protected AverageHash(long addr) { super(addr); } + + // internal usage only + public static AverageHash __fromPtr__(long addr) { return new AverageHash(addr); } + + // + // C++: static Ptr_AverageHash cv::img_hash::AverageHash::create() + // + + //javadoc: AverageHash::create() + public static AverageHash create() + { + + AverageHash retVal = AverageHash.__fromPtr__(create_0()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_AverageHash cv::img_hash::AverageHash::create() + private static native long create_0(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/img_hash/BlockMeanHash.java b/OpenCV/src/main/java/org/opencv/img_hash/BlockMeanHash.java new file mode 100644 index 00000000..23bdfb74 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/img_hash/BlockMeanHash.java @@ -0,0 +1,94 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.img_hash; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfDouble; +import org.opencv.img_hash.BlockMeanHash; +import org.opencv.utils.Converters; + +// C++: class BlockMeanHash +//javadoc: BlockMeanHash + +public class BlockMeanHash extends ImgHashBase { + + protected BlockMeanHash(long addr) { super(addr); } + + // internal usage only + public static BlockMeanHash __fromPtr__(long addr) { return new BlockMeanHash(addr); } + + // + // C++: static Ptr_BlockMeanHash cv::img_hash::BlockMeanHash::create(int mode = BLOCK_MEAN_HASH_MODE_0) + // + + //javadoc: BlockMeanHash::create(mode) + public static BlockMeanHash create(int mode) + { + + BlockMeanHash retVal = BlockMeanHash.__fromPtr__(create_0(mode)); + + return retVal; + } + + //javadoc: BlockMeanHash::create() + public static BlockMeanHash create() + { + + BlockMeanHash retVal = BlockMeanHash.__fromPtr__(create_1()); + + return retVal; + } + + + // + // C++: vector_double cv::img_hash::BlockMeanHash::getMean() + // + + //javadoc: BlockMeanHash::getMean() + public MatOfDouble getMean() + { + + MatOfDouble retVal = MatOfDouble.fromNativeAddr(getMean_0(nativeObj)); + + return retVal; + } + + + // + // C++: void cv::img_hash::BlockMeanHash::setMode(int mode) + // + + //javadoc: BlockMeanHash::setMode(mode) + public void setMode(int mode) + { + + setMode_0(nativeObj, mode); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_BlockMeanHash cv::img_hash::BlockMeanHash::create(int mode = BLOCK_MEAN_HASH_MODE_0) + private static native long create_0(int mode); + private static native long create_1(); + + // C++: vector_double cv::img_hash::BlockMeanHash::getMean() + private static native long getMean_0(long nativeObj); + + // C++: void cv::img_hash::BlockMeanHash::setMode(int mode) + private static native void setMode_0(long nativeObj, int mode); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/img_hash/ColorMomentHash.java b/OpenCV/src/main/java/org/opencv/img_hash/ColorMomentHash.java new file mode 100644 index 00000000..07991d09 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/img_hash/ColorMomentHash.java @@ -0,0 +1,45 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.img_hash; + +import org.opencv.img_hash.ColorMomentHash; + +// C++: class ColorMomentHash +//javadoc: ColorMomentHash + +public class ColorMomentHash extends ImgHashBase { + + protected ColorMomentHash(long addr) { super(addr); } + + // internal usage only + public static ColorMomentHash __fromPtr__(long addr) { return new ColorMomentHash(addr); } + + // + // C++: static Ptr_ColorMomentHash cv::img_hash::ColorMomentHash::create() + // + + //javadoc: ColorMomentHash::create() + public static ColorMomentHash create() + { + + ColorMomentHash retVal = ColorMomentHash.__fromPtr__(create_0()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_ColorMomentHash cv::img_hash::ColorMomentHash::create() + private static native long create_0(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/img_hash/ImgHashBase.java b/OpenCV/src/main/java/org/opencv/img_hash/ImgHashBase.java new file mode 100644 index 00000000..eb36e9e1 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/img_hash/ImgHashBase.java @@ -0,0 +1,63 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.img_hash; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class ImgHashBase +//javadoc: ImgHashBase + +public class ImgHashBase extends Algorithm { + + protected ImgHashBase(long addr) { super(addr); } + + // internal usage only + public static ImgHashBase __fromPtr__(long addr) { return new ImgHashBase(addr); } + + // + // C++: double cv::img_hash::ImgHashBase::compare(Mat hashOne, Mat hashTwo) + // + + //javadoc: ImgHashBase::compare(hashOne, hashTwo) + public double compare(Mat hashOne, Mat hashTwo) + { + + double retVal = compare_0(nativeObj, hashOne.nativeObj, hashTwo.nativeObj); + + return retVal; + } + + + // + // C++: void cv::img_hash::ImgHashBase::compute(Mat inputArr, Mat& outputArr) + // + + //javadoc: ImgHashBase::compute(inputArr, outputArr) + public void compute(Mat inputArr, Mat outputArr) + { + + compute_0(nativeObj, inputArr.nativeObj, outputArr.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: double cv::img_hash::ImgHashBase::compare(Mat hashOne, Mat hashTwo) + private static native double compare_0(long nativeObj, long hashOne_nativeObj, long hashTwo_nativeObj); + + // C++: void cv::img_hash::ImgHashBase::compute(Mat inputArr, Mat& outputArr) + private static native void compute_0(long nativeObj, long inputArr_nativeObj, long outputArr_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/img_hash/Img_hash.java b/OpenCV/src/main/java/org/opencv/img_hash/Img_hash.java new file mode 100644 index 00000000..4a3d1011 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/img_hash/Img_hash.java @@ -0,0 +1,173 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.img_hash; + +import org.opencv.core.Mat; + +// C++: class Img_hash +//javadoc: Img_hash + +public class Img_hash { + + // C++: enum BlockMeanHashMode + public static final int + BLOCK_MEAN_HASH_MODE_0 = 0, + BLOCK_MEAN_HASH_MODE_1 = 1; + + + // + // C++: void cv::img_hash::averageHash(Mat inputArr, Mat& outputArr) + // + + //javadoc: averageHash(inputArr, outputArr) + public static void averageHash(Mat inputArr, Mat outputArr) + { + + averageHash_0(inputArr.nativeObj, outputArr.nativeObj); + + return; + } + + + // + // C++: void cv::img_hash::blockMeanHash(Mat inputArr, Mat& outputArr, int mode = BLOCK_MEAN_HASH_MODE_0) + // + + //javadoc: blockMeanHash(inputArr, outputArr, mode) + public static void blockMeanHash(Mat inputArr, Mat outputArr, int mode) + { + + blockMeanHash_0(inputArr.nativeObj, outputArr.nativeObj, mode); + + return; + } + + //javadoc: blockMeanHash(inputArr, outputArr) + public static void blockMeanHash(Mat inputArr, Mat outputArr) + { + + blockMeanHash_1(inputArr.nativeObj, outputArr.nativeObj); + + return; + } + + + // + // C++: void cv::img_hash::colorMomentHash(Mat inputArr, Mat& outputArr) + // + + //javadoc: colorMomentHash(inputArr, outputArr) + public static void colorMomentHash(Mat inputArr, Mat outputArr) + { + + colorMomentHash_0(inputArr.nativeObj, outputArr.nativeObj); + + return; + } + + + // + // C++: void cv::img_hash::marrHildrethHash(Mat inputArr, Mat& outputArr, float alpha = 2.0f, float scale = 1.0f) + // + + //javadoc: marrHildrethHash(inputArr, outputArr, alpha, scale) + public static void marrHildrethHash(Mat inputArr, Mat outputArr, float alpha, float scale) + { + + marrHildrethHash_0(inputArr.nativeObj, outputArr.nativeObj, alpha, scale); + + return; + } + + //javadoc: marrHildrethHash(inputArr, outputArr, alpha) + public static void marrHildrethHash(Mat inputArr, Mat outputArr, float alpha) + { + + marrHildrethHash_1(inputArr.nativeObj, outputArr.nativeObj, alpha); + + return; + } + + //javadoc: marrHildrethHash(inputArr, outputArr) + public static void marrHildrethHash(Mat inputArr, Mat outputArr) + { + + marrHildrethHash_2(inputArr.nativeObj, outputArr.nativeObj); + + return; + } + + + // + // C++: void cv::img_hash::pHash(Mat inputArr, Mat& outputArr) + // + + //javadoc: pHash(inputArr, outputArr) + public static void pHash(Mat inputArr, Mat outputArr) + { + + pHash_0(inputArr.nativeObj, outputArr.nativeObj); + + return; + } + + + // + // C++: void cv::img_hash::radialVarianceHash(Mat inputArr, Mat& outputArr, double sigma = 1, int numOfAngleLine = 180) + // + + //javadoc: radialVarianceHash(inputArr, outputArr, sigma, numOfAngleLine) + public static void radialVarianceHash(Mat inputArr, Mat outputArr, double sigma, int numOfAngleLine) + { + + radialVarianceHash_0(inputArr.nativeObj, outputArr.nativeObj, sigma, numOfAngleLine); + + return; + } + + //javadoc: radialVarianceHash(inputArr, outputArr, sigma) + public static void radialVarianceHash(Mat inputArr, Mat outputArr, double sigma) + { + + radialVarianceHash_1(inputArr.nativeObj, outputArr.nativeObj, sigma); + + return; + } + + //javadoc: radialVarianceHash(inputArr, outputArr) + public static void radialVarianceHash(Mat inputArr, Mat outputArr) + { + + radialVarianceHash_2(inputArr.nativeObj, outputArr.nativeObj); + + return; + } + + + + + // C++: void cv::img_hash::averageHash(Mat inputArr, Mat& outputArr) + private static native void averageHash_0(long inputArr_nativeObj, long outputArr_nativeObj); + + // C++: void cv::img_hash::blockMeanHash(Mat inputArr, Mat& outputArr, int mode = BLOCK_MEAN_HASH_MODE_0) + private static native void blockMeanHash_0(long inputArr_nativeObj, long outputArr_nativeObj, int mode); + private static native void blockMeanHash_1(long inputArr_nativeObj, long outputArr_nativeObj); + + // C++: void cv::img_hash::colorMomentHash(Mat inputArr, Mat& outputArr) + private static native void colorMomentHash_0(long inputArr_nativeObj, long outputArr_nativeObj); + + // C++: void cv::img_hash::marrHildrethHash(Mat inputArr, Mat& outputArr, float alpha = 2.0f, float scale = 1.0f) + private static native void marrHildrethHash_0(long inputArr_nativeObj, long outputArr_nativeObj, float alpha, float scale); + private static native void marrHildrethHash_1(long inputArr_nativeObj, long outputArr_nativeObj, float alpha); + private static native void marrHildrethHash_2(long inputArr_nativeObj, long outputArr_nativeObj); + + // C++: void cv::img_hash::pHash(Mat inputArr, Mat& outputArr) + private static native void pHash_0(long inputArr_nativeObj, long outputArr_nativeObj); + + // C++: void cv::img_hash::radialVarianceHash(Mat inputArr, Mat& outputArr, double sigma = 1, int numOfAngleLine = 180) + private static native void radialVarianceHash_0(long inputArr_nativeObj, long outputArr_nativeObj, double sigma, int numOfAngleLine); + private static native void radialVarianceHash_1(long inputArr_nativeObj, long outputArr_nativeObj, double sigma); + private static native void radialVarianceHash_2(long inputArr_nativeObj, long outputArr_nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/img_hash/MarrHildrethHash.java b/OpenCV/src/main/java/org/opencv/img_hash/MarrHildrethHash.java new file mode 100644 index 00000000..0322dec3 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/img_hash/MarrHildrethHash.java @@ -0,0 +1,117 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.img_hash; + +import org.opencv.img_hash.ImgHashBase; +import org.opencv.img_hash.MarrHildrethHash; + +// C++: class MarrHildrethHash +//javadoc: MarrHildrethHash + +public class MarrHildrethHash extends ImgHashBase { + + protected MarrHildrethHash(long addr) { super(addr); } + + // internal usage only + public static MarrHildrethHash __fromPtr__(long addr) { return new MarrHildrethHash(addr); } + + // + // C++: static Ptr_MarrHildrethHash cv::img_hash::MarrHildrethHash::create(float alpha = 2.0f, float scale = 1.0f) + // + + //javadoc: MarrHildrethHash::create(alpha, scale) + public static MarrHildrethHash create(float alpha, float scale) + { + + MarrHildrethHash retVal = MarrHildrethHash.__fromPtr__(create_0(alpha, scale)); + + return retVal; + } + + //javadoc: MarrHildrethHash::create(alpha) + public static MarrHildrethHash create(float alpha) + { + + MarrHildrethHash retVal = MarrHildrethHash.__fromPtr__(create_1(alpha)); + + return retVal; + } + + //javadoc: MarrHildrethHash::create() + public static MarrHildrethHash create() + { + + MarrHildrethHash retVal = MarrHildrethHash.__fromPtr__(create_2()); + + return retVal; + } + + + // + // C++: float cv::img_hash::MarrHildrethHash::getAlpha() + // + + //javadoc: MarrHildrethHash::getAlpha() + public float getAlpha() + { + + float retVal = getAlpha_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::img_hash::MarrHildrethHash::getScale() + // + + //javadoc: MarrHildrethHash::getScale() + public float getScale() + { + + float retVal = getScale_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::img_hash::MarrHildrethHash::setKernelParam(float alpha, float scale) + // + + //javadoc: MarrHildrethHash::setKernelParam(alpha, scale) + public void setKernelParam(float alpha, float scale) + { + + setKernelParam_0(nativeObj, alpha, scale); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_MarrHildrethHash cv::img_hash::MarrHildrethHash::create(float alpha = 2.0f, float scale = 1.0f) + private static native long create_0(float alpha, float scale); + private static native long create_1(float alpha); + private static native long create_2(); + + // C++: float cv::img_hash::MarrHildrethHash::getAlpha() + private static native float getAlpha_0(long nativeObj); + + // C++: float cv::img_hash::MarrHildrethHash::getScale() + private static native float getScale_0(long nativeObj); + + // C++: void cv::img_hash::MarrHildrethHash::setKernelParam(float alpha, float scale) + private static native void setKernelParam_0(long nativeObj, float alpha, float scale); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/img_hash/PHash.java b/OpenCV/src/main/java/org/opencv/img_hash/PHash.java new file mode 100644 index 00000000..438f866b --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/img_hash/PHash.java @@ -0,0 +1,46 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.img_hash; + +import org.opencv.img_hash.ImgHashBase; +import org.opencv.img_hash.PHash; + +// C++: class PHash +//javadoc: PHash + +public class PHash extends ImgHashBase { + + protected PHash(long addr) { super(addr); } + + // internal usage only + public static PHash __fromPtr__(long addr) { return new PHash(addr); } + + // + // C++: static Ptr_PHash cv::img_hash::PHash::create() + // + + //javadoc: PHash::create() + public static PHash create() + { + + PHash retVal = PHash.__fromPtr__(create_0()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_PHash cv::img_hash::PHash::create() + private static native long create_0(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/img_hash/RadialVarianceHash.java b/OpenCV/src/main/java/org/opencv/img_hash/RadialVarianceHash.java new file mode 100644 index 00000000..3951881f --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/img_hash/RadialVarianceHash.java @@ -0,0 +1,134 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.img_hash; + +import org.opencv.img_hash.ImgHashBase; +import org.opencv.img_hash.RadialVarianceHash; + +// C++: class RadialVarianceHash +//javadoc: RadialVarianceHash + +public class RadialVarianceHash extends ImgHashBase { + + protected RadialVarianceHash(long addr) { super(addr); } + + // internal usage only + public static RadialVarianceHash __fromPtr__(long addr) { return new RadialVarianceHash(addr); } + + // + // C++: static Ptr_RadialVarianceHash cv::img_hash::RadialVarianceHash::create(double sigma = 1, int numOfAngleLine = 180) + // + + //javadoc: RadialVarianceHash::create(sigma, numOfAngleLine) + public static RadialVarianceHash create(double sigma, int numOfAngleLine) + { + + RadialVarianceHash retVal = RadialVarianceHash.__fromPtr__(create_0(sigma, numOfAngleLine)); + + return retVal; + } + + //javadoc: RadialVarianceHash::create(sigma) + public static RadialVarianceHash create(double sigma) + { + + RadialVarianceHash retVal = RadialVarianceHash.__fromPtr__(create_1(sigma)); + + return retVal; + } + + //javadoc: RadialVarianceHash::create() + public static RadialVarianceHash create() + { + + RadialVarianceHash retVal = RadialVarianceHash.__fromPtr__(create_2()); + + return retVal; + } + + + // + // C++: double cv::img_hash::RadialVarianceHash::getSigma() + // + + //javadoc: RadialVarianceHash::getSigma() + public double getSigma() + { + + double retVal = getSigma_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::img_hash::RadialVarianceHash::getNumOfAngleLine() + // + + //javadoc: RadialVarianceHash::getNumOfAngleLine() + public int getNumOfAngleLine() + { + + int retVal = getNumOfAngleLine_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::img_hash::RadialVarianceHash::setNumOfAngleLine(int value) + // + + //javadoc: RadialVarianceHash::setNumOfAngleLine(value) + public void setNumOfAngleLine(int value) + { + + setNumOfAngleLine_0(nativeObj, value); + + return; + } + + + // + // C++: void cv::img_hash::RadialVarianceHash::setSigma(double value) + // + + //javadoc: RadialVarianceHash::setSigma(value) + public void setSigma(double value) + { + + setSigma_0(nativeObj, value); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_RadialVarianceHash cv::img_hash::RadialVarianceHash::create(double sigma = 1, int numOfAngleLine = 180) + private static native long create_0(double sigma, int numOfAngleLine); + private static native long create_1(double sigma); + private static native long create_2(); + + // C++: double cv::img_hash::RadialVarianceHash::getSigma() + private static native double getSigma_0(long nativeObj); + + // C++: int cv::img_hash::RadialVarianceHash::getNumOfAngleLine() + private static native int getNumOfAngleLine_0(long nativeObj); + + // C++: void cv::img_hash::RadialVarianceHash::setNumOfAngleLine(int value) + private static native void setNumOfAngleLine_0(long nativeObj, int value); + + // C++: void cv::img_hash::RadialVarianceHash::setSigma(double value) + private static native void setSigma_0(long nativeObj, double value); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/imgcodecs/Imgcodecs.java b/OpenCV/src/main/java/org/opencv/imgcodecs/Imgcodecs.java new file mode 100644 index 00000000..17d632ec --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/imgcodecs/Imgcodecs.java @@ -0,0 +1,247 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.imgcodecs; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfByte; +import org.opencv.core.MatOfInt; +import org.opencv.utils.Converters; + +// C++: class Imgcodecs +//javadoc: Imgcodecs + +public class Imgcodecs { + + // C++: enum ImwriteFlags + public static final int + IMWRITE_JPEG_QUALITY = 1, + IMWRITE_JPEG_PROGRESSIVE = 2, + IMWRITE_JPEG_OPTIMIZE = 3, + IMWRITE_JPEG_RST_INTERVAL = 4, + IMWRITE_JPEG_LUMA_QUALITY = 5, + IMWRITE_JPEG_CHROMA_QUALITY = 6, + IMWRITE_PNG_COMPRESSION = 16, + IMWRITE_PNG_STRATEGY = 17, + IMWRITE_PNG_BILEVEL = 18, + IMWRITE_PXM_BINARY = 32, + IMWRITE_EXR_TYPE = (3 << 4) + 0, + IMWRITE_WEBP_QUALITY = 64, + IMWRITE_PAM_TUPLETYPE = 128, + IMWRITE_TIFF_RESUNIT = 256, + IMWRITE_TIFF_XDPI = 257, + IMWRITE_TIFF_YDPI = 258, + IMWRITE_TIFF_COMPRESSION = 259, + IMWRITE_JPEG2000_COMPRESSION_X1000 = 272; + + + // C++: enum ImreadModes + public static final int + IMREAD_UNCHANGED = -1, + IMREAD_GRAYSCALE = 0, + IMREAD_COLOR = 1, + IMREAD_ANYDEPTH = 2, + IMREAD_ANYCOLOR = 4, + IMREAD_LOAD_GDAL = 8, + IMREAD_REDUCED_GRAYSCALE_2 = 16, + IMREAD_REDUCED_COLOR_2 = 17, + IMREAD_REDUCED_GRAYSCALE_4 = 32, + IMREAD_REDUCED_COLOR_4 = 33, + IMREAD_REDUCED_GRAYSCALE_8 = 64, + IMREAD_REDUCED_COLOR_8 = 65, + IMREAD_IGNORE_ORIENTATION = 128; + + + // C++: enum ImwritePAMFlags + public static final int + IMWRITE_PAM_FORMAT_NULL = 0, + IMWRITE_PAM_FORMAT_BLACKANDWHITE = 1, + IMWRITE_PAM_FORMAT_GRAYSCALE = 2, + IMWRITE_PAM_FORMAT_GRAYSCALE_ALPHA = 3, + IMWRITE_PAM_FORMAT_RGB = 4, + IMWRITE_PAM_FORMAT_RGB_ALPHA = 5; + + + // C++: enum ImwriteEXRTypeFlags + public static final int + IMWRITE_EXR_TYPE_HALF = 1, + IMWRITE_EXR_TYPE_FLOAT = 2; + + + // C++: enum ImwritePNGFlags + public static final int + IMWRITE_PNG_STRATEGY_DEFAULT = 0, + IMWRITE_PNG_STRATEGY_FILTERED = 1, + IMWRITE_PNG_STRATEGY_HUFFMAN_ONLY = 2, + IMWRITE_PNG_STRATEGY_RLE = 3, + IMWRITE_PNG_STRATEGY_FIXED = 4; + + + // + // C++: Mat cv::imdecode(Mat buf, int flags) + // + + //javadoc: imdecode(buf, flags) + public static Mat imdecode(Mat buf, int flags) + { + + Mat retVal = new Mat(imdecode_0(buf.nativeObj, flags)); + + return retVal; + } + + + // + // C++: Mat cv::imread(String filename, int flags = IMREAD_COLOR) + // + + //javadoc: imread(filename, flags) + public static Mat imread(String filename, int flags) + { + + Mat retVal = new Mat(imread_0(filename, flags)); + + return retVal; + } + + //javadoc: imread(filename) + public static Mat imread(String filename) + { + + Mat retVal = new Mat(imread_1(filename)); + + return retVal; + } + + + // + // C++: bool cv::haveImageReader(String filename) + // + + //javadoc: haveImageReader(filename) + public static boolean haveImageReader(String filename) + { + + boolean retVal = haveImageReader_0(filename); + + return retVal; + } + + + // + // C++: bool cv::haveImageWriter(String filename) + // + + //javadoc: haveImageWriter(filename) + public static boolean haveImageWriter(String filename) + { + + boolean retVal = haveImageWriter_0(filename); + + return retVal; + } + + + // + // C++: bool cv::imencode(String ext, Mat img, vector_uchar& buf, vector_int params = std::vector()) + // + + //javadoc: imencode(ext, img, buf, params) + public static boolean imencode(String ext, Mat img, MatOfByte buf, MatOfInt params) + { + Mat buf_mat = buf; + Mat params_mat = params; + boolean retVal = imencode_0(ext, img.nativeObj, buf_mat.nativeObj, params_mat.nativeObj); + + return retVal; + } + + //javadoc: imencode(ext, img, buf) + public static boolean imencode(String ext, Mat img, MatOfByte buf) + { + Mat buf_mat = buf; + boolean retVal = imencode_1(ext, img.nativeObj, buf_mat.nativeObj); + + return retVal; + } + + + // + // C++: bool cv::imreadmulti(String filename, vector_Mat& mats, int flags = IMREAD_ANYCOLOR) + // + + //javadoc: imreadmulti(filename, mats, flags) + public static boolean imreadmulti(String filename, List mats, int flags) + { + Mat mats_mat = new Mat(); + boolean retVal = imreadmulti_0(filename, mats_mat.nativeObj, flags); + Converters.Mat_to_vector_Mat(mats_mat, mats); + mats_mat.release(); + return retVal; + } + + //javadoc: imreadmulti(filename, mats) + public static boolean imreadmulti(String filename, List mats) + { + Mat mats_mat = new Mat(); + boolean retVal = imreadmulti_1(filename, mats_mat.nativeObj); + Converters.Mat_to_vector_Mat(mats_mat, mats); + mats_mat.release(); + return retVal; + } + + + // + // C++: bool cv::imwrite(String filename, Mat img, vector_int params = std::vector()) + // + + //javadoc: imwrite(filename, img, params) + public static boolean imwrite(String filename, Mat img, MatOfInt params) + { + Mat params_mat = params; + boolean retVal = imwrite_0(filename, img.nativeObj, params_mat.nativeObj); + + return retVal; + } + + //javadoc: imwrite(filename, img) + public static boolean imwrite(String filename, Mat img) + { + + boolean retVal = imwrite_1(filename, img.nativeObj); + + return retVal; + } + + + + + // C++: Mat cv::imdecode(Mat buf, int flags) + private static native long imdecode_0(long buf_nativeObj, int flags); + + // C++: Mat cv::imread(String filename, int flags = IMREAD_COLOR) + private static native long imread_0(String filename, int flags); + private static native long imread_1(String filename); + + // C++: bool cv::haveImageReader(String filename) + private static native boolean haveImageReader_0(String filename); + + // C++: bool cv::haveImageWriter(String filename) + private static native boolean haveImageWriter_0(String filename); + + // C++: bool cv::imencode(String ext, Mat img, vector_uchar& buf, vector_int params = std::vector()) + private static native boolean imencode_0(String ext, long img_nativeObj, long buf_mat_nativeObj, long params_mat_nativeObj); + private static native boolean imencode_1(String ext, long img_nativeObj, long buf_mat_nativeObj); + + // C++: bool cv::imreadmulti(String filename, vector_Mat& mats, int flags = IMREAD_ANYCOLOR) + private static native boolean imreadmulti_0(String filename, long mats_mat_nativeObj, int flags); + private static native boolean imreadmulti_1(String filename, long mats_mat_nativeObj); + + // C++: bool cv::imwrite(String filename, Mat img, vector_int params = std::vector()) + private static native boolean imwrite_0(String filename, long img_nativeObj, long params_mat_nativeObj); + private static native boolean imwrite_1(String filename, long img_nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/imgproc/CLAHE.java b/OpenCV/src/main/java/org/opencv/imgproc/CLAHE.java new file mode 100644 index 00000000..8a320d4d --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/imgproc/CLAHE.java @@ -0,0 +1,132 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.imgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.core.Size; + +// C++: class CLAHE +//javadoc: CLAHE + +public class CLAHE extends Algorithm { + + protected CLAHE(long addr) { super(addr); } + + // internal usage only + public static CLAHE __fromPtr__(long addr) { return new CLAHE(addr); } + + // + // C++: Size cv::CLAHE::getTilesGridSize() + // + + //javadoc: CLAHE::getTilesGridSize() + public Size getTilesGridSize() + { + + Size retVal = new Size(getTilesGridSize_0(nativeObj)); + + return retVal; + } + + + // + // C++: double cv::CLAHE::getClipLimit() + // + + //javadoc: CLAHE::getClipLimit() + public double getClipLimit() + { + + double retVal = getClipLimit_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::CLAHE::apply(Mat src, Mat& dst) + // + + //javadoc: CLAHE::apply(src, dst) + public void apply(Mat src, Mat dst) + { + + apply_0(nativeObj, src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::CLAHE::collectGarbage() + // + + //javadoc: CLAHE::collectGarbage() + public void collectGarbage() + { + + collectGarbage_0(nativeObj); + + return; + } + + + // + // C++: void cv::CLAHE::setClipLimit(double clipLimit) + // + + //javadoc: CLAHE::setClipLimit(clipLimit) + public void setClipLimit(double clipLimit) + { + + setClipLimit_0(nativeObj, clipLimit); + + return; + } + + + // + // C++: void cv::CLAHE::setTilesGridSize(Size tileGridSize) + // + + //javadoc: CLAHE::setTilesGridSize(tileGridSize) + public void setTilesGridSize(Size tileGridSize) + { + + setTilesGridSize_0(nativeObj, tileGridSize.width, tileGridSize.height); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: Size cv::CLAHE::getTilesGridSize() + private static native double[] getTilesGridSize_0(long nativeObj); + + // C++: double cv::CLAHE::getClipLimit() + private static native double getClipLimit_0(long nativeObj); + + // C++: void cv::CLAHE::apply(Mat src, Mat& dst) + private static native void apply_0(long nativeObj, long src_nativeObj, long dst_nativeObj); + + // C++: void cv::CLAHE::collectGarbage() + private static native void collectGarbage_0(long nativeObj); + + // C++: void cv::CLAHE::setClipLimit(double clipLimit) + private static native void setClipLimit_0(long nativeObj, double clipLimit); + + // C++: void cv::CLAHE::setTilesGridSize(Size tileGridSize) + private static native void setTilesGridSize_0(long nativeObj, double tileGridSize_width, double tileGridSize_height); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/imgproc/GeneralizedHough.java b/OpenCV/src/main/java/org/opencv/imgproc/GeneralizedHough.java new file mode 100644 index 00000000..e5184ee8 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/imgproc/GeneralizedHough.java @@ -0,0 +1,308 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.imgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.core.Point; + +// C++: class GeneralizedHough +//javadoc: GeneralizedHough + +public class GeneralizedHough extends Algorithm { + + protected GeneralizedHough(long addr) { super(addr); } + + // internal usage only + public static GeneralizedHough __fromPtr__(long addr) { return new GeneralizedHough(addr); } + + // + // C++: double cv::GeneralizedHough::getDp() + // + + //javadoc: GeneralizedHough::getDp() + public double getDp() + { + + double retVal = getDp_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::GeneralizedHough::getMinDist() + // + + //javadoc: GeneralizedHough::getMinDist() + public double getMinDist() + { + + double retVal = getMinDist_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::GeneralizedHough::getCannyHighThresh() + // + + //javadoc: GeneralizedHough::getCannyHighThresh() + public int getCannyHighThresh() + { + + int retVal = getCannyHighThresh_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::GeneralizedHough::getCannyLowThresh() + // + + //javadoc: GeneralizedHough::getCannyLowThresh() + public int getCannyLowThresh() + { + + int retVal = getCannyLowThresh_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::GeneralizedHough::getMaxBufferSize() + // + + //javadoc: GeneralizedHough::getMaxBufferSize() + public int getMaxBufferSize() + { + + int retVal = getMaxBufferSize_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::GeneralizedHough::detect(Mat edges, Mat dx, Mat dy, Mat& positions, Mat& votes = Mat()) + // + + //javadoc: GeneralizedHough::detect(edges, dx, dy, positions, votes) + public void detect(Mat edges, Mat dx, Mat dy, Mat positions, Mat votes) + { + + detect_0(nativeObj, edges.nativeObj, dx.nativeObj, dy.nativeObj, positions.nativeObj, votes.nativeObj); + + return; + } + + //javadoc: GeneralizedHough::detect(edges, dx, dy, positions) + public void detect(Mat edges, Mat dx, Mat dy, Mat positions) + { + + detect_1(nativeObj, edges.nativeObj, dx.nativeObj, dy.nativeObj, positions.nativeObj); + + return; + } + + + // + // C++: void cv::GeneralizedHough::detect(Mat image, Mat& positions, Mat& votes = Mat()) + // + + //javadoc: GeneralizedHough::detect(image, positions, votes) + public void detect(Mat image, Mat positions, Mat votes) + { + + detect_2(nativeObj, image.nativeObj, positions.nativeObj, votes.nativeObj); + + return; + } + + //javadoc: GeneralizedHough::detect(image, positions) + public void detect(Mat image, Mat positions) + { + + detect_3(nativeObj, image.nativeObj, positions.nativeObj); + + return; + } + + + // + // C++: void cv::GeneralizedHough::setCannyHighThresh(int cannyHighThresh) + // + + //javadoc: GeneralizedHough::setCannyHighThresh(cannyHighThresh) + public void setCannyHighThresh(int cannyHighThresh) + { + + setCannyHighThresh_0(nativeObj, cannyHighThresh); + + return; + } + + + // + // C++: void cv::GeneralizedHough::setCannyLowThresh(int cannyLowThresh) + // + + //javadoc: GeneralizedHough::setCannyLowThresh(cannyLowThresh) + public void setCannyLowThresh(int cannyLowThresh) + { + + setCannyLowThresh_0(nativeObj, cannyLowThresh); + + return; + } + + + // + // C++: void cv::GeneralizedHough::setDp(double dp) + // + + //javadoc: GeneralizedHough::setDp(dp) + public void setDp(double dp) + { + + setDp_0(nativeObj, dp); + + return; + } + + + // + // C++: void cv::GeneralizedHough::setMaxBufferSize(int maxBufferSize) + // + + //javadoc: GeneralizedHough::setMaxBufferSize(maxBufferSize) + public void setMaxBufferSize(int maxBufferSize) + { + + setMaxBufferSize_0(nativeObj, maxBufferSize); + + return; + } + + + // + // C++: void cv::GeneralizedHough::setMinDist(double minDist) + // + + //javadoc: GeneralizedHough::setMinDist(minDist) + public void setMinDist(double minDist) + { + + setMinDist_0(nativeObj, minDist); + + return; + } + + + // + // C++: void cv::GeneralizedHough::setTemplate(Mat edges, Mat dx, Mat dy, Point templCenter = Point(-1, -1)) + // + + //javadoc: GeneralizedHough::setTemplate(edges, dx, dy, templCenter) + public void setTemplate(Mat edges, Mat dx, Mat dy, Point templCenter) + { + + setTemplate_0(nativeObj, edges.nativeObj, dx.nativeObj, dy.nativeObj, templCenter.x, templCenter.y); + + return; + } + + //javadoc: GeneralizedHough::setTemplate(edges, dx, dy) + public void setTemplate(Mat edges, Mat dx, Mat dy) + { + + setTemplate_1(nativeObj, edges.nativeObj, dx.nativeObj, dy.nativeObj); + + return; + } + + + // + // C++: void cv::GeneralizedHough::setTemplate(Mat templ, Point templCenter = Point(-1, -1)) + // + + //javadoc: GeneralizedHough::setTemplate(templ, templCenter) + public void setTemplate(Mat templ, Point templCenter) + { + + setTemplate_2(nativeObj, templ.nativeObj, templCenter.x, templCenter.y); + + return; + } + + //javadoc: GeneralizedHough::setTemplate(templ) + public void setTemplate(Mat templ) + { + + setTemplate_3(nativeObj, templ.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: double cv::GeneralizedHough::getDp() + private static native double getDp_0(long nativeObj); + + // C++: double cv::GeneralizedHough::getMinDist() + private static native double getMinDist_0(long nativeObj); + + // C++: int cv::GeneralizedHough::getCannyHighThresh() + private static native int getCannyHighThresh_0(long nativeObj); + + // C++: int cv::GeneralizedHough::getCannyLowThresh() + private static native int getCannyLowThresh_0(long nativeObj); + + // C++: int cv::GeneralizedHough::getMaxBufferSize() + private static native int getMaxBufferSize_0(long nativeObj); + + // C++: void cv::GeneralizedHough::detect(Mat edges, Mat dx, Mat dy, Mat& positions, Mat& votes = Mat()) + private static native void detect_0(long nativeObj, long edges_nativeObj, long dx_nativeObj, long dy_nativeObj, long positions_nativeObj, long votes_nativeObj); + private static native void detect_1(long nativeObj, long edges_nativeObj, long dx_nativeObj, long dy_nativeObj, long positions_nativeObj); + + // C++: void cv::GeneralizedHough::detect(Mat image, Mat& positions, Mat& votes = Mat()) + private static native void detect_2(long nativeObj, long image_nativeObj, long positions_nativeObj, long votes_nativeObj); + private static native void detect_3(long nativeObj, long image_nativeObj, long positions_nativeObj); + + // C++: void cv::GeneralizedHough::setCannyHighThresh(int cannyHighThresh) + private static native void setCannyHighThresh_0(long nativeObj, int cannyHighThresh); + + // C++: void cv::GeneralizedHough::setCannyLowThresh(int cannyLowThresh) + private static native void setCannyLowThresh_0(long nativeObj, int cannyLowThresh); + + // C++: void cv::GeneralizedHough::setDp(double dp) + private static native void setDp_0(long nativeObj, double dp); + + // C++: void cv::GeneralizedHough::setMaxBufferSize(int maxBufferSize) + private static native void setMaxBufferSize_0(long nativeObj, int maxBufferSize); + + // C++: void cv::GeneralizedHough::setMinDist(double minDist) + private static native void setMinDist_0(long nativeObj, double minDist); + + // C++: void cv::GeneralizedHough::setTemplate(Mat edges, Mat dx, Mat dy, Point templCenter = Point(-1, -1)) + private static native void setTemplate_0(long nativeObj, long edges_nativeObj, long dx_nativeObj, long dy_nativeObj, double templCenter_x, double templCenter_y); + private static native void setTemplate_1(long nativeObj, long edges_nativeObj, long dx_nativeObj, long dy_nativeObj); + + // C++: void cv::GeneralizedHough::setTemplate(Mat templ, Point templCenter = Point(-1, -1)) + private static native void setTemplate_2(long nativeObj, long templ_nativeObj, double templCenter_x, double templCenter_y); + private static native void setTemplate_3(long nativeObj, long templ_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/imgproc/GeneralizedHoughBallard.java b/OpenCV/src/main/java/org/opencv/imgproc/GeneralizedHoughBallard.java new file mode 100644 index 00000000..e49aeff5 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/imgproc/GeneralizedHoughBallard.java @@ -0,0 +1,96 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.imgproc; + +import org.opencv.imgproc.GeneralizedHough; + +// C++: class GeneralizedHoughBallard +//javadoc: GeneralizedHoughBallard + +public class GeneralizedHoughBallard extends GeneralizedHough { + + protected GeneralizedHoughBallard(long addr) { super(addr); } + + // internal usage only + public static GeneralizedHoughBallard __fromPtr__(long addr) { return new GeneralizedHoughBallard(addr); } + + // + // C++: int cv::GeneralizedHoughBallard::getLevels() + // + + //javadoc: GeneralizedHoughBallard::getLevels() + public int getLevels() + { + + int retVal = getLevels_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::GeneralizedHoughBallard::getVotesThreshold() + // + + //javadoc: GeneralizedHoughBallard::getVotesThreshold() + public int getVotesThreshold() + { + + int retVal = getVotesThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::GeneralizedHoughBallard::setLevels(int levels) + // + + //javadoc: GeneralizedHoughBallard::setLevels(levels) + public void setLevels(int levels) + { + + setLevels_0(nativeObj, levels); + + return; + } + + + // + // C++: void cv::GeneralizedHoughBallard::setVotesThreshold(int votesThreshold) + // + + //javadoc: GeneralizedHoughBallard::setVotesThreshold(votesThreshold) + public void setVotesThreshold(int votesThreshold) + { + + setVotesThreshold_0(nativeObj, votesThreshold); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: int cv::GeneralizedHoughBallard::getLevels() + private static native int getLevels_0(long nativeObj); + + // C++: int cv::GeneralizedHoughBallard::getVotesThreshold() + private static native int getVotesThreshold_0(long nativeObj); + + // C++: void cv::GeneralizedHoughBallard::setLevels(int levels) + private static native void setLevels_0(long nativeObj, int levels); + + // C++: void cv::GeneralizedHoughBallard::setVotesThreshold(int votesThreshold) + private static native void setVotesThreshold_0(long nativeObj, int votesThreshold); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/imgproc/GeneralizedHoughGuil.java b/OpenCV/src/main/java/org/opencv/imgproc/GeneralizedHoughGuil.java new file mode 100644 index 00000000..2453bfb2 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/imgproc/GeneralizedHoughGuil.java @@ -0,0 +1,436 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.imgproc; + +import org.opencv.imgproc.GeneralizedHough; + +// C++: class GeneralizedHoughGuil +//javadoc: GeneralizedHoughGuil + +public class GeneralizedHoughGuil extends GeneralizedHough { + + protected GeneralizedHoughGuil(long addr) { super(addr); } + + // internal usage only + public static GeneralizedHoughGuil __fromPtr__(long addr) { return new GeneralizedHoughGuil(addr); } + + // + // C++: double cv::GeneralizedHoughGuil::getAngleEpsilon() + // + + //javadoc: GeneralizedHoughGuil::getAngleEpsilon() + public double getAngleEpsilon() + { + + double retVal = getAngleEpsilon_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::GeneralizedHoughGuil::getAngleStep() + // + + //javadoc: GeneralizedHoughGuil::getAngleStep() + public double getAngleStep() + { + + double retVal = getAngleStep_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::GeneralizedHoughGuil::getMaxAngle() + // + + //javadoc: GeneralizedHoughGuil::getMaxAngle() + public double getMaxAngle() + { + + double retVal = getMaxAngle_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::GeneralizedHoughGuil::getMaxScale() + // + + //javadoc: GeneralizedHoughGuil::getMaxScale() + public double getMaxScale() + { + + double retVal = getMaxScale_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::GeneralizedHoughGuil::getMinAngle() + // + + //javadoc: GeneralizedHoughGuil::getMinAngle() + public double getMinAngle() + { + + double retVal = getMinAngle_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::GeneralizedHoughGuil::getMinScale() + // + + //javadoc: GeneralizedHoughGuil::getMinScale() + public double getMinScale() + { + + double retVal = getMinScale_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::GeneralizedHoughGuil::getScaleStep() + // + + //javadoc: GeneralizedHoughGuil::getScaleStep() + public double getScaleStep() + { + + double retVal = getScaleStep_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::GeneralizedHoughGuil::getXi() + // + + //javadoc: GeneralizedHoughGuil::getXi() + public double getXi() + { + + double retVal = getXi_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::GeneralizedHoughGuil::getAngleThresh() + // + + //javadoc: GeneralizedHoughGuil::getAngleThresh() + public int getAngleThresh() + { + + int retVal = getAngleThresh_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::GeneralizedHoughGuil::getLevels() + // + + //javadoc: GeneralizedHoughGuil::getLevels() + public int getLevels() + { + + int retVal = getLevels_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::GeneralizedHoughGuil::getPosThresh() + // + + //javadoc: GeneralizedHoughGuil::getPosThresh() + public int getPosThresh() + { + + int retVal = getPosThresh_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::GeneralizedHoughGuil::getScaleThresh() + // + + //javadoc: GeneralizedHoughGuil::getScaleThresh() + public int getScaleThresh() + { + + int retVal = getScaleThresh_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::GeneralizedHoughGuil::setAngleEpsilon(double angleEpsilon) + // + + //javadoc: GeneralizedHoughGuil::setAngleEpsilon(angleEpsilon) + public void setAngleEpsilon(double angleEpsilon) + { + + setAngleEpsilon_0(nativeObj, angleEpsilon); + + return; + } + + + // + // C++: void cv::GeneralizedHoughGuil::setAngleStep(double angleStep) + // + + //javadoc: GeneralizedHoughGuil::setAngleStep(angleStep) + public void setAngleStep(double angleStep) + { + + setAngleStep_0(nativeObj, angleStep); + + return; + } + + + // + // C++: void cv::GeneralizedHoughGuil::setAngleThresh(int angleThresh) + // + + //javadoc: GeneralizedHoughGuil::setAngleThresh(angleThresh) + public void setAngleThresh(int angleThresh) + { + + setAngleThresh_0(nativeObj, angleThresh); + + return; + } + + + // + // C++: void cv::GeneralizedHoughGuil::setLevels(int levels) + // + + //javadoc: GeneralizedHoughGuil::setLevels(levels) + public void setLevels(int levels) + { + + setLevels_0(nativeObj, levels); + + return; + } + + + // + // C++: void cv::GeneralizedHoughGuil::setMaxAngle(double maxAngle) + // + + //javadoc: GeneralizedHoughGuil::setMaxAngle(maxAngle) + public void setMaxAngle(double maxAngle) + { + + setMaxAngle_0(nativeObj, maxAngle); + + return; + } + + + // + // C++: void cv::GeneralizedHoughGuil::setMaxScale(double maxScale) + // + + //javadoc: GeneralizedHoughGuil::setMaxScale(maxScale) + public void setMaxScale(double maxScale) + { + + setMaxScale_0(nativeObj, maxScale); + + return; + } + + + // + // C++: void cv::GeneralizedHoughGuil::setMinAngle(double minAngle) + // + + //javadoc: GeneralizedHoughGuil::setMinAngle(minAngle) + public void setMinAngle(double minAngle) + { + + setMinAngle_0(nativeObj, minAngle); + + return; + } + + + // + // C++: void cv::GeneralizedHoughGuil::setMinScale(double minScale) + // + + //javadoc: GeneralizedHoughGuil::setMinScale(minScale) + public void setMinScale(double minScale) + { + + setMinScale_0(nativeObj, minScale); + + return; + } + + + // + // C++: void cv::GeneralizedHoughGuil::setPosThresh(int posThresh) + // + + //javadoc: GeneralizedHoughGuil::setPosThresh(posThresh) + public void setPosThresh(int posThresh) + { + + setPosThresh_0(nativeObj, posThresh); + + return; + } + + + // + // C++: void cv::GeneralizedHoughGuil::setScaleStep(double scaleStep) + // + + //javadoc: GeneralizedHoughGuil::setScaleStep(scaleStep) + public void setScaleStep(double scaleStep) + { + + setScaleStep_0(nativeObj, scaleStep); + + return; + } + + + // + // C++: void cv::GeneralizedHoughGuil::setScaleThresh(int scaleThresh) + // + + //javadoc: GeneralizedHoughGuil::setScaleThresh(scaleThresh) + public void setScaleThresh(int scaleThresh) + { + + setScaleThresh_0(nativeObj, scaleThresh); + + return; + } + + + // + // C++: void cv::GeneralizedHoughGuil::setXi(double xi) + // + + //javadoc: GeneralizedHoughGuil::setXi(xi) + public void setXi(double xi) + { + + setXi_0(nativeObj, xi); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: double cv::GeneralizedHoughGuil::getAngleEpsilon() + private static native double getAngleEpsilon_0(long nativeObj); + + // C++: double cv::GeneralizedHoughGuil::getAngleStep() + private static native double getAngleStep_0(long nativeObj); + + // C++: double cv::GeneralizedHoughGuil::getMaxAngle() + private static native double getMaxAngle_0(long nativeObj); + + // C++: double cv::GeneralizedHoughGuil::getMaxScale() + private static native double getMaxScale_0(long nativeObj); + + // C++: double cv::GeneralizedHoughGuil::getMinAngle() + private static native double getMinAngle_0(long nativeObj); + + // C++: double cv::GeneralizedHoughGuil::getMinScale() + private static native double getMinScale_0(long nativeObj); + + // C++: double cv::GeneralizedHoughGuil::getScaleStep() + private static native double getScaleStep_0(long nativeObj); + + // C++: double cv::GeneralizedHoughGuil::getXi() + private static native double getXi_0(long nativeObj); + + // C++: int cv::GeneralizedHoughGuil::getAngleThresh() + private static native int getAngleThresh_0(long nativeObj); + + // C++: int cv::GeneralizedHoughGuil::getLevels() + private static native int getLevels_0(long nativeObj); + + // C++: int cv::GeneralizedHoughGuil::getPosThresh() + private static native int getPosThresh_0(long nativeObj); + + // C++: int cv::GeneralizedHoughGuil::getScaleThresh() + private static native int getScaleThresh_0(long nativeObj); + + // C++: void cv::GeneralizedHoughGuil::setAngleEpsilon(double angleEpsilon) + private static native void setAngleEpsilon_0(long nativeObj, double angleEpsilon); + + // C++: void cv::GeneralizedHoughGuil::setAngleStep(double angleStep) + private static native void setAngleStep_0(long nativeObj, double angleStep); + + // C++: void cv::GeneralizedHoughGuil::setAngleThresh(int angleThresh) + private static native void setAngleThresh_0(long nativeObj, int angleThresh); + + // C++: void cv::GeneralizedHoughGuil::setLevels(int levels) + private static native void setLevels_0(long nativeObj, int levels); + + // C++: void cv::GeneralizedHoughGuil::setMaxAngle(double maxAngle) + private static native void setMaxAngle_0(long nativeObj, double maxAngle); + + // C++: void cv::GeneralizedHoughGuil::setMaxScale(double maxScale) + private static native void setMaxScale_0(long nativeObj, double maxScale); + + // C++: void cv::GeneralizedHoughGuil::setMinAngle(double minAngle) + private static native void setMinAngle_0(long nativeObj, double minAngle); + + // C++: void cv::GeneralizedHoughGuil::setMinScale(double minScale) + private static native void setMinScale_0(long nativeObj, double minScale); + + // C++: void cv::GeneralizedHoughGuil::setPosThresh(int posThresh) + private static native void setPosThresh_0(long nativeObj, int posThresh); + + // C++: void cv::GeneralizedHoughGuil::setScaleStep(double scaleStep) + private static native void setScaleStep_0(long nativeObj, double scaleStep); + + // C++: void cv::GeneralizedHoughGuil::setScaleThresh(int scaleThresh) + private static native void setScaleThresh_0(long nativeObj, int scaleThresh); + + // C++: void cv::GeneralizedHoughGuil::setXi(double xi) + private static native void setXi_0(long nativeObj, double xi); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/imgproc/Imgproc.java b/OpenCV/src/main/java/org/opencv/imgproc/Imgproc.java new file mode 100644 index 00000000..74d09f25 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/imgproc/Imgproc.java @@ -0,0 +1,4475 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.imgproc; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfFloat; +import org.opencv.core.MatOfInt; +import org.opencv.core.MatOfInt4; +import org.opencv.core.MatOfPoint; +import org.opencv.core.MatOfPoint2f; +import org.opencv.core.Point; +import org.opencv.core.Rect; +import org.opencv.core.RotatedRect; +import org.opencv.core.Scalar; +import org.opencv.core.Size; +import org.opencv.core.TermCriteria; +import org.opencv.imgproc.CLAHE; +import org.opencv.imgproc.GeneralizedHoughBallard; +import org.opencv.imgproc.GeneralizedHoughGuil; +import org.opencv.imgproc.LineSegmentDetector; +import org.opencv.utils.Converters; + +// C++: class Imgproc +//javadoc: Imgproc + +public class Imgproc { + + private static final int + IPL_BORDER_CONSTANT = 0, + IPL_BORDER_REPLICATE = 1, + IPL_BORDER_REFLECT = 2, + IPL_BORDER_WRAP = 3, + IPL_BORDER_REFLECT_101 = 4, + IPL_BORDER_TRANSPARENT = 5, + CV_INTER_NN = 0, + CV_INTER_LINEAR = 1, + CV_INTER_CUBIC = 2, + CV_INTER_AREA = 3, + CV_INTER_LANCZOS4 = 4, + CV_MOP_ERODE = 0, + CV_MOP_DILATE = 1, + CV_MOP_OPEN = 2, + CV_MOP_CLOSE = 3, + CV_MOP_GRADIENT = 4, + CV_MOP_TOPHAT = 5, + CV_MOP_BLACKHAT = 6, + CV_RETR_EXTERNAL = 0, + CV_RETR_LIST = 1, + CV_RETR_CCOMP = 2, + CV_RETR_TREE = 3, + CV_RETR_FLOODFILL = 4, + CV_CHAIN_APPROX_NONE = 1, + CV_CHAIN_APPROX_SIMPLE = 2, + CV_CHAIN_APPROX_TC89_L1 = 3, + CV_CHAIN_APPROX_TC89_KCOS = 4, + CV_THRESH_BINARY = 0, + CV_THRESH_BINARY_INV = 1, + CV_THRESH_TRUNC = 2, + CV_THRESH_TOZERO = 3, + CV_THRESH_TOZERO_INV = 4, + CV_THRESH_MASK = 7, + CV_THRESH_OTSU = 8, + CV_THRESH_TRIANGLE = 16; + + + // C++: enum HersheyFonts + public static final int + FONT_HERSHEY_SIMPLEX = 0, + FONT_HERSHEY_PLAIN = 1, + FONT_HERSHEY_DUPLEX = 2, + FONT_HERSHEY_COMPLEX = 3, + FONT_HERSHEY_TRIPLEX = 4, + FONT_HERSHEY_COMPLEX_SMALL = 5, + FONT_HERSHEY_SCRIPT_SIMPLEX = 6, + FONT_HERSHEY_SCRIPT_COMPLEX = 7, + FONT_ITALIC = 16; + + + // C++: enum InterpolationMasks + public static final int + INTER_BITS = 5, + INTER_BITS2 = INTER_BITS * 2, + INTER_TAB_SIZE = 1 << INTER_BITS, + INTER_TAB_SIZE2 = INTER_TAB_SIZE * INTER_TAB_SIZE; + + + // C++: enum MorphTypes + public static final int + MORPH_ERODE = 0, + MORPH_DILATE = 1, + MORPH_OPEN = 2, + MORPH_CLOSE = 3, + MORPH_GRADIENT = 4, + MORPH_TOPHAT = 5, + MORPH_BLACKHAT = 6, + MORPH_HITMISS = 7; + + + // C++: enum FloodFillFlags + public static final int + FLOODFILL_FIXED_RANGE = 1 << 16, + FLOODFILL_MASK_ONLY = 1 << 17; + + + // C++: enum HoughModes + public static final int + HOUGH_STANDARD = 0, + HOUGH_PROBABILISTIC = 1, + HOUGH_MULTI_SCALE = 2, + HOUGH_GRADIENT = 3; + + + // C++: enum ConnectedComponentsAlgorithmsTypes + public static final int + CCL_WU = 0, + CCL_DEFAULT = -1, + CCL_GRANA = 1; + + + // C++: enum RetrievalModes + public static final int + RETR_EXTERNAL = 0, + RETR_LIST = 1, + RETR_CCOMP = 2, + RETR_TREE = 3, + RETR_FLOODFILL = 4; + + + // C++: enum GrabCutClasses + public static final int + GC_BGD = 0, + GC_FGD = 1, + GC_PR_BGD = 2, + GC_PR_FGD = 3; + + + // C++: enum ColormapTypes + public static final int + COLORMAP_AUTUMN = 0, + COLORMAP_BONE = 1, + COLORMAP_JET = 2, + COLORMAP_WINTER = 3, + COLORMAP_RAINBOW = 4, + COLORMAP_OCEAN = 5, + COLORMAP_SUMMER = 6, + COLORMAP_SPRING = 7, + COLORMAP_COOL = 8, + COLORMAP_HSV = 9, + COLORMAP_PINK = 10, + COLORMAP_HOT = 11, + COLORMAP_PARULA = 12, + COLORMAP_MAGMA = 13, + COLORMAP_INFERNO = 14, + COLORMAP_PLASMA = 15, + COLORMAP_VIRIDIS = 16, + COLORMAP_CIVIDIS = 17, + COLORMAP_TWILIGHT = 18, + COLORMAP_TWILIGHT_SHIFTED = 19; + + + // C++: enum HistCompMethods + public static final int + HISTCMP_CORREL = 0, + HISTCMP_CHISQR = 1, + HISTCMP_INTERSECT = 2, + HISTCMP_BHATTACHARYYA = 3, + HISTCMP_HELLINGER = HISTCMP_BHATTACHARYYA, + HISTCMP_CHISQR_ALT = 4, + HISTCMP_KL_DIV = 5; + + + // C++: enum LineTypes + public static final int + FILLED = -1, + LINE_4 = 4, + LINE_8 = 8, + LINE_AA = 16; + + + // C++: enum InterpolationFlags + public static final int + INTER_NEAREST = 0, + INTER_LINEAR = 1, + INTER_CUBIC = 2, + INTER_AREA = 3, + INTER_LANCZOS4 = 4, + INTER_LINEAR_EXACT = 5, + INTER_MAX = 7, + WARP_FILL_OUTLIERS = 8, + WARP_INVERSE_MAP = 16; + + + // C++: enum SpecialFilter + public static final int + FILTER_SCHARR = -1; + + + // C++: enum ContourApproximationModes + public static final int + CHAIN_APPROX_NONE = 1, + CHAIN_APPROX_SIMPLE = 2, + CHAIN_APPROX_TC89_L1 = 3, + CHAIN_APPROX_TC89_KCOS = 4; + + + // C++: enum RectanglesIntersectTypes + public static final int + INTERSECT_NONE = 0, + INTERSECT_PARTIAL = 1, + INTERSECT_FULL = 2; + + + // C++: enum + public static final int + CV_GAUSSIAN_5x5 = 7, + CV_SCHARR = -1, + CV_MAX_SOBEL_KSIZE = 7, + CV_RGBA2mRGBA = 125, + CV_mRGBA2RGBA = 126, + CV_WARP_FILL_OUTLIERS = 8, + CV_WARP_INVERSE_MAP = 16, + CV_CHAIN_CODE = 0, + CV_LINK_RUNS = 5, + CV_POLY_APPROX_DP = 0, + CV_CONTOURS_MATCH_I1 = 1, + CV_CONTOURS_MATCH_I2 = 2, + CV_CONTOURS_MATCH_I3 = 3, + CV_CLOCKWISE = 1, + CV_COUNTER_CLOCKWISE = 2, + CV_COMP_CORREL = 0, + CV_COMP_CHISQR = 1, + CV_COMP_INTERSECT = 2, + CV_COMP_BHATTACHARYYA = 3, + CV_COMP_HELLINGER = CV_COMP_BHATTACHARYYA, + CV_COMP_CHISQR_ALT = 4, + CV_COMP_KL_DIV = 5, + CV_DIST_MASK_3 = 3, + CV_DIST_MASK_5 = 5, + CV_DIST_MASK_PRECISE = 0, + CV_DIST_LABEL_CCOMP = 0, + CV_DIST_LABEL_PIXEL = 1, + CV_DIST_USER = -1, + CV_DIST_L1 = 1, + CV_DIST_L2 = 2, + CV_DIST_C = 3, + CV_DIST_L12 = 4, + CV_DIST_FAIR = 5, + CV_DIST_WELSCH = 6, + CV_DIST_HUBER = 7, + CV_CANNY_L2_GRADIENT = (1 << 31), + CV_HOUGH_STANDARD = 0, + CV_HOUGH_PROBABILISTIC = 1, + CV_HOUGH_MULTI_SCALE = 2, + CV_HOUGH_GRADIENT = 3; + + + // C++: enum ShapeMatchModes + public static final int + CONTOURS_MATCH_I1 = 1, + CONTOURS_MATCH_I2 = 2, + CONTOURS_MATCH_I3 = 3; + + + // C++: enum WarpPolarMode + public static final int + WARP_POLAR_LINEAR = 0, + WARP_POLAR_LOG = 256; + + + // C++: enum ColorConversionCodes + public static final int + COLOR_BGR2BGRA = 0, + COLOR_RGB2RGBA = COLOR_BGR2BGRA, + COLOR_BGRA2BGR = 1, + COLOR_RGBA2RGB = COLOR_BGRA2BGR, + COLOR_BGR2RGBA = 2, + COLOR_RGB2BGRA = COLOR_BGR2RGBA, + COLOR_RGBA2BGR = 3, + COLOR_BGRA2RGB = COLOR_RGBA2BGR, + COLOR_BGR2RGB = 4, + COLOR_RGB2BGR = COLOR_BGR2RGB, + COLOR_BGRA2RGBA = 5, + COLOR_RGBA2BGRA = COLOR_BGRA2RGBA, + COLOR_BGR2GRAY = 6, + COLOR_RGB2GRAY = 7, + COLOR_GRAY2BGR = 8, + COLOR_GRAY2RGB = COLOR_GRAY2BGR, + COLOR_GRAY2BGRA = 9, + COLOR_GRAY2RGBA = COLOR_GRAY2BGRA, + COLOR_BGRA2GRAY = 10, + COLOR_RGBA2GRAY = 11, + COLOR_BGR2BGR565 = 12, + COLOR_RGB2BGR565 = 13, + COLOR_BGR5652BGR = 14, + COLOR_BGR5652RGB = 15, + COLOR_BGRA2BGR565 = 16, + COLOR_RGBA2BGR565 = 17, + COLOR_BGR5652BGRA = 18, + COLOR_BGR5652RGBA = 19, + COLOR_GRAY2BGR565 = 20, + COLOR_BGR5652GRAY = 21, + COLOR_BGR2BGR555 = 22, + COLOR_RGB2BGR555 = 23, + COLOR_BGR5552BGR = 24, + COLOR_BGR5552RGB = 25, + COLOR_BGRA2BGR555 = 26, + COLOR_RGBA2BGR555 = 27, + COLOR_BGR5552BGRA = 28, + COLOR_BGR5552RGBA = 29, + COLOR_GRAY2BGR555 = 30, + COLOR_BGR5552GRAY = 31, + COLOR_BGR2XYZ = 32, + COLOR_RGB2XYZ = 33, + COLOR_XYZ2BGR = 34, + COLOR_XYZ2RGB = 35, + COLOR_BGR2YCrCb = 36, + COLOR_RGB2YCrCb = 37, + COLOR_YCrCb2BGR = 38, + COLOR_YCrCb2RGB = 39, + COLOR_BGR2HSV = 40, + COLOR_RGB2HSV = 41, + COLOR_BGR2Lab = 44, + COLOR_RGB2Lab = 45, + COLOR_BGR2Luv = 50, + COLOR_RGB2Luv = 51, + COLOR_BGR2HLS = 52, + COLOR_RGB2HLS = 53, + COLOR_HSV2BGR = 54, + COLOR_HSV2RGB = 55, + COLOR_Lab2BGR = 56, + COLOR_Lab2RGB = 57, + COLOR_Luv2BGR = 58, + COLOR_Luv2RGB = 59, + COLOR_HLS2BGR = 60, + COLOR_HLS2RGB = 61, + COLOR_BGR2HSV_FULL = 66, + COLOR_RGB2HSV_FULL = 67, + COLOR_BGR2HLS_FULL = 68, + COLOR_RGB2HLS_FULL = 69, + COLOR_HSV2BGR_FULL = 70, + COLOR_HSV2RGB_FULL = 71, + COLOR_HLS2BGR_FULL = 72, + COLOR_HLS2RGB_FULL = 73, + COLOR_LBGR2Lab = 74, + COLOR_LRGB2Lab = 75, + COLOR_LBGR2Luv = 76, + COLOR_LRGB2Luv = 77, + COLOR_Lab2LBGR = 78, + COLOR_Lab2LRGB = 79, + COLOR_Luv2LBGR = 80, + COLOR_Luv2LRGB = 81, + COLOR_BGR2YUV = 82, + COLOR_RGB2YUV = 83, + COLOR_YUV2BGR = 84, + COLOR_YUV2RGB = 85, + COLOR_YUV2RGB_NV12 = 90, + COLOR_YUV2BGR_NV12 = 91, + COLOR_YUV2RGB_NV21 = 92, + COLOR_YUV2BGR_NV21 = 93, + COLOR_YUV420sp2RGB = COLOR_YUV2RGB_NV21, + COLOR_YUV420sp2BGR = COLOR_YUV2BGR_NV21, + COLOR_YUV2RGBA_NV12 = 94, + COLOR_YUV2BGRA_NV12 = 95, + COLOR_YUV2RGBA_NV21 = 96, + COLOR_YUV2BGRA_NV21 = 97, + COLOR_YUV420sp2RGBA = COLOR_YUV2RGBA_NV21, + COLOR_YUV420sp2BGRA = COLOR_YUV2BGRA_NV21, + COLOR_YUV2RGB_YV12 = 98, + COLOR_YUV2BGR_YV12 = 99, + COLOR_YUV2RGB_IYUV = 100, + COLOR_YUV2BGR_IYUV = 101, + COLOR_YUV2RGB_I420 = COLOR_YUV2RGB_IYUV, + COLOR_YUV2BGR_I420 = COLOR_YUV2BGR_IYUV, + COLOR_YUV420p2RGB = COLOR_YUV2RGB_YV12, + COLOR_YUV420p2BGR = COLOR_YUV2BGR_YV12, + COLOR_YUV2RGBA_YV12 = 102, + COLOR_YUV2BGRA_YV12 = 103, + COLOR_YUV2RGBA_IYUV = 104, + COLOR_YUV2BGRA_IYUV = 105, + COLOR_YUV2RGBA_I420 = COLOR_YUV2RGBA_IYUV, + COLOR_YUV2BGRA_I420 = COLOR_YUV2BGRA_IYUV, + COLOR_YUV420p2RGBA = COLOR_YUV2RGBA_YV12, + COLOR_YUV420p2BGRA = COLOR_YUV2BGRA_YV12, + COLOR_YUV2GRAY_420 = 106, + COLOR_YUV2GRAY_NV21 = COLOR_YUV2GRAY_420, + COLOR_YUV2GRAY_NV12 = COLOR_YUV2GRAY_420, + COLOR_YUV2GRAY_YV12 = COLOR_YUV2GRAY_420, + COLOR_YUV2GRAY_IYUV = COLOR_YUV2GRAY_420, + COLOR_YUV2GRAY_I420 = COLOR_YUV2GRAY_420, + COLOR_YUV420sp2GRAY = COLOR_YUV2GRAY_420, + COLOR_YUV420p2GRAY = COLOR_YUV2GRAY_420, + COLOR_YUV2RGB_UYVY = 107, + COLOR_YUV2BGR_UYVY = 108, + COLOR_YUV2RGB_Y422 = COLOR_YUV2RGB_UYVY, + COLOR_YUV2BGR_Y422 = COLOR_YUV2BGR_UYVY, + COLOR_YUV2RGB_UYNV = COLOR_YUV2RGB_UYVY, + COLOR_YUV2BGR_UYNV = COLOR_YUV2BGR_UYVY, + COLOR_YUV2RGBA_UYVY = 111, + COLOR_YUV2BGRA_UYVY = 112, + COLOR_YUV2RGBA_Y422 = COLOR_YUV2RGBA_UYVY, + COLOR_YUV2BGRA_Y422 = COLOR_YUV2BGRA_UYVY, + COLOR_YUV2RGBA_UYNV = COLOR_YUV2RGBA_UYVY, + COLOR_YUV2BGRA_UYNV = COLOR_YUV2BGRA_UYVY, + COLOR_YUV2RGB_YUY2 = 115, + COLOR_YUV2BGR_YUY2 = 116, + COLOR_YUV2RGB_YVYU = 117, + COLOR_YUV2BGR_YVYU = 118, + COLOR_YUV2RGB_YUYV = COLOR_YUV2RGB_YUY2, + COLOR_YUV2BGR_YUYV = COLOR_YUV2BGR_YUY2, + COLOR_YUV2RGB_YUNV = COLOR_YUV2RGB_YUY2, + COLOR_YUV2BGR_YUNV = COLOR_YUV2BGR_YUY2, + COLOR_YUV2RGBA_YUY2 = 119, + COLOR_YUV2BGRA_YUY2 = 120, + COLOR_YUV2RGBA_YVYU = 121, + COLOR_YUV2BGRA_YVYU = 122, + COLOR_YUV2RGBA_YUYV = COLOR_YUV2RGBA_YUY2, + COLOR_YUV2BGRA_YUYV = COLOR_YUV2BGRA_YUY2, + COLOR_YUV2RGBA_YUNV = COLOR_YUV2RGBA_YUY2, + COLOR_YUV2BGRA_YUNV = COLOR_YUV2BGRA_YUY2, + COLOR_YUV2GRAY_UYVY = 123, + COLOR_YUV2GRAY_YUY2 = 124, + COLOR_YUV2GRAY_Y422 = COLOR_YUV2GRAY_UYVY, + COLOR_YUV2GRAY_UYNV = COLOR_YUV2GRAY_UYVY, + COLOR_YUV2GRAY_YVYU = COLOR_YUV2GRAY_YUY2, + COLOR_YUV2GRAY_YUYV = COLOR_YUV2GRAY_YUY2, + COLOR_YUV2GRAY_YUNV = COLOR_YUV2GRAY_YUY2, + COLOR_RGBA2mRGBA = 125, + COLOR_mRGBA2RGBA = 126, + COLOR_RGB2YUV_I420 = 127, + COLOR_BGR2YUV_I420 = 128, + COLOR_RGB2YUV_IYUV = COLOR_RGB2YUV_I420, + COLOR_BGR2YUV_IYUV = COLOR_BGR2YUV_I420, + COLOR_RGBA2YUV_I420 = 129, + COLOR_BGRA2YUV_I420 = 130, + COLOR_RGBA2YUV_IYUV = COLOR_RGBA2YUV_I420, + COLOR_BGRA2YUV_IYUV = COLOR_BGRA2YUV_I420, + COLOR_RGB2YUV_YV12 = 131, + COLOR_BGR2YUV_YV12 = 132, + COLOR_RGBA2YUV_YV12 = 133, + COLOR_BGRA2YUV_YV12 = 134, + COLOR_BayerBG2BGR = 46, + COLOR_BayerGB2BGR = 47, + COLOR_BayerRG2BGR = 48, + COLOR_BayerGR2BGR = 49, + COLOR_BayerBG2RGB = COLOR_BayerRG2BGR, + COLOR_BayerGB2RGB = COLOR_BayerGR2BGR, + COLOR_BayerRG2RGB = COLOR_BayerBG2BGR, + COLOR_BayerGR2RGB = COLOR_BayerGB2BGR, + COLOR_BayerBG2GRAY = 86, + COLOR_BayerGB2GRAY = 87, + COLOR_BayerRG2GRAY = 88, + COLOR_BayerGR2GRAY = 89, + COLOR_BayerBG2BGR_VNG = 62, + COLOR_BayerGB2BGR_VNG = 63, + COLOR_BayerRG2BGR_VNG = 64, + COLOR_BayerGR2BGR_VNG = 65, + COLOR_BayerBG2RGB_VNG = COLOR_BayerRG2BGR_VNG, + COLOR_BayerGB2RGB_VNG = COLOR_BayerGR2BGR_VNG, + COLOR_BayerRG2RGB_VNG = COLOR_BayerBG2BGR_VNG, + COLOR_BayerGR2RGB_VNG = COLOR_BayerGB2BGR_VNG, + COLOR_BayerBG2BGR_EA = 135, + COLOR_BayerGB2BGR_EA = 136, + COLOR_BayerRG2BGR_EA = 137, + COLOR_BayerGR2BGR_EA = 138, + COLOR_BayerBG2RGB_EA = COLOR_BayerRG2BGR_EA, + COLOR_BayerGB2RGB_EA = COLOR_BayerGR2BGR_EA, + COLOR_BayerRG2RGB_EA = COLOR_BayerBG2BGR_EA, + COLOR_BayerGR2RGB_EA = COLOR_BayerGB2BGR_EA, + COLOR_BayerBG2BGRA = 139, + COLOR_BayerGB2BGRA = 140, + COLOR_BayerRG2BGRA = 141, + COLOR_BayerGR2BGRA = 142, + COLOR_BayerBG2RGBA = COLOR_BayerRG2BGRA, + COLOR_BayerGB2RGBA = COLOR_BayerGR2BGRA, + COLOR_BayerRG2RGBA = COLOR_BayerBG2BGRA, + COLOR_BayerGR2RGBA = COLOR_BayerGB2BGRA, + COLOR_COLORCVT_MAX = 143; + + + // C++: enum LineSegmentDetectorModes + public static final int + LSD_REFINE_NONE = 0, + LSD_REFINE_STD = 1, + LSD_REFINE_ADV = 2; + + + // C++: enum ThresholdTypes + public static final int + THRESH_BINARY = 0, + THRESH_BINARY_INV = 1, + THRESH_TRUNC = 2, + THRESH_TOZERO = 3, + THRESH_TOZERO_INV = 4, + THRESH_MASK = 7, + THRESH_OTSU = 8, + THRESH_TRIANGLE = 16; + + + // C++: enum AdaptiveThresholdTypes + public static final int + ADAPTIVE_THRESH_MEAN_C = 0, + ADAPTIVE_THRESH_GAUSSIAN_C = 1; + + + // C++: enum MorphShapes_c + public static final int + CV_SHAPE_RECT = 0, + CV_SHAPE_CROSS = 1, + CV_SHAPE_ELLIPSE = 2, + CV_SHAPE_CUSTOM = 100; + + + // C++: enum GrabCutModes + public static final int + GC_INIT_WITH_RECT = 0, + GC_INIT_WITH_MASK = 1, + GC_EVAL = 2, + GC_EVAL_FREEZE_MODEL = 3; + + + // C++: enum MorphShapes + public static final int + MORPH_RECT = 0, + MORPH_CROSS = 1, + MORPH_ELLIPSE = 2; + + + // C++: enum DistanceTransformLabelTypes + public static final int + DIST_LABEL_CCOMP = 0, + DIST_LABEL_PIXEL = 1; + + + // C++: enum DistanceTypes + public static final int + DIST_USER = -1, + DIST_L1 = 1, + DIST_L2 = 2, + DIST_C = 3, + DIST_L12 = 4, + DIST_FAIR = 5, + DIST_WELSCH = 6, + DIST_HUBER = 7; + + + // C++: enum TemplateMatchModes + public static final int + TM_SQDIFF = 0, + TM_SQDIFF_NORMED = 1, + TM_CCORR = 2, + TM_CCORR_NORMED = 3, + TM_CCOEFF = 4, + TM_CCOEFF_NORMED = 5; + + + // C++: enum DistanceTransformMasks + public static final int + DIST_MASK_3 = 3, + DIST_MASK_5 = 5, + DIST_MASK_PRECISE = 0; + + + // C++: enum ConnectedComponentsTypes + public static final int + CC_STAT_LEFT = 0, + CC_STAT_TOP = 1, + CC_STAT_WIDTH = 2, + CC_STAT_HEIGHT = 3, + CC_STAT_AREA = 4, + CC_STAT_MAX = 5; + + + // C++: enum SmoothMethod_c + public static final int + CV_BLUR_NO_SCALE = 0, + CV_BLUR = 1, + CV_GAUSSIAN = 2, + CV_MEDIAN = 3, + CV_BILATERAL = 4; + + + // C++: enum MarkerTypes + public static final int + MARKER_CROSS = 0, + MARKER_TILTED_CROSS = 1, + MARKER_STAR = 2, + MARKER_DIAMOND = 3, + MARKER_SQUARE = 4, + MARKER_TRIANGLE_UP = 5, + MARKER_TRIANGLE_DOWN = 6; + + + // + // C++: Mat cv::getAffineTransform(vector_Point2f src, vector_Point2f dst) + // + + //javadoc: getAffineTransform(src, dst) + public static Mat getAffineTransform(MatOfPoint2f src, MatOfPoint2f dst) + { + Mat src_mat = src; + Mat dst_mat = dst; + Mat retVal = new Mat(getAffineTransform_0(src_mat.nativeObj, dst_mat.nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::getGaborKernel(Size ksize, double sigma, double theta, double lambd, double gamma, double psi = CV_PI*0.5, int ktype = CV_64F) + // + + //javadoc: getGaborKernel(ksize, sigma, theta, lambd, gamma, psi, ktype) + public static Mat getGaborKernel(Size ksize, double sigma, double theta, double lambd, double gamma, double psi, int ktype) + { + + Mat retVal = new Mat(getGaborKernel_0(ksize.width, ksize.height, sigma, theta, lambd, gamma, psi, ktype)); + + return retVal; + } + + //javadoc: getGaborKernel(ksize, sigma, theta, lambd, gamma, psi) + public static Mat getGaborKernel(Size ksize, double sigma, double theta, double lambd, double gamma, double psi) + { + + Mat retVal = new Mat(getGaborKernel_1(ksize.width, ksize.height, sigma, theta, lambd, gamma, psi)); + + return retVal; + } + + //javadoc: getGaborKernel(ksize, sigma, theta, lambd, gamma) + public static Mat getGaborKernel(Size ksize, double sigma, double theta, double lambd, double gamma) + { + + Mat retVal = new Mat(getGaborKernel_2(ksize.width, ksize.height, sigma, theta, lambd, gamma)); + + return retVal; + } + + + // + // C++: Mat cv::getGaussianKernel(int ksize, double sigma, int ktype = CV_64F) + // + + //javadoc: getGaussianKernel(ksize, sigma, ktype) + public static Mat getGaussianKernel(int ksize, double sigma, int ktype) + { + + Mat retVal = new Mat(getGaussianKernel_0(ksize, sigma, ktype)); + + return retVal; + } + + //javadoc: getGaussianKernel(ksize, sigma) + public static Mat getGaussianKernel(int ksize, double sigma) + { + + Mat retVal = new Mat(getGaussianKernel_1(ksize, sigma)); + + return retVal; + } + + + // + // C++: Mat cv::getPerspectiveTransform(Mat src, Mat dst, int solveMethod = DECOMP_LU) + // + + //javadoc: getPerspectiveTransform(src, dst, solveMethod) + public static Mat getPerspectiveTransform(Mat src, Mat dst, int solveMethod) + { + + Mat retVal = new Mat(getPerspectiveTransform_0(src.nativeObj, dst.nativeObj, solveMethod)); + + return retVal; + } + + //javadoc: getPerspectiveTransform(src, dst) + public static Mat getPerspectiveTransform(Mat src, Mat dst) + { + + Mat retVal = new Mat(getPerspectiveTransform_1(src.nativeObj, dst.nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::getRotationMatrix2D(Point2f center, double angle, double scale) + // + + //javadoc: getRotationMatrix2D(center, angle, scale) + public static Mat getRotationMatrix2D(Point center, double angle, double scale) + { + + Mat retVal = new Mat(getRotationMatrix2D_0(center.x, center.y, angle, scale)); + + return retVal; + } + + + // + // C++: Mat cv::getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1)) + // + + //javadoc: getStructuringElement(shape, ksize, anchor) + public static Mat getStructuringElement(int shape, Size ksize, Point anchor) + { + + Mat retVal = new Mat(getStructuringElement_0(shape, ksize.width, ksize.height, anchor.x, anchor.y)); + + return retVal; + } + + //javadoc: getStructuringElement(shape, ksize) + public static Mat getStructuringElement(int shape, Size ksize) + { + + Mat retVal = new Mat(getStructuringElement_1(shape, ksize.width, ksize.height)); + + return retVal; + } + + + // + // C++: Moments cv::moments(Mat array, bool binaryImage = false) + // + + //javadoc: moments(array, binaryImage) + public static Moments moments(Mat array, boolean binaryImage) + { + + Moments retVal = new Moments(moments_0(array.nativeObj, binaryImage)); + + return retVal; + } + + //javadoc: moments(array) + public static Moments moments(Mat array) + { + + Moments retVal = new Moments(moments_1(array.nativeObj)); + + return retVal; + } + + + // + // C++: Point2d cv::phaseCorrelate(Mat src1, Mat src2, Mat window = Mat(), double* response = 0) + // + + //javadoc: phaseCorrelate(src1, src2, window, response) + public static Point phaseCorrelate(Mat src1, Mat src2, Mat window, double[] response) + { + double[] response_out = new double[1]; + Point retVal = new Point(phaseCorrelate_0(src1.nativeObj, src2.nativeObj, window.nativeObj, response_out)); + if(response!=null) response[0] = (double)response_out[0]; + return retVal; + } + + //javadoc: phaseCorrelate(src1, src2, window) + public static Point phaseCorrelate(Mat src1, Mat src2, Mat window) + { + + Point retVal = new Point(phaseCorrelate_1(src1.nativeObj, src2.nativeObj, window.nativeObj)); + + return retVal; + } + + //javadoc: phaseCorrelate(src1, src2) + public static Point phaseCorrelate(Mat src1, Mat src2) + { + + Point retVal = new Point(phaseCorrelate_2(src1.nativeObj, src2.nativeObj)); + + return retVal; + } + + + // + // C++: Ptr_CLAHE cv::createCLAHE(double clipLimit = 40.0, Size tileGridSize = Size(8, 8)) + // + + //javadoc: createCLAHE(clipLimit, tileGridSize) + public static CLAHE createCLAHE(double clipLimit, Size tileGridSize) + { + + CLAHE retVal = CLAHE.__fromPtr__(createCLAHE_0(clipLimit, tileGridSize.width, tileGridSize.height)); + + return retVal; + } + + //javadoc: createCLAHE(clipLimit) + public static CLAHE createCLAHE(double clipLimit) + { + + CLAHE retVal = CLAHE.__fromPtr__(createCLAHE_1(clipLimit)); + + return retVal; + } + + //javadoc: createCLAHE() + public static CLAHE createCLAHE() + { + + CLAHE retVal = CLAHE.__fromPtr__(createCLAHE_2()); + + return retVal; + } + + + // + // C++: Ptr_GeneralizedHoughBallard cv::createGeneralizedHoughBallard() + // + + //javadoc: createGeneralizedHoughBallard() + public static GeneralizedHoughBallard createGeneralizedHoughBallard() + { + + GeneralizedHoughBallard retVal = GeneralizedHoughBallard.__fromPtr__(createGeneralizedHoughBallard_0()); + + return retVal; + } + + + // + // C++: Ptr_GeneralizedHoughGuil cv::createGeneralizedHoughGuil() + // + + //javadoc: createGeneralizedHoughGuil() + public static GeneralizedHoughGuil createGeneralizedHoughGuil() + { + + GeneralizedHoughGuil retVal = GeneralizedHoughGuil.__fromPtr__(createGeneralizedHoughGuil_0()); + + return retVal; + } + + + // + // C++: Ptr_LineSegmentDetector cv::createLineSegmentDetector(int _refine = LSD_REFINE_STD, double _scale = 0.8, double _sigma_scale = 0.6, double _quant = 2.0, double _ang_th = 22.5, double _log_eps = 0, double _density_th = 0.7, int _n_bins = 1024) + // + + //javadoc: createLineSegmentDetector(_refine, _scale, _sigma_scale, _quant, _ang_th, _log_eps, _density_th, _n_bins) + public static LineSegmentDetector createLineSegmentDetector(int _refine, double _scale, double _sigma_scale, double _quant, double _ang_th, double _log_eps, double _density_th, int _n_bins) + { + + LineSegmentDetector retVal = LineSegmentDetector.__fromPtr__(createLineSegmentDetector_0(_refine, _scale, _sigma_scale, _quant, _ang_th, _log_eps, _density_th, _n_bins)); + + return retVal; + } + + //javadoc: createLineSegmentDetector(_refine, _scale, _sigma_scale, _quant, _ang_th, _log_eps, _density_th) + public static LineSegmentDetector createLineSegmentDetector(int _refine, double _scale, double _sigma_scale, double _quant, double _ang_th, double _log_eps, double _density_th) + { + + LineSegmentDetector retVal = LineSegmentDetector.__fromPtr__(createLineSegmentDetector_1(_refine, _scale, _sigma_scale, _quant, _ang_th, _log_eps, _density_th)); + + return retVal; + } + + //javadoc: createLineSegmentDetector(_refine, _scale, _sigma_scale, _quant, _ang_th, _log_eps) + public static LineSegmentDetector createLineSegmentDetector(int _refine, double _scale, double _sigma_scale, double _quant, double _ang_th, double _log_eps) + { + + LineSegmentDetector retVal = LineSegmentDetector.__fromPtr__(createLineSegmentDetector_2(_refine, _scale, _sigma_scale, _quant, _ang_th, _log_eps)); + + return retVal; + } + + //javadoc: createLineSegmentDetector(_refine, _scale, _sigma_scale, _quant, _ang_th) + public static LineSegmentDetector createLineSegmentDetector(int _refine, double _scale, double _sigma_scale, double _quant, double _ang_th) + { + + LineSegmentDetector retVal = LineSegmentDetector.__fromPtr__(createLineSegmentDetector_3(_refine, _scale, _sigma_scale, _quant, _ang_th)); + + return retVal; + } + + //javadoc: createLineSegmentDetector(_refine, _scale, _sigma_scale, _quant) + public static LineSegmentDetector createLineSegmentDetector(int _refine, double _scale, double _sigma_scale, double _quant) + { + + LineSegmentDetector retVal = LineSegmentDetector.__fromPtr__(createLineSegmentDetector_4(_refine, _scale, _sigma_scale, _quant)); + + return retVal; + } + + //javadoc: createLineSegmentDetector(_refine, _scale, _sigma_scale) + public static LineSegmentDetector createLineSegmentDetector(int _refine, double _scale, double _sigma_scale) + { + + LineSegmentDetector retVal = LineSegmentDetector.__fromPtr__(createLineSegmentDetector_5(_refine, _scale, _sigma_scale)); + + return retVal; + } + + //javadoc: createLineSegmentDetector(_refine, _scale) + public static LineSegmentDetector createLineSegmentDetector(int _refine, double _scale) + { + + LineSegmentDetector retVal = LineSegmentDetector.__fromPtr__(createLineSegmentDetector_6(_refine, _scale)); + + return retVal; + } + + //javadoc: createLineSegmentDetector(_refine) + public static LineSegmentDetector createLineSegmentDetector(int _refine) + { + + LineSegmentDetector retVal = LineSegmentDetector.__fromPtr__(createLineSegmentDetector_7(_refine)); + + return retVal; + } + + //javadoc: createLineSegmentDetector() + public static LineSegmentDetector createLineSegmentDetector() + { + + LineSegmentDetector retVal = LineSegmentDetector.__fromPtr__(createLineSegmentDetector_8()); + + return retVal; + } + + + // + // C++: Rect cv::boundingRect(Mat array) + // + + //javadoc: boundingRect(array) + public static Rect boundingRect(Mat array) + { + + Rect retVal = new Rect(boundingRect_0(array.nativeObj)); + + return retVal; + } + + + // + // C++: RotatedRect cv::fitEllipse(vector_Point2f points) + // + + //javadoc: fitEllipse(points) + public static RotatedRect fitEllipse(MatOfPoint2f points) + { + Mat points_mat = points; + RotatedRect retVal = new RotatedRect(fitEllipse_0(points_mat.nativeObj)); + + return retVal; + } + + + // + // C++: RotatedRect cv::fitEllipseAMS(Mat points) + // + + //javadoc: fitEllipseAMS(points) + public static RotatedRect fitEllipseAMS(Mat points) + { + + RotatedRect retVal = new RotatedRect(fitEllipseAMS_0(points.nativeObj)); + + return retVal; + } + + + // + // C++: RotatedRect cv::fitEllipseDirect(Mat points) + // + + //javadoc: fitEllipseDirect(points) + public static RotatedRect fitEllipseDirect(Mat points) + { + + RotatedRect retVal = new RotatedRect(fitEllipseDirect_0(points.nativeObj)); + + return retVal; + } + + + // + // C++: RotatedRect cv::minAreaRect(vector_Point2f points) + // + + //javadoc: minAreaRect(points) + public static RotatedRect minAreaRect(MatOfPoint2f points) + { + Mat points_mat = points; + RotatedRect retVal = new RotatedRect(minAreaRect_0(points_mat.nativeObj)); + + return retVal; + } + + + // + // C++: bool cv::clipLine(Rect imgRect, Point& pt1, Point& pt2) + // + + //javadoc: clipLine(imgRect, pt1, pt2) + public static boolean clipLine(Rect imgRect, Point pt1, Point pt2) + { + double[] pt1_out = new double[2]; + double[] pt2_out = new double[2]; + boolean retVal = clipLine_0(imgRect.x, imgRect.y, imgRect.width, imgRect.height, pt1.x, pt1.y, pt1_out, pt2.x, pt2.y, pt2_out); + if(pt1!=null){ pt1.x = pt1_out[0]; pt1.y = pt1_out[1]; } + if(pt2!=null){ pt2.x = pt2_out[0]; pt2.y = pt2_out[1]; } + return retVal; + } + + + // + // C++: bool cv::isContourConvex(vector_Point contour) + // + + //javadoc: isContourConvex(contour) + public static boolean isContourConvex(MatOfPoint contour) + { + Mat contour_mat = contour; + boolean retVal = isContourConvex_0(contour_mat.nativeObj); + + return retVal; + } + + + // + // C++: double cv::arcLength(vector_Point2f curve, bool closed) + // + + //javadoc: arcLength(curve, closed) + public static double arcLength(MatOfPoint2f curve, boolean closed) + { + Mat curve_mat = curve; + double retVal = arcLength_0(curve_mat.nativeObj, closed); + + return retVal; + } + + + // + // C++: double cv::compareHist(Mat H1, Mat H2, int method) + // + + //javadoc: compareHist(H1, H2, method) + public static double compareHist(Mat H1, Mat H2, int method) + { + + double retVal = compareHist_0(H1.nativeObj, H2.nativeObj, method); + + return retVal; + } + + + // + // C++: double cv::contourArea(Mat contour, bool oriented = false) + // + + //javadoc: contourArea(contour, oriented) + public static double contourArea(Mat contour, boolean oriented) + { + + double retVal = contourArea_0(contour.nativeObj, oriented); + + return retVal; + } + + //javadoc: contourArea(contour) + public static double contourArea(Mat contour) + { + + double retVal = contourArea_1(contour.nativeObj); + + return retVal; + } + + + // + // C++: double cv::getFontScaleFromHeight(int fontFace, int pixelHeight, int thickness = 1) + // + + //javadoc: getFontScaleFromHeight(fontFace, pixelHeight, thickness) + public static double getFontScaleFromHeight(int fontFace, int pixelHeight, int thickness) + { + + double retVal = getFontScaleFromHeight_0(fontFace, pixelHeight, thickness); + + return retVal; + } + + //javadoc: getFontScaleFromHeight(fontFace, pixelHeight) + public static double getFontScaleFromHeight(int fontFace, int pixelHeight) + { + + double retVal = getFontScaleFromHeight_1(fontFace, pixelHeight); + + return retVal; + } + + + // + // C++: double cv::matchShapes(Mat contour1, Mat contour2, int method, double parameter) + // + + //javadoc: matchShapes(contour1, contour2, method, parameter) + public static double matchShapes(Mat contour1, Mat contour2, int method, double parameter) + { + + double retVal = matchShapes_0(contour1.nativeObj, contour2.nativeObj, method, parameter); + + return retVal; + } + + + // + // C++: double cv::minEnclosingTriangle(Mat points, Mat& triangle) + // + + //javadoc: minEnclosingTriangle(points, triangle) + public static double minEnclosingTriangle(Mat points, Mat triangle) + { + + double retVal = minEnclosingTriangle_0(points.nativeObj, triangle.nativeObj); + + return retVal; + } + + + // + // C++: double cv::pointPolygonTest(vector_Point2f contour, Point2f pt, bool measureDist) + // + + //javadoc: pointPolygonTest(contour, pt, measureDist) + public static double pointPolygonTest(MatOfPoint2f contour, Point pt, boolean measureDist) + { + Mat contour_mat = contour; + double retVal = pointPolygonTest_0(contour_mat.nativeObj, pt.x, pt.y, measureDist); + + return retVal; + } + + + // + // C++: double cv::threshold(Mat src, Mat& dst, double thresh, double maxval, int type) + // + + //javadoc: threshold(src, dst, thresh, maxval, type) + public static double threshold(Mat src, Mat dst, double thresh, double maxval, int type) + { + + double retVal = threshold_0(src.nativeObj, dst.nativeObj, thresh, maxval, type); + + return retVal; + } + + + // + // C++: float cv::intersectConvexConvex(Mat _p1, Mat _p2, Mat& _p12, bool handleNested = true) + // + + //javadoc: intersectConvexConvex(_p1, _p2, _p12, handleNested) + public static float intersectConvexConvex(Mat _p1, Mat _p2, Mat _p12, boolean handleNested) + { + + float retVal = intersectConvexConvex_0(_p1.nativeObj, _p2.nativeObj, _p12.nativeObj, handleNested); + + return retVal; + } + + //javadoc: intersectConvexConvex(_p1, _p2, _p12) + public static float intersectConvexConvex(Mat _p1, Mat _p2, Mat _p12) + { + + float retVal = intersectConvexConvex_1(_p1.nativeObj, _p2.nativeObj, _p12.nativeObj); + + return retVal; + } + + + // + // C++: float cv::wrapperEMD(Mat signature1, Mat signature2, int distType, Mat cost = Mat(), Ptr_float& lowerBound = Ptr(), Mat& flow = Mat()) + // + + //javadoc: EMD(signature1, signature2, distType, cost, flow) + public static float EMD(Mat signature1, Mat signature2, int distType, Mat cost, Mat flow) + { + + float retVal = EMD_0(signature1.nativeObj, signature2.nativeObj, distType, cost.nativeObj, flow.nativeObj); + + return retVal; + } + + //javadoc: EMD(signature1, signature2, distType, cost) + public static float EMD(Mat signature1, Mat signature2, int distType, Mat cost) + { + + float retVal = EMD_1(signature1.nativeObj, signature2.nativeObj, distType, cost.nativeObj); + + return retVal; + } + + //javadoc: EMD(signature1, signature2, distType) + public static float EMD(Mat signature1, Mat signature2, int distType) + { + + float retVal = EMD_3(signature1.nativeObj, signature2.nativeObj, distType); + + return retVal; + } + + + // + // C++: int cv::connectedComponents(Mat image, Mat& labels, int connectivity, int ltype, int ccltype) + // + + //javadoc: connectedComponentsWithAlgorithm(image, labels, connectivity, ltype, ccltype) + public static int connectedComponentsWithAlgorithm(Mat image, Mat labels, int connectivity, int ltype, int ccltype) + { + + int retVal = connectedComponentsWithAlgorithm_0(image.nativeObj, labels.nativeObj, connectivity, ltype, ccltype); + + return retVal; + } + + + // + // C++: int cv::connectedComponents(Mat image, Mat& labels, int connectivity = 8, int ltype = CV_32S) + // + + //javadoc: connectedComponents(image, labels, connectivity, ltype) + public static int connectedComponents(Mat image, Mat labels, int connectivity, int ltype) + { + + int retVal = connectedComponents_0(image.nativeObj, labels.nativeObj, connectivity, ltype); + + return retVal; + } + + //javadoc: connectedComponents(image, labels, connectivity) + public static int connectedComponents(Mat image, Mat labels, int connectivity) + { + + int retVal = connectedComponents_1(image.nativeObj, labels.nativeObj, connectivity); + + return retVal; + } + + //javadoc: connectedComponents(image, labels) + public static int connectedComponents(Mat image, Mat labels) + { + + int retVal = connectedComponents_2(image.nativeObj, labels.nativeObj); + + return retVal; + } + + + // + // C++: int cv::connectedComponentsWithStats(Mat image, Mat& labels, Mat& stats, Mat& centroids, int connectivity, int ltype, int ccltype) + // + + //javadoc: connectedComponentsWithStatsWithAlgorithm(image, labels, stats, centroids, connectivity, ltype, ccltype) + public static int connectedComponentsWithStatsWithAlgorithm(Mat image, Mat labels, Mat stats, Mat centroids, int connectivity, int ltype, int ccltype) + { + + int retVal = connectedComponentsWithStatsWithAlgorithm_0(image.nativeObj, labels.nativeObj, stats.nativeObj, centroids.nativeObj, connectivity, ltype, ccltype); + + return retVal; + } + + + // + // C++: int cv::connectedComponentsWithStats(Mat image, Mat& labels, Mat& stats, Mat& centroids, int connectivity = 8, int ltype = CV_32S) + // + + //javadoc: connectedComponentsWithStats(image, labels, stats, centroids, connectivity, ltype) + public static int connectedComponentsWithStats(Mat image, Mat labels, Mat stats, Mat centroids, int connectivity, int ltype) + { + + int retVal = connectedComponentsWithStats_0(image.nativeObj, labels.nativeObj, stats.nativeObj, centroids.nativeObj, connectivity, ltype); + + return retVal; + } + + //javadoc: connectedComponentsWithStats(image, labels, stats, centroids, connectivity) + public static int connectedComponentsWithStats(Mat image, Mat labels, Mat stats, Mat centroids, int connectivity) + { + + int retVal = connectedComponentsWithStats_1(image.nativeObj, labels.nativeObj, stats.nativeObj, centroids.nativeObj, connectivity); + + return retVal; + } + + //javadoc: connectedComponentsWithStats(image, labels, stats, centroids) + public static int connectedComponentsWithStats(Mat image, Mat labels, Mat stats, Mat centroids) + { + + int retVal = connectedComponentsWithStats_2(image.nativeObj, labels.nativeObj, stats.nativeObj, centroids.nativeObj); + + return retVal; + } + + + // + // C++: int cv::floodFill(Mat& image, Mat& mask, Point seedPoint, Scalar newVal, Rect* rect = 0, Scalar loDiff = Scalar(), Scalar upDiff = Scalar(), int flags = 4) + // + + //javadoc: floodFill(image, mask, seedPoint, newVal, rect, loDiff, upDiff, flags) + public static int floodFill(Mat image, Mat mask, Point seedPoint, Scalar newVal, Rect rect, Scalar loDiff, Scalar upDiff, int flags) + { + double[] rect_out = new double[4]; + int retVal = floodFill_0(image.nativeObj, mask.nativeObj, seedPoint.x, seedPoint.y, newVal.val[0], newVal.val[1], newVal.val[2], newVal.val[3], rect_out, loDiff.val[0], loDiff.val[1], loDiff.val[2], loDiff.val[3], upDiff.val[0], upDiff.val[1], upDiff.val[2], upDiff.val[3], flags); + if(rect!=null){ rect.x = (int)rect_out[0]; rect.y = (int)rect_out[1]; rect.width = (int)rect_out[2]; rect.height = (int)rect_out[3]; } + return retVal; + } + + //javadoc: floodFill(image, mask, seedPoint, newVal, rect, loDiff, upDiff) + public static int floodFill(Mat image, Mat mask, Point seedPoint, Scalar newVal, Rect rect, Scalar loDiff, Scalar upDiff) + { + double[] rect_out = new double[4]; + int retVal = floodFill_1(image.nativeObj, mask.nativeObj, seedPoint.x, seedPoint.y, newVal.val[0], newVal.val[1], newVal.val[2], newVal.val[3], rect_out, loDiff.val[0], loDiff.val[1], loDiff.val[2], loDiff.val[3], upDiff.val[0], upDiff.val[1], upDiff.val[2], upDiff.val[3]); + if(rect!=null){ rect.x = (int)rect_out[0]; rect.y = (int)rect_out[1]; rect.width = (int)rect_out[2]; rect.height = (int)rect_out[3]; } + return retVal; + } + + //javadoc: floodFill(image, mask, seedPoint, newVal, rect, loDiff) + public static int floodFill(Mat image, Mat mask, Point seedPoint, Scalar newVal, Rect rect, Scalar loDiff) + { + double[] rect_out = new double[4]; + int retVal = floodFill_2(image.nativeObj, mask.nativeObj, seedPoint.x, seedPoint.y, newVal.val[0], newVal.val[1], newVal.val[2], newVal.val[3], rect_out, loDiff.val[0], loDiff.val[1], loDiff.val[2], loDiff.val[3]); + if(rect!=null){ rect.x = (int)rect_out[0]; rect.y = (int)rect_out[1]; rect.width = (int)rect_out[2]; rect.height = (int)rect_out[3]; } + return retVal; + } + + //javadoc: floodFill(image, mask, seedPoint, newVal, rect) + public static int floodFill(Mat image, Mat mask, Point seedPoint, Scalar newVal, Rect rect) + { + double[] rect_out = new double[4]; + int retVal = floodFill_3(image.nativeObj, mask.nativeObj, seedPoint.x, seedPoint.y, newVal.val[0], newVal.val[1], newVal.val[2], newVal.val[3], rect_out); + if(rect!=null){ rect.x = (int)rect_out[0]; rect.y = (int)rect_out[1]; rect.width = (int)rect_out[2]; rect.height = (int)rect_out[3]; } + return retVal; + } + + //javadoc: floodFill(image, mask, seedPoint, newVal) + public static int floodFill(Mat image, Mat mask, Point seedPoint, Scalar newVal) + { + + int retVal = floodFill_4(image.nativeObj, mask.nativeObj, seedPoint.x, seedPoint.y, newVal.val[0], newVal.val[1], newVal.val[2], newVal.val[3]); + + return retVal; + } + + + // + // C++: int cv::rotatedRectangleIntersection(RotatedRect rect1, RotatedRect rect2, Mat& intersectingRegion) + // + + //javadoc: rotatedRectangleIntersection(rect1, rect2, intersectingRegion) + public static int rotatedRectangleIntersection(RotatedRect rect1, RotatedRect rect2, Mat intersectingRegion) + { + + int retVal = rotatedRectangleIntersection_0(rect1.center.x, rect1.center.y, rect1.size.width, rect1.size.height, rect1.angle, rect2.center.x, rect2.center.y, rect2.size.width, rect2.size.height, rect2.angle, intersectingRegion.nativeObj); + + return retVal; + } + + + // + // C++: void cv::Canny(Mat dx, Mat dy, Mat& edges, double threshold1, double threshold2, bool L2gradient = false) + // + + //javadoc: Canny(dx, dy, edges, threshold1, threshold2, L2gradient) + public static void Canny(Mat dx, Mat dy, Mat edges, double threshold1, double threshold2, boolean L2gradient) + { + + Canny_0(dx.nativeObj, dy.nativeObj, edges.nativeObj, threshold1, threshold2, L2gradient); + + return; + } + + //javadoc: Canny(dx, dy, edges, threshold1, threshold2) + public static void Canny(Mat dx, Mat dy, Mat edges, double threshold1, double threshold2) + { + + Canny_1(dx.nativeObj, dy.nativeObj, edges.nativeObj, threshold1, threshold2); + + return; + } + + + // + // C++: void cv::Canny(Mat image, Mat& edges, double threshold1, double threshold2, int apertureSize = 3, bool L2gradient = false) + // + + //javadoc: Canny(image, edges, threshold1, threshold2, apertureSize, L2gradient) + public static void Canny(Mat image, Mat edges, double threshold1, double threshold2, int apertureSize, boolean L2gradient) + { + + Canny_2(image.nativeObj, edges.nativeObj, threshold1, threshold2, apertureSize, L2gradient); + + return; + } + + //javadoc: Canny(image, edges, threshold1, threshold2, apertureSize) + public static void Canny(Mat image, Mat edges, double threshold1, double threshold2, int apertureSize) + { + + Canny_3(image.nativeObj, edges.nativeObj, threshold1, threshold2, apertureSize); + + return; + } + + //javadoc: Canny(image, edges, threshold1, threshold2) + public static void Canny(Mat image, Mat edges, double threshold1, double threshold2) + { + + Canny_4(image.nativeObj, edges.nativeObj, threshold1, threshold2); + + return; + } + + + // + // C++: void cv::GaussianBlur(Mat src, Mat& dst, Size ksize, double sigmaX, double sigmaY = 0, int borderType = BORDER_DEFAULT) + // + + //javadoc: GaussianBlur(src, dst, ksize, sigmaX, sigmaY, borderType) + public static void GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX, double sigmaY, int borderType) + { + + GaussianBlur_0(src.nativeObj, dst.nativeObj, ksize.width, ksize.height, sigmaX, sigmaY, borderType); + + return; + } + + //javadoc: GaussianBlur(src, dst, ksize, sigmaX, sigmaY) + public static void GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX, double sigmaY) + { + + GaussianBlur_1(src.nativeObj, dst.nativeObj, ksize.width, ksize.height, sigmaX, sigmaY); + + return; + } + + //javadoc: GaussianBlur(src, dst, ksize, sigmaX) + public static void GaussianBlur(Mat src, Mat dst, Size ksize, double sigmaX) + { + + GaussianBlur_2(src.nativeObj, dst.nativeObj, ksize.width, ksize.height, sigmaX); + + return; + } + + + // + // C++: void cv::HoughCircles(Mat image, Mat& circles, int method, double dp, double minDist, double param1 = 100, double param2 = 100, int minRadius = 0, int maxRadius = 0) + // + + //javadoc: HoughCircles(image, circles, method, dp, minDist, param1, param2, minRadius, maxRadius) + public static void HoughCircles(Mat image, Mat circles, int method, double dp, double minDist, double param1, double param2, int minRadius, int maxRadius) + { + + HoughCircles_0(image.nativeObj, circles.nativeObj, method, dp, minDist, param1, param2, minRadius, maxRadius); + + return; + } + + //javadoc: HoughCircles(image, circles, method, dp, minDist, param1, param2, minRadius) + public static void HoughCircles(Mat image, Mat circles, int method, double dp, double minDist, double param1, double param2, int minRadius) + { + + HoughCircles_1(image.nativeObj, circles.nativeObj, method, dp, minDist, param1, param2, minRadius); + + return; + } + + //javadoc: HoughCircles(image, circles, method, dp, minDist, param1, param2) + public static void HoughCircles(Mat image, Mat circles, int method, double dp, double minDist, double param1, double param2) + { + + HoughCircles_2(image.nativeObj, circles.nativeObj, method, dp, minDist, param1, param2); + + return; + } + + //javadoc: HoughCircles(image, circles, method, dp, minDist, param1) + public static void HoughCircles(Mat image, Mat circles, int method, double dp, double minDist, double param1) + { + + HoughCircles_3(image.nativeObj, circles.nativeObj, method, dp, minDist, param1); + + return; + } + + //javadoc: HoughCircles(image, circles, method, dp, minDist) + public static void HoughCircles(Mat image, Mat circles, int method, double dp, double minDist) + { + + HoughCircles_4(image.nativeObj, circles.nativeObj, method, dp, minDist); + + return; + } + + + // + // C++: void cv::HoughLines(Mat image, Mat& lines, double rho, double theta, int threshold, double srn = 0, double stn = 0, double min_theta = 0, double max_theta = CV_PI) + // + + //javadoc: HoughLines(image, lines, rho, theta, threshold, srn, stn, min_theta, max_theta) + public static void HoughLines(Mat image, Mat lines, double rho, double theta, int threshold, double srn, double stn, double min_theta, double max_theta) + { + + HoughLines_0(image.nativeObj, lines.nativeObj, rho, theta, threshold, srn, stn, min_theta, max_theta); + + return; + } + + //javadoc: HoughLines(image, lines, rho, theta, threshold, srn, stn, min_theta) + public static void HoughLines(Mat image, Mat lines, double rho, double theta, int threshold, double srn, double stn, double min_theta) + { + + HoughLines_1(image.nativeObj, lines.nativeObj, rho, theta, threshold, srn, stn, min_theta); + + return; + } + + //javadoc: HoughLines(image, lines, rho, theta, threshold, srn, stn) + public static void HoughLines(Mat image, Mat lines, double rho, double theta, int threshold, double srn, double stn) + { + + HoughLines_2(image.nativeObj, lines.nativeObj, rho, theta, threshold, srn, stn); + + return; + } + + //javadoc: HoughLines(image, lines, rho, theta, threshold, srn) + public static void HoughLines(Mat image, Mat lines, double rho, double theta, int threshold, double srn) + { + + HoughLines_3(image.nativeObj, lines.nativeObj, rho, theta, threshold, srn); + + return; + } + + //javadoc: HoughLines(image, lines, rho, theta, threshold) + public static void HoughLines(Mat image, Mat lines, double rho, double theta, int threshold) + { + + HoughLines_4(image.nativeObj, lines.nativeObj, rho, theta, threshold); + + return; + } + + + // + // C++: void cv::HoughLinesP(Mat image, Mat& lines, double rho, double theta, int threshold, double minLineLength = 0, double maxLineGap = 0) + // + + //javadoc: HoughLinesP(image, lines, rho, theta, threshold, minLineLength, maxLineGap) + public static void HoughLinesP(Mat image, Mat lines, double rho, double theta, int threshold, double minLineLength, double maxLineGap) + { + + HoughLinesP_0(image.nativeObj, lines.nativeObj, rho, theta, threshold, minLineLength, maxLineGap); + + return; + } + + //javadoc: HoughLinesP(image, lines, rho, theta, threshold, minLineLength) + public static void HoughLinesP(Mat image, Mat lines, double rho, double theta, int threshold, double minLineLength) + { + + HoughLinesP_1(image.nativeObj, lines.nativeObj, rho, theta, threshold, minLineLength); + + return; + } + + //javadoc: HoughLinesP(image, lines, rho, theta, threshold) + public static void HoughLinesP(Mat image, Mat lines, double rho, double theta, int threshold) + { + + HoughLinesP_2(image.nativeObj, lines.nativeObj, rho, theta, threshold); + + return; + } + + + // + // C++: void cv::HoughLinesPointSet(Mat _point, Mat& _lines, int lines_max, int threshold, double min_rho, double max_rho, double rho_step, double min_theta, double max_theta, double theta_step) + // + + //javadoc: HoughLinesPointSet(_point, _lines, lines_max, threshold, min_rho, max_rho, rho_step, min_theta, max_theta, theta_step) + public static void HoughLinesPointSet(Mat _point, Mat _lines, int lines_max, int threshold, double min_rho, double max_rho, double rho_step, double min_theta, double max_theta, double theta_step) + { + + HoughLinesPointSet_0(_point.nativeObj, _lines.nativeObj, lines_max, threshold, min_rho, max_rho, rho_step, min_theta, max_theta, theta_step); + + return; + } + + + // + // C++: void cv::HuMoments(Moments m, Mat& hu) + // + + //javadoc: HuMoments(m, hu) + public static void HuMoments(Moments m, Mat hu) + { + + HuMoments_0(m.m00, m.m10, m.m01, m.m20, m.m11, m.m02, m.m30, m.m21, m.m12, m.m03, hu.nativeObj); + + return; + } + + + // + // C++: void cv::Laplacian(Mat src, Mat& dst, int ddepth, int ksize = 1, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT) + // + + //javadoc: Laplacian(src, dst, ddepth, ksize, scale, delta, borderType) + public static void Laplacian(Mat src, Mat dst, int ddepth, int ksize, double scale, double delta, int borderType) + { + + Laplacian_0(src.nativeObj, dst.nativeObj, ddepth, ksize, scale, delta, borderType); + + return; + } + + //javadoc: Laplacian(src, dst, ddepth, ksize, scale, delta) + public static void Laplacian(Mat src, Mat dst, int ddepth, int ksize, double scale, double delta) + { + + Laplacian_1(src.nativeObj, dst.nativeObj, ddepth, ksize, scale, delta); + + return; + } + + //javadoc: Laplacian(src, dst, ddepth, ksize, scale) + public static void Laplacian(Mat src, Mat dst, int ddepth, int ksize, double scale) + { + + Laplacian_2(src.nativeObj, dst.nativeObj, ddepth, ksize, scale); + + return; + } + + //javadoc: Laplacian(src, dst, ddepth, ksize) + public static void Laplacian(Mat src, Mat dst, int ddepth, int ksize) + { + + Laplacian_3(src.nativeObj, dst.nativeObj, ddepth, ksize); + + return; + } + + //javadoc: Laplacian(src, dst, ddepth) + public static void Laplacian(Mat src, Mat dst, int ddepth) + { + + Laplacian_4(src.nativeObj, dst.nativeObj, ddepth); + + return; + } + + + // + // C++: void cv::Scharr(Mat src, Mat& dst, int ddepth, int dx, int dy, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT) + // + + //javadoc: Scharr(src, dst, ddepth, dx, dy, scale, delta, borderType) + public static void Scharr(Mat src, Mat dst, int ddepth, int dx, int dy, double scale, double delta, int borderType) + { + + Scharr_0(src.nativeObj, dst.nativeObj, ddepth, dx, dy, scale, delta, borderType); + + return; + } + + //javadoc: Scharr(src, dst, ddepth, dx, dy, scale, delta) + public static void Scharr(Mat src, Mat dst, int ddepth, int dx, int dy, double scale, double delta) + { + + Scharr_1(src.nativeObj, dst.nativeObj, ddepth, dx, dy, scale, delta); + + return; + } + + //javadoc: Scharr(src, dst, ddepth, dx, dy, scale) + public static void Scharr(Mat src, Mat dst, int ddepth, int dx, int dy, double scale) + { + + Scharr_2(src.nativeObj, dst.nativeObj, ddepth, dx, dy, scale); + + return; + } + + //javadoc: Scharr(src, dst, ddepth, dx, dy) + public static void Scharr(Mat src, Mat dst, int ddepth, int dx, int dy) + { + + Scharr_3(src.nativeObj, dst.nativeObj, ddepth, dx, dy); + + return; + } + + + // + // C++: void cv::Sobel(Mat src, Mat& dst, int ddepth, int dx, int dy, int ksize = 3, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT) + // + + //javadoc: Sobel(src, dst, ddepth, dx, dy, ksize, scale, delta, borderType) + public static void Sobel(Mat src, Mat dst, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType) + { + + Sobel_0(src.nativeObj, dst.nativeObj, ddepth, dx, dy, ksize, scale, delta, borderType); + + return; + } + + //javadoc: Sobel(src, dst, ddepth, dx, dy, ksize, scale, delta) + public static void Sobel(Mat src, Mat dst, int ddepth, int dx, int dy, int ksize, double scale, double delta) + { + + Sobel_1(src.nativeObj, dst.nativeObj, ddepth, dx, dy, ksize, scale, delta); + + return; + } + + //javadoc: Sobel(src, dst, ddepth, dx, dy, ksize, scale) + public static void Sobel(Mat src, Mat dst, int ddepth, int dx, int dy, int ksize, double scale) + { + + Sobel_2(src.nativeObj, dst.nativeObj, ddepth, dx, dy, ksize, scale); + + return; + } + + //javadoc: Sobel(src, dst, ddepth, dx, dy, ksize) + public static void Sobel(Mat src, Mat dst, int ddepth, int dx, int dy, int ksize) + { + + Sobel_3(src.nativeObj, dst.nativeObj, ddepth, dx, dy, ksize); + + return; + } + + //javadoc: Sobel(src, dst, ddepth, dx, dy) + public static void Sobel(Mat src, Mat dst, int ddepth, int dx, int dy) + { + + Sobel_4(src.nativeObj, dst.nativeObj, ddepth, dx, dy); + + return; + } + + + // + // C++: void cv::accumulate(Mat src, Mat& dst, Mat mask = Mat()) + // + + //javadoc: accumulate(src, dst, mask) + public static void accumulate(Mat src, Mat dst, Mat mask) + { + + accumulate_0(src.nativeObj, dst.nativeObj, mask.nativeObj); + + return; + } + + //javadoc: accumulate(src, dst) + public static void accumulate(Mat src, Mat dst) + { + + accumulate_1(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::accumulateProduct(Mat src1, Mat src2, Mat& dst, Mat mask = Mat()) + // + + //javadoc: accumulateProduct(src1, src2, dst, mask) + public static void accumulateProduct(Mat src1, Mat src2, Mat dst, Mat mask) + { + + accumulateProduct_0(src1.nativeObj, src2.nativeObj, dst.nativeObj, mask.nativeObj); + + return; + } + + //javadoc: accumulateProduct(src1, src2, dst) + public static void accumulateProduct(Mat src1, Mat src2, Mat dst) + { + + accumulateProduct_1(src1.nativeObj, src2.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::accumulateSquare(Mat src, Mat& dst, Mat mask = Mat()) + // + + //javadoc: accumulateSquare(src, dst, mask) + public static void accumulateSquare(Mat src, Mat dst, Mat mask) + { + + accumulateSquare_0(src.nativeObj, dst.nativeObj, mask.nativeObj); + + return; + } + + //javadoc: accumulateSquare(src, dst) + public static void accumulateSquare(Mat src, Mat dst) + { + + accumulateSquare_1(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::accumulateWeighted(Mat src, Mat& dst, double alpha, Mat mask = Mat()) + // + + //javadoc: accumulateWeighted(src, dst, alpha, mask) + public static void accumulateWeighted(Mat src, Mat dst, double alpha, Mat mask) + { + + accumulateWeighted_0(src.nativeObj, dst.nativeObj, alpha, mask.nativeObj); + + return; + } + + //javadoc: accumulateWeighted(src, dst, alpha) + public static void accumulateWeighted(Mat src, Mat dst, double alpha) + { + + accumulateWeighted_1(src.nativeObj, dst.nativeObj, alpha); + + return; + } + + + // + // C++: void cv::adaptiveThreshold(Mat src, Mat& dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C) + // + + //javadoc: adaptiveThreshold(src, dst, maxValue, adaptiveMethod, thresholdType, blockSize, C) + public static void adaptiveThreshold(Mat src, Mat dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C) + { + + adaptiveThreshold_0(src.nativeObj, dst.nativeObj, maxValue, adaptiveMethod, thresholdType, blockSize, C); + + return; + } + + + // + // C++: void cv::applyColorMap(Mat src, Mat& dst, Mat userColor) + // + + //javadoc: applyColorMap(src, dst, userColor) + public static void applyColorMap(Mat src, Mat dst, Mat userColor) + { + + applyColorMap_0(src.nativeObj, dst.nativeObj, userColor.nativeObj); + + return; + } + + + // + // C++: void cv::applyColorMap(Mat src, Mat& dst, int colormap) + // + + //javadoc: applyColorMap(src, dst, colormap) + public static void applyColorMap(Mat src, Mat dst, int colormap) + { + + applyColorMap_1(src.nativeObj, dst.nativeObj, colormap); + + return; + } + + + // + // C++: void cv::approxPolyDP(vector_Point2f curve, vector_Point2f& approxCurve, double epsilon, bool closed) + // + + //javadoc: approxPolyDP(curve, approxCurve, epsilon, closed) + public static void approxPolyDP(MatOfPoint2f curve, MatOfPoint2f approxCurve, double epsilon, boolean closed) + { + Mat curve_mat = curve; + Mat approxCurve_mat = approxCurve; + approxPolyDP_0(curve_mat.nativeObj, approxCurve_mat.nativeObj, epsilon, closed); + + return; + } + + + // + // C++: void cv::arrowedLine(Mat& img, Point pt1, Point pt2, Scalar color, int thickness = 1, int line_type = 8, int shift = 0, double tipLength = 0.1) + // + + //javadoc: arrowedLine(img, pt1, pt2, color, thickness, line_type, shift, tipLength) + public static void arrowedLine(Mat img, Point pt1, Point pt2, Scalar color, int thickness, int line_type, int shift, double tipLength) + { + + arrowedLine_0(img.nativeObj, pt1.x, pt1.y, pt2.x, pt2.y, color.val[0], color.val[1], color.val[2], color.val[3], thickness, line_type, shift, tipLength); + + return; + } + + //javadoc: arrowedLine(img, pt1, pt2, color, thickness, line_type, shift) + public static void arrowedLine(Mat img, Point pt1, Point pt2, Scalar color, int thickness, int line_type, int shift) + { + + arrowedLine_1(img.nativeObj, pt1.x, pt1.y, pt2.x, pt2.y, color.val[0], color.val[1], color.val[2], color.val[3], thickness, line_type, shift); + + return; + } + + //javadoc: arrowedLine(img, pt1, pt2, color, thickness, line_type) + public static void arrowedLine(Mat img, Point pt1, Point pt2, Scalar color, int thickness, int line_type) + { + + arrowedLine_2(img.nativeObj, pt1.x, pt1.y, pt2.x, pt2.y, color.val[0], color.val[1], color.val[2], color.val[3], thickness, line_type); + + return; + } + + //javadoc: arrowedLine(img, pt1, pt2, color, thickness) + public static void arrowedLine(Mat img, Point pt1, Point pt2, Scalar color, int thickness) + { + + arrowedLine_3(img.nativeObj, pt1.x, pt1.y, pt2.x, pt2.y, color.val[0], color.val[1], color.val[2], color.val[3], thickness); + + return; + } + + //javadoc: arrowedLine(img, pt1, pt2, color) + public static void arrowedLine(Mat img, Point pt1, Point pt2, Scalar color) + { + + arrowedLine_4(img.nativeObj, pt1.x, pt1.y, pt2.x, pt2.y, color.val[0], color.val[1], color.val[2], color.val[3]); + + return; + } + + + // + // C++: void cv::bilateralFilter(Mat src, Mat& dst, int d, double sigmaColor, double sigmaSpace, int borderType = BORDER_DEFAULT) + // + + //javadoc: bilateralFilter(src, dst, d, sigmaColor, sigmaSpace, borderType) + public static void bilateralFilter(Mat src, Mat dst, int d, double sigmaColor, double sigmaSpace, int borderType) + { + + bilateralFilter_0(src.nativeObj, dst.nativeObj, d, sigmaColor, sigmaSpace, borderType); + + return; + } + + //javadoc: bilateralFilter(src, dst, d, sigmaColor, sigmaSpace) + public static void bilateralFilter(Mat src, Mat dst, int d, double sigmaColor, double sigmaSpace) + { + + bilateralFilter_1(src.nativeObj, dst.nativeObj, d, sigmaColor, sigmaSpace); + + return; + } + + + // + // C++: void cv::blur(Mat src, Mat& dst, Size ksize, Point anchor = Point(-1,-1), int borderType = BORDER_DEFAULT) + // + + //javadoc: blur(src, dst, ksize, anchor, borderType) + public static void blur(Mat src, Mat dst, Size ksize, Point anchor, int borderType) + { + + blur_0(src.nativeObj, dst.nativeObj, ksize.width, ksize.height, anchor.x, anchor.y, borderType); + + return; + } + + //javadoc: blur(src, dst, ksize, anchor) + public static void blur(Mat src, Mat dst, Size ksize, Point anchor) + { + + blur_1(src.nativeObj, dst.nativeObj, ksize.width, ksize.height, anchor.x, anchor.y); + + return; + } + + //javadoc: blur(src, dst, ksize) + public static void blur(Mat src, Mat dst, Size ksize) + { + + blur_2(src.nativeObj, dst.nativeObj, ksize.width, ksize.height); + + return; + } + + + // + // C++: void cv::boxFilter(Mat src, Mat& dst, int ddepth, Size ksize, Point anchor = Point(-1,-1), bool normalize = true, int borderType = BORDER_DEFAULT) + // + + //javadoc: boxFilter(src, dst, ddepth, ksize, anchor, normalize, borderType) + public static void boxFilter(Mat src, Mat dst, int ddepth, Size ksize, Point anchor, boolean normalize, int borderType) + { + + boxFilter_0(src.nativeObj, dst.nativeObj, ddepth, ksize.width, ksize.height, anchor.x, anchor.y, normalize, borderType); + + return; + } + + //javadoc: boxFilter(src, dst, ddepth, ksize, anchor, normalize) + public static void boxFilter(Mat src, Mat dst, int ddepth, Size ksize, Point anchor, boolean normalize) + { + + boxFilter_1(src.nativeObj, dst.nativeObj, ddepth, ksize.width, ksize.height, anchor.x, anchor.y, normalize); + + return; + } + + //javadoc: boxFilter(src, dst, ddepth, ksize, anchor) + public static void boxFilter(Mat src, Mat dst, int ddepth, Size ksize, Point anchor) + { + + boxFilter_2(src.nativeObj, dst.nativeObj, ddepth, ksize.width, ksize.height, anchor.x, anchor.y); + + return; + } + + //javadoc: boxFilter(src, dst, ddepth, ksize) + public static void boxFilter(Mat src, Mat dst, int ddepth, Size ksize) + { + + boxFilter_3(src.nativeObj, dst.nativeObj, ddepth, ksize.width, ksize.height); + + return; + } + + + // + // C++: void cv::boxPoints(RotatedRect box, Mat& points) + // + + //javadoc: boxPoints(box, points) + public static void boxPoints(RotatedRect box, Mat points) + { + + boxPoints_0(box.center.x, box.center.y, box.size.width, box.size.height, box.angle, points.nativeObj); + + return; + } + + + // + // C++: void cv::calcBackProject(vector_Mat images, vector_int channels, Mat hist, Mat& dst, vector_float ranges, double scale) + // + + //javadoc: calcBackProject(images, channels, hist, dst, ranges, scale) + public static void calcBackProject(List images, MatOfInt channels, Mat hist, Mat dst, MatOfFloat ranges, double scale) + { + Mat images_mat = Converters.vector_Mat_to_Mat(images); + Mat channels_mat = channels; + Mat ranges_mat = ranges; + calcBackProject_0(images_mat.nativeObj, channels_mat.nativeObj, hist.nativeObj, dst.nativeObj, ranges_mat.nativeObj, scale); + + return; + } + + + // + // C++: void cv::calcHist(vector_Mat images, vector_int channels, Mat mask, Mat& hist, vector_int histSize, vector_float ranges, bool accumulate = false) + // + + //javadoc: calcHist(images, channels, mask, hist, histSize, ranges, accumulate) + public static void calcHist(List images, MatOfInt channels, Mat mask, Mat hist, MatOfInt histSize, MatOfFloat ranges, boolean accumulate) + { + Mat images_mat = Converters.vector_Mat_to_Mat(images); + Mat channels_mat = channels; + Mat histSize_mat = histSize; + Mat ranges_mat = ranges; + calcHist_0(images_mat.nativeObj, channels_mat.nativeObj, mask.nativeObj, hist.nativeObj, histSize_mat.nativeObj, ranges_mat.nativeObj, accumulate); + + return; + } + + //javadoc: calcHist(images, channels, mask, hist, histSize, ranges) + public static void calcHist(List images, MatOfInt channels, Mat mask, Mat hist, MatOfInt histSize, MatOfFloat ranges) + { + Mat images_mat = Converters.vector_Mat_to_Mat(images); + Mat channels_mat = channels; + Mat histSize_mat = histSize; + Mat ranges_mat = ranges; + calcHist_1(images_mat.nativeObj, channels_mat.nativeObj, mask.nativeObj, hist.nativeObj, histSize_mat.nativeObj, ranges_mat.nativeObj); + + return; + } + + + // + // C++: void cv::circle(Mat& img, Point center, int radius, Scalar color, int thickness = 1, int lineType = LINE_8, int shift = 0) + // + + //javadoc: circle(img, center, radius, color, thickness, lineType, shift) + public static void circle(Mat img, Point center, int radius, Scalar color, int thickness, int lineType, int shift) + { + + circle_0(img.nativeObj, center.x, center.y, radius, color.val[0], color.val[1], color.val[2], color.val[3], thickness, lineType, shift); + + return; + } + + //javadoc: circle(img, center, radius, color, thickness, lineType) + public static void circle(Mat img, Point center, int radius, Scalar color, int thickness, int lineType) + { + + circle_1(img.nativeObj, center.x, center.y, radius, color.val[0], color.val[1], color.val[2], color.val[3], thickness, lineType); + + return; + } + + //javadoc: circle(img, center, radius, color, thickness) + public static void circle(Mat img, Point center, int radius, Scalar color, int thickness) + { + + circle_2(img.nativeObj, center.x, center.y, radius, color.val[0], color.val[1], color.val[2], color.val[3], thickness); + + return; + } + + //javadoc: circle(img, center, radius, color) + public static void circle(Mat img, Point center, int radius, Scalar color) + { + + circle_3(img.nativeObj, center.x, center.y, radius, color.val[0], color.val[1], color.val[2], color.val[3]); + + return; + } + + + // + // C++: void cv::convertMaps(Mat map1, Mat map2, Mat& dstmap1, Mat& dstmap2, int dstmap1type, bool nninterpolation = false) + // + + //javadoc: convertMaps(map1, map2, dstmap1, dstmap2, dstmap1type, nninterpolation) + public static void convertMaps(Mat map1, Mat map2, Mat dstmap1, Mat dstmap2, int dstmap1type, boolean nninterpolation) + { + + convertMaps_0(map1.nativeObj, map2.nativeObj, dstmap1.nativeObj, dstmap2.nativeObj, dstmap1type, nninterpolation); + + return; + } + + //javadoc: convertMaps(map1, map2, dstmap1, dstmap2, dstmap1type) + public static void convertMaps(Mat map1, Mat map2, Mat dstmap1, Mat dstmap2, int dstmap1type) + { + + convertMaps_1(map1.nativeObj, map2.nativeObj, dstmap1.nativeObj, dstmap2.nativeObj, dstmap1type); + + return; + } + + + // + // C++: void cv::convexHull(vector_Point points, vector_int& hull, bool clockwise = false, _hidden_ returnPoints = true) + // + + //javadoc: convexHull(points, hull, clockwise) + public static void convexHull(MatOfPoint points, MatOfInt hull, boolean clockwise) + { + Mat points_mat = points; + Mat hull_mat = hull; + convexHull_0(points_mat.nativeObj, hull_mat.nativeObj, clockwise); + + return; + } + + //javadoc: convexHull(points, hull) + public static void convexHull(MatOfPoint points, MatOfInt hull) + { + Mat points_mat = points; + Mat hull_mat = hull; + convexHull_2(points_mat.nativeObj, hull_mat.nativeObj); + + return; + } + + + // + // C++: void cv::convexityDefects(vector_Point contour, vector_int convexhull, vector_Vec4i& convexityDefects) + // + + //javadoc: convexityDefects(contour, convexhull, convexityDefects) + public static void convexityDefects(MatOfPoint contour, MatOfInt convexhull, MatOfInt4 convexityDefects) + { + Mat contour_mat = contour; + Mat convexhull_mat = convexhull; + Mat convexityDefects_mat = convexityDefects; + convexityDefects_0(contour_mat.nativeObj, convexhull_mat.nativeObj, convexityDefects_mat.nativeObj); + + return; + } + + + // + // C++: void cv::cornerEigenValsAndVecs(Mat src, Mat& dst, int blockSize, int ksize, int borderType = BORDER_DEFAULT) + // + + //javadoc: cornerEigenValsAndVecs(src, dst, blockSize, ksize, borderType) + public static void cornerEigenValsAndVecs(Mat src, Mat dst, int blockSize, int ksize, int borderType) + { + + cornerEigenValsAndVecs_0(src.nativeObj, dst.nativeObj, blockSize, ksize, borderType); + + return; + } + + //javadoc: cornerEigenValsAndVecs(src, dst, blockSize, ksize) + public static void cornerEigenValsAndVecs(Mat src, Mat dst, int blockSize, int ksize) + { + + cornerEigenValsAndVecs_1(src.nativeObj, dst.nativeObj, blockSize, ksize); + + return; + } + + + // + // C++: void cv::cornerHarris(Mat src, Mat& dst, int blockSize, int ksize, double k, int borderType = BORDER_DEFAULT) + // + + //javadoc: cornerHarris(src, dst, blockSize, ksize, k, borderType) + public static void cornerHarris(Mat src, Mat dst, int blockSize, int ksize, double k, int borderType) + { + + cornerHarris_0(src.nativeObj, dst.nativeObj, blockSize, ksize, k, borderType); + + return; + } + + //javadoc: cornerHarris(src, dst, blockSize, ksize, k) + public static void cornerHarris(Mat src, Mat dst, int blockSize, int ksize, double k) + { + + cornerHarris_1(src.nativeObj, dst.nativeObj, blockSize, ksize, k); + + return; + } + + + // + // C++: void cv::cornerMinEigenVal(Mat src, Mat& dst, int blockSize, int ksize = 3, int borderType = BORDER_DEFAULT) + // + + //javadoc: cornerMinEigenVal(src, dst, blockSize, ksize, borderType) + public static void cornerMinEigenVal(Mat src, Mat dst, int blockSize, int ksize, int borderType) + { + + cornerMinEigenVal_0(src.nativeObj, dst.nativeObj, blockSize, ksize, borderType); + + return; + } + + //javadoc: cornerMinEigenVal(src, dst, blockSize, ksize) + public static void cornerMinEigenVal(Mat src, Mat dst, int blockSize, int ksize) + { + + cornerMinEigenVal_1(src.nativeObj, dst.nativeObj, blockSize, ksize); + + return; + } + + //javadoc: cornerMinEigenVal(src, dst, blockSize) + public static void cornerMinEigenVal(Mat src, Mat dst, int blockSize) + { + + cornerMinEigenVal_2(src.nativeObj, dst.nativeObj, blockSize); + + return; + } + + + // + // C++: void cv::cornerSubPix(Mat image, Mat& corners, Size winSize, Size zeroZone, TermCriteria criteria) + // + + //javadoc: cornerSubPix(image, corners, winSize, zeroZone, criteria) + public static void cornerSubPix(Mat image, Mat corners, Size winSize, Size zeroZone, TermCriteria criteria) + { + + cornerSubPix_0(image.nativeObj, corners.nativeObj, winSize.width, winSize.height, zeroZone.width, zeroZone.height, criteria.type, criteria.maxCount, criteria.epsilon); + + return; + } + + + // + // C++: void cv::createHanningWindow(Mat& dst, Size winSize, int type) + // + + //javadoc: createHanningWindow(dst, winSize, type) + public static void createHanningWindow(Mat dst, Size winSize, int type) + { + + createHanningWindow_0(dst.nativeObj, winSize.width, winSize.height, type); + + return; + } + + + // + // C++: void cv::cvtColor(Mat src, Mat& dst, int code, int dstCn = 0) + // + + //javadoc: cvtColor(src, dst, code, dstCn) + public static void cvtColor(Mat src, Mat dst, int code, int dstCn) + { + + cvtColor_0(src.nativeObj, dst.nativeObj, code, dstCn); + + return; + } + + //javadoc: cvtColor(src, dst, code) + public static void cvtColor(Mat src, Mat dst, int code) + { + + cvtColor_1(src.nativeObj, dst.nativeObj, code); + + return; + } + + + // + // C++: void cv::cvtColorTwoPlane(Mat src1, Mat src2, Mat& dst, int code) + // + + //javadoc: cvtColorTwoPlane(src1, src2, dst, code) + public static void cvtColorTwoPlane(Mat src1, Mat src2, Mat dst, int code) + { + + cvtColorTwoPlane_0(src1.nativeObj, src2.nativeObj, dst.nativeObj, code); + + return; + } + + + // + // C++: void cv::demosaicing(Mat src, Mat& dst, int code, int dstCn = 0) + // + + //javadoc: demosaicing(src, dst, code, dstCn) + public static void demosaicing(Mat src, Mat dst, int code, int dstCn) + { + + demosaicing_0(src.nativeObj, dst.nativeObj, code, dstCn); + + return; + } + + //javadoc: demosaicing(src, dst, code) + public static void demosaicing(Mat src, Mat dst, int code) + { + + demosaicing_1(src.nativeObj, dst.nativeObj, code); + + return; + } + + + // + // C++: void cv::dilate(Mat src, Mat& dst, Mat kernel, Point anchor = Point(-1,-1), int iterations = 1, int borderType = BORDER_CONSTANT, Scalar borderValue = morphologyDefaultBorderValue()) + // + + //javadoc: dilate(src, dst, kernel, anchor, iterations, borderType, borderValue) + public static void dilate(Mat src, Mat dst, Mat kernel, Point anchor, int iterations, int borderType, Scalar borderValue) + { + + dilate_0(src.nativeObj, dst.nativeObj, kernel.nativeObj, anchor.x, anchor.y, iterations, borderType, borderValue.val[0], borderValue.val[1], borderValue.val[2], borderValue.val[3]); + + return; + } + + //javadoc: dilate(src, dst, kernel, anchor, iterations, borderType) + public static void dilate(Mat src, Mat dst, Mat kernel, Point anchor, int iterations, int borderType) + { + + dilate_1(src.nativeObj, dst.nativeObj, kernel.nativeObj, anchor.x, anchor.y, iterations, borderType); + + return; + } + + //javadoc: dilate(src, dst, kernel, anchor, iterations) + public static void dilate(Mat src, Mat dst, Mat kernel, Point anchor, int iterations) + { + + dilate_2(src.nativeObj, dst.nativeObj, kernel.nativeObj, anchor.x, anchor.y, iterations); + + return; + } + + //javadoc: dilate(src, dst, kernel, anchor) + public static void dilate(Mat src, Mat dst, Mat kernel, Point anchor) + { + + dilate_3(src.nativeObj, dst.nativeObj, kernel.nativeObj, anchor.x, anchor.y); + + return; + } + + //javadoc: dilate(src, dst, kernel) + public static void dilate(Mat src, Mat dst, Mat kernel) + { + + dilate_4(src.nativeObj, dst.nativeObj, kernel.nativeObj); + + return; + } + + + // + // C++: void cv::distanceTransform(Mat src, Mat& dst, Mat& labels, int distanceType, int maskSize, int labelType = DIST_LABEL_CCOMP) + // + + //javadoc: distanceTransformWithLabels(src, dst, labels, distanceType, maskSize, labelType) + public static void distanceTransformWithLabels(Mat src, Mat dst, Mat labels, int distanceType, int maskSize, int labelType) + { + + distanceTransformWithLabels_0(src.nativeObj, dst.nativeObj, labels.nativeObj, distanceType, maskSize, labelType); + + return; + } + + //javadoc: distanceTransformWithLabels(src, dst, labels, distanceType, maskSize) + public static void distanceTransformWithLabels(Mat src, Mat dst, Mat labels, int distanceType, int maskSize) + { + + distanceTransformWithLabels_1(src.nativeObj, dst.nativeObj, labels.nativeObj, distanceType, maskSize); + + return; + } + + + // + // C++: void cv::distanceTransform(Mat src, Mat& dst, int distanceType, int maskSize, int dstType = CV_32F) + // + + //javadoc: distanceTransform(src, dst, distanceType, maskSize, dstType) + public static void distanceTransform(Mat src, Mat dst, int distanceType, int maskSize, int dstType) + { + + distanceTransform_0(src.nativeObj, dst.nativeObj, distanceType, maskSize, dstType); + + return; + } + + //javadoc: distanceTransform(src, dst, distanceType, maskSize) + public static void distanceTransform(Mat src, Mat dst, int distanceType, int maskSize) + { + + distanceTransform_1(src.nativeObj, dst.nativeObj, distanceType, maskSize); + + return; + } + + + // + // C++: void cv::drawContours(Mat& image, vector_vector_Point contours, int contourIdx, Scalar color, int thickness = 1, int lineType = LINE_8, Mat hierarchy = Mat(), int maxLevel = INT_MAX, Point offset = Point()) + // + + //javadoc: drawContours(image, contours, contourIdx, color, thickness, lineType, hierarchy, maxLevel, offset) + public static void drawContours(Mat image, List contours, int contourIdx, Scalar color, int thickness, int lineType, Mat hierarchy, int maxLevel, Point offset) + { + List contours_tmplm = new ArrayList((contours != null) ? contours.size() : 0); + Mat contours_mat = Converters.vector_vector_Point_to_Mat(contours, contours_tmplm); + drawContours_0(image.nativeObj, contours_mat.nativeObj, contourIdx, color.val[0], color.val[1], color.val[2], color.val[3], thickness, lineType, hierarchy.nativeObj, maxLevel, offset.x, offset.y); + + return; + } + + //javadoc: drawContours(image, contours, contourIdx, color, thickness, lineType, hierarchy, maxLevel) + public static void drawContours(Mat image, List contours, int contourIdx, Scalar color, int thickness, int lineType, Mat hierarchy, int maxLevel) + { + List contours_tmplm = new ArrayList((contours != null) ? contours.size() : 0); + Mat contours_mat = Converters.vector_vector_Point_to_Mat(contours, contours_tmplm); + drawContours_1(image.nativeObj, contours_mat.nativeObj, contourIdx, color.val[0], color.val[1], color.val[2], color.val[3], thickness, lineType, hierarchy.nativeObj, maxLevel); + + return; + } + + //javadoc: drawContours(image, contours, contourIdx, color, thickness, lineType, hierarchy) + public static void drawContours(Mat image, List contours, int contourIdx, Scalar color, int thickness, int lineType, Mat hierarchy) + { + List contours_tmplm = new ArrayList((contours != null) ? contours.size() : 0); + Mat contours_mat = Converters.vector_vector_Point_to_Mat(contours, contours_tmplm); + drawContours_2(image.nativeObj, contours_mat.nativeObj, contourIdx, color.val[0], color.val[1], color.val[2], color.val[3], thickness, lineType, hierarchy.nativeObj); + + return; + } + + //javadoc: drawContours(image, contours, contourIdx, color, thickness, lineType) + public static void drawContours(Mat image, List contours, int contourIdx, Scalar color, int thickness, int lineType) + { + List contours_tmplm = new ArrayList((contours != null) ? contours.size() : 0); + Mat contours_mat = Converters.vector_vector_Point_to_Mat(contours, contours_tmplm); + drawContours_3(image.nativeObj, contours_mat.nativeObj, contourIdx, color.val[0], color.val[1], color.val[2], color.val[3], thickness, lineType); + + return; + } + + //javadoc: drawContours(image, contours, contourIdx, color, thickness) + public static void drawContours(Mat image, List contours, int contourIdx, Scalar color, int thickness) + { + List contours_tmplm = new ArrayList((contours != null) ? contours.size() : 0); + Mat contours_mat = Converters.vector_vector_Point_to_Mat(contours, contours_tmplm); + drawContours_4(image.nativeObj, contours_mat.nativeObj, contourIdx, color.val[0], color.val[1], color.val[2], color.val[3], thickness); + + return; + } + + //javadoc: drawContours(image, contours, contourIdx, color) + public static void drawContours(Mat image, List contours, int contourIdx, Scalar color) + { + List contours_tmplm = new ArrayList((contours != null) ? contours.size() : 0); + Mat contours_mat = Converters.vector_vector_Point_to_Mat(contours, contours_tmplm); + drawContours_5(image.nativeObj, contours_mat.nativeObj, contourIdx, color.val[0], color.val[1], color.val[2], color.val[3]); + + return; + } + + + // + // C++: void cv::drawMarker(Mat& img, Point position, Scalar color, int markerType = MARKER_CROSS, int markerSize = 20, int thickness = 1, int line_type = 8) + // + + //javadoc: drawMarker(img, position, color, markerType, markerSize, thickness, line_type) + public static void drawMarker(Mat img, Point position, Scalar color, int markerType, int markerSize, int thickness, int line_type) + { + + drawMarker_0(img.nativeObj, position.x, position.y, color.val[0], color.val[1], color.val[2], color.val[3], markerType, markerSize, thickness, line_type); + + return; + } + + //javadoc: drawMarker(img, position, color, markerType, markerSize, thickness) + public static void drawMarker(Mat img, Point position, Scalar color, int markerType, int markerSize, int thickness) + { + + drawMarker_1(img.nativeObj, position.x, position.y, color.val[0], color.val[1], color.val[2], color.val[3], markerType, markerSize, thickness); + + return; + } + + //javadoc: drawMarker(img, position, color, markerType, markerSize) + public static void drawMarker(Mat img, Point position, Scalar color, int markerType, int markerSize) + { + + drawMarker_2(img.nativeObj, position.x, position.y, color.val[0], color.val[1], color.val[2], color.val[3], markerType, markerSize); + + return; + } + + //javadoc: drawMarker(img, position, color, markerType) + public static void drawMarker(Mat img, Point position, Scalar color, int markerType) + { + + drawMarker_3(img.nativeObj, position.x, position.y, color.val[0], color.val[1], color.val[2], color.val[3], markerType); + + return; + } + + //javadoc: drawMarker(img, position, color) + public static void drawMarker(Mat img, Point position, Scalar color) + { + + drawMarker_4(img.nativeObj, position.x, position.y, color.val[0], color.val[1], color.val[2], color.val[3]); + + return; + } + + + // + // C++: void cv::ellipse(Mat& img, Point center, Size axes, double angle, double startAngle, double endAngle, Scalar color, int thickness = 1, int lineType = LINE_8, int shift = 0) + // + + //javadoc: ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness, lineType, shift) + public static void ellipse(Mat img, Point center, Size axes, double angle, double startAngle, double endAngle, Scalar color, int thickness, int lineType, int shift) + { + + ellipse_0(img.nativeObj, center.x, center.y, axes.width, axes.height, angle, startAngle, endAngle, color.val[0], color.val[1], color.val[2], color.val[3], thickness, lineType, shift); + + return; + } + + //javadoc: ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness, lineType) + public static void ellipse(Mat img, Point center, Size axes, double angle, double startAngle, double endAngle, Scalar color, int thickness, int lineType) + { + + ellipse_1(img.nativeObj, center.x, center.y, axes.width, axes.height, angle, startAngle, endAngle, color.val[0], color.val[1], color.val[2], color.val[3], thickness, lineType); + + return; + } + + //javadoc: ellipse(img, center, axes, angle, startAngle, endAngle, color, thickness) + public static void ellipse(Mat img, Point center, Size axes, double angle, double startAngle, double endAngle, Scalar color, int thickness) + { + + ellipse_2(img.nativeObj, center.x, center.y, axes.width, axes.height, angle, startAngle, endAngle, color.val[0], color.val[1], color.val[2], color.val[3], thickness); + + return; + } + + //javadoc: ellipse(img, center, axes, angle, startAngle, endAngle, color) + public static void ellipse(Mat img, Point center, Size axes, double angle, double startAngle, double endAngle, Scalar color) + { + + ellipse_3(img.nativeObj, center.x, center.y, axes.width, axes.height, angle, startAngle, endAngle, color.val[0], color.val[1], color.val[2], color.val[3]); + + return; + } + + + // + // C++: void cv::ellipse(Mat& img, RotatedRect box, Scalar color, int thickness = 1, int lineType = LINE_8) + // + + //javadoc: ellipse(img, box, color, thickness, lineType) + public static void ellipse(Mat img, RotatedRect box, Scalar color, int thickness, int lineType) + { + + ellipse_4(img.nativeObj, box.center.x, box.center.y, box.size.width, box.size.height, box.angle, color.val[0], color.val[1], color.val[2], color.val[3], thickness, lineType); + + return; + } + + //javadoc: ellipse(img, box, color, thickness) + public static void ellipse(Mat img, RotatedRect box, Scalar color, int thickness) + { + + ellipse_5(img.nativeObj, box.center.x, box.center.y, box.size.width, box.size.height, box.angle, color.val[0], color.val[1], color.val[2], color.val[3], thickness); + + return; + } + + //javadoc: ellipse(img, box, color) + public static void ellipse(Mat img, RotatedRect box, Scalar color) + { + + ellipse_6(img.nativeObj, box.center.x, box.center.y, box.size.width, box.size.height, box.angle, color.val[0], color.val[1], color.val[2], color.val[3]); + + return; + } + + + // + // C++: void cv::ellipse2Poly(Point center, Size axes, int angle, int arcStart, int arcEnd, int delta, vector_Point& pts) + // + + //javadoc: ellipse2Poly(center, axes, angle, arcStart, arcEnd, delta, pts) + public static void ellipse2Poly(Point center, Size axes, int angle, int arcStart, int arcEnd, int delta, MatOfPoint pts) + { + Mat pts_mat = pts; + ellipse2Poly_0(center.x, center.y, axes.width, axes.height, angle, arcStart, arcEnd, delta, pts_mat.nativeObj); + + return; + } + + + // + // C++: void cv::equalizeHist(Mat src, Mat& dst) + // + + //javadoc: equalizeHist(src, dst) + public static void equalizeHist(Mat src, Mat dst) + { + + equalizeHist_0(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::erode(Mat src, Mat& dst, Mat kernel, Point anchor = Point(-1,-1), int iterations = 1, int borderType = BORDER_CONSTANT, Scalar borderValue = morphologyDefaultBorderValue()) + // + + //javadoc: erode(src, dst, kernel, anchor, iterations, borderType, borderValue) + public static void erode(Mat src, Mat dst, Mat kernel, Point anchor, int iterations, int borderType, Scalar borderValue) + { + + erode_0(src.nativeObj, dst.nativeObj, kernel.nativeObj, anchor.x, anchor.y, iterations, borderType, borderValue.val[0], borderValue.val[1], borderValue.val[2], borderValue.val[3]); + + return; + } + + //javadoc: erode(src, dst, kernel, anchor, iterations, borderType) + public static void erode(Mat src, Mat dst, Mat kernel, Point anchor, int iterations, int borderType) + { + + erode_1(src.nativeObj, dst.nativeObj, kernel.nativeObj, anchor.x, anchor.y, iterations, borderType); + + return; + } + + //javadoc: erode(src, dst, kernel, anchor, iterations) + public static void erode(Mat src, Mat dst, Mat kernel, Point anchor, int iterations) + { + + erode_2(src.nativeObj, dst.nativeObj, kernel.nativeObj, anchor.x, anchor.y, iterations); + + return; + } + + //javadoc: erode(src, dst, kernel, anchor) + public static void erode(Mat src, Mat dst, Mat kernel, Point anchor) + { + + erode_3(src.nativeObj, dst.nativeObj, kernel.nativeObj, anchor.x, anchor.y); + + return; + } + + //javadoc: erode(src, dst, kernel) + public static void erode(Mat src, Mat dst, Mat kernel) + { + + erode_4(src.nativeObj, dst.nativeObj, kernel.nativeObj); + + return; + } + + + // + // C++: void cv::fillConvexPoly(Mat& img, vector_Point points, Scalar color, int lineType = LINE_8, int shift = 0) + // + + //javadoc: fillConvexPoly(img, points, color, lineType, shift) + public static void fillConvexPoly(Mat img, MatOfPoint points, Scalar color, int lineType, int shift) + { + Mat points_mat = points; + fillConvexPoly_0(img.nativeObj, points_mat.nativeObj, color.val[0], color.val[1], color.val[2], color.val[3], lineType, shift); + + return; + } + + //javadoc: fillConvexPoly(img, points, color, lineType) + public static void fillConvexPoly(Mat img, MatOfPoint points, Scalar color, int lineType) + { + Mat points_mat = points; + fillConvexPoly_1(img.nativeObj, points_mat.nativeObj, color.val[0], color.val[1], color.val[2], color.val[3], lineType); + + return; + } + + //javadoc: fillConvexPoly(img, points, color) + public static void fillConvexPoly(Mat img, MatOfPoint points, Scalar color) + { + Mat points_mat = points; + fillConvexPoly_2(img.nativeObj, points_mat.nativeObj, color.val[0], color.val[1], color.val[2], color.val[3]); + + return; + } + + + // + // C++: void cv::fillPoly(Mat& img, vector_vector_Point pts, Scalar color, int lineType = LINE_8, int shift = 0, Point offset = Point()) + // + + //javadoc: fillPoly(img, pts, color, lineType, shift, offset) + public static void fillPoly(Mat img, List pts, Scalar color, int lineType, int shift, Point offset) + { + List pts_tmplm = new ArrayList((pts != null) ? pts.size() : 0); + Mat pts_mat = Converters.vector_vector_Point_to_Mat(pts, pts_tmplm); + fillPoly_0(img.nativeObj, pts_mat.nativeObj, color.val[0], color.val[1], color.val[2], color.val[3], lineType, shift, offset.x, offset.y); + + return; + } + + //javadoc: fillPoly(img, pts, color, lineType, shift) + public static void fillPoly(Mat img, List pts, Scalar color, int lineType, int shift) + { + List pts_tmplm = new ArrayList((pts != null) ? pts.size() : 0); + Mat pts_mat = Converters.vector_vector_Point_to_Mat(pts, pts_tmplm); + fillPoly_1(img.nativeObj, pts_mat.nativeObj, color.val[0], color.val[1], color.val[2], color.val[3], lineType, shift); + + return; + } + + //javadoc: fillPoly(img, pts, color, lineType) + public static void fillPoly(Mat img, List pts, Scalar color, int lineType) + { + List pts_tmplm = new ArrayList((pts != null) ? pts.size() : 0); + Mat pts_mat = Converters.vector_vector_Point_to_Mat(pts, pts_tmplm); + fillPoly_2(img.nativeObj, pts_mat.nativeObj, color.val[0], color.val[1], color.val[2], color.val[3], lineType); + + return; + } + + //javadoc: fillPoly(img, pts, color) + public static void fillPoly(Mat img, List pts, Scalar color) + { + List pts_tmplm = new ArrayList((pts != null) ? pts.size() : 0); + Mat pts_mat = Converters.vector_vector_Point_to_Mat(pts, pts_tmplm); + fillPoly_3(img.nativeObj, pts_mat.nativeObj, color.val[0], color.val[1], color.val[2], color.val[3]); + + return; + } + + + // + // C++: void cv::filter2D(Mat src, Mat& dst, int ddepth, Mat kernel, Point anchor = Point(-1,-1), double delta = 0, int borderType = BORDER_DEFAULT) + // + + //javadoc: filter2D(src, dst, ddepth, kernel, anchor, delta, borderType) + public static void filter2D(Mat src, Mat dst, int ddepth, Mat kernel, Point anchor, double delta, int borderType) + { + + filter2D_0(src.nativeObj, dst.nativeObj, ddepth, kernel.nativeObj, anchor.x, anchor.y, delta, borderType); + + return; + } + + //javadoc: filter2D(src, dst, ddepth, kernel, anchor, delta) + public static void filter2D(Mat src, Mat dst, int ddepth, Mat kernel, Point anchor, double delta) + { + + filter2D_1(src.nativeObj, dst.nativeObj, ddepth, kernel.nativeObj, anchor.x, anchor.y, delta); + + return; + } + + //javadoc: filter2D(src, dst, ddepth, kernel, anchor) + public static void filter2D(Mat src, Mat dst, int ddepth, Mat kernel, Point anchor) + { + + filter2D_2(src.nativeObj, dst.nativeObj, ddepth, kernel.nativeObj, anchor.x, anchor.y); + + return; + } + + //javadoc: filter2D(src, dst, ddepth, kernel) + public static void filter2D(Mat src, Mat dst, int ddepth, Mat kernel) + { + + filter2D_3(src.nativeObj, dst.nativeObj, ddepth, kernel.nativeObj); + + return; + } + + + // + // C++: void cv::findContours(Mat image, vector_vector_Point& contours, Mat& hierarchy, int mode, int method, Point offset = Point()) + // + + //javadoc: findContours(image, contours, hierarchy, mode, method, offset) + public static void findContours(Mat image, List contours, Mat hierarchy, int mode, int method, Point offset) + { + Mat contours_mat = new Mat(); + findContours_0(image.nativeObj, contours_mat.nativeObj, hierarchy.nativeObj, mode, method, offset.x, offset.y); + Converters.Mat_to_vector_vector_Point(contours_mat, contours); + contours_mat.release(); + return; + } + + //javadoc: findContours(image, contours, hierarchy, mode, method) + public static void findContours(Mat image, List contours, Mat hierarchy, int mode, int method) + { + Mat contours_mat = new Mat(); + findContours_1(image.nativeObj, contours_mat.nativeObj, hierarchy.nativeObj, mode, method); + Converters.Mat_to_vector_vector_Point(contours_mat, contours); + contours_mat.release(); + return; + } + + + // + // C++: void cv::fitLine(Mat points, Mat& line, int distType, double param, double reps, double aeps) + // + + //javadoc: fitLine(points, line, distType, param, reps, aeps) + public static void fitLine(Mat points, Mat line, int distType, double param, double reps, double aeps) + { + + fitLine_0(points.nativeObj, line.nativeObj, distType, param, reps, aeps); + + return; + } + + + // + // C++: void cv::getDerivKernels(Mat& kx, Mat& ky, int dx, int dy, int ksize, bool normalize = false, int ktype = CV_32F) + // + + //javadoc: getDerivKernels(kx, ky, dx, dy, ksize, normalize, ktype) + public static void getDerivKernels(Mat kx, Mat ky, int dx, int dy, int ksize, boolean normalize, int ktype) + { + + getDerivKernels_0(kx.nativeObj, ky.nativeObj, dx, dy, ksize, normalize, ktype); + + return; + } + + //javadoc: getDerivKernels(kx, ky, dx, dy, ksize, normalize) + public static void getDerivKernels(Mat kx, Mat ky, int dx, int dy, int ksize, boolean normalize) + { + + getDerivKernels_1(kx.nativeObj, ky.nativeObj, dx, dy, ksize, normalize); + + return; + } + + //javadoc: getDerivKernels(kx, ky, dx, dy, ksize) + public static void getDerivKernels(Mat kx, Mat ky, int dx, int dy, int ksize) + { + + getDerivKernels_2(kx.nativeObj, ky.nativeObj, dx, dy, ksize); + + return; + } + + + // + // C++: void cv::getRectSubPix(Mat image, Size patchSize, Point2f center, Mat& patch, int patchType = -1) + // + + //javadoc: getRectSubPix(image, patchSize, center, patch, patchType) + public static void getRectSubPix(Mat image, Size patchSize, Point center, Mat patch, int patchType) + { + + getRectSubPix_0(image.nativeObj, patchSize.width, patchSize.height, center.x, center.y, patch.nativeObj, patchType); + + return; + } + + //javadoc: getRectSubPix(image, patchSize, center, patch) + public static void getRectSubPix(Mat image, Size patchSize, Point center, Mat patch) + { + + getRectSubPix_1(image.nativeObj, patchSize.width, patchSize.height, center.x, center.y, patch.nativeObj); + + return; + } + + + // + // C++: void cv::goodFeaturesToTrack(Mat image, vector_Point& corners, int maxCorners, double qualityLevel, double minDistance, Mat mask, int blockSize, int gradientSize, bool useHarrisDetector = false, double k = 0.04) + // + + //javadoc: goodFeaturesToTrack(image, corners, maxCorners, qualityLevel, minDistance, mask, blockSize, gradientSize, useHarrisDetector, k) + public static void goodFeaturesToTrack(Mat image, MatOfPoint corners, int maxCorners, double qualityLevel, double minDistance, Mat mask, int blockSize, int gradientSize, boolean useHarrisDetector, double k) + { + Mat corners_mat = corners; + goodFeaturesToTrack_0(image.nativeObj, corners_mat.nativeObj, maxCorners, qualityLevel, minDistance, mask.nativeObj, blockSize, gradientSize, useHarrisDetector, k); + + return; + } + + //javadoc: goodFeaturesToTrack(image, corners, maxCorners, qualityLevel, minDistance, mask, blockSize, gradientSize, useHarrisDetector) + public static void goodFeaturesToTrack(Mat image, MatOfPoint corners, int maxCorners, double qualityLevel, double minDistance, Mat mask, int blockSize, int gradientSize, boolean useHarrisDetector) + { + Mat corners_mat = corners; + goodFeaturesToTrack_1(image.nativeObj, corners_mat.nativeObj, maxCorners, qualityLevel, minDistance, mask.nativeObj, blockSize, gradientSize, useHarrisDetector); + + return; + } + + //javadoc: goodFeaturesToTrack(image, corners, maxCorners, qualityLevel, minDistance, mask, blockSize, gradientSize) + public static void goodFeaturesToTrack(Mat image, MatOfPoint corners, int maxCorners, double qualityLevel, double minDistance, Mat mask, int blockSize, int gradientSize) + { + Mat corners_mat = corners; + goodFeaturesToTrack_2(image.nativeObj, corners_mat.nativeObj, maxCorners, qualityLevel, minDistance, mask.nativeObj, blockSize, gradientSize); + + return; + } + + + // + // C++: void cv::goodFeaturesToTrack(Mat image, vector_Point& corners, int maxCorners, double qualityLevel, double minDistance, Mat mask = Mat(), int blockSize = 3, bool useHarrisDetector = false, double k = 0.04) + // + + //javadoc: goodFeaturesToTrack(image, corners, maxCorners, qualityLevel, minDistance, mask, blockSize, useHarrisDetector, k) + public static void goodFeaturesToTrack(Mat image, MatOfPoint corners, int maxCorners, double qualityLevel, double minDistance, Mat mask, int blockSize, boolean useHarrisDetector, double k) + { + Mat corners_mat = corners; + goodFeaturesToTrack_3(image.nativeObj, corners_mat.nativeObj, maxCorners, qualityLevel, minDistance, mask.nativeObj, blockSize, useHarrisDetector, k); + + return; + } + + //javadoc: goodFeaturesToTrack(image, corners, maxCorners, qualityLevel, minDistance, mask, blockSize, useHarrisDetector) + public static void goodFeaturesToTrack(Mat image, MatOfPoint corners, int maxCorners, double qualityLevel, double minDistance, Mat mask, int blockSize, boolean useHarrisDetector) + { + Mat corners_mat = corners; + goodFeaturesToTrack_4(image.nativeObj, corners_mat.nativeObj, maxCorners, qualityLevel, minDistance, mask.nativeObj, blockSize, useHarrisDetector); + + return; + } + + //javadoc: goodFeaturesToTrack(image, corners, maxCorners, qualityLevel, minDistance, mask, blockSize) + public static void goodFeaturesToTrack(Mat image, MatOfPoint corners, int maxCorners, double qualityLevel, double minDistance, Mat mask, int blockSize) + { + Mat corners_mat = corners; + goodFeaturesToTrack_5(image.nativeObj, corners_mat.nativeObj, maxCorners, qualityLevel, minDistance, mask.nativeObj, blockSize); + + return; + } + + //javadoc: goodFeaturesToTrack(image, corners, maxCorners, qualityLevel, minDistance, mask) + public static void goodFeaturesToTrack(Mat image, MatOfPoint corners, int maxCorners, double qualityLevel, double minDistance, Mat mask) + { + Mat corners_mat = corners; + goodFeaturesToTrack_6(image.nativeObj, corners_mat.nativeObj, maxCorners, qualityLevel, minDistance, mask.nativeObj); + + return; + } + + //javadoc: goodFeaturesToTrack(image, corners, maxCorners, qualityLevel, minDistance) + public static void goodFeaturesToTrack(Mat image, MatOfPoint corners, int maxCorners, double qualityLevel, double minDistance) + { + Mat corners_mat = corners; + goodFeaturesToTrack_7(image.nativeObj, corners_mat.nativeObj, maxCorners, qualityLevel, minDistance); + + return; + } + + + // + // C++: void cv::grabCut(Mat img, Mat& mask, Rect rect, Mat& bgdModel, Mat& fgdModel, int iterCount, int mode = GC_EVAL) + // + + //javadoc: grabCut(img, mask, rect, bgdModel, fgdModel, iterCount, mode) + public static void grabCut(Mat img, Mat mask, Rect rect, Mat bgdModel, Mat fgdModel, int iterCount, int mode) + { + + grabCut_0(img.nativeObj, mask.nativeObj, rect.x, rect.y, rect.width, rect.height, bgdModel.nativeObj, fgdModel.nativeObj, iterCount, mode); + + return; + } + + //javadoc: grabCut(img, mask, rect, bgdModel, fgdModel, iterCount) + public static void grabCut(Mat img, Mat mask, Rect rect, Mat bgdModel, Mat fgdModel, int iterCount) + { + + grabCut_1(img.nativeObj, mask.nativeObj, rect.x, rect.y, rect.width, rect.height, bgdModel.nativeObj, fgdModel.nativeObj, iterCount); + + return; + } + + + // + // C++: void cv::integral(Mat src, Mat& sum, Mat& sqsum, Mat& tilted, int sdepth = -1, int sqdepth = -1) + // + + //javadoc: integral3(src, sum, sqsum, tilted, sdepth, sqdepth) + public static void integral3(Mat src, Mat sum, Mat sqsum, Mat tilted, int sdepth, int sqdepth) + { + + integral3_0(src.nativeObj, sum.nativeObj, sqsum.nativeObj, tilted.nativeObj, sdepth, sqdepth); + + return; + } + + //javadoc: integral3(src, sum, sqsum, tilted, sdepth) + public static void integral3(Mat src, Mat sum, Mat sqsum, Mat tilted, int sdepth) + { + + integral3_1(src.nativeObj, sum.nativeObj, sqsum.nativeObj, tilted.nativeObj, sdepth); + + return; + } + + //javadoc: integral3(src, sum, sqsum, tilted) + public static void integral3(Mat src, Mat sum, Mat sqsum, Mat tilted) + { + + integral3_2(src.nativeObj, sum.nativeObj, sqsum.nativeObj, tilted.nativeObj); + + return; + } + + + // + // C++: void cv::integral(Mat src, Mat& sum, Mat& sqsum, int sdepth = -1, int sqdepth = -1) + // + + //javadoc: integral2(src, sum, sqsum, sdepth, sqdepth) + public static void integral2(Mat src, Mat sum, Mat sqsum, int sdepth, int sqdepth) + { + + integral2_0(src.nativeObj, sum.nativeObj, sqsum.nativeObj, sdepth, sqdepth); + + return; + } + + //javadoc: integral2(src, sum, sqsum, sdepth) + public static void integral2(Mat src, Mat sum, Mat sqsum, int sdepth) + { + + integral2_1(src.nativeObj, sum.nativeObj, sqsum.nativeObj, sdepth); + + return; + } + + //javadoc: integral2(src, sum, sqsum) + public static void integral2(Mat src, Mat sum, Mat sqsum) + { + + integral2_2(src.nativeObj, sum.nativeObj, sqsum.nativeObj); + + return; + } + + + // + // C++: void cv::integral(Mat src, Mat& sum, int sdepth = -1) + // + + //javadoc: integral(src, sum, sdepth) + public static void integral(Mat src, Mat sum, int sdepth) + { + + integral_0(src.nativeObj, sum.nativeObj, sdepth); + + return; + } + + //javadoc: integral(src, sum) + public static void integral(Mat src, Mat sum) + { + + integral_1(src.nativeObj, sum.nativeObj); + + return; + } + + + // + // C++: void cv::invertAffineTransform(Mat M, Mat& iM) + // + + //javadoc: invertAffineTransform(M, iM) + public static void invertAffineTransform(Mat M, Mat iM) + { + + invertAffineTransform_0(M.nativeObj, iM.nativeObj); + + return; + } + + + // + // C++: void cv::line(Mat& img, Point pt1, Point pt2, Scalar color, int thickness = 1, int lineType = LINE_8, int shift = 0) + // + + //javadoc: line(img, pt1, pt2, color, thickness, lineType, shift) + public static void line(Mat img, Point pt1, Point pt2, Scalar color, int thickness, int lineType, int shift) + { + + line_0(img.nativeObj, pt1.x, pt1.y, pt2.x, pt2.y, color.val[0], color.val[1], color.val[2], color.val[3], thickness, lineType, shift); + + return; + } + + //javadoc: line(img, pt1, pt2, color, thickness, lineType) + public static void line(Mat img, Point pt1, Point pt2, Scalar color, int thickness, int lineType) + { + + line_1(img.nativeObj, pt1.x, pt1.y, pt2.x, pt2.y, color.val[0], color.val[1], color.val[2], color.val[3], thickness, lineType); + + return; + } + + //javadoc: line(img, pt1, pt2, color, thickness) + public static void line(Mat img, Point pt1, Point pt2, Scalar color, int thickness) + { + + line_2(img.nativeObj, pt1.x, pt1.y, pt2.x, pt2.y, color.val[0], color.val[1], color.val[2], color.val[3], thickness); + + return; + } + + //javadoc: line(img, pt1, pt2, color) + public static void line(Mat img, Point pt1, Point pt2, Scalar color) + { + + line_3(img.nativeObj, pt1.x, pt1.y, pt2.x, pt2.y, color.val[0], color.val[1], color.val[2], color.val[3]); + + return; + } + + + // + // C++: void cv::linearPolar(Mat src, Mat& dst, Point2f center, double maxRadius, int flags) + // + + //javadoc: linearPolar(src, dst, center, maxRadius, flags) + @Deprecated + public static void linearPolar(Mat src, Mat dst, Point center, double maxRadius, int flags) + { + + linearPolar_0(src.nativeObj, dst.nativeObj, center.x, center.y, maxRadius, flags); + + return; + } + + + // + // C++: void cv::logPolar(Mat src, Mat& dst, Point2f center, double M, int flags) + // + + //javadoc: logPolar(src, dst, center, M, flags) + @Deprecated + public static void logPolar(Mat src, Mat dst, Point center, double M, int flags) + { + + logPolar_0(src.nativeObj, dst.nativeObj, center.x, center.y, M, flags); + + return; + } + + + // + // C++: void cv::matchTemplate(Mat image, Mat templ, Mat& result, int method, Mat mask = Mat()) + // + + //javadoc: matchTemplate(image, templ, result, method, mask) + public static void matchTemplate(Mat image, Mat templ, Mat result, int method, Mat mask) + { + + matchTemplate_0(image.nativeObj, templ.nativeObj, result.nativeObj, method, mask.nativeObj); + + return; + } + + //javadoc: matchTemplate(image, templ, result, method) + public static void matchTemplate(Mat image, Mat templ, Mat result, int method) + { + + matchTemplate_1(image.nativeObj, templ.nativeObj, result.nativeObj, method); + + return; + } + + + // + // C++: void cv::medianBlur(Mat src, Mat& dst, int ksize) + // + + //javadoc: medianBlur(src, dst, ksize) + public static void medianBlur(Mat src, Mat dst, int ksize) + { + + medianBlur_0(src.nativeObj, dst.nativeObj, ksize); + + return; + } + + + // + // C++: void cv::minEnclosingCircle(vector_Point2f points, Point2f& center, float& radius) + // + + //javadoc: minEnclosingCircle(points, center, radius) + public static void minEnclosingCircle(MatOfPoint2f points, Point center, float[] radius) + { + Mat points_mat = points; + double[] center_out = new double[2]; + double[] radius_out = new double[1]; + minEnclosingCircle_0(points_mat.nativeObj, center_out, radius_out); + if(center!=null){ center.x = center_out[0]; center.y = center_out[1]; } + if(radius!=null) radius[0] = (float)radius_out[0]; + return; + } + + + // + // C++: void cv::morphologyEx(Mat src, Mat& dst, int op, Mat kernel, Point anchor = Point(-1,-1), int iterations = 1, int borderType = BORDER_CONSTANT, Scalar borderValue = morphologyDefaultBorderValue()) + // + + //javadoc: morphologyEx(src, dst, op, kernel, anchor, iterations, borderType, borderValue) + public static void morphologyEx(Mat src, Mat dst, int op, Mat kernel, Point anchor, int iterations, int borderType, Scalar borderValue) + { + + morphologyEx_0(src.nativeObj, dst.nativeObj, op, kernel.nativeObj, anchor.x, anchor.y, iterations, borderType, borderValue.val[0], borderValue.val[1], borderValue.val[2], borderValue.val[3]); + + return; + } + + //javadoc: morphologyEx(src, dst, op, kernel, anchor, iterations, borderType) + public static void morphologyEx(Mat src, Mat dst, int op, Mat kernel, Point anchor, int iterations, int borderType) + { + + morphologyEx_1(src.nativeObj, dst.nativeObj, op, kernel.nativeObj, anchor.x, anchor.y, iterations, borderType); + + return; + } + + //javadoc: morphologyEx(src, dst, op, kernel, anchor, iterations) + public static void morphologyEx(Mat src, Mat dst, int op, Mat kernel, Point anchor, int iterations) + { + + morphologyEx_2(src.nativeObj, dst.nativeObj, op, kernel.nativeObj, anchor.x, anchor.y, iterations); + + return; + } + + //javadoc: morphologyEx(src, dst, op, kernel, anchor) + public static void morphologyEx(Mat src, Mat dst, int op, Mat kernel, Point anchor) + { + + morphologyEx_3(src.nativeObj, dst.nativeObj, op, kernel.nativeObj, anchor.x, anchor.y); + + return; + } + + //javadoc: morphologyEx(src, dst, op, kernel) + public static void morphologyEx(Mat src, Mat dst, int op, Mat kernel) + { + + morphologyEx_4(src.nativeObj, dst.nativeObj, op, kernel.nativeObj); + + return; + } + + + // + // C++: void cv::polylines(Mat& img, vector_vector_Point pts, bool isClosed, Scalar color, int thickness = 1, int lineType = LINE_8, int shift = 0) + // + + //javadoc: polylines(img, pts, isClosed, color, thickness, lineType, shift) + public static void polylines(Mat img, List pts, boolean isClosed, Scalar color, int thickness, int lineType, int shift) + { + List pts_tmplm = new ArrayList((pts != null) ? pts.size() : 0); + Mat pts_mat = Converters.vector_vector_Point_to_Mat(pts, pts_tmplm); + polylines_0(img.nativeObj, pts_mat.nativeObj, isClosed, color.val[0], color.val[1], color.val[2], color.val[3], thickness, lineType, shift); + + return; + } + + //javadoc: polylines(img, pts, isClosed, color, thickness, lineType) + public static void polylines(Mat img, List pts, boolean isClosed, Scalar color, int thickness, int lineType) + { + List pts_tmplm = new ArrayList((pts != null) ? pts.size() : 0); + Mat pts_mat = Converters.vector_vector_Point_to_Mat(pts, pts_tmplm); + polylines_1(img.nativeObj, pts_mat.nativeObj, isClosed, color.val[0], color.val[1], color.val[2], color.val[3], thickness, lineType); + + return; + } + + //javadoc: polylines(img, pts, isClosed, color, thickness) + public static void polylines(Mat img, List pts, boolean isClosed, Scalar color, int thickness) + { + List pts_tmplm = new ArrayList((pts != null) ? pts.size() : 0); + Mat pts_mat = Converters.vector_vector_Point_to_Mat(pts, pts_tmplm); + polylines_2(img.nativeObj, pts_mat.nativeObj, isClosed, color.val[0], color.val[1], color.val[2], color.val[3], thickness); + + return; + } + + //javadoc: polylines(img, pts, isClosed, color) + public static void polylines(Mat img, List pts, boolean isClosed, Scalar color) + { + List pts_tmplm = new ArrayList((pts != null) ? pts.size() : 0); + Mat pts_mat = Converters.vector_vector_Point_to_Mat(pts, pts_tmplm); + polylines_3(img.nativeObj, pts_mat.nativeObj, isClosed, color.val[0], color.val[1], color.val[2], color.val[3]); + + return; + } + + + // + // C++: void cv::preCornerDetect(Mat src, Mat& dst, int ksize, int borderType = BORDER_DEFAULT) + // + + //javadoc: preCornerDetect(src, dst, ksize, borderType) + public static void preCornerDetect(Mat src, Mat dst, int ksize, int borderType) + { + + preCornerDetect_0(src.nativeObj, dst.nativeObj, ksize, borderType); + + return; + } + + //javadoc: preCornerDetect(src, dst, ksize) + public static void preCornerDetect(Mat src, Mat dst, int ksize) + { + + preCornerDetect_1(src.nativeObj, dst.nativeObj, ksize); + + return; + } + + + // + // C++: void cv::putText(Mat& img, String text, Point org, int fontFace, double fontScale, Scalar color, int thickness = 1, int lineType = LINE_8, bool bottomLeftOrigin = false) + // + + //javadoc: putText(img, text, org, fontFace, fontScale, color, thickness, lineType, bottomLeftOrigin) + public static void putText(Mat img, String text, Point org, int fontFace, double fontScale, Scalar color, int thickness, int lineType, boolean bottomLeftOrigin) + { + + putText_0(img.nativeObj, text, org.x, org.y, fontFace, fontScale, color.val[0], color.val[1], color.val[2], color.val[3], thickness, lineType, bottomLeftOrigin); + + return; + } + + //javadoc: putText(img, text, org, fontFace, fontScale, color, thickness, lineType) + public static void putText(Mat img, String text, Point org, int fontFace, double fontScale, Scalar color, int thickness, int lineType) + { + + putText_1(img.nativeObj, text, org.x, org.y, fontFace, fontScale, color.val[0], color.val[1], color.val[2], color.val[3], thickness, lineType); + + return; + } + + //javadoc: putText(img, text, org, fontFace, fontScale, color, thickness) + public static void putText(Mat img, String text, Point org, int fontFace, double fontScale, Scalar color, int thickness) + { + + putText_2(img.nativeObj, text, org.x, org.y, fontFace, fontScale, color.val[0], color.val[1], color.val[2], color.val[3], thickness); + + return; + } + + //javadoc: putText(img, text, org, fontFace, fontScale, color) + public static void putText(Mat img, String text, Point org, int fontFace, double fontScale, Scalar color) + { + + putText_3(img.nativeObj, text, org.x, org.y, fontFace, fontScale, color.val[0], color.val[1], color.val[2], color.val[3]); + + return; + } + + + // + // C++: void cv::pyrDown(Mat src, Mat& dst, Size dstsize = Size(), int borderType = BORDER_DEFAULT) + // + + //javadoc: pyrDown(src, dst, dstsize, borderType) + public static void pyrDown(Mat src, Mat dst, Size dstsize, int borderType) + { + + pyrDown_0(src.nativeObj, dst.nativeObj, dstsize.width, dstsize.height, borderType); + + return; + } + + //javadoc: pyrDown(src, dst, dstsize) + public static void pyrDown(Mat src, Mat dst, Size dstsize) + { + + pyrDown_1(src.nativeObj, dst.nativeObj, dstsize.width, dstsize.height); + + return; + } + + //javadoc: pyrDown(src, dst) + public static void pyrDown(Mat src, Mat dst) + { + + pyrDown_2(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::pyrMeanShiftFiltering(Mat src, Mat& dst, double sp, double sr, int maxLevel = 1, TermCriteria termcrit = TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS,5,1)) + // + + //javadoc: pyrMeanShiftFiltering(src, dst, sp, sr, maxLevel, termcrit) + public static void pyrMeanShiftFiltering(Mat src, Mat dst, double sp, double sr, int maxLevel, TermCriteria termcrit) + { + + pyrMeanShiftFiltering_0(src.nativeObj, dst.nativeObj, sp, sr, maxLevel, termcrit.type, termcrit.maxCount, termcrit.epsilon); + + return; + } + + //javadoc: pyrMeanShiftFiltering(src, dst, sp, sr, maxLevel) + public static void pyrMeanShiftFiltering(Mat src, Mat dst, double sp, double sr, int maxLevel) + { + + pyrMeanShiftFiltering_1(src.nativeObj, dst.nativeObj, sp, sr, maxLevel); + + return; + } + + //javadoc: pyrMeanShiftFiltering(src, dst, sp, sr) + public static void pyrMeanShiftFiltering(Mat src, Mat dst, double sp, double sr) + { + + pyrMeanShiftFiltering_2(src.nativeObj, dst.nativeObj, sp, sr); + + return; + } + + + // + // C++: void cv::pyrUp(Mat src, Mat& dst, Size dstsize = Size(), int borderType = BORDER_DEFAULT) + // + + //javadoc: pyrUp(src, dst, dstsize, borderType) + public static void pyrUp(Mat src, Mat dst, Size dstsize, int borderType) + { + + pyrUp_0(src.nativeObj, dst.nativeObj, dstsize.width, dstsize.height, borderType); + + return; + } + + //javadoc: pyrUp(src, dst, dstsize) + public static void pyrUp(Mat src, Mat dst, Size dstsize) + { + + pyrUp_1(src.nativeObj, dst.nativeObj, dstsize.width, dstsize.height); + + return; + } + + //javadoc: pyrUp(src, dst) + public static void pyrUp(Mat src, Mat dst) + { + + pyrUp_2(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::rectangle(Mat& img, Point pt1, Point pt2, Scalar color, int thickness = 1, int lineType = LINE_8, int shift = 0) + // + + //javadoc: rectangle(img, pt1, pt2, color, thickness, lineType, shift) + public static void rectangle(Mat img, Point pt1, Point pt2, Scalar color, int thickness, int lineType, int shift) + { + + rectangle_0(img.nativeObj, pt1.x, pt1.y, pt2.x, pt2.y, color.val[0], color.val[1], color.val[2], color.val[3], thickness, lineType, shift); + + return; + } + + //javadoc: rectangle(img, pt1, pt2, color, thickness, lineType) + public static void rectangle(Mat img, Point pt1, Point pt2, Scalar color, int thickness, int lineType) + { + + rectangle_1(img.nativeObj, pt1.x, pt1.y, pt2.x, pt2.y, color.val[0], color.val[1], color.val[2], color.val[3], thickness, lineType); + + return; + } + + //javadoc: rectangle(img, pt1, pt2, color, thickness) + public static void rectangle(Mat img, Point pt1, Point pt2, Scalar color, int thickness) + { + + rectangle_2(img.nativeObj, pt1.x, pt1.y, pt2.x, pt2.y, color.val[0], color.val[1], color.val[2], color.val[3], thickness); + + return; + } + + //javadoc: rectangle(img, pt1, pt2, color) + public static void rectangle(Mat img, Point pt1, Point pt2, Scalar color) + { + + rectangle_3(img.nativeObj, pt1.x, pt1.y, pt2.x, pt2.y, color.val[0], color.val[1], color.val[2], color.val[3]); + + return; + } + + + // + // C++: void cv::rectangle(Mat& img, Rect rec, Scalar color, int thickness = 1, int lineType = LINE_8, int shift = 0) + // + + //javadoc: rectangle(img, rec, color, thickness, lineType, shift) + public static void rectangle(Mat img, Rect rec, Scalar color, int thickness, int lineType, int shift) + { + + rectangle_4(img.nativeObj, rec.x, rec.y, rec.width, rec.height, color.val[0], color.val[1], color.val[2], color.val[3], thickness, lineType, shift); + + return; + } + + //javadoc: rectangle(img, rec, color, thickness, lineType) + public static void rectangle(Mat img, Rect rec, Scalar color, int thickness, int lineType) + { + + rectangle_5(img.nativeObj, rec.x, rec.y, rec.width, rec.height, color.val[0], color.val[1], color.val[2], color.val[3], thickness, lineType); + + return; + } + + //javadoc: rectangle(img, rec, color, thickness) + public static void rectangle(Mat img, Rect rec, Scalar color, int thickness) + { + + rectangle_6(img.nativeObj, rec.x, rec.y, rec.width, rec.height, color.val[0], color.val[1], color.val[2], color.val[3], thickness); + + return; + } + + //javadoc: rectangle(img, rec, color) + public static void rectangle(Mat img, Rect rec, Scalar color) + { + + rectangle_7(img.nativeObj, rec.x, rec.y, rec.width, rec.height, color.val[0], color.val[1], color.val[2], color.val[3]); + + return; + } + + + // + // C++: void cv::remap(Mat src, Mat& dst, Mat map1, Mat map2, int interpolation, int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar()) + // + + //javadoc: remap(src, dst, map1, map2, interpolation, borderMode, borderValue) + public static void remap(Mat src, Mat dst, Mat map1, Mat map2, int interpolation, int borderMode, Scalar borderValue) + { + + remap_0(src.nativeObj, dst.nativeObj, map1.nativeObj, map2.nativeObj, interpolation, borderMode, borderValue.val[0], borderValue.val[1], borderValue.val[2], borderValue.val[3]); + + return; + } + + //javadoc: remap(src, dst, map1, map2, interpolation, borderMode) + public static void remap(Mat src, Mat dst, Mat map1, Mat map2, int interpolation, int borderMode) + { + + remap_1(src.nativeObj, dst.nativeObj, map1.nativeObj, map2.nativeObj, interpolation, borderMode); + + return; + } + + //javadoc: remap(src, dst, map1, map2, interpolation) + public static void remap(Mat src, Mat dst, Mat map1, Mat map2, int interpolation) + { + + remap_2(src.nativeObj, dst.nativeObj, map1.nativeObj, map2.nativeObj, interpolation); + + return; + } + + + // + // C++: void cv::resize(Mat src, Mat& dst, Size dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR) + // + + //javadoc: resize(src, dst, dsize, fx, fy, interpolation) + public static void resize(Mat src, Mat dst, Size dsize, double fx, double fy, int interpolation) + { + + resize_0(src.nativeObj, dst.nativeObj, dsize.width, dsize.height, fx, fy, interpolation); + + return; + } + + //javadoc: resize(src, dst, dsize, fx, fy) + public static void resize(Mat src, Mat dst, Size dsize, double fx, double fy) + { + + resize_1(src.nativeObj, dst.nativeObj, dsize.width, dsize.height, fx, fy); + + return; + } + + //javadoc: resize(src, dst, dsize, fx) + public static void resize(Mat src, Mat dst, Size dsize, double fx) + { + + resize_2(src.nativeObj, dst.nativeObj, dsize.width, dsize.height, fx); + + return; + } + + //javadoc: resize(src, dst, dsize) + public static void resize(Mat src, Mat dst, Size dsize) + { + + resize_3(src.nativeObj, dst.nativeObj, dsize.width, dsize.height); + + return; + } + + + // + // C++: void cv::sepFilter2D(Mat src, Mat& dst, int ddepth, Mat kernelX, Mat kernelY, Point anchor = Point(-1,-1), double delta = 0, int borderType = BORDER_DEFAULT) + // + + //javadoc: sepFilter2D(src, dst, ddepth, kernelX, kernelY, anchor, delta, borderType) + public static void sepFilter2D(Mat src, Mat dst, int ddepth, Mat kernelX, Mat kernelY, Point anchor, double delta, int borderType) + { + + sepFilter2D_0(src.nativeObj, dst.nativeObj, ddepth, kernelX.nativeObj, kernelY.nativeObj, anchor.x, anchor.y, delta, borderType); + + return; + } + + //javadoc: sepFilter2D(src, dst, ddepth, kernelX, kernelY, anchor, delta) + public static void sepFilter2D(Mat src, Mat dst, int ddepth, Mat kernelX, Mat kernelY, Point anchor, double delta) + { + + sepFilter2D_1(src.nativeObj, dst.nativeObj, ddepth, kernelX.nativeObj, kernelY.nativeObj, anchor.x, anchor.y, delta); + + return; + } + + //javadoc: sepFilter2D(src, dst, ddepth, kernelX, kernelY, anchor) + public static void sepFilter2D(Mat src, Mat dst, int ddepth, Mat kernelX, Mat kernelY, Point anchor) + { + + sepFilter2D_2(src.nativeObj, dst.nativeObj, ddepth, kernelX.nativeObj, kernelY.nativeObj, anchor.x, anchor.y); + + return; + } + + //javadoc: sepFilter2D(src, dst, ddepth, kernelX, kernelY) + public static void sepFilter2D(Mat src, Mat dst, int ddepth, Mat kernelX, Mat kernelY) + { + + sepFilter2D_3(src.nativeObj, dst.nativeObj, ddepth, kernelX.nativeObj, kernelY.nativeObj); + + return; + } + + + // + // C++: void cv::spatialGradient(Mat src, Mat& dx, Mat& dy, int ksize = 3, int borderType = BORDER_DEFAULT) + // + + //javadoc: spatialGradient(src, dx, dy, ksize, borderType) + public static void spatialGradient(Mat src, Mat dx, Mat dy, int ksize, int borderType) + { + + spatialGradient_0(src.nativeObj, dx.nativeObj, dy.nativeObj, ksize, borderType); + + return; + } + + //javadoc: spatialGradient(src, dx, dy, ksize) + public static void spatialGradient(Mat src, Mat dx, Mat dy, int ksize) + { + + spatialGradient_1(src.nativeObj, dx.nativeObj, dy.nativeObj, ksize); + + return; + } + + //javadoc: spatialGradient(src, dx, dy) + public static void spatialGradient(Mat src, Mat dx, Mat dy) + { + + spatialGradient_2(src.nativeObj, dx.nativeObj, dy.nativeObj); + + return; + } + + + // + // C++: void cv::sqrBoxFilter(Mat src, Mat& dst, int ddepth, Size ksize, Point anchor = Point(-1, -1), bool normalize = true, int borderType = BORDER_DEFAULT) + // + + //javadoc: sqrBoxFilter(src, dst, ddepth, ksize, anchor, normalize, borderType) + public static void sqrBoxFilter(Mat src, Mat dst, int ddepth, Size ksize, Point anchor, boolean normalize, int borderType) + { + + sqrBoxFilter_0(src.nativeObj, dst.nativeObj, ddepth, ksize.width, ksize.height, anchor.x, anchor.y, normalize, borderType); + + return; + } + + //javadoc: sqrBoxFilter(src, dst, ddepth, ksize, anchor, normalize) + public static void sqrBoxFilter(Mat src, Mat dst, int ddepth, Size ksize, Point anchor, boolean normalize) + { + + sqrBoxFilter_1(src.nativeObj, dst.nativeObj, ddepth, ksize.width, ksize.height, anchor.x, anchor.y, normalize); + + return; + } + + //javadoc: sqrBoxFilter(src, dst, ddepth, ksize, anchor) + public static void sqrBoxFilter(Mat src, Mat dst, int ddepth, Size ksize, Point anchor) + { + + sqrBoxFilter_2(src.nativeObj, dst.nativeObj, ddepth, ksize.width, ksize.height, anchor.x, anchor.y); + + return; + } + + //javadoc: sqrBoxFilter(src, dst, ddepth, ksize) + public static void sqrBoxFilter(Mat src, Mat dst, int ddepth, Size ksize) + { + + sqrBoxFilter_3(src.nativeObj, dst.nativeObj, ddepth, ksize.width, ksize.height); + + return; + } + + + // + // C++: void cv::warpAffine(Mat src, Mat& dst, Mat M, Size dsize, int flags = INTER_LINEAR, int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar()) + // + + //javadoc: warpAffine(src, dst, M, dsize, flags, borderMode, borderValue) + public static void warpAffine(Mat src, Mat dst, Mat M, Size dsize, int flags, int borderMode, Scalar borderValue) + { + + warpAffine_0(src.nativeObj, dst.nativeObj, M.nativeObj, dsize.width, dsize.height, flags, borderMode, borderValue.val[0], borderValue.val[1], borderValue.val[2], borderValue.val[3]); + + return; + } + + //javadoc: warpAffine(src, dst, M, dsize, flags, borderMode) + public static void warpAffine(Mat src, Mat dst, Mat M, Size dsize, int flags, int borderMode) + { + + warpAffine_1(src.nativeObj, dst.nativeObj, M.nativeObj, dsize.width, dsize.height, flags, borderMode); + + return; + } + + //javadoc: warpAffine(src, dst, M, dsize, flags) + public static void warpAffine(Mat src, Mat dst, Mat M, Size dsize, int flags) + { + + warpAffine_2(src.nativeObj, dst.nativeObj, M.nativeObj, dsize.width, dsize.height, flags); + + return; + } + + //javadoc: warpAffine(src, dst, M, dsize) + public static void warpAffine(Mat src, Mat dst, Mat M, Size dsize) + { + + warpAffine_3(src.nativeObj, dst.nativeObj, M.nativeObj, dsize.width, dsize.height); + + return; + } + + + // + // C++: void cv::warpPerspective(Mat src, Mat& dst, Mat M, Size dsize, int flags = INTER_LINEAR, int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar()) + // + + //javadoc: warpPerspective(src, dst, M, dsize, flags, borderMode, borderValue) + public static void warpPerspective(Mat src, Mat dst, Mat M, Size dsize, int flags, int borderMode, Scalar borderValue) + { + + warpPerspective_0(src.nativeObj, dst.nativeObj, M.nativeObj, dsize.width, dsize.height, flags, borderMode, borderValue.val[0], borderValue.val[1], borderValue.val[2], borderValue.val[3]); + + return; + } + + //javadoc: warpPerspective(src, dst, M, dsize, flags, borderMode) + public static void warpPerspective(Mat src, Mat dst, Mat M, Size dsize, int flags, int borderMode) + { + + warpPerspective_1(src.nativeObj, dst.nativeObj, M.nativeObj, dsize.width, dsize.height, flags, borderMode); + + return; + } + + //javadoc: warpPerspective(src, dst, M, dsize, flags) + public static void warpPerspective(Mat src, Mat dst, Mat M, Size dsize, int flags) + { + + warpPerspective_2(src.nativeObj, dst.nativeObj, M.nativeObj, dsize.width, dsize.height, flags); + + return; + } + + //javadoc: warpPerspective(src, dst, M, dsize) + public static void warpPerspective(Mat src, Mat dst, Mat M, Size dsize) + { + + warpPerspective_3(src.nativeObj, dst.nativeObj, M.nativeObj, dsize.width, dsize.height); + + return; + } + + + // + // C++: void cv::warpPolar(Mat src, Mat& dst, Size dsize, Point2f center, double maxRadius, int flags) + // + + //javadoc: warpPolar(src, dst, dsize, center, maxRadius, flags) + public static void warpPolar(Mat src, Mat dst, Size dsize, Point center, double maxRadius, int flags) + { + + warpPolar_0(src.nativeObj, dst.nativeObj, dsize.width, dsize.height, center.x, center.y, maxRadius, flags); + + return; + } + + + // + // C++: void cv::watershed(Mat image, Mat& markers) + // + + //javadoc: watershed(image, markers) + public static void watershed(Mat image, Mat markers) + { + + watershed_0(image.nativeObj, markers.nativeObj); + + return; + } + + + +// C++: Size getTextSize(const String& text, int fontFace, double fontScale, int thickness, int* baseLine); +//javadoc:getTextSize(text, fontFace, fontScale, thickness, baseLine) +public static Size getTextSize(String text, int fontFace, double fontScale, int thickness, int[] baseLine) { + if(baseLine != null && baseLine.length != 1) + throw new java.lang.IllegalArgumentException("'baseLine' must be 'int[1]' or 'null'."); + Size retVal = new Size(n_getTextSize(text, fontFace, fontScale, thickness, baseLine)); + return retVal; +} + + + + + // C++: Mat cv::getAffineTransform(vector_Point2f src, vector_Point2f dst) + private static native long getAffineTransform_0(long src_mat_nativeObj, long dst_mat_nativeObj); + + // C++: Mat cv::getGaborKernel(Size ksize, double sigma, double theta, double lambd, double gamma, double psi = CV_PI*0.5, int ktype = CV_64F) + private static native long getGaborKernel_0(double ksize_width, double ksize_height, double sigma, double theta, double lambd, double gamma, double psi, int ktype); + private static native long getGaborKernel_1(double ksize_width, double ksize_height, double sigma, double theta, double lambd, double gamma, double psi); + private static native long getGaborKernel_2(double ksize_width, double ksize_height, double sigma, double theta, double lambd, double gamma); + + // C++: Mat cv::getGaussianKernel(int ksize, double sigma, int ktype = CV_64F) + private static native long getGaussianKernel_0(int ksize, double sigma, int ktype); + private static native long getGaussianKernel_1(int ksize, double sigma); + + // C++: Mat cv::getPerspectiveTransform(Mat src, Mat dst, int solveMethod = DECOMP_LU) + private static native long getPerspectiveTransform_0(long src_nativeObj, long dst_nativeObj, int solveMethod); + private static native long getPerspectiveTransform_1(long src_nativeObj, long dst_nativeObj); + + // C++: Mat cv::getRotationMatrix2D(Point2f center, double angle, double scale) + private static native long getRotationMatrix2D_0(double center_x, double center_y, double angle, double scale); + + // C++: Mat cv::getStructuringElement(int shape, Size ksize, Point anchor = Point(-1,-1)) + private static native long getStructuringElement_0(int shape, double ksize_width, double ksize_height, double anchor_x, double anchor_y); + private static native long getStructuringElement_1(int shape, double ksize_width, double ksize_height); + + // C++: Moments cv::moments(Mat array, bool binaryImage = false) + private static native double[] moments_0(long array_nativeObj, boolean binaryImage); + private static native double[] moments_1(long array_nativeObj); + + // C++: Point2d cv::phaseCorrelate(Mat src1, Mat src2, Mat window = Mat(), double* response = 0) + private static native double[] phaseCorrelate_0(long src1_nativeObj, long src2_nativeObj, long window_nativeObj, double[] response_out); + private static native double[] phaseCorrelate_1(long src1_nativeObj, long src2_nativeObj, long window_nativeObj); + private static native double[] phaseCorrelate_2(long src1_nativeObj, long src2_nativeObj); + + // C++: Ptr_CLAHE cv::createCLAHE(double clipLimit = 40.0, Size tileGridSize = Size(8, 8)) + private static native long createCLAHE_0(double clipLimit, double tileGridSize_width, double tileGridSize_height); + private static native long createCLAHE_1(double clipLimit); + private static native long createCLAHE_2(); + + // C++: Ptr_GeneralizedHoughBallard cv::createGeneralizedHoughBallard() + private static native long createGeneralizedHoughBallard_0(); + + // C++: Ptr_GeneralizedHoughGuil cv::createGeneralizedHoughGuil() + private static native long createGeneralizedHoughGuil_0(); + + // C++: Ptr_LineSegmentDetector cv::createLineSegmentDetector(int _refine = LSD_REFINE_STD, double _scale = 0.8, double _sigma_scale = 0.6, double _quant = 2.0, double _ang_th = 22.5, double _log_eps = 0, double _density_th = 0.7, int _n_bins = 1024) + private static native long createLineSegmentDetector_0(int _refine, double _scale, double _sigma_scale, double _quant, double _ang_th, double _log_eps, double _density_th, int _n_bins); + private static native long createLineSegmentDetector_1(int _refine, double _scale, double _sigma_scale, double _quant, double _ang_th, double _log_eps, double _density_th); + private static native long createLineSegmentDetector_2(int _refine, double _scale, double _sigma_scale, double _quant, double _ang_th, double _log_eps); + private static native long createLineSegmentDetector_3(int _refine, double _scale, double _sigma_scale, double _quant, double _ang_th); + private static native long createLineSegmentDetector_4(int _refine, double _scale, double _sigma_scale, double _quant); + private static native long createLineSegmentDetector_5(int _refine, double _scale, double _sigma_scale); + private static native long createLineSegmentDetector_6(int _refine, double _scale); + private static native long createLineSegmentDetector_7(int _refine); + private static native long createLineSegmentDetector_8(); + + // C++: Rect cv::boundingRect(Mat array) + private static native double[] boundingRect_0(long array_nativeObj); + + // C++: RotatedRect cv::fitEllipse(vector_Point2f points) + private static native double[] fitEllipse_0(long points_mat_nativeObj); + + // C++: RotatedRect cv::fitEllipseAMS(Mat points) + private static native double[] fitEllipseAMS_0(long points_nativeObj); + + // C++: RotatedRect cv::fitEllipseDirect(Mat points) + private static native double[] fitEllipseDirect_0(long points_nativeObj); + + // C++: RotatedRect cv::minAreaRect(vector_Point2f points) + private static native double[] minAreaRect_0(long points_mat_nativeObj); + + // C++: bool cv::clipLine(Rect imgRect, Point& pt1, Point& pt2) + private static native boolean clipLine_0(int imgRect_x, int imgRect_y, int imgRect_width, int imgRect_height, double pt1_x, double pt1_y, double[] pt1_out, double pt2_x, double pt2_y, double[] pt2_out); + + // C++: bool cv::isContourConvex(vector_Point contour) + private static native boolean isContourConvex_0(long contour_mat_nativeObj); + + // C++: double cv::arcLength(vector_Point2f curve, bool closed) + private static native double arcLength_0(long curve_mat_nativeObj, boolean closed); + + // C++: double cv::compareHist(Mat H1, Mat H2, int method) + private static native double compareHist_0(long H1_nativeObj, long H2_nativeObj, int method); + + // C++: double cv::contourArea(Mat contour, bool oriented = false) + private static native double contourArea_0(long contour_nativeObj, boolean oriented); + private static native double contourArea_1(long contour_nativeObj); + + // C++: double cv::getFontScaleFromHeight(int fontFace, int pixelHeight, int thickness = 1) + private static native double getFontScaleFromHeight_0(int fontFace, int pixelHeight, int thickness); + private static native double getFontScaleFromHeight_1(int fontFace, int pixelHeight); + + // C++: double cv::matchShapes(Mat contour1, Mat contour2, int method, double parameter) + private static native double matchShapes_0(long contour1_nativeObj, long contour2_nativeObj, int method, double parameter); + + // C++: double cv::minEnclosingTriangle(Mat points, Mat& triangle) + private static native double minEnclosingTriangle_0(long points_nativeObj, long triangle_nativeObj); + + // C++: double cv::pointPolygonTest(vector_Point2f contour, Point2f pt, bool measureDist) + private static native double pointPolygonTest_0(long contour_mat_nativeObj, double pt_x, double pt_y, boolean measureDist); + + // C++: double cv::threshold(Mat src, Mat& dst, double thresh, double maxval, int type) + private static native double threshold_0(long src_nativeObj, long dst_nativeObj, double thresh, double maxval, int type); + + // C++: float cv::intersectConvexConvex(Mat _p1, Mat _p2, Mat& _p12, bool handleNested = true) + private static native float intersectConvexConvex_0(long _p1_nativeObj, long _p2_nativeObj, long _p12_nativeObj, boolean handleNested); + private static native float intersectConvexConvex_1(long _p1_nativeObj, long _p2_nativeObj, long _p12_nativeObj); + + // C++: float cv::wrapperEMD(Mat signature1, Mat signature2, int distType, Mat cost = Mat(), Ptr_float& lowerBound = Ptr(), Mat& flow = Mat()) + private static native float EMD_0(long signature1_nativeObj, long signature2_nativeObj, int distType, long cost_nativeObj, long flow_nativeObj); + private static native float EMD_1(long signature1_nativeObj, long signature2_nativeObj, int distType, long cost_nativeObj); + private static native float EMD_3(long signature1_nativeObj, long signature2_nativeObj, int distType); + + // C++: int cv::connectedComponents(Mat image, Mat& labels, int connectivity, int ltype, int ccltype) + private static native int connectedComponentsWithAlgorithm_0(long image_nativeObj, long labels_nativeObj, int connectivity, int ltype, int ccltype); + + // C++: int cv::connectedComponents(Mat image, Mat& labels, int connectivity = 8, int ltype = CV_32S) + private static native int connectedComponents_0(long image_nativeObj, long labels_nativeObj, int connectivity, int ltype); + private static native int connectedComponents_1(long image_nativeObj, long labels_nativeObj, int connectivity); + private static native int connectedComponents_2(long image_nativeObj, long labels_nativeObj); + + // C++: int cv::connectedComponentsWithStats(Mat image, Mat& labels, Mat& stats, Mat& centroids, int connectivity, int ltype, int ccltype) + private static native int connectedComponentsWithStatsWithAlgorithm_0(long image_nativeObj, long labels_nativeObj, long stats_nativeObj, long centroids_nativeObj, int connectivity, int ltype, int ccltype); + + // C++: int cv::connectedComponentsWithStats(Mat image, Mat& labels, Mat& stats, Mat& centroids, int connectivity = 8, int ltype = CV_32S) + private static native int connectedComponentsWithStats_0(long image_nativeObj, long labels_nativeObj, long stats_nativeObj, long centroids_nativeObj, int connectivity, int ltype); + private static native int connectedComponentsWithStats_1(long image_nativeObj, long labels_nativeObj, long stats_nativeObj, long centroids_nativeObj, int connectivity); + private static native int connectedComponentsWithStats_2(long image_nativeObj, long labels_nativeObj, long stats_nativeObj, long centroids_nativeObj); + + // C++: int cv::floodFill(Mat& image, Mat& mask, Point seedPoint, Scalar newVal, Rect* rect = 0, Scalar loDiff = Scalar(), Scalar upDiff = Scalar(), int flags = 4) + private static native int floodFill_0(long image_nativeObj, long mask_nativeObj, double seedPoint_x, double seedPoint_y, double newVal_val0, double newVal_val1, double newVal_val2, double newVal_val3, double[] rect_out, double loDiff_val0, double loDiff_val1, double loDiff_val2, double loDiff_val3, double upDiff_val0, double upDiff_val1, double upDiff_val2, double upDiff_val3, int flags); + private static native int floodFill_1(long image_nativeObj, long mask_nativeObj, double seedPoint_x, double seedPoint_y, double newVal_val0, double newVal_val1, double newVal_val2, double newVal_val3, double[] rect_out, double loDiff_val0, double loDiff_val1, double loDiff_val2, double loDiff_val3, double upDiff_val0, double upDiff_val1, double upDiff_val2, double upDiff_val3); + private static native int floodFill_2(long image_nativeObj, long mask_nativeObj, double seedPoint_x, double seedPoint_y, double newVal_val0, double newVal_val1, double newVal_val2, double newVal_val3, double[] rect_out, double loDiff_val0, double loDiff_val1, double loDiff_val2, double loDiff_val3); + private static native int floodFill_3(long image_nativeObj, long mask_nativeObj, double seedPoint_x, double seedPoint_y, double newVal_val0, double newVal_val1, double newVal_val2, double newVal_val3, double[] rect_out); + private static native int floodFill_4(long image_nativeObj, long mask_nativeObj, double seedPoint_x, double seedPoint_y, double newVal_val0, double newVal_val1, double newVal_val2, double newVal_val3); + + // C++: int cv::rotatedRectangleIntersection(RotatedRect rect1, RotatedRect rect2, Mat& intersectingRegion) + private static native int rotatedRectangleIntersection_0(double rect1_center_x, double rect1_center_y, double rect1_size_width, double rect1_size_height, double rect1_angle, double rect2_center_x, double rect2_center_y, double rect2_size_width, double rect2_size_height, double rect2_angle, long intersectingRegion_nativeObj); + + // C++: void cv::Canny(Mat dx, Mat dy, Mat& edges, double threshold1, double threshold2, bool L2gradient = false) + private static native void Canny_0(long dx_nativeObj, long dy_nativeObj, long edges_nativeObj, double threshold1, double threshold2, boolean L2gradient); + private static native void Canny_1(long dx_nativeObj, long dy_nativeObj, long edges_nativeObj, double threshold1, double threshold2); + + // C++: void cv::Canny(Mat image, Mat& edges, double threshold1, double threshold2, int apertureSize = 3, bool L2gradient = false) + private static native void Canny_2(long image_nativeObj, long edges_nativeObj, double threshold1, double threshold2, int apertureSize, boolean L2gradient); + private static native void Canny_3(long image_nativeObj, long edges_nativeObj, double threshold1, double threshold2, int apertureSize); + private static native void Canny_4(long image_nativeObj, long edges_nativeObj, double threshold1, double threshold2); + + // C++: void cv::GaussianBlur(Mat src, Mat& dst, Size ksize, double sigmaX, double sigmaY = 0, int borderType = BORDER_DEFAULT) + private static native void GaussianBlur_0(long src_nativeObj, long dst_nativeObj, double ksize_width, double ksize_height, double sigmaX, double sigmaY, int borderType); + private static native void GaussianBlur_1(long src_nativeObj, long dst_nativeObj, double ksize_width, double ksize_height, double sigmaX, double sigmaY); + private static native void GaussianBlur_2(long src_nativeObj, long dst_nativeObj, double ksize_width, double ksize_height, double sigmaX); + + // C++: void cv::HoughCircles(Mat image, Mat& circles, int method, double dp, double minDist, double param1 = 100, double param2 = 100, int minRadius = 0, int maxRadius = 0) + private static native void HoughCircles_0(long image_nativeObj, long circles_nativeObj, int method, double dp, double minDist, double param1, double param2, int minRadius, int maxRadius); + private static native void HoughCircles_1(long image_nativeObj, long circles_nativeObj, int method, double dp, double minDist, double param1, double param2, int minRadius); + private static native void HoughCircles_2(long image_nativeObj, long circles_nativeObj, int method, double dp, double minDist, double param1, double param2); + private static native void HoughCircles_3(long image_nativeObj, long circles_nativeObj, int method, double dp, double minDist, double param1); + private static native void HoughCircles_4(long image_nativeObj, long circles_nativeObj, int method, double dp, double minDist); + + // C++: void cv::HoughLines(Mat image, Mat& lines, double rho, double theta, int threshold, double srn = 0, double stn = 0, double min_theta = 0, double max_theta = CV_PI) + private static native void HoughLines_0(long image_nativeObj, long lines_nativeObj, double rho, double theta, int threshold, double srn, double stn, double min_theta, double max_theta); + private static native void HoughLines_1(long image_nativeObj, long lines_nativeObj, double rho, double theta, int threshold, double srn, double stn, double min_theta); + private static native void HoughLines_2(long image_nativeObj, long lines_nativeObj, double rho, double theta, int threshold, double srn, double stn); + private static native void HoughLines_3(long image_nativeObj, long lines_nativeObj, double rho, double theta, int threshold, double srn); + private static native void HoughLines_4(long image_nativeObj, long lines_nativeObj, double rho, double theta, int threshold); + + // C++: void cv::HoughLinesP(Mat image, Mat& lines, double rho, double theta, int threshold, double minLineLength = 0, double maxLineGap = 0) + private static native void HoughLinesP_0(long image_nativeObj, long lines_nativeObj, double rho, double theta, int threshold, double minLineLength, double maxLineGap); + private static native void HoughLinesP_1(long image_nativeObj, long lines_nativeObj, double rho, double theta, int threshold, double minLineLength); + private static native void HoughLinesP_2(long image_nativeObj, long lines_nativeObj, double rho, double theta, int threshold); + + // C++: void cv::HoughLinesPointSet(Mat _point, Mat& _lines, int lines_max, int threshold, double min_rho, double max_rho, double rho_step, double min_theta, double max_theta, double theta_step) + private static native void HoughLinesPointSet_0(long _point_nativeObj, long _lines_nativeObj, int lines_max, int threshold, double min_rho, double max_rho, double rho_step, double min_theta, double max_theta, double theta_step); + + // C++: void cv::HuMoments(Moments m, Mat& hu) + private static native void HuMoments_0(double m_m00, double m_m10, double m_m01, double m_m20, double m_m11, double m_m02, double m_m30, double m_m21, double m_m12, double m_m03, long hu_nativeObj); + + // C++: void cv::Laplacian(Mat src, Mat& dst, int ddepth, int ksize = 1, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT) + private static native void Laplacian_0(long src_nativeObj, long dst_nativeObj, int ddepth, int ksize, double scale, double delta, int borderType); + private static native void Laplacian_1(long src_nativeObj, long dst_nativeObj, int ddepth, int ksize, double scale, double delta); + private static native void Laplacian_2(long src_nativeObj, long dst_nativeObj, int ddepth, int ksize, double scale); + private static native void Laplacian_3(long src_nativeObj, long dst_nativeObj, int ddepth, int ksize); + private static native void Laplacian_4(long src_nativeObj, long dst_nativeObj, int ddepth); + + // C++: void cv::Scharr(Mat src, Mat& dst, int ddepth, int dx, int dy, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT) + private static native void Scharr_0(long src_nativeObj, long dst_nativeObj, int ddepth, int dx, int dy, double scale, double delta, int borderType); + private static native void Scharr_1(long src_nativeObj, long dst_nativeObj, int ddepth, int dx, int dy, double scale, double delta); + private static native void Scharr_2(long src_nativeObj, long dst_nativeObj, int ddepth, int dx, int dy, double scale); + private static native void Scharr_3(long src_nativeObj, long dst_nativeObj, int ddepth, int dx, int dy); + + // C++: void cv::Sobel(Mat src, Mat& dst, int ddepth, int dx, int dy, int ksize = 3, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT) + private static native void Sobel_0(long src_nativeObj, long dst_nativeObj, int ddepth, int dx, int dy, int ksize, double scale, double delta, int borderType); + private static native void Sobel_1(long src_nativeObj, long dst_nativeObj, int ddepth, int dx, int dy, int ksize, double scale, double delta); + private static native void Sobel_2(long src_nativeObj, long dst_nativeObj, int ddepth, int dx, int dy, int ksize, double scale); + private static native void Sobel_3(long src_nativeObj, long dst_nativeObj, int ddepth, int dx, int dy, int ksize); + private static native void Sobel_4(long src_nativeObj, long dst_nativeObj, int ddepth, int dx, int dy); + + // C++: void cv::accumulate(Mat src, Mat& dst, Mat mask = Mat()) + private static native void accumulate_0(long src_nativeObj, long dst_nativeObj, long mask_nativeObj); + private static native void accumulate_1(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::accumulateProduct(Mat src1, Mat src2, Mat& dst, Mat mask = Mat()) + private static native void accumulateProduct_0(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj, long mask_nativeObj); + private static native void accumulateProduct_1(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj); + + // C++: void cv::accumulateSquare(Mat src, Mat& dst, Mat mask = Mat()) + private static native void accumulateSquare_0(long src_nativeObj, long dst_nativeObj, long mask_nativeObj); + private static native void accumulateSquare_1(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::accumulateWeighted(Mat src, Mat& dst, double alpha, Mat mask = Mat()) + private static native void accumulateWeighted_0(long src_nativeObj, long dst_nativeObj, double alpha, long mask_nativeObj); + private static native void accumulateWeighted_1(long src_nativeObj, long dst_nativeObj, double alpha); + + // C++: void cv::adaptiveThreshold(Mat src, Mat& dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C) + private static native void adaptiveThreshold_0(long src_nativeObj, long dst_nativeObj, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C); + + // C++: void cv::applyColorMap(Mat src, Mat& dst, Mat userColor) + private static native void applyColorMap_0(long src_nativeObj, long dst_nativeObj, long userColor_nativeObj); + + // C++: void cv::applyColorMap(Mat src, Mat& dst, int colormap) + private static native void applyColorMap_1(long src_nativeObj, long dst_nativeObj, int colormap); + + // C++: void cv::approxPolyDP(vector_Point2f curve, vector_Point2f& approxCurve, double epsilon, bool closed) + private static native void approxPolyDP_0(long curve_mat_nativeObj, long approxCurve_mat_nativeObj, double epsilon, boolean closed); + + // C++: void cv::arrowedLine(Mat& img, Point pt1, Point pt2, Scalar color, int thickness = 1, int line_type = 8, int shift = 0, double tipLength = 0.1) + private static native void arrowedLine_0(long img_nativeObj, double pt1_x, double pt1_y, double pt2_x, double pt2_y, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int line_type, int shift, double tipLength); + private static native void arrowedLine_1(long img_nativeObj, double pt1_x, double pt1_y, double pt2_x, double pt2_y, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int line_type, int shift); + private static native void arrowedLine_2(long img_nativeObj, double pt1_x, double pt1_y, double pt2_x, double pt2_y, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int line_type); + private static native void arrowedLine_3(long img_nativeObj, double pt1_x, double pt1_y, double pt2_x, double pt2_y, double color_val0, double color_val1, double color_val2, double color_val3, int thickness); + private static native void arrowedLine_4(long img_nativeObj, double pt1_x, double pt1_y, double pt2_x, double pt2_y, double color_val0, double color_val1, double color_val2, double color_val3); + + // C++: void cv::bilateralFilter(Mat src, Mat& dst, int d, double sigmaColor, double sigmaSpace, int borderType = BORDER_DEFAULT) + private static native void bilateralFilter_0(long src_nativeObj, long dst_nativeObj, int d, double sigmaColor, double sigmaSpace, int borderType); + private static native void bilateralFilter_1(long src_nativeObj, long dst_nativeObj, int d, double sigmaColor, double sigmaSpace); + + // C++: void cv::blur(Mat src, Mat& dst, Size ksize, Point anchor = Point(-1,-1), int borderType = BORDER_DEFAULT) + private static native void blur_0(long src_nativeObj, long dst_nativeObj, double ksize_width, double ksize_height, double anchor_x, double anchor_y, int borderType); + private static native void blur_1(long src_nativeObj, long dst_nativeObj, double ksize_width, double ksize_height, double anchor_x, double anchor_y); + private static native void blur_2(long src_nativeObj, long dst_nativeObj, double ksize_width, double ksize_height); + + // C++: void cv::boxFilter(Mat src, Mat& dst, int ddepth, Size ksize, Point anchor = Point(-1,-1), bool normalize = true, int borderType = BORDER_DEFAULT) + private static native void boxFilter_0(long src_nativeObj, long dst_nativeObj, int ddepth, double ksize_width, double ksize_height, double anchor_x, double anchor_y, boolean normalize, int borderType); + private static native void boxFilter_1(long src_nativeObj, long dst_nativeObj, int ddepth, double ksize_width, double ksize_height, double anchor_x, double anchor_y, boolean normalize); + private static native void boxFilter_2(long src_nativeObj, long dst_nativeObj, int ddepth, double ksize_width, double ksize_height, double anchor_x, double anchor_y); + private static native void boxFilter_3(long src_nativeObj, long dst_nativeObj, int ddepth, double ksize_width, double ksize_height); + + // C++: void cv::boxPoints(RotatedRect box, Mat& points) + private static native void boxPoints_0(double box_center_x, double box_center_y, double box_size_width, double box_size_height, double box_angle, long points_nativeObj); + + // C++: void cv::calcBackProject(vector_Mat images, vector_int channels, Mat hist, Mat& dst, vector_float ranges, double scale) + private static native void calcBackProject_0(long images_mat_nativeObj, long channels_mat_nativeObj, long hist_nativeObj, long dst_nativeObj, long ranges_mat_nativeObj, double scale); + + // C++: void cv::calcHist(vector_Mat images, vector_int channels, Mat mask, Mat& hist, vector_int histSize, vector_float ranges, bool accumulate = false) + private static native void calcHist_0(long images_mat_nativeObj, long channels_mat_nativeObj, long mask_nativeObj, long hist_nativeObj, long histSize_mat_nativeObj, long ranges_mat_nativeObj, boolean accumulate); + private static native void calcHist_1(long images_mat_nativeObj, long channels_mat_nativeObj, long mask_nativeObj, long hist_nativeObj, long histSize_mat_nativeObj, long ranges_mat_nativeObj); + + // C++: void cv::circle(Mat& img, Point center, int radius, Scalar color, int thickness = 1, int lineType = LINE_8, int shift = 0) + private static native void circle_0(long img_nativeObj, double center_x, double center_y, int radius, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int lineType, int shift); + private static native void circle_1(long img_nativeObj, double center_x, double center_y, int radius, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int lineType); + private static native void circle_2(long img_nativeObj, double center_x, double center_y, int radius, double color_val0, double color_val1, double color_val2, double color_val3, int thickness); + private static native void circle_3(long img_nativeObj, double center_x, double center_y, int radius, double color_val0, double color_val1, double color_val2, double color_val3); + + // C++: void cv::convertMaps(Mat map1, Mat map2, Mat& dstmap1, Mat& dstmap2, int dstmap1type, bool nninterpolation = false) + private static native void convertMaps_0(long map1_nativeObj, long map2_nativeObj, long dstmap1_nativeObj, long dstmap2_nativeObj, int dstmap1type, boolean nninterpolation); + private static native void convertMaps_1(long map1_nativeObj, long map2_nativeObj, long dstmap1_nativeObj, long dstmap2_nativeObj, int dstmap1type); + + // C++: void cv::convexHull(vector_Point points, vector_int& hull, bool clockwise = false, _hidden_ returnPoints = true) + private static native void convexHull_0(long points_mat_nativeObj, long hull_mat_nativeObj, boolean clockwise); + private static native void convexHull_2(long points_mat_nativeObj, long hull_mat_nativeObj); + + // C++: void cv::convexityDefects(vector_Point contour, vector_int convexhull, vector_Vec4i& convexityDefects) + private static native void convexityDefects_0(long contour_mat_nativeObj, long convexhull_mat_nativeObj, long convexityDefects_mat_nativeObj); + + // C++: void cv::cornerEigenValsAndVecs(Mat src, Mat& dst, int blockSize, int ksize, int borderType = BORDER_DEFAULT) + private static native void cornerEigenValsAndVecs_0(long src_nativeObj, long dst_nativeObj, int blockSize, int ksize, int borderType); + private static native void cornerEigenValsAndVecs_1(long src_nativeObj, long dst_nativeObj, int blockSize, int ksize); + + // C++: void cv::cornerHarris(Mat src, Mat& dst, int blockSize, int ksize, double k, int borderType = BORDER_DEFAULT) + private static native void cornerHarris_0(long src_nativeObj, long dst_nativeObj, int blockSize, int ksize, double k, int borderType); + private static native void cornerHarris_1(long src_nativeObj, long dst_nativeObj, int blockSize, int ksize, double k); + + // C++: void cv::cornerMinEigenVal(Mat src, Mat& dst, int blockSize, int ksize = 3, int borderType = BORDER_DEFAULT) + private static native void cornerMinEigenVal_0(long src_nativeObj, long dst_nativeObj, int blockSize, int ksize, int borderType); + private static native void cornerMinEigenVal_1(long src_nativeObj, long dst_nativeObj, int blockSize, int ksize); + private static native void cornerMinEigenVal_2(long src_nativeObj, long dst_nativeObj, int blockSize); + + // C++: void cv::cornerSubPix(Mat image, Mat& corners, Size winSize, Size zeroZone, TermCriteria criteria) + private static native void cornerSubPix_0(long image_nativeObj, long corners_nativeObj, double winSize_width, double winSize_height, double zeroZone_width, double zeroZone_height, int criteria_type, int criteria_maxCount, double criteria_epsilon); + + // C++: void cv::createHanningWindow(Mat& dst, Size winSize, int type) + private static native void createHanningWindow_0(long dst_nativeObj, double winSize_width, double winSize_height, int type); + + // C++: void cv::cvtColor(Mat src, Mat& dst, int code, int dstCn = 0) + private static native void cvtColor_0(long src_nativeObj, long dst_nativeObj, int code, int dstCn); + private static native void cvtColor_1(long src_nativeObj, long dst_nativeObj, int code); + + // C++: void cv::cvtColorTwoPlane(Mat src1, Mat src2, Mat& dst, int code) + private static native void cvtColorTwoPlane_0(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj, int code); + + // C++: void cv::demosaicing(Mat src, Mat& dst, int code, int dstCn = 0) + private static native void demosaicing_0(long src_nativeObj, long dst_nativeObj, int code, int dstCn); + private static native void demosaicing_1(long src_nativeObj, long dst_nativeObj, int code); + + // C++: void cv::dilate(Mat src, Mat& dst, Mat kernel, Point anchor = Point(-1,-1), int iterations = 1, int borderType = BORDER_CONSTANT, Scalar borderValue = morphologyDefaultBorderValue()) + private static native void dilate_0(long src_nativeObj, long dst_nativeObj, long kernel_nativeObj, double anchor_x, double anchor_y, int iterations, int borderType, double borderValue_val0, double borderValue_val1, double borderValue_val2, double borderValue_val3); + private static native void dilate_1(long src_nativeObj, long dst_nativeObj, long kernel_nativeObj, double anchor_x, double anchor_y, int iterations, int borderType); + private static native void dilate_2(long src_nativeObj, long dst_nativeObj, long kernel_nativeObj, double anchor_x, double anchor_y, int iterations); + private static native void dilate_3(long src_nativeObj, long dst_nativeObj, long kernel_nativeObj, double anchor_x, double anchor_y); + private static native void dilate_4(long src_nativeObj, long dst_nativeObj, long kernel_nativeObj); + + // C++: void cv::distanceTransform(Mat src, Mat& dst, Mat& labels, int distanceType, int maskSize, int labelType = DIST_LABEL_CCOMP) + private static native void distanceTransformWithLabels_0(long src_nativeObj, long dst_nativeObj, long labels_nativeObj, int distanceType, int maskSize, int labelType); + private static native void distanceTransformWithLabels_1(long src_nativeObj, long dst_nativeObj, long labels_nativeObj, int distanceType, int maskSize); + + // C++: void cv::distanceTransform(Mat src, Mat& dst, int distanceType, int maskSize, int dstType = CV_32F) + private static native void distanceTransform_0(long src_nativeObj, long dst_nativeObj, int distanceType, int maskSize, int dstType); + private static native void distanceTransform_1(long src_nativeObj, long dst_nativeObj, int distanceType, int maskSize); + + // C++: void cv::drawContours(Mat& image, vector_vector_Point contours, int contourIdx, Scalar color, int thickness = 1, int lineType = LINE_8, Mat hierarchy = Mat(), int maxLevel = INT_MAX, Point offset = Point()) + private static native void drawContours_0(long image_nativeObj, long contours_mat_nativeObj, int contourIdx, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int lineType, long hierarchy_nativeObj, int maxLevel, double offset_x, double offset_y); + private static native void drawContours_1(long image_nativeObj, long contours_mat_nativeObj, int contourIdx, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int lineType, long hierarchy_nativeObj, int maxLevel); + private static native void drawContours_2(long image_nativeObj, long contours_mat_nativeObj, int contourIdx, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int lineType, long hierarchy_nativeObj); + private static native void drawContours_3(long image_nativeObj, long contours_mat_nativeObj, int contourIdx, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int lineType); + private static native void drawContours_4(long image_nativeObj, long contours_mat_nativeObj, int contourIdx, double color_val0, double color_val1, double color_val2, double color_val3, int thickness); + private static native void drawContours_5(long image_nativeObj, long contours_mat_nativeObj, int contourIdx, double color_val0, double color_val1, double color_val2, double color_val3); + + // C++: void cv::drawMarker(Mat& img, Point position, Scalar color, int markerType = MARKER_CROSS, int markerSize = 20, int thickness = 1, int line_type = 8) + private static native void drawMarker_0(long img_nativeObj, double position_x, double position_y, double color_val0, double color_val1, double color_val2, double color_val3, int markerType, int markerSize, int thickness, int line_type); + private static native void drawMarker_1(long img_nativeObj, double position_x, double position_y, double color_val0, double color_val1, double color_val2, double color_val3, int markerType, int markerSize, int thickness); + private static native void drawMarker_2(long img_nativeObj, double position_x, double position_y, double color_val0, double color_val1, double color_val2, double color_val3, int markerType, int markerSize); + private static native void drawMarker_3(long img_nativeObj, double position_x, double position_y, double color_val0, double color_val1, double color_val2, double color_val3, int markerType); + private static native void drawMarker_4(long img_nativeObj, double position_x, double position_y, double color_val0, double color_val1, double color_val2, double color_val3); + + // C++: void cv::ellipse(Mat& img, Point center, Size axes, double angle, double startAngle, double endAngle, Scalar color, int thickness = 1, int lineType = LINE_8, int shift = 0) + private static native void ellipse_0(long img_nativeObj, double center_x, double center_y, double axes_width, double axes_height, double angle, double startAngle, double endAngle, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int lineType, int shift); + private static native void ellipse_1(long img_nativeObj, double center_x, double center_y, double axes_width, double axes_height, double angle, double startAngle, double endAngle, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int lineType); + private static native void ellipse_2(long img_nativeObj, double center_x, double center_y, double axes_width, double axes_height, double angle, double startAngle, double endAngle, double color_val0, double color_val1, double color_val2, double color_val3, int thickness); + private static native void ellipse_3(long img_nativeObj, double center_x, double center_y, double axes_width, double axes_height, double angle, double startAngle, double endAngle, double color_val0, double color_val1, double color_val2, double color_val3); + + // C++: void cv::ellipse(Mat& img, RotatedRect box, Scalar color, int thickness = 1, int lineType = LINE_8) + private static native void ellipse_4(long img_nativeObj, double box_center_x, double box_center_y, double box_size_width, double box_size_height, double box_angle, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int lineType); + private static native void ellipse_5(long img_nativeObj, double box_center_x, double box_center_y, double box_size_width, double box_size_height, double box_angle, double color_val0, double color_val1, double color_val2, double color_val3, int thickness); + private static native void ellipse_6(long img_nativeObj, double box_center_x, double box_center_y, double box_size_width, double box_size_height, double box_angle, double color_val0, double color_val1, double color_val2, double color_val3); + + // C++: void cv::ellipse2Poly(Point center, Size axes, int angle, int arcStart, int arcEnd, int delta, vector_Point& pts) + private static native void ellipse2Poly_0(double center_x, double center_y, double axes_width, double axes_height, int angle, int arcStart, int arcEnd, int delta, long pts_mat_nativeObj); + + // C++: void cv::equalizeHist(Mat src, Mat& dst) + private static native void equalizeHist_0(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::erode(Mat src, Mat& dst, Mat kernel, Point anchor = Point(-1,-1), int iterations = 1, int borderType = BORDER_CONSTANT, Scalar borderValue = morphologyDefaultBorderValue()) + private static native void erode_0(long src_nativeObj, long dst_nativeObj, long kernel_nativeObj, double anchor_x, double anchor_y, int iterations, int borderType, double borderValue_val0, double borderValue_val1, double borderValue_val2, double borderValue_val3); + private static native void erode_1(long src_nativeObj, long dst_nativeObj, long kernel_nativeObj, double anchor_x, double anchor_y, int iterations, int borderType); + private static native void erode_2(long src_nativeObj, long dst_nativeObj, long kernel_nativeObj, double anchor_x, double anchor_y, int iterations); + private static native void erode_3(long src_nativeObj, long dst_nativeObj, long kernel_nativeObj, double anchor_x, double anchor_y); + private static native void erode_4(long src_nativeObj, long dst_nativeObj, long kernel_nativeObj); + + // C++: void cv::fillConvexPoly(Mat& img, vector_Point points, Scalar color, int lineType = LINE_8, int shift = 0) + private static native void fillConvexPoly_0(long img_nativeObj, long points_mat_nativeObj, double color_val0, double color_val1, double color_val2, double color_val3, int lineType, int shift); + private static native void fillConvexPoly_1(long img_nativeObj, long points_mat_nativeObj, double color_val0, double color_val1, double color_val2, double color_val3, int lineType); + private static native void fillConvexPoly_2(long img_nativeObj, long points_mat_nativeObj, double color_val0, double color_val1, double color_val2, double color_val3); + + // C++: void cv::fillPoly(Mat& img, vector_vector_Point pts, Scalar color, int lineType = LINE_8, int shift = 0, Point offset = Point()) + private static native void fillPoly_0(long img_nativeObj, long pts_mat_nativeObj, double color_val0, double color_val1, double color_val2, double color_val3, int lineType, int shift, double offset_x, double offset_y); + private static native void fillPoly_1(long img_nativeObj, long pts_mat_nativeObj, double color_val0, double color_val1, double color_val2, double color_val3, int lineType, int shift); + private static native void fillPoly_2(long img_nativeObj, long pts_mat_nativeObj, double color_val0, double color_val1, double color_val2, double color_val3, int lineType); + private static native void fillPoly_3(long img_nativeObj, long pts_mat_nativeObj, double color_val0, double color_val1, double color_val2, double color_val3); + + // C++: void cv::filter2D(Mat src, Mat& dst, int ddepth, Mat kernel, Point anchor = Point(-1,-1), double delta = 0, int borderType = BORDER_DEFAULT) + private static native void filter2D_0(long src_nativeObj, long dst_nativeObj, int ddepth, long kernel_nativeObj, double anchor_x, double anchor_y, double delta, int borderType); + private static native void filter2D_1(long src_nativeObj, long dst_nativeObj, int ddepth, long kernel_nativeObj, double anchor_x, double anchor_y, double delta); + private static native void filter2D_2(long src_nativeObj, long dst_nativeObj, int ddepth, long kernel_nativeObj, double anchor_x, double anchor_y); + private static native void filter2D_3(long src_nativeObj, long dst_nativeObj, int ddepth, long kernel_nativeObj); + + // C++: void cv::findContours(Mat image, vector_vector_Point& contours, Mat& hierarchy, int mode, int method, Point offset = Point()) + private static native void findContours_0(long image_nativeObj, long contours_mat_nativeObj, long hierarchy_nativeObj, int mode, int method, double offset_x, double offset_y); + private static native void findContours_1(long image_nativeObj, long contours_mat_nativeObj, long hierarchy_nativeObj, int mode, int method); + + // C++: void cv::fitLine(Mat points, Mat& line, int distType, double param, double reps, double aeps) + private static native void fitLine_0(long points_nativeObj, long line_nativeObj, int distType, double param, double reps, double aeps); + + // C++: void cv::getDerivKernels(Mat& kx, Mat& ky, int dx, int dy, int ksize, bool normalize = false, int ktype = CV_32F) + private static native void getDerivKernels_0(long kx_nativeObj, long ky_nativeObj, int dx, int dy, int ksize, boolean normalize, int ktype); + private static native void getDerivKernels_1(long kx_nativeObj, long ky_nativeObj, int dx, int dy, int ksize, boolean normalize); + private static native void getDerivKernels_2(long kx_nativeObj, long ky_nativeObj, int dx, int dy, int ksize); + + // C++: void cv::getRectSubPix(Mat image, Size patchSize, Point2f center, Mat& patch, int patchType = -1) + private static native void getRectSubPix_0(long image_nativeObj, double patchSize_width, double patchSize_height, double center_x, double center_y, long patch_nativeObj, int patchType); + private static native void getRectSubPix_1(long image_nativeObj, double patchSize_width, double patchSize_height, double center_x, double center_y, long patch_nativeObj); + + // C++: void cv::goodFeaturesToTrack(Mat image, vector_Point& corners, int maxCorners, double qualityLevel, double minDistance, Mat mask, int blockSize, int gradientSize, bool useHarrisDetector = false, double k = 0.04) + private static native void goodFeaturesToTrack_0(long image_nativeObj, long corners_mat_nativeObj, int maxCorners, double qualityLevel, double minDistance, long mask_nativeObj, int blockSize, int gradientSize, boolean useHarrisDetector, double k); + private static native void goodFeaturesToTrack_1(long image_nativeObj, long corners_mat_nativeObj, int maxCorners, double qualityLevel, double minDistance, long mask_nativeObj, int blockSize, int gradientSize, boolean useHarrisDetector); + private static native void goodFeaturesToTrack_2(long image_nativeObj, long corners_mat_nativeObj, int maxCorners, double qualityLevel, double minDistance, long mask_nativeObj, int blockSize, int gradientSize); + + // C++: void cv::goodFeaturesToTrack(Mat image, vector_Point& corners, int maxCorners, double qualityLevel, double minDistance, Mat mask = Mat(), int blockSize = 3, bool useHarrisDetector = false, double k = 0.04) + private static native void goodFeaturesToTrack_3(long image_nativeObj, long corners_mat_nativeObj, int maxCorners, double qualityLevel, double minDistance, long mask_nativeObj, int blockSize, boolean useHarrisDetector, double k); + private static native void goodFeaturesToTrack_4(long image_nativeObj, long corners_mat_nativeObj, int maxCorners, double qualityLevel, double minDistance, long mask_nativeObj, int blockSize, boolean useHarrisDetector); + private static native void goodFeaturesToTrack_5(long image_nativeObj, long corners_mat_nativeObj, int maxCorners, double qualityLevel, double minDistance, long mask_nativeObj, int blockSize); + private static native void goodFeaturesToTrack_6(long image_nativeObj, long corners_mat_nativeObj, int maxCorners, double qualityLevel, double minDistance, long mask_nativeObj); + private static native void goodFeaturesToTrack_7(long image_nativeObj, long corners_mat_nativeObj, int maxCorners, double qualityLevel, double minDistance); + + // C++: void cv::grabCut(Mat img, Mat& mask, Rect rect, Mat& bgdModel, Mat& fgdModel, int iterCount, int mode = GC_EVAL) + private static native void grabCut_0(long img_nativeObj, long mask_nativeObj, int rect_x, int rect_y, int rect_width, int rect_height, long bgdModel_nativeObj, long fgdModel_nativeObj, int iterCount, int mode); + private static native void grabCut_1(long img_nativeObj, long mask_nativeObj, int rect_x, int rect_y, int rect_width, int rect_height, long bgdModel_nativeObj, long fgdModel_nativeObj, int iterCount); + + // C++: void cv::integral(Mat src, Mat& sum, Mat& sqsum, Mat& tilted, int sdepth = -1, int sqdepth = -1) + private static native void integral3_0(long src_nativeObj, long sum_nativeObj, long sqsum_nativeObj, long tilted_nativeObj, int sdepth, int sqdepth); + private static native void integral3_1(long src_nativeObj, long sum_nativeObj, long sqsum_nativeObj, long tilted_nativeObj, int sdepth); + private static native void integral3_2(long src_nativeObj, long sum_nativeObj, long sqsum_nativeObj, long tilted_nativeObj); + + // C++: void cv::integral(Mat src, Mat& sum, Mat& sqsum, int sdepth = -1, int sqdepth = -1) + private static native void integral2_0(long src_nativeObj, long sum_nativeObj, long sqsum_nativeObj, int sdepth, int sqdepth); + private static native void integral2_1(long src_nativeObj, long sum_nativeObj, long sqsum_nativeObj, int sdepth); + private static native void integral2_2(long src_nativeObj, long sum_nativeObj, long sqsum_nativeObj); + + // C++: void cv::integral(Mat src, Mat& sum, int sdepth = -1) + private static native void integral_0(long src_nativeObj, long sum_nativeObj, int sdepth); + private static native void integral_1(long src_nativeObj, long sum_nativeObj); + + // C++: void cv::invertAffineTransform(Mat M, Mat& iM) + private static native void invertAffineTransform_0(long M_nativeObj, long iM_nativeObj); + + // C++: void cv::line(Mat& img, Point pt1, Point pt2, Scalar color, int thickness = 1, int lineType = LINE_8, int shift = 0) + private static native void line_0(long img_nativeObj, double pt1_x, double pt1_y, double pt2_x, double pt2_y, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int lineType, int shift); + private static native void line_1(long img_nativeObj, double pt1_x, double pt1_y, double pt2_x, double pt2_y, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int lineType); + private static native void line_2(long img_nativeObj, double pt1_x, double pt1_y, double pt2_x, double pt2_y, double color_val0, double color_val1, double color_val2, double color_val3, int thickness); + private static native void line_3(long img_nativeObj, double pt1_x, double pt1_y, double pt2_x, double pt2_y, double color_val0, double color_val1, double color_val2, double color_val3); + + // C++: void cv::linearPolar(Mat src, Mat& dst, Point2f center, double maxRadius, int flags) + private static native void linearPolar_0(long src_nativeObj, long dst_nativeObj, double center_x, double center_y, double maxRadius, int flags); + + // C++: void cv::logPolar(Mat src, Mat& dst, Point2f center, double M, int flags) + private static native void logPolar_0(long src_nativeObj, long dst_nativeObj, double center_x, double center_y, double M, int flags); + + // C++: void cv::matchTemplate(Mat image, Mat templ, Mat& result, int method, Mat mask = Mat()) + private static native void matchTemplate_0(long image_nativeObj, long templ_nativeObj, long result_nativeObj, int method, long mask_nativeObj); + private static native void matchTemplate_1(long image_nativeObj, long templ_nativeObj, long result_nativeObj, int method); + + // C++: void cv::medianBlur(Mat src, Mat& dst, int ksize) + private static native void medianBlur_0(long src_nativeObj, long dst_nativeObj, int ksize); + + // C++: void cv::minEnclosingCircle(vector_Point2f points, Point2f& center, float& radius) + private static native void minEnclosingCircle_0(long points_mat_nativeObj, double[] center_out, double[] radius_out); + + // C++: void cv::morphologyEx(Mat src, Mat& dst, int op, Mat kernel, Point anchor = Point(-1,-1), int iterations = 1, int borderType = BORDER_CONSTANT, Scalar borderValue = morphologyDefaultBorderValue()) + private static native void morphologyEx_0(long src_nativeObj, long dst_nativeObj, int op, long kernel_nativeObj, double anchor_x, double anchor_y, int iterations, int borderType, double borderValue_val0, double borderValue_val1, double borderValue_val2, double borderValue_val3); + private static native void morphologyEx_1(long src_nativeObj, long dst_nativeObj, int op, long kernel_nativeObj, double anchor_x, double anchor_y, int iterations, int borderType); + private static native void morphologyEx_2(long src_nativeObj, long dst_nativeObj, int op, long kernel_nativeObj, double anchor_x, double anchor_y, int iterations); + private static native void morphologyEx_3(long src_nativeObj, long dst_nativeObj, int op, long kernel_nativeObj, double anchor_x, double anchor_y); + private static native void morphologyEx_4(long src_nativeObj, long dst_nativeObj, int op, long kernel_nativeObj); + + // C++: void cv::polylines(Mat& img, vector_vector_Point pts, bool isClosed, Scalar color, int thickness = 1, int lineType = LINE_8, int shift = 0) + private static native void polylines_0(long img_nativeObj, long pts_mat_nativeObj, boolean isClosed, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int lineType, int shift); + private static native void polylines_1(long img_nativeObj, long pts_mat_nativeObj, boolean isClosed, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int lineType); + private static native void polylines_2(long img_nativeObj, long pts_mat_nativeObj, boolean isClosed, double color_val0, double color_val1, double color_val2, double color_val3, int thickness); + private static native void polylines_3(long img_nativeObj, long pts_mat_nativeObj, boolean isClosed, double color_val0, double color_val1, double color_val2, double color_val3); + + // C++: void cv::preCornerDetect(Mat src, Mat& dst, int ksize, int borderType = BORDER_DEFAULT) + private static native void preCornerDetect_0(long src_nativeObj, long dst_nativeObj, int ksize, int borderType); + private static native void preCornerDetect_1(long src_nativeObj, long dst_nativeObj, int ksize); + + // C++: void cv::putText(Mat& img, String text, Point org, int fontFace, double fontScale, Scalar color, int thickness = 1, int lineType = LINE_8, bool bottomLeftOrigin = false) + private static native void putText_0(long img_nativeObj, String text, double org_x, double org_y, int fontFace, double fontScale, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int lineType, boolean bottomLeftOrigin); + private static native void putText_1(long img_nativeObj, String text, double org_x, double org_y, int fontFace, double fontScale, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int lineType); + private static native void putText_2(long img_nativeObj, String text, double org_x, double org_y, int fontFace, double fontScale, double color_val0, double color_val1, double color_val2, double color_val3, int thickness); + private static native void putText_3(long img_nativeObj, String text, double org_x, double org_y, int fontFace, double fontScale, double color_val0, double color_val1, double color_val2, double color_val3); + + // C++: void cv::pyrDown(Mat src, Mat& dst, Size dstsize = Size(), int borderType = BORDER_DEFAULT) + private static native void pyrDown_0(long src_nativeObj, long dst_nativeObj, double dstsize_width, double dstsize_height, int borderType); + private static native void pyrDown_1(long src_nativeObj, long dst_nativeObj, double dstsize_width, double dstsize_height); + private static native void pyrDown_2(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::pyrMeanShiftFiltering(Mat src, Mat& dst, double sp, double sr, int maxLevel = 1, TermCriteria termcrit = TermCriteria(TermCriteria::MAX_ITER+TermCriteria::EPS,5,1)) + private static native void pyrMeanShiftFiltering_0(long src_nativeObj, long dst_nativeObj, double sp, double sr, int maxLevel, int termcrit_type, int termcrit_maxCount, double termcrit_epsilon); + private static native void pyrMeanShiftFiltering_1(long src_nativeObj, long dst_nativeObj, double sp, double sr, int maxLevel); + private static native void pyrMeanShiftFiltering_2(long src_nativeObj, long dst_nativeObj, double sp, double sr); + + // C++: void cv::pyrUp(Mat src, Mat& dst, Size dstsize = Size(), int borderType = BORDER_DEFAULT) + private static native void pyrUp_0(long src_nativeObj, long dst_nativeObj, double dstsize_width, double dstsize_height, int borderType); + private static native void pyrUp_1(long src_nativeObj, long dst_nativeObj, double dstsize_width, double dstsize_height); + private static native void pyrUp_2(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::rectangle(Mat& img, Point pt1, Point pt2, Scalar color, int thickness = 1, int lineType = LINE_8, int shift = 0) + private static native void rectangle_0(long img_nativeObj, double pt1_x, double pt1_y, double pt2_x, double pt2_y, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int lineType, int shift); + private static native void rectangle_1(long img_nativeObj, double pt1_x, double pt1_y, double pt2_x, double pt2_y, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int lineType); + private static native void rectangle_2(long img_nativeObj, double pt1_x, double pt1_y, double pt2_x, double pt2_y, double color_val0, double color_val1, double color_val2, double color_val3, int thickness); + private static native void rectangle_3(long img_nativeObj, double pt1_x, double pt1_y, double pt2_x, double pt2_y, double color_val0, double color_val1, double color_val2, double color_val3); + + // C++: void cv::rectangle(Mat& img, Rect rec, Scalar color, int thickness = 1, int lineType = LINE_8, int shift = 0) + private static native void rectangle_4(long img_nativeObj, int rec_x, int rec_y, int rec_width, int rec_height, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int lineType, int shift); + private static native void rectangle_5(long img_nativeObj, int rec_x, int rec_y, int rec_width, int rec_height, double color_val0, double color_val1, double color_val2, double color_val3, int thickness, int lineType); + private static native void rectangle_6(long img_nativeObj, int rec_x, int rec_y, int rec_width, int rec_height, double color_val0, double color_val1, double color_val2, double color_val3, int thickness); + private static native void rectangle_7(long img_nativeObj, int rec_x, int rec_y, int rec_width, int rec_height, double color_val0, double color_val1, double color_val2, double color_val3); + + // C++: void cv::remap(Mat src, Mat& dst, Mat map1, Mat map2, int interpolation, int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar()) + private static native void remap_0(long src_nativeObj, long dst_nativeObj, long map1_nativeObj, long map2_nativeObj, int interpolation, int borderMode, double borderValue_val0, double borderValue_val1, double borderValue_val2, double borderValue_val3); + private static native void remap_1(long src_nativeObj, long dst_nativeObj, long map1_nativeObj, long map2_nativeObj, int interpolation, int borderMode); + private static native void remap_2(long src_nativeObj, long dst_nativeObj, long map1_nativeObj, long map2_nativeObj, int interpolation); + + // C++: void cv::resize(Mat src, Mat& dst, Size dsize, double fx = 0, double fy = 0, int interpolation = INTER_LINEAR) + private static native void resize_0(long src_nativeObj, long dst_nativeObj, double dsize_width, double dsize_height, double fx, double fy, int interpolation); + private static native void resize_1(long src_nativeObj, long dst_nativeObj, double dsize_width, double dsize_height, double fx, double fy); + private static native void resize_2(long src_nativeObj, long dst_nativeObj, double dsize_width, double dsize_height, double fx); + private static native void resize_3(long src_nativeObj, long dst_nativeObj, double dsize_width, double dsize_height); + + // C++: void cv::sepFilter2D(Mat src, Mat& dst, int ddepth, Mat kernelX, Mat kernelY, Point anchor = Point(-1,-1), double delta = 0, int borderType = BORDER_DEFAULT) + private static native void sepFilter2D_0(long src_nativeObj, long dst_nativeObj, int ddepth, long kernelX_nativeObj, long kernelY_nativeObj, double anchor_x, double anchor_y, double delta, int borderType); + private static native void sepFilter2D_1(long src_nativeObj, long dst_nativeObj, int ddepth, long kernelX_nativeObj, long kernelY_nativeObj, double anchor_x, double anchor_y, double delta); + private static native void sepFilter2D_2(long src_nativeObj, long dst_nativeObj, int ddepth, long kernelX_nativeObj, long kernelY_nativeObj, double anchor_x, double anchor_y); + private static native void sepFilter2D_3(long src_nativeObj, long dst_nativeObj, int ddepth, long kernelX_nativeObj, long kernelY_nativeObj); + + // C++: void cv::spatialGradient(Mat src, Mat& dx, Mat& dy, int ksize = 3, int borderType = BORDER_DEFAULT) + private static native void spatialGradient_0(long src_nativeObj, long dx_nativeObj, long dy_nativeObj, int ksize, int borderType); + private static native void spatialGradient_1(long src_nativeObj, long dx_nativeObj, long dy_nativeObj, int ksize); + private static native void spatialGradient_2(long src_nativeObj, long dx_nativeObj, long dy_nativeObj); + + // C++: void cv::sqrBoxFilter(Mat src, Mat& dst, int ddepth, Size ksize, Point anchor = Point(-1, -1), bool normalize = true, int borderType = BORDER_DEFAULT) + private static native void sqrBoxFilter_0(long src_nativeObj, long dst_nativeObj, int ddepth, double ksize_width, double ksize_height, double anchor_x, double anchor_y, boolean normalize, int borderType); + private static native void sqrBoxFilter_1(long src_nativeObj, long dst_nativeObj, int ddepth, double ksize_width, double ksize_height, double anchor_x, double anchor_y, boolean normalize); + private static native void sqrBoxFilter_2(long src_nativeObj, long dst_nativeObj, int ddepth, double ksize_width, double ksize_height, double anchor_x, double anchor_y); + private static native void sqrBoxFilter_3(long src_nativeObj, long dst_nativeObj, int ddepth, double ksize_width, double ksize_height); + + // C++: void cv::warpAffine(Mat src, Mat& dst, Mat M, Size dsize, int flags = INTER_LINEAR, int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar()) + private static native void warpAffine_0(long src_nativeObj, long dst_nativeObj, long M_nativeObj, double dsize_width, double dsize_height, int flags, int borderMode, double borderValue_val0, double borderValue_val1, double borderValue_val2, double borderValue_val3); + private static native void warpAffine_1(long src_nativeObj, long dst_nativeObj, long M_nativeObj, double dsize_width, double dsize_height, int flags, int borderMode); + private static native void warpAffine_2(long src_nativeObj, long dst_nativeObj, long M_nativeObj, double dsize_width, double dsize_height, int flags); + private static native void warpAffine_3(long src_nativeObj, long dst_nativeObj, long M_nativeObj, double dsize_width, double dsize_height); + + // C++: void cv::warpPerspective(Mat src, Mat& dst, Mat M, Size dsize, int flags = INTER_LINEAR, int borderMode = BORDER_CONSTANT, Scalar borderValue = Scalar()) + private static native void warpPerspective_0(long src_nativeObj, long dst_nativeObj, long M_nativeObj, double dsize_width, double dsize_height, int flags, int borderMode, double borderValue_val0, double borderValue_val1, double borderValue_val2, double borderValue_val3); + private static native void warpPerspective_1(long src_nativeObj, long dst_nativeObj, long M_nativeObj, double dsize_width, double dsize_height, int flags, int borderMode); + private static native void warpPerspective_2(long src_nativeObj, long dst_nativeObj, long M_nativeObj, double dsize_width, double dsize_height, int flags); + private static native void warpPerspective_3(long src_nativeObj, long dst_nativeObj, long M_nativeObj, double dsize_width, double dsize_height); + + // C++: void cv::warpPolar(Mat src, Mat& dst, Size dsize, Point2f center, double maxRadius, int flags) + private static native void warpPolar_0(long src_nativeObj, long dst_nativeObj, double dsize_width, double dsize_height, double center_x, double center_y, double maxRadius, int flags); + + // C++: void cv::watershed(Mat image, Mat& markers) + private static native void watershed_0(long image_nativeObj, long markers_nativeObj); +private static native double[] n_getTextSize(String text, int fontFace, double fontScale, int thickness, int[] baseLine); + +} diff --git a/OpenCV/src/main/java/org/opencv/imgproc/LineSegmentDetector.java b/OpenCV/src/main/java/org/opencv/imgproc/LineSegmentDetector.java new file mode 100644 index 00000000..b7bd36ff --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/imgproc/LineSegmentDetector.java @@ -0,0 +1,121 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.imgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.core.Size; + +// C++: class LineSegmentDetector +//javadoc: LineSegmentDetector + +public class LineSegmentDetector extends Algorithm { + + protected LineSegmentDetector(long addr) { super(addr); } + + // internal usage only + public static LineSegmentDetector __fromPtr__(long addr) { return new LineSegmentDetector(addr); } + + // + // C++: int cv::LineSegmentDetector::compareSegments(Size size, Mat lines1, Mat lines2, Mat& _image = Mat()) + // + + //javadoc: LineSegmentDetector::compareSegments(size, lines1, lines2, _image) + public int compareSegments(Size size, Mat lines1, Mat lines2, Mat _image) + { + + int retVal = compareSegments_0(nativeObj, size.width, size.height, lines1.nativeObj, lines2.nativeObj, _image.nativeObj); + + return retVal; + } + + //javadoc: LineSegmentDetector::compareSegments(size, lines1, lines2) + public int compareSegments(Size size, Mat lines1, Mat lines2) + { + + int retVal = compareSegments_1(nativeObj, size.width, size.height, lines1.nativeObj, lines2.nativeObj); + + return retVal; + } + + + // + // C++: void cv::LineSegmentDetector::detect(Mat _image, Mat& _lines, Mat& width = Mat(), Mat& prec = Mat(), Mat& nfa = Mat()) + // + + //javadoc: LineSegmentDetector::detect(_image, _lines, width, prec, nfa) + public void detect(Mat _image, Mat _lines, Mat width, Mat prec, Mat nfa) + { + + detect_0(nativeObj, _image.nativeObj, _lines.nativeObj, width.nativeObj, prec.nativeObj, nfa.nativeObj); + + return; + } + + //javadoc: LineSegmentDetector::detect(_image, _lines, width, prec) + public void detect(Mat _image, Mat _lines, Mat width, Mat prec) + { + + detect_1(nativeObj, _image.nativeObj, _lines.nativeObj, width.nativeObj, prec.nativeObj); + + return; + } + + //javadoc: LineSegmentDetector::detect(_image, _lines, width) + public void detect(Mat _image, Mat _lines, Mat width) + { + + detect_2(nativeObj, _image.nativeObj, _lines.nativeObj, width.nativeObj); + + return; + } + + //javadoc: LineSegmentDetector::detect(_image, _lines) + public void detect(Mat _image, Mat _lines) + { + + detect_3(nativeObj, _image.nativeObj, _lines.nativeObj); + + return; + } + + + // + // C++: void cv::LineSegmentDetector::drawSegments(Mat& _image, Mat lines) + // + + //javadoc: LineSegmentDetector::drawSegments(_image, lines) + public void drawSegments(Mat _image, Mat lines) + { + + drawSegments_0(nativeObj, _image.nativeObj, lines.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: int cv::LineSegmentDetector::compareSegments(Size size, Mat lines1, Mat lines2, Mat& _image = Mat()) + private static native int compareSegments_0(long nativeObj, double size_width, double size_height, long lines1_nativeObj, long lines2_nativeObj, long _image_nativeObj); + private static native int compareSegments_1(long nativeObj, double size_width, double size_height, long lines1_nativeObj, long lines2_nativeObj); + + // C++: void cv::LineSegmentDetector::detect(Mat _image, Mat& _lines, Mat& width = Mat(), Mat& prec = Mat(), Mat& nfa = Mat()) + private static native void detect_0(long nativeObj, long _image_nativeObj, long _lines_nativeObj, long width_nativeObj, long prec_nativeObj, long nfa_nativeObj); + private static native void detect_1(long nativeObj, long _image_nativeObj, long _lines_nativeObj, long width_nativeObj, long prec_nativeObj); + private static native void detect_2(long nativeObj, long _image_nativeObj, long _lines_nativeObj, long width_nativeObj); + private static native void detect_3(long nativeObj, long _image_nativeObj, long _lines_nativeObj); + + // C++: void cv::LineSegmentDetector::drawSegments(Mat& _image, Mat lines) + private static native void drawSegments_0(long nativeObj, long _image_nativeObj, long lines_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/imgproc/Moments.java b/OpenCV/src/main/java/org/opencv/imgproc/Moments.java new file mode 100644 index 00000000..5c3d94c7 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/imgproc/Moments.java @@ -0,0 +1,242 @@ +package org.opencv.imgproc; + +//javadoc:Moments +public class Moments { + + public double m00; + public double m10; + public double m01; + public double m20; + public double m11; + public double m02; + public double m30; + public double m21; + public double m12; + public double m03; + + public double mu20; + public double mu11; + public double mu02; + public double mu30; + public double mu21; + public double mu12; + public double mu03; + + public double nu20; + public double nu11; + public double nu02; + public double nu30; + public double nu21; + public double nu12; + public double nu03; + + public Moments( + double m00, + double m10, + double m01, + double m20, + double m11, + double m02, + double m30, + double m21, + double m12, + double m03) + { + this.m00 = m00; + this.m10 = m10; + this.m01 = m01; + this.m20 = m20; + this.m11 = m11; + this.m02 = m02; + this.m30 = m30; + this.m21 = m21; + this.m12 = m12; + this.m03 = m03; + this.completeState(); + } + + public Moments() { + this(0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + } + + public Moments(double[] vals) { + set(vals); + } + + public void set(double[] vals) { + if (vals != null) { + m00 = vals.length > 0 ? vals[0] : 0; + m10 = vals.length > 1 ? vals[1] : 0; + m01 = vals.length > 2 ? vals[2] : 0; + m20 = vals.length > 3 ? vals[3] : 0; + m11 = vals.length > 4 ? vals[4] : 0; + m02 = vals.length > 5 ? vals[5] : 0; + m30 = vals.length > 6 ? vals[6] : 0; + m21 = vals.length > 7 ? vals[7] : 0; + m12 = vals.length > 8 ? vals[8] : 0; + m03 = vals.length > 9 ? vals[9] : 0; + this.completeState(); + } else { + m00 = 0; + m10 = 0; + m01 = 0; + m20 = 0; + m11 = 0; + m02 = 0; + m30 = 0; + m21 = 0; + m12 = 0; + m03 = 0; + mu20 = 0; + mu11 = 0; + mu02 = 0; + mu30 = 0; + mu21 = 0; + mu12 = 0; + mu03 = 0; + nu20 = 0; + nu11 = 0; + nu02 = 0; + nu30 = 0; + nu21 = 0; + nu12 = 0; + nu03 = 0; + } + } + + @Override + public String toString() { + return "Moments [ " + + "\n" + + "m00=" + m00 + ", " + + "\n" + + "m10=" + m10 + ", " + + "m01=" + m01 + ", " + + "\n" + + "m20=" + m20 + ", " + + "m11=" + m11 + ", " + + "m02=" + m02 + ", " + + "\n" + + "m30=" + m30 + ", " + + "m21=" + m21 + ", " + + "m12=" + m12 + ", " + + "m03=" + m03 + ", " + + "\n" + + "mu20=" + mu20 + ", " + + "mu11=" + mu11 + ", " + + "mu02=" + mu02 + ", " + + "\n" + + "mu30=" + mu30 + ", " + + "mu21=" + mu21 + ", " + + "mu12=" + mu12 + ", " + + "mu03=" + mu03 + ", " + + "\n" + + "nu20=" + nu20 + ", " + + "nu11=" + nu11 + ", " + + "nu02=" + nu02 + ", " + + "\n" + + "nu30=" + nu30 + ", " + + "nu21=" + nu21 + ", " + + "nu12=" + nu12 + ", " + + "nu03=" + nu03 + ", " + + "\n]"; + } + + protected void completeState() + { + double cx = 0, cy = 0; + double mu20, mu11, mu02; + double inv_m00 = 0.0; + + if( Math.abs(this.m00) > 0.00000001 ) + { + inv_m00 = 1. / this.m00; + cx = this.m10 * inv_m00; + cy = this.m01 * inv_m00; + } + + // mu20 = m20 - m10*cx + mu20 = this.m20 - this.m10 * cx; + // mu11 = m11 - m10*cy + mu11 = this.m11 - this.m10 * cy; + // mu02 = m02 - m01*cy + mu02 = this.m02 - this.m01 * cy; + + this.mu20 = mu20; + this.mu11 = mu11; + this.mu02 = mu02; + + // mu30 = m30 - cx*(3*mu20 + cx*m10) + this.mu30 = this.m30 - cx * (3 * mu20 + cx * this.m10); + mu11 += mu11; + // mu21 = m21 - cx*(2*mu11 + cx*m01) - cy*mu20 + this.mu21 = this.m21 - cx * (mu11 + cx * this.m01) - cy * mu20; + // mu12 = m12 - cy*(2*mu11 + cy*m10) - cx*mu02 + this.mu12 = this.m12 - cy * (mu11 + cy * this.m10) - cx * mu02; + // mu03 = m03 - cy*(3*mu02 + cy*m01) + this.mu03 = this.m03 - cy * (3 * mu02 + cy * this.m01); + + + double inv_sqrt_m00 = Math.sqrt(Math.abs(inv_m00)); + double s2 = inv_m00*inv_m00, s3 = s2*inv_sqrt_m00; + + this.nu20 = this.mu20*s2; + this.nu11 = this.mu11*s2; + this.nu02 = this.mu02*s2; + this.nu30 = this.mu30*s3; + this.nu21 = this.mu21*s3; + this.nu12 = this.mu12*s3; + this.nu03 = this.mu03*s3; + + } + + public double get_m00() { return this.m00; } + public double get_m10() { return this.m10; } + public double get_m01() { return this.m01; } + public double get_m20() { return this.m20; } + public double get_m11() { return this.m11; } + public double get_m02() { return this.m02; } + public double get_m30() { return this.m30; } + public double get_m21() { return this.m21; } + public double get_m12() { return this.m12; } + public double get_m03() { return this.m03; } + public double get_mu20() { return this.mu20; } + public double get_mu11() { return this.mu11; } + public double get_mu02() { return this.mu02; } + public double get_mu30() { return this.mu30; } + public double get_mu21() { return this.mu21; } + public double get_mu12() { return this.mu12; } + public double get_mu03() { return this.mu03; } + public double get_nu20() { return this.nu20; } + public double get_nu11() { return this.nu11; } + public double get_nu02() { return this.nu02; } + public double get_nu30() { return this.nu30; } + public double get_nu21() { return this.nu21; } + public double get_nu12() { return this.nu12; } + public double get_nu03() { return this.nu03; } + + public void set_m00(double m00) { this.m00 = m00; } + public void set_m10(double m10) { this.m10 = m10; } + public void set_m01(double m01) { this.m01 = m01; } + public void set_m20(double m20) { this.m20 = m20; } + public void set_m11(double m11) { this.m11 = m11; } + public void set_m02(double m02) { this.m02 = m02; } + public void set_m30(double m30) { this.m30 = m30; } + public void set_m21(double m21) { this.m21 = m21; } + public void set_m12(double m12) { this.m12 = m12; } + public void set_m03(double m03) { this.m03 = m03; } + public void set_mu20(double mu20) { this.mu20 = mu20; } + public void set_mu11(double mu11) { this.mu11 = mu11; } + public void set_mu02(double mu02) { this.mu02 = mu02; } + public void set_mu30(double mu30) { this.mu30 = mu30; } + public void set_mu21(double mu21) { this.mu21 = mu21; } + public void set_mu12(double mu12) { this.mu12 = mu12; } + public void set_mu03(double mu03) { this.mu03 = mu03; } + public void set_nu20(double nu20) { this.nu20 = nu20; } + public void set_nu11(double nu11) { this.nu11 = nu11; } + public void set_nu02(double nu02) { this.nu02 = nu02; } + public void set_nu30(double nu30) { this.nu30 = nu30; } + public void set_nu21(double nu21) { this.nu21 = nu21; } + public void set_nu12(double nu12) { this.nu12 = nu12; } + public void set_nu03(double nu03) { this.nu03 = nu03; } +} diff --git a/OpenCV/src/main/java/org/opencv/imgproc/Subdiv2D.java b/OpenCV/src/main/java/org/opencv/imgproc/Subdiv2D.java new file mode 100644 index 00000000..2ae1d292 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/imgproc/Subdiv2D.java @@ -0,0 +1,408 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.imgproc; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfFloat4; +import org.opencv.core.MatOfFloat6; +import org.opencv.core.MatOfInt; +import org.opencv.core.MatOfPoint2f; +import org.opencv.core.Point; +import org.opencv.core.Rect; +import org.opencv.utils.Converters; + +// C++: class Subdiv2D +//javadoc: Subdiv2D + +public class Subdiv2D { + + protected final long nativeObj; + protected Subdiv2D(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static Subdiv2D __fromPtr__(long addr) { return new Subdiv2D(addr); } + + // C++: enum + public static final int + PTLOC_ERROR = -2, + PTLOC_OUTSIDE_RECT = -1, + PTLOC_INSIDE = 0, + PTLOC_VERTEX = 1, + PTLOC_ON_EDGE = 2, + NEXT_AROUND_ORG = 0x00, + NEXT_AROUND_DST = 0x22, + PREV_AROUND_ORG = 0x11, + PREV_AROUND_DST = 0x33, + NEXT_AROUND_LEFT = 0x13, + NEXT_AROUND_RIGHT = 0x31, + PREV_AROUND_LEFT = 0x20, + PREV_AROUND_RIGHT = 0x02; + + + // + // C++: cv::Subdiv2D::Subdiv2D(Rect rect) + // + + //javadoc: Subdiv2D::Subdiv2D(rect) + public Subdiv2D(Rect rect) + { + + nativeObj = Subdiv2D_0(rect.x, rect.y, rect.width, rect.height); + + return; + } + + + // + // C++: cv::Subdiv2D::Subdiv2D() + // + + //javadoc: Subdiv2D::Subdiv2D() + public Subdiv2D() + { + + nativeObj = Subdiv2D_1(); + + return; + } + + + // + // C++: Point2f cv::Subdiv2D::getVertex(int vertex, int* firstEdge = 0) + // + + //javadoc: Subdiv2D::getVertex(vertex, firstEdge) + public Point getVertex(int vertex, int[] firstEdge) + { + double[] firstEdge_out = new double[1]; + Point retVal = new Point(getVertex_0(nativeObj, vertex, firstEdge_out)); + if(firstEdge!=null) firstEdge[0] = (int)firstEdge_out[0]; + return retVal; + } + + //javadoc: Subdiv2D::getVertex(vertex) + public Point getVertex(int vertex) + { + + Point retVal = new Point(getVertex_1(nativeObj, vertex)); + + return retVal; + } + + + // + // C++: int cv::Subdiv2D::edgeDst(int edge, Point2f* dstpt = 0) + // + + //javadoc: Subdiv2D::edgeDst(edge, dstpt) + public int edgeDst(int edge, Point dstpt) + { + double[] dstpt_out = new double[2]; + int retVal = edgeDst_0(nativeObj, edge, dstpt_out); + if(dstpt!=null){ dstpt.x = dstpt_out[0]; dstpt.y = dstpt_out[1]; } + return retVal; + } + + //javadoc: Subdiv2D::edgeDst(edge) + public int edgeDst(int edge) + { + + int retVal = edgeDst_1(nativeObj, edge); + + return retVal; + } + + + // + // C++: int cv::Subdiv2D::edgeOrg(int edge, Point2f* orgpt = 0) + // + + //javadoc: Subdiv2D::edgeOrg(edge, orgpt) + public int edgeOrg(int edge, Point orgpt) + { + double[] orgpt_out = new double[2]; + int retVal = edgeOrg_0(nativeObj, edge, orgpt_out); + if(orgpt!=null){ orgpt.x = orgpt_out[0]; orgpt.y = orgpt_out[1]; } + return retVal; + } + + //javadoc: Subdiv2D::edgeOrg(edge) + public int edgeOrg(int edge) + { + + int retVal = edgeOrg_1(nativeObj, edge); + + return retVal; + } + + + // + // C++: int cv::Subdiv2D::findNearest(Point2f pt, Point2f* nearestPt = 0) + // + + //javadoc: Subdiv2D::findNearest(pt, nearestPt) + public int findNearest(Point pt, Point nearestPt) + { + double[] nearestPt_out = new double[2]; + int retVal = findNearest_0(nativeObj, pt.x, pt.y, nearestPt_out); + if(nearestPt!=null){ nearestPt.x = nearestPt_out[0]; nearestPt.y = nearestPt_out[1]; } + return retVal; + } + + //javadoc: Subdiv2D::findNearest(pt) + public int findNearest(Point pt) + { + + int retVal = findNearest_1(nativeObj, pt.x, pt.y); + + return retVal; + } + + + // + // C++: int cv::Subdiv2D::getEdge(int edge, int nextEdgeType) + // + + //javadoc: Subdiv2D::getEdge(edge, nextEdgeType) + public int getEdge(int edge, int nextEdgeType) + { + + int retVal = getEdge_0(nativeObj, edge, nextEdgeType); + + return retVal; + } + + + // + // C++: int cv::Subdiv2D::insert(Point2f pt) + // + + //javadoc: Subdiv2D::insert(pt) + public int insert(Point pt) + { + + int retVal = insert_0(nativeObj, pt.x, pt.y); + + return retVal; + } + + + // + // C++: int cv::Subdiv2D::locate(Point2f pt, int& edge, int& vertex) + // + + //javadoc: Subdiv2D::locate(pt, edge, vertex) + public int locate(Point pt, int[] edge, int[] vertex) + { + double[] edge_out = new double[1]; + double[] vertex_out = new double[1]; + int retVal = locate_0(nativeObj, pt.x, pt.y, edge_out, vertex_out); + if(edge!=null) edge[0] = (int)edge_out[0]; + if(vertex!=null) vertex[0] = (int)vertex_out[0]; + return retVal; + } + + + // + // C++: int cv::Subdiv2D::nextEdge(int edge) + // + + //javadoc: Subdiv2D::nextEdge(edge) + public int nextEdge(int edge) + { + + int retVal = nextEdge_0(nativeObj, edge); + + return retVal; + } + + + // + // C++: int cv::Subdiv2D::rotateEdge(int edge, int rotate) + // + + //javadoc: Subdiv2D::rotateEdge(edge, rotate) + public int rotateEdge(int edge, int rotate) + { + + int retVal = rotateEdge_0(nativeObj, edge, rotate); + + return retVal; + } + + + // + // C++: int cv::Subdiv2D::symEdge(int edge) + // + + //javadoc: Subdiv2D::symEdge(edge) + public int symEdge(int edge) + { + + int retVal = symEdge_0(nativeObj, edge); + + return retVal; + } + + + // + // C++: void cv::Subdiv2D::getEdgeList(vector_Vec4f& edgeList) + // + + //javadoc: Subdiv2D::getEdgeList(edgeList) + public void getEdgeList(MatOfFloat4 edgeList) + { + Mat edgeList_mat = edgeList; + getEdgeList_0(nativeObj, edgeList_mat.nativeObj); + + return; + } + + + // + // C++: void cv::Subdiv2D::getLeadingEdgeList(vector_int& leadingEdgeList) + // + + //javadoc: Subdiv2D::getLeadingEdgeList(leadingEdgeList) + public void getLeadingEdgeList(MatOfInt leadingEdgeList) + { + Mat leadingEdgeList_mat = leadingEdgeList; + getLeadingEdgeList_0(nativeObj, leadingEdgeList_mat.nativeObj); + + return; + } + + + // + // C++: void cv::Subdiv2D::getTriangleList(vector_Vec6f& triangleList) + // + + //javadoc: Subdiv2D::getTriangleList(triangleList) + public void getTriangleList(MatOfFloat6 triangleList) + { + Mat triangleList_mat = triangleList; + getTriangleList_0(nativeObj, triangleList_mat.nativeObj); + + return; + } + + + // + // C++: void cv::Subdiv2D::getVoronoiFacetList(vector_int idx, vector_vector_Point2f& facetList, vector_Point2f& facetCenters) + // + + //javadoc: Subdiv2D::getVoronoiFacetList(idx, facetList, facetCenters) + public void getVoronoiFacetList(MatOfInt idx, List facetList, MatOfPoint2f facetCenters) + { + Mat idx_mat = idx; + Mat facetList_mat = new Mat(); + Mat facetCenters_mat = facetCenters; + getVoronoiFacetList_0(nativeObj, idx_mat.nativeObj, facetList_mat.nativeObj, facetCenters_mat.nativeObj); + Converters.Mat_to_vector_vector_Point2f(facetList_mat, facetList); + facetList_mat.release(); + return; + } + + + // + // C++: void cv::Subdiv2D::initDelaunay(Rect rect) + // + + //javadoc: Subdiv2D::initDelaunay(rect) + public void initDelaunay(Rect rect) + { + + initDelaunay_0(nativeObj, rect.x, rect.y, rect.width, rect.height); + + return; + } + + + // + // C++: void cv::Subdiv2D::insert(vector_Point2f ptvec) + // + + //javadoc: Subdiv2D::insert(ptvec) + public void insert(MatOfPoint2f ptvec) + { + Mat ptvec_mat = ptvec; + insert_1(nativeObj, ptvec_mat.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: cv::Subdiv2D::Subdiv2D(Rect rect) + private static native long Subdiv2D_0(int rect_x, int rect_y, int rect_width, int rect_height); + + // C++: cv::Subdiv2D::Subdiv2D() + private static native long Subdiv2D_1(); + + // C++: Point2f cv::Subdiv2D::getVertex(int vertex, int* firstEdge = 0) + private static native double[] getVertex_0(long nativeObj, int vertex, double[] firstEdge_out); + private static native double[] getVertex_1(long nativeObj, int vertex); + + // C++: int cv::Subdiv2D::edgeDst(int edge, Point2f* dstpt = 0) + private static native int edgeDst_0(long nativeObj, int edge, double[] dstpt_out); + private static native int edgeDst_1(long nativeObj, int edge); + + // C++: int cv::Subdiv2D::edgeOrg(int edge, Point2f* orgpt = 0) + private static native int edgeOrg_0(long nativeObj, int edge, double[] orgpt_out); + private static native int edgeOrg_1(long nativeObj, int edge); + + // C++: int cv::Subdiv2D::findNearest(Point2f pt, Point2f* nearestPt = 0) + private static native int findNearest_0(long nativeObj, double pt_x, double pt_y, double[] nearestPt_out); + private static native int findNearest_1(long nativeObj, double pt_x, double pt_y); + + // C++: int cv::Subdiv2D::getEdge(int edge, int nextEdgeType) + private static native int getEdge_0(long nativeObj, int edge, int nextEdgeType); + + // C++: int cv::Subdiv2D::insert(Point2f pt) + private static native int insert_0(long nativeObj, double pt_x, double pt_y); + + // C++: int cv::Subdiv2D::locate(Point2f pt, int& edge, int& vertex) + private static native int locate_0(long nativeObj, double pt_x, double pt_y, double[] edge_out, double[] vertex_out); + + // C++: int cv::Subdiv2D::nextEdge(int edge) + private static native int nextEdge_0(long nativeObj, int edge); + + // C++: int cv::Subdiv2D::rotateEdge(int edge, int rotate) + private static native int rotateEdge_0(long nativeObj, int edge, int rotate); + + // C++: int cv::Subdiv2D::symEdge(int edge) + private static native int symEdge_0(long nativeObj, int edge); + + // C++: void cv::Subdiv2D::getEdgeList(vector_Vec4f& edgeList) + private static native void getEdgeList_0(long nativeObj, long edgeList_mat_nativeObj); + + // C++: void cv::Subdiv2D::getLeadingEdgeList(vector_int& leadingEdgeList) + private static native void getLeadingEdgeList_0(long nativeObj, long leadingEdgeList_mat_nativeObj); + + // C++: void cv::Subdiv2D::getTriangleList(vector_Vec6f& triangleList) + private static native void getTriangleList_0(long nativeObj, long triangleList_mat_nativeObj); + + // C++: void cv::Subdiv2D::getVoronoiFacetList(vector_int idx, vector_vector_Point2f& facetList, vector_Point2f& facetCenters) + private static native void getVoronoiFacetList_0(long nativeObj, long idx_mat_nativeObj, long facetList_mat_nativeObj, long facetCenters_mat_nativeObj); + + // C++: void cv::Subdiv2D::initDelaunay(Rect rect) + private static native void initDelaunay_0(long nativeObj, int rect_x, int rect_y, int rect_width, int rect_height); + + // C++: void cv::Subdiv2D::insert(vector_Point2f ptvec) + private static native void insert_1(long nativeObj, long ptvec_mat_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ml/ANN_MLP.java b/OpenCV/src/main/java/org/opencv/ml/ANN_MLP.java new file mode 100644 index 00000000..ace0c653 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ml/ANN_MLP.java @@ -0,0 +1,639 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ml; + +import java.lang.String; +import org.opencv.core.Mat; +import org.opencv.core.TermCriteria; +import org.opencv.ml.ANN_MLP; +import org.opencv.ml.StatModel; + +// C++: class ANN_MLP +//javadoc: ANN_MLP + +public class ANN_MLP extends StatModel { + + protected ANN_MLP(long addr) { super(addr); } + + // internal usage only + public static ANN_MLP __fromPtr__(long addr) { return new ANN_MLP(addr); } + + // C++: enum TrainingMethods + public static final int + BACKPROP = 0, + RPROP = 1, + ANNEAL = 2; + + + // C++: enum TrainFlags + public static final int + UPDATE_WEIGHTS = 1, + NO_INPUT_SCALE = 2, + NO_OUTPUT_SCALE = 4; + + + // C++: enum ActivationFunctions + public static final int + IDENTITY = 0, + SIGMOID_SYM = 1, + GAUSSIAN = 2, + RELU = 3, + LEAKYRELU = 4; + + + // + // C++: Mat cv::ml::ANN_MLP::getLayerSizes() + // + + //javadoc: ANN_MLP::getLayerSizes() + public Mat getLayerSizes() + { + + Mat retVal = new Mat(getLayerSizes_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::ANN_MLP::getWeights(int layerIdx) + // + + //javadoc: ANN_MLP::getWeights(layerIdx) + public Mat getWeights(int layerIdx) + { + + Mat retVal = new Mat(getWeights_0(nativeObj, layerIdx)); + + return retVal; + } + + + // + // C++: static Ptr_ANN_MLP cv::ml::ANN_MLP::create() + // + + //javadoc: ANN_MLP::create() + public static ANN_MLP create() + { + + ANN_MLP retVal = ANN_MLP.__fromPtr__(create_0()); + + return retVal; + } + + + // + // C++: static Ptr_ANN_MLP cv::ml::ANN_MLP::load(String filepath) + // + + //javadoc: ANN_MLP::load(filepath) + public static ANN_MLP load(String filepath) + { + + ANN_MLP retVal = ANN_MLP.__fromPtr__(load_0(filepath)); + + return retVal; + } + + + // + // C++: TermCriteria cv::ml::ANN_MLP::getTermCriteria() + // + + //javadoc: ANN_MLP::getTermCriteria() + public TermCriteria getTermCriteria() + { + + TermCriteria retVal = new TermCriteria(getTermCriteria_0(nativeObj)); + + return retVal; + } + + + // + // C++: double cv::ml::ANN_MLP::getAnnealCoolingRatio() + // + + //javadoc: ANN_MLP::getAnnealCoolingRatio() + public double getAnnealCoolingRatio() + { + + double retVal = getAnnealCoolingRatio_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::ml::ANN_MLP::getAnnealFinalT() + // + + //javadoc: ANN_MLP::getAnnealFinalT() + public double getAnnealFinalT() + { + + double retVal = getAnnealFinalT_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::ml::ANN_MLP::getAnnealInitialT() + // + + //javadoc: ANN_MLP::getAnnealInitialT() + public double getAnnealInitialT() + { + + double retVal = getAnnealInitialT_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::ml::ANN_MLP::getBackpropMomentumScale() + // + + //javadoc: ANN_MLP::getBackpropMomentumScale() + public double getBackpropMomentumScale() + { + + double retVal = getBackpropMomentumScale_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::ml::ANN_MLP::getBackpropWeightScale() + // + + //javadoc: ANN_MLP::getBackpropWeightScale() + public double getBackpropWeightScale() + { + + double retVal = getBackpropWeightScale_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::ml::ANN_MLP::getRpropDW0() + // + + //javadoc: ANN_MLP::getRpropDW0() + public double getRpropDW0() + { + + double retVal = getRpropDW0_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::ml::ANN_MLP::getRpropDWMax() + // + + //javadoc: ANN_MLP::getRpropDWMax() + public double getRpropDWMax() + { + + double retVal = getRpropDWMax_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::ml::ANN_MLP::getRpropDWMin() + // + + //javadoc: ANN_MLP::getRpropDWMin() + public double getRpropDWMin() + { + + double retVal = getRpropDWMin_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::ml::ANN_MLP::getRpropDWMinus() + // + + //javadoc: ANN_MLP::getRpropDWMinus() + public double getRpropDWMinus() + { + + double retVal = getRpropDWMinus_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::ml::ANN_MLP::getRpropDWPlus() + // + + //javadoc: ANN_MLP::getRpropDWPlus() + public double getRpropDWPlus() + { + + double retVal = getRpropDWPlus_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::ANN_MLP::getAnnealItePerStep() + // + + //javadoc: ANN_MLP::getAnnealItePerStep() + public int getAnnealItePerStep() + { + + int retVal = getAnnealItePerStep_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::ANN_MLP::getTrainMethod() + // + + //javadoc: ANN_MLP::getTrainMethod() + public int getTrainMethod() + { + + int retVal = getTrainMethod_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::ml::ANN_MLP::setActivationFunction(int type, double param1 = 0, double param2 = 0) + // + + //javadoc: ANN_MLP::setActivationFunction(type, param1, param2) + public void setActivationFunction(int type, double param1, double param2) + { + + setActivationFunction_0(nativeObj, type, param1, param2); + + return; + } + + //javadoc: ANN_MLP::setActivationFunction(type, param1) + public void setActivationFunction(int type, double param1) + { + + setActivationFunction_1(nativeObj, type, param1); + + return; + } + + //javadoc: ANN_MLP::setActivationFunction(type) + public void setActivationFunction(int type) + { + + setActivationFunction_2(nativeObj, type); + + return; + } + + + // + // C++: void cv::ml::ANN_MLP::setAnnealCoolingRatio(double val) + // + + //javadoc: ANN_MLP::setAnnealCoolingRatio(val) + public void setAnnealCoolingRatio(double val) + { + + setAnnealCoolingRatio_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::ANN_MLP::setAnnealFinalT(double val) + // + + //javadoc: ANN_MLP::setAnnealFinalT(val) + public void setAnnealFinalT(double val) + { + + setAnnealFinalT_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::ANN_MLP::setAnnealInitialT(double val) + // + + //javadoc: ANN_MLP::setAnnealInitialT(val) + public void setAnnealInitialT(double val) + { + + setAnnealInitialT_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::ANN_MLP::setAnnealItePerStep(int val) + // + + //javadoc: ANN_MLP::setAnnealItePerStep(val) + public void setAnnealItePerStep(int val) + { + + setAnnealItePerStep_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::ANN_MLP::setBackpropMomentumScale(double val) + // + + //javadoc: ANN_MLP::setBackpropMomentumScale(val) + public void setBackpropMomentumScale(double val) + { + + setBackpropMomentumScale_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::ANN_MLP::setBackpropWeightScale(double val) + // + + //javadoc: ANN_MLP::setBackpropWeightScale(val) + public void setBackpropWeightScale(double val) + { + + setBackpropWeightScale_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::ANN_MLP::setLayerSizes(Mat _layer_sizes) + // + + //javadoc: ANN_MLP::setLayerSizes(_layer_sizes) + public void setLayerSizes(Mat _layer_sizes) + { + + setLayerSizes_0(nativeObj, _layer_sizes.nativeObj); + + return; + } + + + // + // C++: void cv::ml::ANN_MLP::setRpropDW0(double val) + // + + //javadoc: ANN_MLP::setRpropDW0(val) + public void setRpropDW0(double val) + { + + setRpropDW0_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::ANN_MLP::setRpropDWMax(double val) + // + + //javadoc: ANN_MLP::setRpropDWMax(val) + public void setRpropDWMax(double val) + { + + setRpropDWMax_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::ANN_MLP::setRpropDWMin(double val) + // + + //javadoc: ANN_MLP::setRpropDWMin(val) + public void setRpropDWMin(double val) + { + + setRpropDWMin_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::ANN_MLP::setRpropDWMinus(double val) + // + + //javadoc: ANN_MLP::setRpropDWMinus(val) + public void setRpropDWMinus(double val) + { + + setRpropDWMinus_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::ANN_MLP::setRpropDWPlus(double val) + // + + //javadoc: ANN_MLP::setRpropDWPlus(val) + public void setRpropDWPlus(double val) + { + + setRpropDWPlus_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::ANN_MLP::setTermCriteria(TermCriteria val) + // + + //javadoc: ANN_MLP::setTermCriteria(val) + public void setTermCriteria(TermCriteria val) + { + + setTermCriteria_0(nativeObj, val.type, val.maxCount, val.epsilon); + + return; + } + + + // + // C++: void cv::ml::ANN_MLP::setTrainMethod(int method, double param1 = 0, double param2 = 0) + // + + //javadoc: ANN_MLP::setTrainMethod(method, param1, param2) + public void setTrainMethod(int method, double param1, double param2) + { + + setTrainMethod_0(nativeObj, method, param1, param2); + + return; + } + + //javadoc: ANN_MLP::setTrainMethod(method, param1) + public void setTrainMethod(int method, double param1) + { + + setTrainMethod_1(nativeObj, method, param1); + + return; + } + + //javadoc: ANN_MLP::setTrainMethod(method) + public void setTrainMethod(int method) + { + + setTrainMethod_2(nativeObj, method); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: Mat cv::ml::ANN_MLP::getLayerSizes() + private static native long getLayerSizes_0(long nativeObj); + + // C++: Mat cv::ml::ANN_MLP::getWeights(int layerIdx) + private static native long getWeights_0(long nativeObj, int layerIdx); + + // C++: static Ptr_ANN_MLP cv::ml::ANN_MLP::create() + private static native long create_0(); + + // C++: static Ptr_ANN_MLP cv::ml::ANN_MLP::load(String filepath) + private static native long load_0(String filepath); + + // C++: TermCriteria cv::ml::ANN_MLP::getTermCriteria() + private static native double[] getTermCriteria_0(long nativeObj); + + // C++: double cv::ml::ANN_MLP::getAnnealCoolingRatio() + private static native double getAnnealCoolingRatio_0(long nativeObj); + + // C++: double cv::ml::ANN_MLP::getAnnealFinalT() + private static native double getAnnealFinalT_0(long nativeObj); + + // C++: double cv::ml::ANN_MLP::getAnnealInitialT() + private static native double getAnnealInitialT_0(long nativeObj); + + // C++: double cv::ml::ANN_MLP::getBackpropMomentumScale() + private static native double getBackpropMomentumScale_0(long nativeObj); + + // C++: double cv::ml::ANN_MLP::getBackpropWeightScale() + private static native double getBackpropWeightScale_0(long nativeObj); + + // C++: double cv::ml::ANN_MLP::getRpropDW0() + private static native double getRpropDW0_0(long nativeObj); + + // C++: double cv::ml::ANN_MLP::getRpropDWMax() + private static native double getRpropDWMax_0(long nativeObj); + + // C++: double cv::ml::ANN_MLP::getRpropDWMin() + private static native double getRpropDWMin_0(long nativeObj); + + // C++: double cv::ml::ANN_MLP::getRpropDWMinus() + private static native double getRpropDWMinus_0(long nativeObj); + + // C++: double cv::ml::ANN_MLP::getRpropDWPlus() + private static native double getRpropDWPlus_0(long nativeObj); + + // C++: int cv::ml::ANN_MLP::getAnnealItePerStep() + private static native int getAnnealItePerStep_0(long nativeObj); + + // C++: int cv::ml::ANN_MLP::getTrainMethod() + private static native int getTrainMethod_0(long nativeObj); + + // C++: void cv::ml::ANN_MLP::setActivationFunction(int type, double param1 = 0, double param2 = 0) + private static native void setActivationFunction_0(long nativeObj, int type, double param1, double param2); + private static native void setActivationFunction_1(long nativeObj, int type, double param1); + private static native void setActivationFunction_2(long nativeObj, int type); + + // C++: void cv::ml::ANN_MLP::setAnnealCoolingRatio(double val) + private static native void setAnnealCoolingRatio_0(long nativeObj, double val); + + // C++: void cv::ml::ANN_MLP::setAnnealFinalT(double val) + private static native void setAnnealFinalT_0(long nativeObj, double val); + + // C++: void cv::ml::ANN_MLP::setAnnealInitialT(double val) + private static native void setAnnealInitialT_0(long nativeObj, double val); + + // C++: void cv::ml::ANN_MLP::setAnnealItePerStep(int val) + private static native void setAnnealItePerStep_0(long nativeObj, int val); + + // C++: void cv::ml::ANN_MLP::setBackpropMomentumScale(double val) + private static native void setBackpropMomentumScale_0(long nativeObj, double val); + + // C++: void cv::ml::ANN_MLP::setBackpropWeightScale(double val) + private static native void setBackpropWeightScale_0(long nativeObj, double val); + + // C++: void cv::ml::ANN_MLP::setLayerSizes(Mat _layer_sizes) + private static native void setLayerSizes_0(long nativeObj, long _layer_sizes_nativeObj); + + // C++: void cv::ml::ANN_MLP::setRpropDW0(double val) + private static native void setRpropDW0_0(long nativeObj, double val); + + // C++: void cv::ml::ANN_MLP::setRpropDWMax(double val) + private static native void setRpropDWMax_0(long nativeObj, double val); + + // C++: void cv::ml::ANN_MLP::setRpropDWMin(double val) + private static native void setRpropDWMin_0(long nativeObj, double val); + + // C++: void cv::ml::ANN_MLP::setRpropDWMinus(double val) + private static native void setRpropDWMinus_0(long nativeObj, double val); + + // C++: void cv::ml::ANN_MLP::setRpropDWPlus(double val) + private static native void setRpropDWPlus_0(long nativeObj, double val); + + // C++: void cv::ml::ANN_MLP::setTermCriteria(TermCriteria val) + private static native void setTermCriteria_0(long nativeObj, int val_type, int val_maxCount, double val_epsilon); + + // C++: void cv::ml::ANN_MLP::setTrainMethod(int method, double param1 = 0, double param2 = 0) + private static native void setTrainMethod_0(long nativeObj, int method, double param1, double param2); + private static native void setTrainMethod_1(long nativeObj, int method, double param1); + private static native void setTrainMethod_2(long nativeObj, int method); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ml/Boost.java b/OpenCV/src/main/java/org/opencv/ml/Boost.java new file mode 100644 index 00000000..441ef059 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ml/Boost.java @@ -0,0 +1,184 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ml; + +import java.lang.String; +import org.opencv.ml.Boost; +import org.opencv.ml.DTrees; + +// C++: class Boost +//javadoc: Boost + +public class Boost extends DTrees { + + protected Boost(long addr) { super(addr); } + + // internal usage only + public static Boost __fromPtr__(long addr) { return new Boost(addr); } + + // C++: enum Types + public static final int + DISCRETE = 0, + REAL = 1, + LOGIT = 2, + GENTLE = 3; + + + // + // C++: static Ptr_Boost cv::ml::Boost::create() + // + + //javadoc: Boost::create() + public static Boost create() + { + + Boost retVal = Boost.__fromPtr__(create_0()); + + return retVal; + } + + + // + // C++: static Ptr_Boost cv::ml::Boost::load(String filepath, String nodeName = String()) + // + + //javadoc: Boost::load(filepath, nodeName) + public static Boost load(String filepath, String nodeName) + { + + Boost retVal = Boost.__fromPtr__(load_0(filepath, nodeName)); + + return retVal; + } + + //javadoc: Boost::load(filepath) + public static Boost load(String filepath) + { + + Boost retVal = Boost.__fromPtr__(load_1(filepath)); + + return retVal; + } + + + // + // C++: double cv::ml::Boost::getWeightTrimRate() + // + + //javadoc: Boost::getWeightTrimRate() + public double getWeightTrimRate() + { + + double retVal = getWeightTrimRate_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::Boost::getBoostType() + // + + //javadoc: Boost::getBoostType() + public int getBoostType() + { + + int retVal = getBoostType_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::Boost::getWeakCount() + // + + //javadoc: Boost::getWeakCount() + public int getWeakCount() + { + + int retVal = getWeakCount_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::ml::Boost::setBoostType(int val) + // + + //javadoc: Boost::setBoostType(val) + public void setBoostType(int val) + { + + setBoostType_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::Boost::setWeakCount(int val) + // + + //javadoc: Boost::setWeakCount(val) + public void setWeakCount(int val) + { + + setWeakCount_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::Boost::setWeightTrimRate(double val) + // + + //javadoc: Boost::setWeightTrimRate(val) + public void setWeightTrimRate(double val) + { + + setWeightTrimRate_0(nativeObj, val); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_Boost cv::ml::Boost::create() + private static native long create_0(); + + // C++: static Ptr_Boost cv::ml::Boost::load(String filepath, String nodeName = String()) + private static native long load_0(String filepath, String nodeName); + private static native long load_1(String filepath); + + // C++: double cv::ml::Boost::getWeightTrimRate() + private static native double getWeightTrimRate_0(long nativeObj); + + // C++: int cv::ml::Boost::getBoostType() + private static native int getBoostType_0(long nativeObj); + + // C++: int cv::ml::Boost::getWeakCount() + private static native int getWeakCount_0(long nativeObj); + + // C++: void cv::ml::Boost::setBoostType(int val) + private static native void setBoostType_0(long nativeObj, int val); + + // C++: void cv::ml::Boost::setWeakCount(int val) + private static native void setWeakCount_0(long nativeObj, int val); + + // C++: void cv::ml::Boost::setWeightTrimRate(double val) + private static native void setWeightTrimRate_0(long nativeObj, double val); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ml/DTrees.java b/OpenCV/src/main/java/org/opencv/ml/DTrees.java new file mode 100644 index 00000000..ed95a384 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ml/DTrees.java @@ -0,0 +1,389 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ml; + +import java.lang.String; +import org.opencv.core.Mat; +import org.opencv.ml.DTrees; +import org.opencv.ml.StatModel; + +// C++: class DTrees +//javadoc: DTrees + +public class DTrees extends StatModel { + + protected DTrees(long addr) { super(addr); } + + // internal usage only + public static DTrees __fromPtr__(long addr) { return new DTrees(addr); } + + // C++: enum Flags + public static final int + PREDICT_AUTO = 0, + PREDICT_SUM = (1<<8), + PREDICT_MAX_VOTE = (2<<8), + PREDICT_MASK = (3<<8); + + + // + // C++: Mat cv::ml::DTrees::getPriors() + // + + //javadoc: DTrees::getPriors() + public Mat getPriors() + { + + Mat retVal = new Mat(getPriors_0(nativeObj)); + + return retVal; + } + + + // + // C++: static Ptr_DTrees cv::ml::DTrees::create() + // + + //javadoc: DTrees::create() + public static DTrees create() + { + + DTrees retVal = DTrees.__fromPtr__(create_0()); + + return retVal; + } + + + // + // C++: static Ptr_DTrees cv::ml::DTrees::load(String filepath, String nodeName = String()) + // + + //javadoc: DTrees::load(filepath, nodeName) + public static DTrees load(String filepath, String nodeName) + { + + DTrees retVal = DTrees.__fromPtr__(load_0(filepath, nodeName)); + + return retVal; + } + + //javadoc: DTrees::load(filepath) + public static DTrees load(String filepath) + { + + DTrees retVal = DTrees.__fromPtr__(load_1(filepath)); + + return retVal; + } + + + // + // C++: bool cv::ml::DTrees::getTruncatePrunedTree() + // + + //javadoc: DTrees::getTruncatePrunedTree() + public boolean getTruncatePrunedTree() + { + + boolean retVal = getTruncatePrunedTree_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::ml::DTrees::getUse1SERule() + // + + //javadoc: DTrees::getUse1SERule() + public boolean getUse1SERule() + { + + boolean retVal = getUse1SERule_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::ml::DTrees::getUseSurrogates() + // + + //javadoc: DTrees::getUseSurrogates() + public boolean getUseSurrogates() + { + + boolean retVal = getUseSurrogates_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ml::DTrees::getRegressionAccuracy() + // + + //javadoc: DTrees::getRegressionAccuracy() + public float getRegressionAccuracy() + { + + float retVal = getRegressionAccuracy_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::DTrees::getCVFolds() + // + + //javadoc: DTrees::getCVFolds() + public int getCVFolds() + { + + int retVal = getCVFolds_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::DTrees::getMaxCategories() + // + + //javadoc: DTrees::getMaxCategories() + public int getMaxCategories() + { + + int retVal = getMaxCategories_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::DTrees::getMaxDepth() + // + + //javadoc: DTrees::getMaxDepth() + public int getMaxDepth() + { + + int retVal = getMaxDepth_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::DTrees::getMinSampleCount() + // + + //javadoc: DTrees::getMinSampleCount() + public int getMinSampleCount() + { + + int retVal = getMinSampleCount_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::ml::DTrees::setCVFolds(int val) + // + + //javadoc: DTrees::setCVFolds(val) + public void setCVFolds(int val) + { + + setCVFolds_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::DTrees::setMaxCategories(int val) + // + + //javadoc: DTrees::setMaxCategories(val) + public void setMaxCategories(int val) + { + + setMaxCategories_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::DTrees::setMaxDepth(int val) + // + + //javadoc: DTrees::setMaxDepth(val) + public void setMaxDepth(int val) + { + + setMaxDepth_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::DTrees::setMinSampleCount(int val) + // + + //javadoc: DTrees::setMinSampleCount(val) + public void setMinSampleCount(int val) + { + + setMinSampleCount_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::DTrees::setPriors(Mat val) + // + + //javadoc: DTrees::setPriors(val) + public void setPriors(Mat val) + { + + setPriors_0(nativeObj, val.nativeObj); + + return; + } + + + // + // C++: void cv::ml::DTrees::setRegressionAccuracy(float val) + // + + //javadoc: DTrees::setRegressionAccuracy(val) + public void setRegressionAccuracy(float val) + { + + setRegressionAccuracy_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::DTrees::setTruncatePrunedTree(bool val) + // + + //javadoc: DTrees::setTruncatePrunedTree(val) + public void setTruncatePrunedTree(boolean val) + { + + setTruncatePrunedTree_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::DTrees::setUse1SERule(bool val) + // + + //javadoc: DTrees::setUse1SERule(val) + public void setUse1SERule(boolean val) + { + + setUse1SERule_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::DTrees::setUseSurrogates(bool val) + // + + //javadoc: DTrees::setUseSurrogates(val) + public void setUseSurrogates(boolean val) + { + + setUseSurrogates_0(nativeObj, val); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: Mat cv::ml::DTrees::getPriors() + private static native long getPriors_0(long nativeObj); + + // C++: static Ptr_DTrees cv::ml::DTrees::create() + private static native long create_0(); + + // C++: static Ptr_DTrees cv::ml::DTrees::load(String filepath, String nodeName = String()) + private static native long load_0(String filepath, String nodeName); + private static native long load_1(String filepath); + + // C++: bool cv::ml::DTrees::getTruncatePrunedTree() + private static native boolean getTruncatePrunedTree_0(long nativeObj); + + // C++: bool cv::ml::DTrees::getUse1SERule() + private static native boolean getUse1SERule_0(long nativeObj); + + // C++: bool cv::ml::DTrees::getUseSurrogates() + private static native boolean getUseSurrogates_0(long nativeObj); + + // C++: float cv::ml::DTrees::getRegressionAccuracy() + private static native float getRegressionAccuracy_0(long nativeObj); + + // C++: int cv::ml::DTrees::getCVFolds() + private static native int getCVFolds_0(long nativeObj); + + // C++: int cv::ml::DTrees::getMaxCategories() + private static native int getMaxCategories_0(long nativeObj); + + // C++: int cv::ml::DTrees::getMaxDepth() + private static native int getMaxDepth_0(long nativeObj); + + // C++: int cv::ml::DTrees::getMinSampleCount() + private static native int getMinSampleCount_0(long nativeObj); + + // C++: void cv::ml::DTrees::setCVFolds(int val) + private static native void setCVFolds_0(long nativeObj, int val); + + // C++: void cv::ml::DTrees::setMaxCategories(int val) + private static native void setMaxCategories_0(long nativeObj, int val); + + // C++: void cv::ml::DTrees::setMaxDepth(int val) + private static native void setMaxDepth_0(long nativeObj, int val); + + // C++: void cv::ml::DTrees::setMinSampleCount(int val) + private static native void setMinSampleCount_0(long nativeObj, int val); + + // C++: void cv::ml::DTrees::setPriors(Mat val) + private static native void setPriors_0(long nativeObj, long val_nativeObj); + + // C++: void cv::ml::DTrees::setRegressionAccuracy(float val) + private static native void setRegressionAccuracy_0(long nativeObj, float val); + + // C++: void cv::ml::DTrees::setTruncatePrunedTree(bool val) + private static native void setTruncatePrunedTree_0(long nativeObj, boolean val); + + // C++: void cv::ml::DTrees::setUse1SERule(bool val) + private static native void setUse1SERule_0(long nativeObj, boolean val); + + // C++: void cv::ml::DTrees::setUseSurrogates(bool val) + private static native void setUseSurrogates_0(long nativeObj, boolean val); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ml/EM.java b/OpenCV/src/main/java/org/opencv/ml/EM.java new file mode 100644 index 00000000..80092da2 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ml/EM.java @@ -0,0 +1,465 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ml; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.TermCriteria; +import org.opencv.ml.EM; +import org.opencv.ml.StatModel; +import org.opencv.utils.Converters; + +// C++: class EM +//javadoc: EM + +public class EM extends StatModel { + + protected EM(long addr) { super(addr); } + + // internal usage only + public static EM __fromPtr__(long addr) { return new EM(addr); } + + // C++: enum + public static final int + DEFAULT_NCLUSTERS = 5, + DEFAULT_MAX_ITERS = 100, + START_E_STEP = 1, + START_M_STEP = 2, + START_AUTO_STEP = 0; + + + // C++: enum Types + public static final int + COV_MAT_SPHERICAL = 0, + COV_MAT_DIAGONAL = 1, + COV_MAT_GENERIC = 2, + COV_MAT_DEFAULT = COV_MAT_DIAGONAL; + + + // + // C++: Mat cv::ml::EM::getMeans() + // + + //javadoc: EM::getMeans() + public Mat getMeans() + { + + Mat retVal = new Mat(getMeans_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::EM::getWeights() + // + + //javadoc: EM::getWeights() + public Mat getWeights() + { + + Mat retVal = new Mat(getWeights_0(nativeObj)); + + return retVal; + } + + + // + // C++: static Ptr_EM cv::ml::EM::create() + // + + //javadoc: EM::create() + public static EM create() + { + + EM retVal = EM.__fromPtr__(create_0()); + + return retVal; + } + + + // + // C++: static Ptr_EM cv::ml::EM::load(String filepath, String nodeName = String()) + // + + //javadoc: EM::load(filepath, nodeName) + public static EM load(String filepath, String nodeName) + { + + EM retVal = EM.__fromPtr__(load_0(filepath, nodeName)); + + return retVal; + } + + //javadoc: EM::load(filepath) + public static EM load(String filepath) + { + + EM retVal = EM.__fromPtr__(load_1(filepath)); + + return retVal; + } + + + // + // C++: TermCriteria cv::ml::EM::getTermCriteria() + // + + //javadoc: EM::getTermCriteria() + public TermCriteria getTermCriteria() + { + + TermCriteria retVal = new TermCriteria(getTermCriteria_0(nativeObj)); + + return retVal; + } + + + // + // C++: Vec2d cv::ml::EM::predict2(Mat sample, Mat& probs) + // + + //javadoc: EM::predict2(sample, probs) + public double[] predict2(Mat sample, Mat probs) + { + + double[] retVal = predict2_0(nativeObj, sample.nativeObj, probs.nativeObj); + + return retVal; + } + + + // + // C++: bool cv::ml::EM::trainE(Mat samples, Mat means0, Mat covs0 = Mat(), Mat weights0 = Mat(), Mat& logLikelihoods = Mat(), Mat& labels = Mat(), Mat& probs = Mat()) + // + + //javadoc: EM::trainE(samples, means0, covs0, weights0, logLikelihoods, labels, probs) + public boolean trainE(Mat samples, Mat means0, Mat covs0, Mat weights0, Mat logLikelihoods, Mat labels, Mat probs) + { + + boolean retVal = trainE_0(nativeObj, samples.nativeObj, means0.nativeObj, covs0.nativeObj, weights0.nativeObj, logLikelihoods.nativeObj, labels.nativeObj, probs.nativeObj); + + return retVal; + } + + //javadoc: EM::trainE(samples, means0, covs0, weights0, logLikelihoods, labels) + public boolean trainE(Mat samples, Mat means0, Mat covs0, Mat weights0, Mat logLikelihoods, Mat labels) + { + + boolean retVal = trainE_1(nativeObj, samples.nativeObj, means0.nativeObj, covs0.nativeObj, weights0.nativeObj, logLikelihoods.nativeObj, labels.nativeObj); + + return retVal; + } + + //javadoc: EM::trainE(samples, means0, covs0, weights0, logLikelihoods) + public boolean trainE(Mat samples, Mat means0, Mat covs0, Mat weights0, Mat logLikelihoods) + { + + boolean retVal = trainE_2(nativeObj, samples.nativeObj, means0.nativeObj, covs0.nativeObj, weights0.nativeObj, logLikelihoods.nativeObj); + + return retVal; + } + + //javadoc: EM::trainE(samples, means0, covs0, weights0) + public boolean trainE(Mat samples, Mat means0, Mat covs0, Mat weights0) + { + + boolean retVal = trainE_3(nativeObj, samples.nativeObj, means0.nativeObj, covs0.nativeObj, weights0.nativeObj); + + return retVal; + } + + //javadoc: EM::trainE(samples, means0, covs0) + public boolean trainE(Mat samples, Mat means0, Mat covs0) + { + + boolean retVal = trainE_4(nativeObj, samples.nativeObj, means0.nativeObj, covs0.nativeObj); + + return retVal; + } + + //javadoc: EM::trainE(samples, means0) + public boolean trainE(Mat samples, Mat means0) + { + + boolean retVal = trainE_5(nativeObj, samples.nativeObj, means0.nativeObj); + + return retVal; + } + + + // + // C++: bool cv::ml::EM::trainEM(Mat samples, Mat& logLikelihoods = Mat(), Mat& labels = Mat(), Mat& probs = Mat()) + // + + //javadoc: EM::trainEM(samples, logLikelihoods, labels, probs) + public boolean trainEM(Mat samples, Mat logLikelihoods, Mat labels, Mat probs) + { + + boolean retVal = trainEM_0(nativeObj, samples.nativeObj, logLikelihoods.nativeObj, labels.nativeObj, probs.nativeObj); + + return retVal; + } + + //javadoc: EM::trainEM(samples, logLikelihoods, labels) + public boolean trainEM(Mat samples, Mat logLikelihoods, Mat labels) + { + + boolean retVal = trainEM_1(nativeObj, samples.nativeObj, logLikelihoods.nativeObj, labels.nativeObj); + + return retVal; + } + + //javadoc: EM::trainEM(samples, logLikelihoods) + public boolean trainEM(Mat samples, Mat logLikelihoods) + { + + boolean retVal = trainEM_2(nativeObj, samples.nativeObj, logLikelihoods.nativeObj); + + return retVal; + } + + //javadoc: EM::trainEM(samples) + public boolean trainEM(Mat samples) + { + + boolean retVal = trainEM_3(nativeObj, samples.nativeObj); + + return retVal; + } + + + // + // C++: bool cv::ml::EM::trainM(Mat samples, Mat probs0, Mat& logLikelihoods = Mat(), Mat& labels = Mat(), Mat& probs = Mat()) + // + + //javadoc: EM::trainM(samples, probs0, logLikelihoods, labels, probs) + public boolean trainM(Mat samples, Mat probs0, Mat logLikelihoods, Mat labels, Mat probs) + { + + boolean retVal = trainM_0(nativeObj, samples.nativeObj, probs0.nativeObj, logLikelihoods.nativeObj, labels.nativeObj, probs.nativeObj); + + return retVal; + } + + //javadoc: EM::trainM(samples, probs0, logLikelihoods, labels) + public boolean trainM(Mat samples, Mat probs0, Mat logLikelihoods, Mat labels) + { + + boolean retVal = trainM_1(nativeObj, samples.nativeObj, probs0.nativeObj, logLikelihoods.nativeObj, labels.nativeObj); + + return retVal; + } + + //javadoc: EM::trainM(samples, probs0, logLikelihoods) + public boolean trainM(Mat samples, Mat probs0, Mat logLikelihoods) + { + + boolean retVal = trainM_2(nativeObj, samples.nativeObj, probs0.nativeObj, logLikelihoods.nativeObj); + + return retVal; + } + + //javadoc: EM::trainM(samples, probs0) + public boolean trainM(Mat samples, Mat probs0) + { + + boolean retVal = trainM_3(nativeObj, samples.nativeObj, probs0.nativeObj); + + return retVal; + } + + + // + // C++: float cv::ml::EM::predict(Mat samples, Mat& results = Mat(), int flags = 0) + // + + //javadoc: EM::predict(samples, results, flags) + public float predict(Mat samples, Mat results, int flags) + { + + float retVal = predict_0(nativeObj, samples.nativeObj, results.nativeObj, flags); + + return retVal; + } + + //javadoc: EM::predict(samples, results) + public float predict(Mat samples, Mat results) + { + + float retVal = predict_1(nativeObj, samples.nativeObj, results.nativeObj); + + return retVal; + } + + //javadoc: EM::predict(samples) + public float predict(Mat samples) + { + + float retVal = predict_2(nativeObj, samples.nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::EM::getClustersNumber() + // + + //javadoc: EM::getClustersNumber() + public int getClustersNumber() + { + + int retVal = getClustersNumber_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::EM::getCovarianceMatrixType() + // + + //javadoc: EM::getCovarianceMatrixType() + public int getCovarianceMatrixType() + { + + int retVal = getCovarianceMatrixType_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::ml::EM::getCovs(vector_Mat& covs) + // + + //javadoc: EM::getCovs(covs) + public void getCovs(List covs) + { + Mat covs_mat = new Mat(); + getCovs_0(nativeObj, covs_mat.nativeObj); + Converters.Mat_to_vector_Mat(covs_mat, covs); + covs_mat.release(); + return; + } + + + // + // C++: void cv::ml::EM::setClustersNumber(int val) + // + + //javadoc: EM::setClustersNumber(val) + public void setClustersNumber(int val) + { + + setClustersNumber_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::EM::setCovarianceMatrixType(int val) + // + + //javadoc: EM::setCovarianceMatrixType(val) + public void setCovarianceMatrixType(int val) + { + + setCovarianceMatrixType_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::EM::setTermCriteria(TermCriteria val) + // + + //javadoc: EM::setTermCriteria(val) + public void setTermCriteria(TermCriteria val) + { + + setTermCriteria_0(nativeObj, val.type, val.maxCount, val.epsilon); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: Mat cv::ml::EM::getMeans() + private static native long getMeans_0(long nativeObj); + + // C++: Mat cv::ml::EM::getWeights() + private static native long getWeights_0(long nativeObj); + + // C++: static Ptr_EM cv::ml::EM::create() + private static native long create_0(); + + // C++: static Ptr_EM cv::ml::EM::load(String filepath, String nodeName = String()) + private static native long load_0(String filepath, String nodeName); + private static native long load_1(String filepath); + + // C++: TermCriteria cv::ml::EM::getTermCriteria() + private static native double[] getTermCriteria_0(long nativeObj); + + // C++: Vec2d cv::ml::EM::predict2(Mat sample, Mat& probs) + private static native double[] predict2_0(long nativeObj, long sample_nativeObj, long probs_nativeObj); + + // C++: bool cv::ml::EM::trainE(Mat samples, Mat means0, Mat covs0 = Mat(), Mat weights0 = Mat(), Mat& logLikelihoods = Mat(), Mat& labels = Mat(), Mat& probs = Mat()) + private static native boolean trainE_0(long nativeObj, long samples_nativeObj, long means0_nativeObj, long covs0_nativeObj, long weights0_nativeObj, long logLikelihoods_nativeObj, long labels_nativeObj, long probs_nativeObj); + private static native boolean trainE_1(long nativeObj, long samples_nativeObj, long means0_nativeObj, long covs0_nativeObj, long weights0_nativeObj, long logLikelihoods_nativeObj, long labels_nativeObj); + private static native boolean trainE_2(long nativeObj, long samples_nativeObj, long means0_nativeObj, long covs0_nativeObj, long weights0_nativeObj, long logLikelihoods_nativeObj); + private static native boolean trainE_3(long nativeObj, long samples_nativeObj, long means0_nativeObj, long covs0_nativeObj, long weights0_nativeObj); + private static native boolean trainE_4(long nativeObj, long samples_nativeObj, long means0_nativeObj, long covs0_nativeObj); + private static native boolean trainE_5(long nativeObj, long samples_nativeObj, long means0_nativeObj); + + // C++: bool cv::ml::EM::trainEM(Mat samples, Mat& logLikelihoods = Mat(), Mat& labels = Mat(), Mat& probs = Mat()) + private static native boolean trainEM_0(long nativeObj, long samples_nativeObj, long logLikelihoods_nativeObj, long labels_nativeObj, long probs_nativeObj); + private static native boolean trainEM_1(long nativeObj, long samples_nativeObj, long logLikelihoods_nativeObj, long labels_nativeObj); + private static native boolean trainEM_2(long nativeObj, long samples_nativeObj, long logLikelihoods_nativeObj); + private static native boolean trainEM_3(long nativeObj, long samples_nativeObj); + + // C++: bool cv::ml::EM::trainM(Mat samples, Mat probs0, Mat& logLikelihoods = Mat(), Mat& labels = Mat(), Mat& probs = Mat()) + private static native boolean trainM_0(long nativeObj, long samples_nativeObj, long probs0_nativeObj, long logLikelihoods_nativeObj, long labels_nativeObj, long probs_nativeObj); + private static native boolean trainM_1(long nativeObj, long samples_nativeObj, long probs0_nativeObj, long logLikelihoods_nativeObj, long labels_nativeObj); + private static native boolean trainM_2(long nativeObj, long samples_nativeObj, long probs0_nativeObj, long logLikelihoods_nativeObj); + private static native boolean trainM_3(long nativeObj, long samples_nativeObj, long probs0_nativeObj); + + // C++: float cv::ml::EM::predict(Mat samples, Mat& results = Mat(), int flags = 0) + private static native float predict_0(long nativeObj, long samples_nativeObj, long results_nativeObj, int flags); + private static native float predict_1(long nativeObj, long samples_nativeObj, long results_nativeObj); + private static native float predict_2(long nativeObj, long samples_nativeObj); + + // C++: int cv::ml::EM::getClustersNumber() + private static native int getClustersNumber_0(long nativeObj); + + // C++: int cv::ml::EM::getCovarianceMatrixType() + private static native int getCovarianceMatrixType_0(long nativeObj); + + // C++: void cv::ml::EM::getCovs(vector_Mat& covs) + private static native void getCovs_0(long nativeObj, long covs_mat_nativeObj); + + // C++: void cv::ml::EM::setClustersNumber(int val) + private static native void setClustersNumber_0(long nativeObj, int val); + + // C++: void cv::ml::EM::setCovarianceMatrixType(int val) + private static native void setCovarianceMatrixType_0(long nativeObj, int val); + + // C++: void cv::ml::EM::setTermCriteria(TermCriteria val) + private static native void setTermCriteria_0(long nativeObj, int val_type, int val_maxCount, double val_epsilon); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ml/KNearest.java b/OpenCV/src/main/java/org/opencv/ml/KNearest.java new file mode 100644 index 00000000..abda161f --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ml/KNearest.java @@ -0,0 +1,244 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ml; + +import java.lang.String; +import org.opencv.core.Mat; +import org.opencv.ml.KNearest; +import org.opencv.ml.StatModel; + +// C++: class KNearest +//javadoc: KNearest + +public class KNearest extends StatModel { + + protected KNearest(long addr) { super(addr); } + + // internal usage only + public static KNearest __fromPtr__(long addr) { return new KNearest(addr); } + + // C++: enum Types + public static final int + BRUTE_FORCE = 1, + KDTREE = 2; + + + // + // C++: static Ptr_KNearest cv::ml::KNearest::create() + // + + //javadoc: KNearest::create() + public static KNearest create() + { + + KNearest retVal = KNearest.__fromPtr__(create_0()); + + return retVal; + } + + + // + // C++: static Ptr_KNearest cv::ml::KNearest::load(String filepath) + // + + //javadoc: KNearest::load(filepath) + public static KNearest load(String filepath) + { + + KNearest retVal = KNearest.__fromPtr__(load_0(filepath)); + + return retVal; + } + + + // + // C++: bool cv::ml::KNearest::getIsClassifier() + // + + //javadoc: KNearest::getIsClassifier() + public boolean getIsClassifier() + { + + boolean retVal = getIsClassifier_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ml::KNearest::findNearest(Mat samples, int k, Mat& results, Mat& neighborResponses = Mat(), Mat& dist = Mat()) + // + + //javadoc: KNearest::findNearest(samples, k, results, neighborResponses, dist) + public float findNearest(Mat samples, int k, Mat results, Mat neighborResponses, Mat dist) + { + + float retVal = findNearest_0(nativeObj, samples.nativeObj, k, results.nativeObj, neighborResponses.nativeObj, dist.nativeObj); + + return retVal; + } + + //javadoc: KNearest::findNearest(samples, k, results, neighborResponses) + public float findNearest(Mat samples, int k, Mat results, Mat neighborResponses) + { + + float retVal = findNearest_1(nativeObj, samples.nativeObj, k, results.nativeObj, neighborResponses.nativeObj); + + return retVal; + } + + //javadoc: KNearest::findNearest(samples, k, results) + public float findNearest(Mat samples, int k, Mat results) + { + + float retVal = findNearest_2(nativeObj, samples.nativeObj, k, results.nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::KNearest::getAlgorithmType() + // + + //javadoc: KNearest::getAlgorithmType() + public int getAlgorithmType() + { + + int retVal = getAlgorithmType_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::KNearest::getDefaultK() + // + + //javadoc: KNearest::getDefaultK() + public int getDefaultK() + { + + int retVal = getDefaultK_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::KNearest::getEmax() + // + + //javadoc: KNearest::getEmax() + public int getEmax() + { + + int retVal = getEmax_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::ml::KNearest::setAlgorithmType(int val) + // + + //javadoc: KNearest::setAlgorithmType(val) + public void setAlgorithmType(int val) + { + + setAlgorithmType_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::KNearest::setDefaultK(int val) + // + + //javadoc: KNearest::setDefaultK(val) + public void setDefaultK(int val) + { + + setDefaultK_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::KNearest::setEmax(int val) + // + + //javadoc: KNearest::setEmax(val) + public void setEmax(int val) + { + + setEmax_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::KNearest::setIsClassifier(bool val) + // + + //javadoc: KNearest::setIsClassifier(val) + public void setIsClassifier(boolean val) + { + + setIsClassifier_0(nativeObj, val); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_KNearest cv::ml::KNearest::create() + private static native long create_0(); + + // C++: static Ptr_KNearest cv::ml::KNearest::load(String filepath) + private static native long load_0(String filepath); + + // C++: bool cv::ml::KNearest::getIsClassifier() + private static native boolean getIsClassifier_0(long nativeObj); + + // C++: float cv::ml::KNearest::findNearest(Mat samples, int k, Mat& results, Mat& neighborResponses = Mat(), Mat& dist = Mat()) + private static native float findNearest_0(long nativeObj, long samples_nativeObj, int k, long results_nativeObj, long neighborResponses_nativeObj, long dist_nativeObj); + private static native float findNearest_1(long nativeObj, long samples_nativeObj, int k, long results_nativeObj, long neighborResponses_nativeObj); + private static native float findNearest_2(long nativeObj, long samples_nativeObj, int k, long results_nativeObj); + + // C++: int cv::ml::KNearest::getAlgorithmType() + private static native int getAlgorithmType_0(long nativeObj); + + // C++: int cv::ml::KNearest::getDefaultK() + private static native int getDefaultK_0(long nativeObj); + + // C++: int cv::ml::KNearest::getEmax() + private static native int getEmax_0(long nativeObj); + + // C++: void cv::ml::KNearest::setAlgorithmType(int val) + private static native void setAlgorithmType_0(long nativeObj, int val); + + // C++: void cv::ml::KNearest::setDefaultK(int val) + private static native void setDefaultK_0(long nativeObj, int val); + + // C++: void cv::ml::KNearest::setEmax(int val) + private static native void setEmax_0(long nativeObj, int val); + + // C++: void cv::ml::KNearest::setIsClassifier(bool val) + private static native void setIsClassifier_0(long nativeObj, boolean val); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ml/LogisticRegression.java b/OpenCV/src/main/java/org/opencv/ml/LogisticRegression.java new file mode 100644 index 00000000..c34a673b --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ml/LogisticRegression.java @@ -0,0 +1,347 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ml; + +import java.lang.String; +import org.opencv.core.Mat; +import org.opencv.core.TermCriteria; +import org.opencv.ml.LogisticRegression; +import org.opencv.ml.StatModel; + +// C++: class LogisticRegression +//javadoc: LogisticRegression + +public class LogisticRegression extends StatModel { + + protected LogisticRegression(long addr) { super(addr); } + + // internal usage only + public static LogisticRegression __fromPtr__(long addr) { return new LogisticRegression(addr); } + + // C++: enum RegKinds + public static final int + REG_DISABLE = -1, + REG_L1 = 0, + REG_L2 = 1; + + + // C++: enum Methods + public static final int + BATCH = 0, + MINI_BATCH = 1; + + + // + // C++: Mat cv::ml::LogisticRegression::get_learnt_thetas() + // + + //javadoc: LogisticRegression::get_learnt_thetas() + public Mat get_learnt_thetas() + { + + Mat retVal = new Mat(get_learnt_thetas_0(nativeObj)); + + return retVal; + } + + + // + // C++: static Ptr_LogisticRegression cv::ml::LogisticRegression::create() + // + + //javadoc: LogisticRegression::create() + public static LogisticRegression create() + { + + LogisticRegression retVal = LogisticRegression.__fromPtr__(create_0()); + + return retVal; + } + + + // + // C++: static Ptr_LogisticRegression cv::ml::LogisticRegression::load(String filepath, String nodeName = String()) + // + + //javadoc: LogisticRegression::load(filepath, nodeName) + public static LogisticRegression load(String filepath, String nodeName) + { + + LogisticRegression retVal = LogisticRegression.__fromPtr__(load_0(filepath, nodeName)); + + return retVal; + } + + //javadoc: LogisticRegression::load(filepath) + public static LogisticRegression load(String filepath) + { + + LogisticRegression retVal = LogisticRegression.__fromPtr__(load_1(filepath)); + + return retVal; + } + + + // + // C++: TermCriteria cv::ml::LogisticRegression::getTermCriteria() + // + + //javadoc: LogisticRegression::getTermCriteria() + public TermCriteria getTermCriteria() + { + + TermCriteria retVal = new TermCriteria(getTermCriteria_0(nativeObj)); + + return retVal; + } + + + // + // C++: double cv::ml::LogisticRegression::getLearningRate() + // + + //javadoc: LogisticRegression::getLearningRate() + public double getLearningRate() + { + + double retVal = getLearningRate_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ml::LogisticRegression::predict(Mat samples, Mat& results = Mat(), int flags = 0) + // + + //javadoc: LogisticRegression::predict(samples, results, flags) + public float predict(Mat samples, Mat results, int flags) + { + + float retVal = predict_0(nativeObj, samples.nativeObj, results.nativeObj, flags); + + return retVal; + } + + //javadoc: LogisticRegression::predict(samples, results) + public float predict(Mat samples, Mat results) + { + + float retVal = predict_1(nativeObj, samples.nativeObj, results.nativeObj); + + return retVal; + } + + //javadoc: LogisticRegression::predict(samples) + public float predict(Mat samples) + { + + float retVal = predict_2(nativeObj, samples.nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::LogisticRegression::getIterations() + // + + //javadoc: LogisticRegression::getIterations() + public int getIterations() + { + + int retVal = getIterations_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::LogisticRegression::getMiniBatchSize() + // + + //javadoc: LogisticRegression::getMiniBatchSize() + public int getMiniBatchSize() + { + + int retVal = getMiniBatchSize_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::LogisticRegression::getRegularization() + // + + //javadoc: LogisticRegression::getRegularization() + public int getRegularization() + { + + int retVal = getRegularization_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::LogisticRegression::getTrainMethod() + // + + //javadoc: LogisticRegression::getTrainMethod() + public int getTrainMethod() + { + + int retVal = getTrainMethod_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::ml::LogisticRegression::setIterations(int val) + // + + //javadoc: LogisticRegression::setIterations(val) + public void setIterations(int val) + { + + setIterations_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::LogisticRegression::setLearningRate(double val) + // + + //javadoc: LogisticRegression::setLearningRate(val) + public void setLearningRate(double val) + { + + setLearningRate_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::LogisticRegression::setMiniBatchSize(int val) + // + + //javadoc: LogisticRegression::setMiniBatchSize(val) + public void setMiniBatchSize(int val) + { + + setMiniBatchSize_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::LogisticRegression::setRegularization(int val) + // + + //javadoc: LogisticRegression::setRegularization(val) + public void setRegularization(int val) + { + + setRegularization_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::LogisticRegression::setTermCriteria(TermCriteria val) + // + + //javadoc: LogisticRegression::setTermCriteria(val) + public void setTermCriteria(TermCriteria val) + { + + setTermCriteria_0(nativeObj, val.type, val.maxCount, val.epsilon); + + return; + } + + + // + // C++: void cv::ml::LogisticRegression::setTrainMethod(int val) + // + + //javadoc: LogisticRegression::setTrainMethod(val) + public void setTrainMethod(int val) + { + + setTrainMethod_0(nativeObj, val); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: Mat cv::ml::LogisticRegression::get_learnt_thetas() + private static native long get_learnt_thetas_0(long nativeObj); + + // C++: static Ptr_LogisticRegression cv::ml::LogisticRegression::create() + private static native long create_0(); + + // C++: static Ptr_LogisticRegression cv::ml::LogisticRegression::load(String filepath, String nodeName = String()) + private static native long load_0(String filepath, String nodeName); + private static native long load_1(String filepath); + + // C++: TermCriteria cv::ml::LogisticRegression::getTermCriteria() + private static native double[] getTermCriteria_0(long nativeObj); + + // C++: double cv::ml::LogisticRegression::getLearningRate() + private static native double getLearningRate_0(long nativeObj); + + // C++: float cv::ml::LogisticRegression::predict(Mat samples, Mat& results = Mat(), int flags = 0) + private static native float predict_0(long nativeObj, long samples_nativeObj, long results_nativeObj, int flags); + private static native float predict_1(long nativeObj, long samples_nativeObj, long results_nativeObj); + private static native float predict_2(long nativeObj, long samples_nativeObj); + + // C++: int cv::ml::LogisticRegression::getIterations() + private static native int getIterations_0(long nativeObj); + + // C++: int cv::ml::LogisticRegression::getMiniBatchSize() + private static native int getMiniBatchSize_0(long nativeObj); + + // C++: int cv::ml::LogisticRegression::getRegularization() + private static native int getRegularization_0(long nativeObj); + + // C++: int cv::ml::LogisticRegression::getTrainMethod() + private static native int getTrainMethod_0(long nativeObj); + + // C++: void cv::ml::LogisticRegression::setIterations(int val) + private static native void setIterations_0(long nativeObj, int val); + + // C++: void cv::ml::LogisticRegression::setLearningRate(double val) + private static native void setLearningRate_0(long nativeObj, double val); + + // C++: void cv::ml::LogisticRegression::setMiniBatchSize(int val) + private static native void setMiniBatchSize_0(long nativeObj, int val); + + // C++: void cv::ml::LogisticRegression::setRegularization(int val) + private static native void setRegularization_0(long nativeObj, int val); + + // C++: void cv::ml::LogisticRegression::setTermCriteria(TermCriteria val) + private static native void setTermCriteria_0(long nativeObj, int val_type, int val_maxCount, double val_epsilon); + + // C++: void cv::ml::LogisticRegression::setTrainMethod(int val) + private static native void setTrainMethod_0(long nativeObj, int val); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ml/Ml.java b/OpenCV/src/main/java/org/opencv/ml/Ml.java new file mode 100644 index 00000000..a7f4679c --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ml/Ml.java @@ -0,0 +1,34 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ml; + + + +// C++: class Ml +//javadoc: Ml + +public class Ml { + + // C++: enum SampleTypes + public static final int + ROW_SAMPLE = 0, + COL_SAMPLE = 1; + + + // C++: enum VariableTypes + public static final int + VAR_NUMERICAL = 0, + VAR_ORDERED = 0, + VAR_CATEGORICAL = 1; + + + // C++: enum ErrorTypes + public static final int + TEST_ERROR = 0, + TRAIN_ERROR = 1; + + + + +} diff --git a/OpenCV/src/main/java/org/opencv/ml/NormalBayesClassifier.java b/OpenCV/src/main/java/org/opencv/ml/NormalBayesClassifier.java new file mode 100644 index 00000000..b8039312 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ml/NormalBayesClassifier.java @@ -0,0 +1,102 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ml; + +import java.lang.String; +import org.opencv.core.Mat; +import org.opencv.ml.NormalBayesClassifier; +import org.opencv.ml.StatModel; + +// C++: class NormalBayesClassifier +//javadoc: NormalBayesClassifier + +public class NormalBayesClassifier extends StatModel { + + protected NormalBayesClassifier(long addr) { super(addr); } + + // internal usage only + public static NormalBayesClassifier __fromPtr__(long addr) { return new NormalBayesClassifier(addr); } + + // + // C++: static Ptr_NormalBayesClassifier cv::ml::NormalBayesClassifier::create() + // + + //javadoc: NormalBayesClassifier::create() + public static NormalBayesClassifier create() + { + + NormalBayesClassifier retVal = NormalBayesClassifier.__fromPtr__(create_0()); + + return retVal; + } + + + // + // C++: static Ptr_NormalBayesClassifier cv::ml::NormalBayesClassifier::load(String filepath, String nodeName = String()) + // + + //javadoc: NormalBayesClassifier::load(filepath, nodeName) + public static NormalBayesClassifier load(String filepath, String nodeName) + { + + NormalBayesClassifier retVal = NormalBayesClassifier.__fromPtr__(load_0(filepath, nodeName)); + + return retVal; + } + + //javadoc: NormalBayesClassifier::load(filepath) + public static NormalBayesClassifier load(String filepath) + { + + NormalBayesClassifier retVal = NormalBayesClassifier.__fromPtr__(load_1(filepath)); + + return retVal; + } + + + // + // C++: float cv::ml::NormalBayesClassifier::predictProb(Mat inputs, Mat& outputs, Mat& outputProbs, int flags = 0) + // + + //javadoc: NormalBayesClassifier::predictProb(inputs, outputs, outputProbs, flags) + public float predictProb(Mat inputs, Mat outputs, Mat outputProbs, int flags) + { + + float retVal = predictProb_0(nativeObj, inputs.nativeObj, outputs.nativeObj, outputProbs.nativeObj, flags); + + return retVal; + } + + //javadoc: NormalBayesClassifier::predictProb(inputs, outputs, outputProbs) + public float predictProb(Mat inputs, Mat outputs, Mat outputProbs) + { + + float retVal = predictProb_1(nativeObj, inputs.nativeObj, outputs.nativeObj, outputProbs.nativeObj); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_NormalBayesClassifier cv::ml::NormalBayesClassifier::create() + private static native long create_0(); + + // C++: static Ptr_NormalBayesClassifier cv::ml::NormalBayesClassifier::load(String filepath, String nodeName = String()) + private static native long load_0(String filepath, String nodeName); + private static native long load_1(String filepath); + + // C++: float cv::ml::NormalBayesClassifier::predictProb(Mat inputs, Mat& outputs, Mat& outputProbs, int flags = 0) + private static native float predictProb_0(long nativeObj, long inputs_nativeObj, long outputs_nativeObj, long outputProbs_nativeObj, int flags); + private static native float predictProb_1(long nativeObj, long inputs_nativeObj, long outputs_nativeObj, long outputProbs_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ml/ParamGrid.java b/OpenCV/src/main/java/org/opencv/ml/ParamGrid.java new file mode 100644 index 00000000..fa6dc199 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ml/ParamGrid.java @@ -0,0 +1,180 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ml; + +import org.opencv.ml.ParamGrid; + +// C++: class ParamGrid +//javadoc: ParamGrid + +public class ParamGrid { + + protected final long nativeObj; + protected ParamGrid(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static ParamGrid __fromPtr__(long addr) { return new ParamGrid(addr); } + + // + // C++: static Ptr_ParamGrid cv::ml::ParamGrid::create(double minVal = 0., double maxVal = 0., double logstep = 1.) + // + + //javadoc: ParamGrid::create(minVal, maxVal, logstep) + public static ParamGrid create(double minVal, double maxVal, double logstep) + { + + ParamGrid retVal = ParamGrid.__fromPtr__(create_0(minVal, maxVal, logstep)); + + return retVal; + } + + //javadoc: ParamGrid::create(minVal, maxVal) + public static ParamGrid create(double minVal, double maxVal) + { + + ParamGrid retVal = ParamGrid.__fromPtr__(create_1(minVal, maxVal)); + + return retVal; + } + + //javadoc: ParamGrid::create(minVal) + public static ParamGrid create(double minVal) + { + + ParamGrid retVal = ParamGrid.__fromPtr__(create_2(minVal)); + + return retVal; + } + + //javadoc: ParamGrid::create() + public static ParamGrid create() + { + + ParamGrid retVal = ParamGrid.__fromPtr__(create_3()); + + return retVal; + } + + + // + // C++: double ParamGrid::minVal + // + + //javadoc: ParamGrid::get_minVal() + public double get_minVal() + { + + double retVal = get_minVal_0(nativeObj); + + return retVal; + } + + + // + // C++: void ParamGrid::minVal + // + + //javadoc: ParamGrid::set_minVal(minVal) + public void set_minVal(double minVal) + { + + set_minVal_0(nativeObj, minVal); + + return; + } + + + // + // C++: double ParamGrid::maxVal + // + + //javadoc: ParamGrid::get_maxVal() + public double get_maxVal() + { + + double retVal = get_maxVal_0(nativeObj); + + return retVal; + } + + + // + // C++: void ParamGrid::maxVal + // + + //javadoc: ParamGrid::set_maxVal(maxVal) + public void set_maxVal(double maxVal) + { + + set_maxVal_0(nativeObj, maxVal); + + return; + } + + + // + // C++: double ParamGrid::logStep + // + + //javadoc: ParamGrid::get_logStep() + public double get_logStep() + { + + double retVal = get_logStep_0(nativeObj); + + return retVal; + } + + + // + // C++: void ParamGrid::logStep + // + + //javadoc: ParamGrid::set_logStep(logStep) + public void set_logStep(double logStep) + { + + set_logStep_0(nativeObj, logStep); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_ParamGrid cv::ml::ParamGrid::create(double minVal = 0., double maxVal = 0., double logstep = 1.) + private static native long create_0(double minVal, double maxVal, double logstep); + private static native long create_1(double minVal, double maxVal); + private static native long create_2(double minVal); + private static native long create_3(); + + // C++: double ParamGrid::minVal + private static native double get_minVal_0(long nativeObj); + + // C++: void ParamGrid::minVal + private static native void set_minVal_0(long nativeObj, double minVal); + + // C++: double ParamGrid::maxVal + private static native double get_maxVal_0(long nativeObj); + + // C++: void ParamGrid::maxVal + private static native void set_maxVal_0(long nativeObj, double maxVal); + + // C++: double ParamGrid::logStep + private static native double get_logStep_0(long nativeObj); + + // C++: void ParamGrid::logStep + private static native void set_logStep_0(long nativeObj, double logStep); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ml/RTrees.java b/OpenCV/src/main/java/org/opencv/ml/RTrees.java new file mode 100644 index 00000000..80297ed1 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ml/RTrees.java @@ -0,0 +1,212 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ml; + +import java.lang.String; +import org.opencv.core.Mat; +import org.opencv.core.TermCriteria; +import org.opencv.ml.DTrees; +import org.opencv.ml.RTrees; + +// C++: class RTrees +//javadoc: RTrees + +public class RTrees extends DTrees { + + protected RTrees(long addr) { super(addr); } + + // internal usage only + public static RTrees __fromPtr__(long addr) { return new RTrees(addr); } + + // + // C++: Mat cv::ml::RTrees::getVarImportance() + // + + //javadoc: RTrees::getVarImportance() + public Mat getVarImportance() + { + + Mat retVal = new Mat(getVarImportance_0(nativeObj)); + + return retVal; + } + + + // + // C++: static Ptr_RTrees cv::ml::RTrees::create() + // + + //javadoc: RTrees::create() + public static RTrees create() + { + + RTrees retVal = RTrees.__fromPtr__(create_0()); + + return retVal; + } + + + // + // C++: static Ptr_RTrees cv::ml::RTrees::load(String filepath, String nodeName = String()) + // + + //javadoc: RTrees::load(filepath, nodeName) + public static RTrees load(String filepath, String nodeName) + { + + RTrees retVal = RTrees.__fromPtr__(load_0(filepath, nodeName)); + + return retVal; + } + + //javadoc: RTrees::load(filepath) + public static RTrees load(String filepath) + { + + RTrees retVal = RTrees.__fromPtr__(load_1(filepath)); + + return retVal; + } + + + // + // C++: TermCriteria cv::ml::RTrees::getTermCriteria() + // + + //javadoc: RTrees::getTermCriteria() + public TermCriteria getTermCriteria() + { + + TermCriteria retVal = new TermCriteria(getTermCriteria_0(nativeObj)); + + return retVal; + } + + + // + // C++: bool cv::ml::RTrees::getCalculateVarImportance() + // + + //javadoc: RTrees::getCalculateVarImportance() + public boolean getCalculateVarImportance() + { + + boolean retVal = getCalculateVarImportance_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::RTrees::getActiveVarCount() + // + + //javadoc: RTrees::getActiveVarCount() + public int getActiveVarCount() + { + + int retVal = getActiveVarCount_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::ml::RTrees::getVotes(Mat samples, Mat& results, int flags) + // + + //javadoc: RTrees::getVotes(samples, results, flags) + public void getVotes(Mat samples, Mat results, int flags) + { + + getVotes_0(nativeObj, samples.nativeObj, results.nativeObj, flags); + + return; + } + + + // + // C++: void cv::ml::RTrees::setActiveVarCount(int val) + // + + //javadoc: RTrees::setActiveVarCount(val) + public void setActiveVarCount(int val) + { + + setActiveVarCount_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::RTrees::setCalculateVarImportance(bool val) + // + + //javadoc: RTrees::setCalculateVarImportance(val) + public void setCalculateVarImportance(boolean val) + { + + setCalculateVarImportance_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::RTrees::setTermCriteria(TermCriteria val) + // + + //javadoc: RTrees::setTermCriteria(val) + public void setTermCriteria(TermCriteria val) + { + + setTermCriteria_0(nativeObj, val.type, val.maxCount, val.epsilon); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: Mat cv::ml::RTrees::getVarImportance() + private static native long getVarImportance_0(long nativeObj); + + // C++: static Ptr_RTrees cv::ml::RTrees::create() + private static native long create_0(); + + // C++: static Ptr_RTrees cv::ml::RTrees::load(String filepath, String nodeName = String()) + private static native long load_0(String filepath, String nodeName); + private static native long load_1(String filepath); + + // C++: TermCriteria cv::ml::RTrees::getTermCriteria() + private static native double[] getTermCriteria_0(long nativeObj); + + // C++: bool cv::ml::RTrees::getCalculateVarImportance() + private static native boolean getCalculateVarImportance_0(long nativeObj); + + // C++: int cv::ml::RTrees::getActiveVarCount() + private static native int getActiveVarCount_0(long nativeObj); + + // C++: void cv::ml::RTrees::getVotes(Mat samples, Mat& results, int flags) + private static native void getVotes_0(long nativeObj, long samples_nativeObj, long results_nativeObj, int flags); + + // C++: void cv::ml::RTrees::setActiveVarCount(int val) + private static native void setActiveVarCount_0(long nativeObj, int val); + + // C++: void cv::ml::RTrees::setCalculateVarImportance(bool val) + private static native void setCalculateVarImportance_0(long nativeObj, boolean val); + + // C++: void cv::ml::RTrees::setTermCriteria(TermCriteria val) + private static native void setTermCriteria_0(long nativeObj, int val_type, int val_maxCount, double val_epsilon); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ml/SVM.java b/OpenCV/src/main/java/org/opencv/ml/SVM.java new file mode 100644 index 00000000..5100d68e --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ml/SVM.java @@ -0,0 +1,602 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ml; + +import java.lang.String; +import org.opencv.core.Mat; +import org.opencv.core.TermCriteria; +import org.opencv.ml.ParamGrid; +import org.opencv.ml.SVM; +import org.opencv.ml.StatModel; + +// C++: class SVM +//javadoc: SVM + +public class SVM extends StatModel { + + protected SVM(long addr) { super(addr); } + + // internal usage only + public static SVM __fromPtr__(long addr) { return new SVM(addr); } + + // C++: enum KernelTypes + public static final int + CUSTOM = -1, + LINEAR = 0, + POLY = 1, + RBF = 2, + SIGMOID = 3, + CHI2 = 4, + INTER = 5; + + + // C++: enum Types + public static final int + C_SVC = 100, + NU_SVC = 101, + ONE_CLASS = 102, + EPS_SVR = 103, + NU_SVR = 104; + + + // C++: enum ParamTypes + public static final int + C = 0, + GAMMA = 1, + P = 2, + NU = 3, + COEF = 4, + DEGREE = 5; + + + // + // C++: Mat cv::ml::SVM::getClassWeights() + // + + //javadoc: SVM::getClassWeights() + public Mat getClassWeights() + { + + Mat retVal = new Mat(getClassWeights_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::SVM::getSupportVectors() + // + + //javadoc: SVM::getSupportVectors() + public Mat getSupportVectors() + { + + Mat retVal = new Mat(getSupportVectors_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::SVM::getUncompressedSupportVectors() + // + + //javadoc: SVM::getUncompressedSupportVectors() + public Mat getUncompressedSupportVectors() + { + + Mat retVal = new Mat(getUncompressedSupportVectors_0(nativeObj)); + + return retVal; + } + + + // + // C++: static Ptr_ParamGrid cv::ml::SVM::getDefaultGridPtr(int param_id) + // + + //javadoc: SVM::getDefaultGridPtr(param_id) + public static ParamGrid getDefaultGridPtr(int param_id) + { + + ParamGrid retVal = ParamGrid.__fromPtr__(getDefaultGridPtr_0(param_id)); + + return retVal; + } + + + // + // C++: static Ptr_SVM cv::ml::SVM::create() + // + + //javadoc: SVM::create() + public static SVM create() + { + + SVM retVal = SVM.__fromPtr__(create_0()); + + return retVal; + } + + + // + // C++: static Ptr_SVM cv::ml::SVM::load(String filepath) + // + + //javadoc: SVM::load(filepath) + public static SVM load(String filepath) + { + + SVM retVal = SVM.__fromPtr__(load_0(filepath)); + + return retVal; + } + + + // + // C++: TermCriteria cv::ml::SVM::getTermCriteria() + // + + //javadoc: SVM::getTermCriteria() + public TermCriteria getTermCriteria() + { + + TermCriteria retVal = new TermCriteria(getTermCriteria_0(nativeObj)); + + return retVal; + } + + + // + // C++: bool cv::ml::SVM::trainAuto(Mat samples, int layout, Mat responses, int kFold = 10, Ptr_ParamGrid Cgrid = SVM::getDefaultGridPtr(SVM::C), Ptr_ParamGrid gammaGrid = SVM::getDefaultGridPtr(SVM::GAMMA), Ptr_ParamGrid pGrid = SVM::getDefaultGridPtr(SVM::P), Ptr_ParamGrid nuGrid = SVM::getDefaultGridPtr(SVM::NU), Ptr_ParamGrid coeffGrid = SVM::getDefaultGridPtr(SVM::COEF), Ptr_ParamGrid degreeGrid = SVM::getDefaultGridPtr(SVM::DEGREE), bool balanced = false) + // + + //javadoc: SVM::trainAuto(samples, layout, responses, kFold, Cgrid, gammaGrid, pGrid, nuGrid, coeffGrid, degreeGrid, balanced) + public boolean trainAuto(Mat samples, int layout, Mat responses, int kFold, ParamGrid Cgrid, ParamGrid gammaGrid, ParamGrid pGrid, ParamGrid nuGrid, ParamGrid coeffGrid, ParamGrid degreeGrid, boolean balanced) + { + + boolean retVal = trainAuto_0(nativeObj, samples.nativeObj, layout, responses.nativeObj, kFold, Cgrid.getNativeObjAddr(), gammaGrid.getNativeObjAddr(), pGrid.getNativeObjAddr(), nuGrid.getNativeObjAddr(), coeffGrid.getNativeObjAddr(), degreeGrid.getNativeObjAddr(), balanced); + + return retVal; + } + + //javadoc: SVM::trainAuto(samples, layout, responses, kFold, Cgrid, gammaGrid, pGrid, nuGrid, coeffGrid, degreeGrid) + public boolean trainAuto(Mat samples, int layout, Mat responses, int kFold, ParamGrid Cgrid, ParamGrid gammaGrid, ParamGrid pGrid, ParamGrid nuGrid, ParamGrid coeffGrid, ParamGrid degreeGrid) + { + + boolean retVal = trainAuto_1(nativeObj, samples.nativeObj, layout, responses.nativeObj, kFold, Cgrid.getNativeObjAddr(), gammaGrid.getNativeObjAddr(), pGrid.getNativeObjAddr(), nuGrid.getNativeObjAddr(), coeffGrid.getNativeObjAddr(), degreeGrid.getNativeObjAddr()); + + return retVal; + } + + //javadoc: SVM::trainAuto(samples, layout, responses, kFold, Cgrid, gammaGrid, pGrid, nuGrid, coeffGrid) + public boolean trainAuto(Mat samples, int layout, Mat responses, int kFold, ParamGrid Cgrid, ParamGrid gammaGrid, ParamGrid pGrid, ParamGrid nuGrid, ParamGrid coeffGrid) + { + + boolean retVal = trainAuto_2(nativeObj, samples.nativeObj, layout, responses.nativeObj, kFold, Cgrid.getNativeObjAddr(), gammaGrid.getNativeObjAddr(), pGrid.getNativeObjAddr(), nuGrid.getNativeObjAddr(), coeffGrid.getNativeObjAddr()); + + return retVal; + } + + //javadoc: SVM::trainAuto(samples, layout, responses, kFold, Cgrid, gammaGrid, pGrid, nuGrid) + public boolean trainAuto(Mat samples, int layout, Mat responses, int kFold, ParamGrid Cgrid, ParamGrid gammaGrid, ParamGrid pGrid, ParamGrid nuGrid) + { + + boolean retVal = trainAuto_3(nativeObj, samples.nativeObj, layout, responses.nativeObj, kFold, Cgrid.getNativeObjAddr(), gammaGrid.getNativeObjAddr(), pGrid.getNativeObjAddr(), nuGrid.getNativeObjAddr()); + + return retVal; + } + + //javadoc: SVM::trainAuto(samples, layout, responses, kFold, Cgrid, gammaGrid, pGrid) + public boolean trainAuto(Mat samples, int layout, Mat responses, int kFold, ParamGrid Cgrid, ParamGrid gammaGrid, ParamGrid pGrid) + { + + boolean retVal = trainAuto_4(nativeObj, samples.nativeObj, layout, responses.nativeObj, kFold, Cgrid.getNativeObjAddr(), gammaGrid.getNativeObjAddr(), pGrid.getNativeObjAddr()); + + return retVal; + } + + //javadoc: SVM::trainAuto(samples, layout, responses, kFold, Cgrid, gammaGrid) + public boolean trainAuto(Mat samples, int layout, Mat responses, int kFold, ParamGrid Cgrid, ParamGrid gammaGrid) + { + + boolean retVal = trainAuto_5(nativeObj, samples.nativeObj, layout, responses.nativeObj, kFold, Cgrid.getNativeObjAddr(), gammaGrid.getNativeObjAddr()); + + return retVal; + } + + //javadoc: SVM::trainAuto(samples, layout, responses, kFold, Cgrid) + public boolean trainAuto(Mat samples, int layout, Mat responses, int kFold, ParamGrid Cgrid) + { + + boolean retVal = trainAuto_6(nativeObj, samples.nativeObj, layout, responses.nativeObj, kFold, Cgrid.getNativeObjAddr()); + + return retVal; + } + + //javadoc: SVM::trainAuto(samples, layout, responses, kFold) + public boolean trainAuto(Mat samples, int layout, Mat responses, int kFold) + { + + boolean retVal = trainAuto_7(nativeObj, samples.nativeObj, layout, responses.nativeObj, kFold); + + return retVal; + } + + //javadoc: SVM::trainAuto(samples, layout, responses) + public boolean trainAuto(Mat samples, int layout, Mat responses) + { + + boolean retVal = trainAuto_8(nativeObj, samples.nativeObj, layout, responses.nativeObj); + + return retVal; + } + + + // + // C++: double cv::ml::SVM::getC() + // + + //javadoc: SVM::getC() + public double getC() + { + + double retVal = getC_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::ml::SVM::getCoef0() + // + + //javadoc: SVM::getCoef0() + public double getCoef0() + { + + double retVal = getCoef0_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::ml::SVM::getDecisionFunction(int i, Mat& alpha, Mat& svidx) + // + + //javadoc: SVM::getDecisionFunction(i, alpha, svidx) + public double getDecisionFunction(int i, Mat alpha, Mat svidx) + { + + double retVal = getDecisionFunction_0(nativeObj, i, alpha.nativeObj, svidx.nativeObj); + + return retVal; + } + + + // + // C++: double cv::ml::SVM::getDegree() + // + + //javadoc: SVM::getDegree() + public double getDegree() + { + + double retVal = getDegree_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::ml::SVM::getGamma() + // + + //javadoc: SVM::getGamma() + public double getGamma() + { + + double retVal = getGamma_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::ml::SVM::getNu() + // + + //javadoc: SVM::getNu() + public double getNu() + { + + double retVal = getNu_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::ml::SVM::getP() + // + + //javadoc: SVM::getP() + public double getP() + { + + double retVal = getP_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::SVM::getKernelType() + // + + //javadoc: SVM::getKernelType() + public int getKernelType() + { + + int retVal = getKernelType_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::SVM::getType() + // + + //javadoc: SVM::getType() + public int getType() + { + + int retVal = getType_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::ml::SVM::setC(double val) + // + + //javadoc: SVM::setC(val) + public void setC(double val) + { + + setC_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::SVM::setClassWeights(Mat val) + // + + //javadoc: SVM::setClassWeights(val) + public void setClassWeights(Mat val) + { + + setClassWeights_0(nativeObj, val.nativeObj); + + return; + } + + + // + // C++: void cv::ml::SVM::setCoef0(double val) + // + + //javadoc: SVM::setCoef0(val) + public void setCoef0(double val) + { + + setCoef0_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::SVM::setDegree(double val) + // + + //javadoc: SVM::setDegree(val) + public void setDegree(double val) + { + + setDegree_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::SVM::setGamma(double val) + // + + //javadoc: SVM::setGamma(val) + public void setGamma(double val) + { + + setGamma_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::SVM::setKernel(int kernelType) + // + + //javadoc: SVM::setKernel(kernelType) + public void setKernel(int kernelType) + { + + setKernel_0(nativeObj, kernelType); + + return; + } + + + // + // C++: void cv::ml::SVM::setNu(double val) + // + + //javadoc: SVM::setNu(val) + public void setNu(double val) + { + + setNu_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::SVM::setP(double val) + // + + //javadoc: SVM::setP(val) + public void setP(double val) + { + + setP_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::ml::SVM::setTermCriteria(TermCriteria val) + // + + //javadoc: SVM::setTermCriteria(val) + public void setTermCriteria(TermCriteria val) + { + + setTermCriteria_0(nativeObj, val.type, val.maxCount, val.epsilon); + + return; + } + + + // + // C++: void cv::ml::SVM::setType(int val) + // + + //javadoc: SVM::setType(val) + public void setType(int val) + { + + setType_0(nativeObj, val); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: Mat cv::ml::SVM::getClassWeights() + private static native long getClassWeights_0(long nativeObj); + + // C++: Mat cv::ml::SVM::getSupportVectors() + private static native long getSupportVectors_0(long nativeObj); + + // C++: Mat cv::ml::SVM::getUncompressedSupportVectors() + private static native long getUncompressedSupportVectors_0(long nativeObj); + + // C++: static Ptr_ParamGrid cv::ml::SVM::getDefaultGridPtr(int param_id) + private static native long getDefaultGridPtr_0(int param_id); + + // C++: static Ptr_SVM cv::ml::SVM::create() + private static native long create_0(); + + // C++: static Ptr_SVM cv::ml::SVM::load(String filepath) + private static native long load_0(String filepath); + + // C++: TermCriteria cv::ml::SVM::getTermCriteria() + private static native double[] getTermCriteria_0(long nativeObj); + + // C++: bool cv::ml::SVM::trainAuto(Mat samples, int layout, Mat responses, int kFold = 10, Ptr_ParamGrid Cgrid = SVM::getDefaultGridPtr(SVM::C), Ptr_ParamGrid gammaGrid = SVM::getDefaultGridPtr(SVM::GAMMA), Ptr_ParamGrid pGrid = SVM::getDefaultGridPtr(SVM::P), Ptr_ParamGrid nuGrid = SVM::getDefaultGridPtr(SVM::NU), Ptr_ParamGrid coeffGrid = SVM::getDefaultGridPtr(SVM::COEF), Ptr_ParamGrid degreeGrid = SVM::getDefaultGridPtr(SVM::DEGREE), bool balanced = false) + private static native boolean trainAuto_0(long nativeObj, long samples_nativeObj, int layout, long responses_nativeObj, int kFold, long Cgrid_nativeObj, long gammaGrid_nativeObj, long pGrid_nativeObj, long nuGrid_nativeObj, long coeffGrid_nativeObj, long degreeGrid_nativeObj, boolean balanced); + private static native boolean trainAuto_1(long nativeObj, long samples_nativeObj, int layout, long responses_nativeObj, int kFold, long Cgrid_nativeObj, long gammaGrid_nativeObj, long pGrid_nativeObj, long nuGrid_nativeObj, long coeffGrid_nativeObj, long degreeGrid_nativeObj); + private static native boolean trainAuto_2(long nativeObj, long samples_nativeObj, int layout, long responses_nativeObj, int kFold, long Cgrid_nativeObj, long gammaGrid_nativeObj, long pGrid_nativeObj, long nuGrid_nativeObj, long coeffGrid_nativeObj); + private static native boolean trainAuto_3(long nativeObj, long samples_nativeObj, int layout, long responses_nativeObj, int kFold, long Cgrid_nativeObj, long gammaGrid_nativeObj, long pGrid_nativeObj, long nuGrid_nativeObj); + private static native boolean trainAuto_4(long nativeObj, long samples_nativeObj, int layout, long responses_nativeObj, int kFold, long Cgrid_nativeObj, long gammaGrid_nativeObj, long pGrid_nativeObj); + private static native boolean trainAuto_5(long nativeObj, long samples_nativeObj, int layout, long responses_nativeObj, int kFold, long Cgrid_nativeObj, long gammaGrid_nativeObj); + private static native boolean trainAuto_6(long nativeObj, long samples_nativeObj, int layout, long responses_nativeObj, int kFold, long Cgrid_nativeObj); + private static native boolean trainAuto_7(long nativeObj, long samples_nativeObj, int layout, long responses_nativeObj, int kFold); + private static native boolean trainAuto_8(long nativeObj, long samples_nativeObj, int layout, long responses_nativeObj); + + // C++: double cv::ml::SVM::getC() + private static native double getC_0(long nativeObj); + + // C++: double cv::ml::SVM::getCoef0() + private static native double getCoef0_0(long nativeObj); + + // C++: double cv::ml::SVM::getDecisionFunction(int i, Mat& alpha, Mat& svidx) + private static native double getDecisionFunction_0(long nativeObj, int i, long alpha_nativeObj, long svidx_nativeObj); + + // C++: double cv::ml::SVM::getDegree() + private static native double getDegree_0(long nativeObj); + + // C++: double cv::ml::SVM::getGamma() + private static native double getGamma_0(long nativeObj); + + // C++: double cv::ml::SVM::getNu() + private static native double getNu_0(long nativeObj); + + // C++: double cv::ml::SVM::getP() + private static native double getP_0(long nativeObj); + + // C++: int cv::ml::SVM::getKernelType() + private static native int getKernelType_0(long nativeObj); + + // C++: int cv::ml::SVM::getType() + private static native int getType_0(long nativeObj); + + // C++: void cv::ml::SVM::setC(double val) + private static native void setC_0(long nativeObj, double val); + + // C++: void cv::ml::SVM::setClassWeights(Mat val) + private static native void setClassWeights_0(long nativeObj, long val_nativeObj); + + // C++: void cv::ml::SVM::setCoef0(double val) + private static native void setCoef0_0(long nativeObj, double val); + + // C++: void cv::ml::SVM::setDegree(double val) + private static native void setDegree_0(long nativeObj, double val); + + // C++: void cv::ml::SVM::setGamma(double val) + private static native void setGamma_0(long nativeObj, double val); + + // C++: void cv::ml::SVM::setKernel(int kernelType) + private static native void setKernel_0(long nativeObj, int kernelType); + + // C++: void cv::ml::SVM::setNu(double val) + private static native void setNu_0(long nativeObj, double val); + + // C++: void cv::ml::SVM::setP(double val) + private static native void setP_0(long nativeObj, double val); + + // C++: void cv::ml::SVM::setTermCriteria(TermCriteria val) + private static native void setTermCriteria_0(long nativeObj, int val_type, int val_maxCount, double val_epsilon); + + // C++: void cv::ml::SVM::setType(int val) + private static native void setType_0(long nativeObj, int val); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ml/SVMSGD.java b/OpenCV/src/main/java/org/opencv/ml/SVMSGD.java new file mode 100644 index 00000000..539e527f --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ml/SVMSGD.java @@ -0,0 +1,363 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ml; + +import java.lang.String; +import org.opencv.core.Mat; +import org.opencv.core.TermCriteria; +import org.opencv.ml.SVMSGD; +import org.opencv.ml.StatModel; + +// C++: class SVMSGD +//javadoc: SVMSGD + +public class SVMSGD extends StatModel { + + protected SVMSGD(long addr) { super(addr); } + + // internal usage only + public static SVMSGD __fromPtr__(long addr) { return new SVMSGD(addr); } + + // C++: enum SvmsgdType + public static final int + SGD = 0, + ASGD = 1; + + + // C++: enum MarginType + public static final int + SOFT_MARGIN = 0, + HARD_MARGIN = 1; + + + // + // C++: Mat cv::ml::SVMSGD::getWeights() + // + + //javadoc: SVMSGD::getWeights() + public Mat getWeights() + { + + Mat retVal = new Mat(getWeights_0(nativeObj)); + + return retVal; + } + + + // + // C++: static Ptr_SVMSGD cv::ml::SVMSGD::create() + // + + //javadoc: SVMSGD::create() + public static SVMSGD create() + { + + SVMSGD retVal = SVMSGD.__fromPtr__(create_0()); + + return retVal; + } + + + // + // C++: static Ptr_SVMSGD cv::ml::SVMSGD::load(String filepath, String nodeName = String()) + // + + //javadoc: SVMSGD::load(filepath, nodeName) + public static SVMSGD load(String filepath, String nodeName) + { + + SVMSGD retVal = SVMSGD.__fromPtr__(load_0(filepath, nodeName)); + + return retVal; + } + + //javadoc: SVMSGD::load(filepath) + public static SVMSGD load(String filepath) + { + + SVMSGD retVal = SVMSGD.__fromPtr__(load_1(filepath)); + + return retVal; + } + + + // + // C++: TermCriteria cv::ml::SVMSGD::getTermCriteria() + // + + //javadoc: SVMSGD::getTermCriteria() + public TermCriteria getTermCriteria() + { + + TermCriteria retVal = new TermCriteria(getTermCriteria_0(nativeObj)); + + return retVal; + } + + + // + // C++: float cv::ml::SVMSGD::getInitialStepSize() + // + + //javadoc: SVMSGD::getInitialStepSize() + public float getInitialStepSize() + { + + float retVal = getInitialStepSize_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ml::SVMSGD::getMarginRegularization() + // + + //javadoc: SVMSGD::getMarginRegularization() + public float getMarginRegularization() + { + + float retVal = getMarginRegularization_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ml::SVMSGD::getShift() + // + + //javadoc: SVMSGD::getShift() + public float getShift() + { + + float retVal = getShift_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ml::SVMSGD::getStepDecreasingPower() + // + + //javadoc: SVMSGD::getStepDecreasingPower() + public float getStepDecreasingPower() + { + + float retVal = getStepDecreasingPower_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::SVMSGD::getMarginType() + // + + //javadoc: SVMSGD::getMarginType() + public int getMarginType() + { + + int retVal = getMarginType_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::SVMSGD::getSvmsgdType() + // + + //javadoc: SVMSGD::getSvmsgdType() + public int getSvmsgdType() + { + + int retVal = getSvmsgdType_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::ml::SVMSGD::setInitialStepSize(float InitialStepSize) + // + + //javadoc: SVMSGD::setInitialStepSize(InitialStepSize) + public void setInitialStepSize(float InitialStepSize) + { + + setInitialStepSize_0(nativeObj, InitialStepSize); + + return; + } + + + // + // C++: void cv::ml::SVMSGD::setMarginRegularization(float marginRegularization) + // + + //javadoc: SVMSGD::setMarginRegularization(marginRegularization) + public void setMarginRegularization(float marginRegularization) + { + + setMarginRegularization_0(nativeObj, marginRegularization); + + return; + } + + + // + // C++: void cv::ml::SVMSGD::setMarginType(int marginType) + // + + //javadoc: SVMSGD::setMarginType(marginType) + public void setMarginType(int marginType) + { + + setMarginType_0(nativeObj, marginType); + + return; + } + + + // + // C++: void cv::ml::SVMSGD::setOptimalParameters(int svmsgdType = SVMSGD::ASGD, int marginType = SVMSGD::SOFT_MARGIN) + // + + //javadoc: SVMSGD::setOptimalParameters(svmsgdType, marginType) + public void setOptimalParameters(int svmsgdType, int marginType) + { + + setOptimalParameters_0(nativeObj, svmsgdType, marginType); + + return; + } + + //javadoc: SVMSGD::setOptimalParameters(svmsgdType) + public void setOptimalParameters(int svmsgdType) + { + + setOptimalParameters_1(nativeObj, svmsgdType); + + return; + } + + //javadoc: SVMSGD::setOptimalParameters() + public void setOptimalParameters() + { + + setOptimalParameters_2(nativeObj); + + return; + } + + + // + // C++: void cv::ml::SVMSGD::setStepDecreasingPower(float stepDecreasingPower) + // + + //javadoc: SVMSGD::setStepDecreasingPower(stepDecreasingPower) + public void setStepDecreasingPower(float stepDecreasingPower) + { + + setStepDecreasingPower_0(nativeObj, stepDecreasingPower); + + return; + } + + + // + // C++: void cv::ml::SVMSGD::setSvmsgdType(int svmsgdType) + // + + //javadoc: SVMSGD::setSvmsgdType(svmsgdType) + public void setSvmsgdType(int svmsgdType) + { + + setSvmsgdType_0(nativeObj, svmsgdType); + + return; + } + + + // + // C++: void cv::ml::SVMSGD::setTermCriteria(TermCriteria val) + // + + //javadoc: SVMSGD::setTermCriteria(val) + public void setTermCriteria(TermCriteria val) + { + + setTermCriteria_0(nativeObj, val.type, val.maxCount, val.epsilon); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: Mat cv::ml::SVMSGD::getWeights() + private static native long getWeights_0(long nativeObj); + + // C++: static Ptr_SVMSGD cv::ml::SVMSGD::create() + private static native long create_0(); + + // C++: static Ptr_SVMSGD cv::ml::SVMSGD::load(String filepath, String nodeName = String()) + private static native long load_0(String filepath, String nodeName); + private static native long load_1(String filepath); + + // C++: TermCriteria cv::ml::SVMSGD::getTermCriteria() + private static native double[] getTermCriteria_0(long nativeObj); + + // C++: float cv::ml::SVMSGD::getInitialStepSize() + private static native float getInitialStepSize_0(long nativeObj); + + // C++: float cv::ml::SVMSGD::getMarginRegularization() + private static native float getMarginRegularization_0(long nativeObj); + + // C++: float cv::ml::SVMSGD::getShift() + private static native float getShift_0(long nativeObj); + + // C++: float cv::ml::SVMSGD::getStepDecreasingPower() + private static native float getStepDecreasingPower_0(long nativeObj); + + // C++: int cv::ml::SVMSGD::getMarginType() + private static native int getMarginType_0(long nativeObj); + + // C++: int cv::ml::SVMSGD::getSvmsgdType() + private static native int getSvmsgdType_0(long nativeObj); + + // C++: void cv::ml::SVMSGD::setInitialStepSize(float InitialStepSize) + private static native void setInitialStepSize_0(long nativeObj, float InitialStepSize); + + // C++: void cv::ml::SVMSGD::setMarginRegularization(float marginRegularization) + private static native void setMarginRegularization_0(long nativeObj, float marginRegularization); + + // C++: void cv::ml::SVMSGD::setMarginType(int marginType) + private static native void setMarginType_0(long nativeObj, int marginType); + + // C++: void cv::ml::SVMSGD::setOptimalParameters(int svmsgdType = SVMSGD::ASGD, int marginType = SVMSGD::SOFT_MARGIN) + private static native void setOptimalParameters_0(long nativeObj, int svmsgdType, int marginType); + private static native void setOptimalParameters_1(long nativeObj, int svmsgdType); + private static native void setOptimalParameters_2(long nativeObj); + + // C++: void cv::ml::SVMSGD::setStepDecreasingPower(float stepDecreasingPower) + private static native void setStepDecreasingPower_0(long nativeObj, float stepDecreasingPower); + + // C++: void cv::ml::SVMSGD::setSvmsgdType(int svmsgdType) + private static native void setSvmsgdType_0(long nativeObj, int svmsgdType); + + // C++: void cv::ml::SVMSGD::setTermCriteria(TermCriteria val) + private static native void setTermCriteria_0(long nativeObj, int val_type, int val_maxCount, double val_epsilon); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ml/StatModel.java b/OpenCV/src/main/java/org/opencv/ml/StatModel.java new file mode 100644 index 00000000..cf84e51b --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ml/StatModel.java @@ -0,0 +1,204 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ml; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.ml.TrainData; + +// C++: class StatModel +//javadoc: StatModel + +public class StatModel extends Algorithm { + + protected StatModel(long addr) { super(addr); } + + // internal usage only + public static StatModel __fromPtr__(long addr) { return new StatModel(addr); } + + // C++: enum Flags + public static final int + UPDATE_MODEL = 1, + RAW_OUTPUT = 1, + COMPRESSED_INPUT = 2, + PREPROCESSED_INPUT = 4; + + + // + // C++: bool cv::ml::StatModel::empty() + // + + //javadoc: StatModel::empty() + public boolean empty() + { + + boolean retVal = empty_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::ml::StatModel::isClassifier() + // + + //javadoc: StatModel::isClassifier() + public boolean isClassifier() + { + + boolean retVal = isClassifier_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::ml::StatModel::isTrained() + // + + //javadoc: StatModel::isTrained() + public boolean isTrained() + { + + boolean retVal = isTrained_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::ml::StatModel::train(Mat samples, int layout, Mat responses) + // + + //javadoc: StatModel::train(samples, layout, responses) + public boolean train(Mat samples, int layout, Mat responses) + { + + boolean retVal = train_0(nativeObj, samples.nativeObj, layout, responses.nativeObj); + + return retVal; + } + + + // + // C++: bool cv::ml::StatModel::train(Ptr_TrainData trainData, int flags = 0) + // + + //javadoc: StatModel::train(trainData, flags) + public boolean train(TrainData trainData, int flags) + { + + boolean retVal = train_1(nativeObj, trainData.getNativeObjAddr(), flags); + + return retVal; + } + + //javadoc: StatModel::train(trainData) + public boolean train(TrainData trainData) + { + + boolean retVal = train_2(nativeObj, trainData.getNativeObjAddr()); + + return retVal; + } + + + // + // C++: float cv::ml::StatModel::calcError(Ptr_TrainData data, bool test, Mat& resp) + // + + //javadoc: StatModel::calcError(data, test, resp) + public float calcError(TrainData data, boolean test, Mat resp) + { + + float retVal = calcError_0(nativeObj, data.getNativeObjAddr(), test, resp.nativeObj); + + return retVal; + } + + + // + // C++: float cv::ml::StatModel::predict(Mat samples, Mat& results = Mat(), int flags = 0) + // + + //javadoc: StatModel::predict(samples, results, flags) + public float predict(Mat samples, Mat results, int flags) + { + + float retVal = predict_0(nativeObj, samples.nativeObj, results.nativeObj, flags); + + return retVal; + } + + //javadoc: StatModel::predict(samples, results) + public float predict(Mat samples, Mat results) + { + + float retVal = predict_1(nativeObj, samples.nativeObj, results.nativeObj); + + return retVal; + } + + //javadoc: StatModel::predict(samples) + public float predict(Mat samples) + { + + float retVal = predict_2(nativeObj, samples.nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::StatModel::getVarCount() + // + + //javadoc: StatModel::getVarCount() + public int getVarCount() + { + + int retVal = getVarCount_0(nativeObj); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: bool cv::ml::StatModel::empty() + private static native boolean empty_0(long nativeObj); + + // C++: bool cv::ml::StatModel::isClassifier() + private static native boolean isClassifier_0(long nativeObj); + + // C++: bool cv::ml::StatModel::isTrained() + private static native boolean isTrained_0(long nativeObj); + + // C++: bool cv::ml::StatModel::train(Mat samples, int layout, Mat responses) + private static native boolean train_0(long nativeObj, long samples_nativeObj, int layout, long responses_nativeObj); + + // C++: bool cv::ml::StatModel::train(Ptr_TrainData trainData, int flags = 0) + private static native boolean train_1(long nativeObj, long trainData_nativeObj, int flags); + private static native boolean train_2(long nativeObj, long trainData_nativeObj); + + // C++: float cv::ml::StatModel::calcError(Ptr_TrainData data, bool test, Mat& resp) + private static native float calcError_0(long nativeObj, long data_nativeObj, boolean test, long resp_nativeObj); + + // C++: float cv::ml::StatModel::predict(Mat samples, Mat& results = Mat(), int flags = 0) + private static native float predict_0(long nativeObj, long samples_nativeObj, long results_nativeObj, int flags); + private static native float predict_1(long nativeObj, long samples_nativeObj, long results_nativeObj); + private static native float predict_2(long nativeObj, long samples_nativeObj); + + // C++: int cv::ml::StatModel::getVarCount() + private static native int getVarCount_0(long nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ml/TrainData.java b/OpenCV/src/main/java/org/opencv/ml/TrainData.java new file mode 100644 index 00000000..174a496d --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ml/TrainData.java @@ -0,0 +1,789 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ml; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.ml.TrainData; +import org.opencv.utils.Converters; + +// C++: class TrainData +//javadoc: TrainData + +public class TrainData { + + protected final long nativeObj; + protected TrainData(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static TrainData __fromPtr__(long addr) { return new TrainData(addr); } + + // + // C++: Mat cv::ml::TrainData::getCatMap() + // + + //javadoc: TrainData::getCatMap() + public Mat getCatMap() + { + + Mat retVal = new Mat(getCatMap_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getCatOfs() + // + + //javadoc: TrainData::getCatOfs() + public Mat getCatOfs() + { + + Mat retVal = new Mat(getCatOfs_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getClassLabels() + // + + //javadoc: TrainData::getClassLabels() + public Mat getClassLabels() + { + + Mat retVal = new Mat(getClassLabels_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getDefaultSubstValues() + // + + //javadoc: TrainData::getDefaultSubstValues() + public Mat getDefaultSubstValues() + { + + Mat retVal = new Mat(getDefaultSubstValues_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getMissing() + // + + //javadoc: TrainData::getMissing() + public Mat getMissing() + { + + Mat retVal = new Mat(getMissing_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getNormCatResponses() + // + + //javadoc: TrainData::getNormCatResponses() + public Mat getNormCatResponses() + { + + Mat retVal = new Mat(getNormCatResponses_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getResponses() + // + + //javadoc: TrainData::getResponses() + public Mat getResponses() + { + + Mat retVal = new Mat(getResponses_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getSampleWeights() + // + + //javadoc: TrainData::getSampleWeights() + public Mat getSampleWeights() + { + + Mat retVal = new Mat(getSampleWeights_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getSamples() + // + + //javadoc: TrainData::getSamples() + public Mat getSamples() + { + + Mat retVal = new Mat(getSamples_0(nativeObj)); + + return retVal; + } + + + // + // C++: static Mat cv::ml::TrainData::getSubMatrix(Mat matrix, Mat idx, int layout) + // + + //javadoc: TrainData::getSubMatrix(matrix, idx, layout) + public static Mat getSubMatrix(Mat matrix, Mat idx, int layout) + { + + Mat retVal = new Mat(getSubMatrix_0(matrix.nativeObj, idx.nativeObj, layout)); + + return retVal; + } + + + // + // C++: static Mat cv::ml::TrainData::getSubVector(Mat vec, Mat idx) + // + + //javadoc: TrainData::getSubVector(vec, idx) + public static Mat getSubVector(Mat vec, Mat idx) + { + + Mat retVal = new Mat(getSubVector_0(vec.nativeObj, idx.nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getTestNormCatResponses() + // + + //javadoc: TrainData::getTestNormCatResponses() + public Mat getTestNormCatResponses() + { + + Mat retVal = new Mat(getTestNormCatResponses_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getTestResponses() + // + + //javadoc: TrainData::getTestResponses() + public Mat getTestResponses() + { + + Mat retVal = new Mat(getTestResponses_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getTestSampleIdx() + // + + //javadoc: TrainData::getTestSampleIdx() + public Mat getTestSampleIdx() + { + + Mat retVal = new Mat(getTestSampleIdx_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getTestSampleWeights() + // + + //javadoc: TrainData::getTestSampleWeights() + public Mat getTestSampleWeights() + { + + Mat retVal = new Mat(getTestSampleWeights_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getTestSamples() + // + + //javadoc: TrainData::getTestSamples() + public Mat getTestSamples() + { + + Mat retVal = new Mat(getTestSamples_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getTrainNormCatResponses() + // + + //javadoc: TrainData::getTrainNormCatResponses() + public Mat getTrainNormCatResponses() + { + + Mat retVal = new Mat(getTrainNormCatResponses_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getTrainResponses() + // + + //javadoc: TrainData::getTrainResponses() + public Mat getTrainResponses() + { + + Mat retVal = new Mat(getTrainResponses_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getTrainSampleIdx() + // + + //javadoc: TrainData::getTrainSampleIdx() + public Mat getTrainSampleIdx() + { + + Mat retVal = new Mat(getTrainSampleIdx_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getTrainSampleWeights() + // + + //javadoc: TrainData::getTrainSampleWeights() + public Mat getTrainSampleWeights() + { + + Mat retVal = new Mat(getTrainSampleWeights_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getTrainSamples(int layout = ROW_SAMPLE, bool compressSamples = true, bool compressVars = true) + // + + //javadoc: TrainData::getTrainSamples(layout, compressSamples, compressVars) + public Mat getTrainSamples(int layout, boolean compressSamples, boolean compressVars) + { + + Mat retVal = new Mat(getTrainSamples_0(nativeObj, layout, compressSamples, compressVars)); + + return retVal; + } + + //javadoc: TrainData::getTrainSamples(layout, compressSamples) + public Mat getTrainSamples(int layout, boolean compressSamples) + { + + Mat retVal = new Mat(getTrainSamples_1(nativeObj, layout, compressSamples)); + + return retVal; + } + + //javadoc: TrainData::getTrainSamples(layout) + public Mat getTrainSamples(int layout) + { + + Mat retVal = new Mat(getTrainSamples_2(nativeObj, layout)); + + return retVal; + } + + //javadoc: TrainData::getTrainSamples() + public Mat getTrainSamples() + { + + Mat retVal = new Mat(getTrainSamples_3(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getVarIdx() + // + + //javadoc: TrainData::getVarIdx() + public Mat getVarIdx() + { + + Mat retVal = new Mat(getVarIdx_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getVarSymbolFlags() + // + + //javadoc: TrainData::getVarSymbolFlags() + public Mat getVarSymbolFlags() + { + + Mat retVal = new Mat(getVarSymbolFlags_0(nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::ml::TrainData::getVarType() + // + + //javadoc: TrainData::getVarType() + public Mat getVarType() + { + + Mat retVal = new Mat(getVarType_0(nativeObj)); + + return retVal; + } + + + // + // C++: static Ptr_TrainData cv::ml::TrainData::create(Mat samples, int layout, Mat responses, Mat varIdx = Mat(), Mat sampleIdx = Mat(), Mat sampleWeights = Mat(), Mat varType = Mat()) + // + + //javadoc: TrainData::create(samples, layout, responses, varIdx, sampleIdx, sampleWeights, varType) + public static TrainData create(Mat samples, int layout, Mat responses, Mat varIdx, Mat sampleIdx, Mat sampleWeights, Mat varType) + { + + TrainData retVal = TrainData.__fromPtr__(create_0(samples.nativeObj, layout, responses.nativeObj, varIdx.nativeObj, sampleIdx.nativeObj, sampleWeights.nativeObj, varType.nativeObj)); + + return retVal; + } + + //javadoc: TrainData::create(samples, layout, responses, varIdx, sampleIdx, sampleWeights) + public static TrainData create(Mat samples, int layout, Mat responses, Mat varIdx, Mat sampleIdx, Mat sampleWeights) + { + + TrainData retVal = TrainData.__fromPtr__(create_1(samples.nativeObj, layout, responses.nativeObj, varIdx.nativeObj, sampleIdx.nativeObj, sampleWeights.nativeObj)); + + return retVal; + } + + //javadoc: TrainData::create(samples, layout, responses, varIdx, sampleIdx) + public static TrainData create(Mat samples, int layout, Mat responses, Mat varIdx, Mat sampleIdx) + { + + TrainData retVal = TrainData.__fromPtr__(create_2(samples.nativeObj, layout, responses.nativeObj, varIdx.nativeObj, sampleIdx.nativeObj)); + + return retVal; + } + + //javadoc: TrainData::create(samples, layout, responses, varIdx) + public static TrainData create(Mat samples, int layout, Mat responses, Mat varIdx) + { + + TrainData retVal = TrainData.__fromPtr__(create_3(samples.nativeObj, layout, responses.nativeObj, varIdx.nativeObj)); + + return retVal; + } + + //javadoc: TrainData::create(samples, layout, responses) + public static TrainData create(Mat samples, int layout, Mat responses) + { + + TrainData retVal = TrainData.__fromPtr__(create_4(samples.nativeObj, layout, responses.nativeObj)); + + return retVal; + } + + + // + // C++: int cv::ml::TrainData::getCatCount(int vi) + // + + //javadoc: TrainData::getCatCount(vi) + public int getCatCount(int vi) + { + + int retVal = getCatCount_0(nativeObj, vi); + + return retVal; + } + + + // + // C++: int cv::ml::TrainData::getLayout() + // + + //javadoc: TrainData::getLayout() + public int getLayout() + { + + int retVal = getLayout_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::TrainData::getNAllVars() + // + + //javadoc: TrainData::getNAllVars() + public int getNAllVars() + { + + int retVal = getNAllVars_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::TrainData::getNSamples() + // + + //javadoc: TrainData::getNSamples() + public int getNSamples() + { + + int retVal = getNSamples_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::TrainData::getNTestSamples() + // + + //javadoc: TrainData::getNTestSamples() + public int getNTestSamples() + { + + int retVal = getNTestSamples_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::TrainData::getNTrainSamples() + // + + //javadoc: TrainData::getNTrainSamples() + public int getNTrainSamples() + { + + int retVal = getNTrainSamples_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::TrainData::getNVars() + // + + //javadoc: TrainData::getNVars() + public int getNVars() + { + + int retVal = getNVars_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ml::TrainData::getResponseType() + // + + //javadoc: TrainData::getResponseType() + public int getResponseType() + { + + int retVal = getResponseType_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::ml::TrainData::getNames(vector_String names) + // + + //javadoc: TrainData::getNames(names) + public void getNames(List names) + { + + getNames_0(nativeObj, names); + + return; + } + + + // + // C++: void cv::ml::TrainData::getSample(Mat varIdx, int sidx, float* buf) + // + + //javadoc: TrainData::getSample(varIdx, sidx, buf) + public void getSample(Mat varIdx, int sidx, float buf) + { + + getSample_0(nativeObj, varIdx.nativeObj, sidx, buf); + + return; + } + + + // + // C++: void cv::ml::TrainData::getValues(int vi, Mat sidx, float* values) + // + + //javadoc: TrainData::getValues(vi, sidx, values) + public void getValues(int vi, Mat sidx, float values) + { + + getValues_0(nativeObj, vi, sidx.nativeObj, values); + + return; + } + + + // + // C++: void cv::ml::TrainData::setTrainTestSplit(int count, bool shuffle = true) + // + + //javadoc: TrainData::setTrainTestSplit(count, shuffle) + public void setTrainTestSplit(int count, boolean shuffle) + { + + setTrainTestSplit_0(nativeObj, count, shuffle); + + return; + } + + //javadoc: TrainData::setTrainTestSplit(count) + public void setTrainTestSplit(int count) + { + + setTrainTestSplit_1(nativeObj, count); + + return; + } + + + // + // C++: void cv::ml::TrainData::setTrainTestSplitRatio(double ratio, bool shuffle = true) + // + + //javadoc: TrainData::setTrainTestSplitRatio(ratio, shuffle) + public void setTrainTestSplitRatio(double ratio, boolean shuffle) + { + + setTrainTestSplitRatio_0(nativeObj, ratio, shuffle); + + return; + } + + //javadoc: TrainData::setTrainTestSplitRatio(ratio) + public void setTrainTestSplitRatio(double ratio) + { + + setTrainTestSplitRatio_1(nativeObj, ratio); + + return; + } + + + // + // C++: void cv::ml::TrainData::shuffleTrainTest() + // + + //javadoc: TrainData::shuffleTrainTest() + public void shuffleTrainTest() + { + + shuffleTrainTest_0(nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: Mat cv::ml::TrainData::getCatMap() + private static native long getCatMap_0(long nativeObj); + + // C++: Mat cv::ml::TrainData::getCatOfs() + private static native long getCatOfs_0(long nativeObj); + + // C++: Mat cv::ml::TrainData::getClassLabels() + private static native long getClassLabels_0(long nativeObj); + + // C++: Mat cv::ml::TrainData::getDefaultSubstValues() + private static native long getDefaultSubstValues_0(long nativeObj); + + // C++: Mat cv::ml::TrainData::getMissing() + private static native long getMissing_0(long nativeObj); + + // C++: Mat cv::ml::TrainData::getNormCatResponses() + private static native long getNormCatResponses_0(long nativeObj); + + // C++: Mat cv::ml::TrainData::getResponses() + private static native long getResponses_0(long nativeObj); + + // C++: Mat cv::ml::TrainData::getSampleWeights() + private static native long getSampleWeights_0(long nativeObj); + + // C++: Mat cv::ml::TrainData::getSamples() + private static native long getSamples_0(long nativeObj); + + // C++: static Mat cv::ml::TrainData::getSubMatrix(Mat matrix, Mat idx, int layout) + private static native long getSubMatrix_0(long matrix_nativeObj, long idx_nativeObj, int layout); + + // C++: static Mat cv::ml::TrainData::getSubVector(Mat vec, Mat idx) + private static native long getSubVector_0(long vec_nativeObj, long idx_nativeObj); + + // C++: Mat cv::ml::TrainData::getTestNormCatResponses() + private static native long getTestNormCatResponses_0(long nativeObj); + + // C++: Mat cv::ml::TrainData::getTestResponses() + private static native long getTestResponses_0(long nativeObj); + + // C++: Mat cv::ml::TrainData::getTestSampleIdx() + private static native long getTestSampleIdx_0(long nativeObj); + + // C++: Mat cv::ml::TrainData::getTestSampleWeights() + private static native long getTestSampleWeights_0(long nativeObj); + + // C++: Mat cv::ml::TrainData::getTestSamples() + private static native long getTestSamples_0(long nativeObj); + + // C++: Mat cv::ml::TrainData::getTrainNormCatResponses() + private static native long getTrainNormCatResponses_0(long nativeObj); + + // C++: Mat cv::ml::TrainData::getTrainResponses() + private static native long getTrainResponses_0(long nativeObj); + + // C++: Mat cv::ml::TrainData::getTrainSampleIdx() + private static native long getTrainSampleIdx_0(long nativeObj); + + // C++: Mat cv::ml::TrainData::getTrainSampleWeights() + private static native long getTrainSampleWeights_0(long nativeObj); + + // C++: Mat cv::ml::TrainData::getTrainSamples(int layout = ROW_SAMPLE, bool compressSamples = true, bool compressVars = true) + private static native long getTrainSamples_0(long nativeObj, int layout, boolean compressSamples, boolean compressVars); + private static native long getTrainSamples_1(long nativeObj, int layout, boolean compressSamples); + private static native long getTrainSamples_2(long nativeObj, int layout); + private static native long getTrainSamples_3(long nativeObj); + + // C++: Mat cv::ml::TrainData::getVarIdx() + private static native long getVarIdx_0(long nativeObj); + + // C++: Mat cv::ml::TrainData::getVarSymbolFlags() + private static native long getVarSymbolFlags_0(long nativeObj); + + // C++: Mat cv::ml::TrainData::getVarType() + private static native long getVarType_0(long nativeObj); + + // C++: static Ptr_TrainData cv::ml::TrainData::create(Mat samples, int layout, Mat responses, Mat varIdx = Mat(), Mat sampleIdx = Mat(), Mat sampleWeights = Mat(), Mat varType = Mat()) + private static native long create_0(long samples_nativeObj, int layout, long responses_nativeObj, long varIdx_nativeObj, long sampleIdx_nativeObj, long sampleWeights_nativeObj, long varType_nativeObj); + private static native long create_1(long samples_nativeObj, int layout, long responses_nativeObj, long varIdx_nativeObj, long sampleIdx_nativeObj, long sampleWeights_nativeObj); + private static native long create_2(long samples_nativeObj, int layout, long responses_nativeObj, long varIdx_nativeObj, long sampleIdx_nativeObj); + private static native long create_3(long samples_nativeObj, int layout, long responses_nativeObj, long varIdx_nativeObj); + private static native long create_4(long samples_nativeObj, int layout, long responses_nativeObj); + + // C++: int cv::ml::TrainData::getCatCount(int vi) + private static native int getCatCount_0(long nativeObj, int vi); + + // C++: int cv::ml::TrainData::getLayout() + private static native int getLayout_0(long nativeObj); + + // C++: int cv::ml::TrainData::getNAllVars() + private static native int getNAllVars_0(long nativeObj); + + // C++: int cv::ml::TrainData::getNSamples() + private static native int getNSamples_0(long nativeObj); + + // C++: int cv::ml::TrainData::getNTestSamples() + private static native int getNTestSamples_0(long nativeObj); + + // C++: int cv::ml::TrainData::getNTrainSamples() + private static native int getNTrainSamples_0(long nativeObj); + + // C++: int cv::ml::TrainData::getNVars() + private static native int getNVars_0(long nativeObj); + + // C++: int cv::ml::TrainData::getResponseType() + private static native int getResponseType_0(long nativeObj); + + // C++: void cv::ml::TrainData::getNames(vector_String names) + private static native void getNames_0(long nativeObj, List names); + + // C++: void cv::ml::TrainData::getSample(Mat varIdx, int sidx, float* buf) + private static native void getSample_0(long nativeObj, long varIdx_nativeObj, int sidx, float buf); + + // C++: void cv::ml::TrainData::getValues(int vi, Mat sidx, float* values) + private static native void getValues_0(long nativeObj, int vi, long sidx_nativeObj, float values); + + // C++: void cv::ml::TrainData::setTrainTestSplit(int count, bool shuffle = true) + private static native void setTrainTestSplit_0(long nativeObj, int count, boolean shuffle); + private static native void setTrainTestSplit_1(long nativeObj, int count); + + // C++: void cv::ml::TrainData::setTrainTestSplitRatio(double ratio, bool shuffle = true) + private static native void setTrainTestSplitRatio_0(long nativeObj, double ratio, boolean shuffle); + private static native void setTrainTestSplitRatio_1(long nativeObj, double ratio); + + // C++: void cv::ml::TrainData::shuffleTrainTest() + private static native void shuffleTrainTest_0(long nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/objdetect/BaseCascadeClassifier.java b/OpenCV/src/main/java/org/opencv/objdetect/BaseCascadeClassifier.java new file mode 100644 index 00000000..8e9afa09 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/objdetect/BaseCascadeClassifier.java @@ -0,0 +1,28 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.objdetect; + +import org.opencv.core.Algorithm; + +// C++: class BaseCascadeClassifier +//javadoc: BaseCascadeClassifier + +public class BaseCascadeClassifier extends Algorithm { + + protected BaseCascadeClassifier(long addr) { super(addr); } + + // internal usage only + public static BaseCascadeClassifier __fromPtr__(long addr) { return new BaseCascadeClassifier(addr); } + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/objdetect/CascadeClassifier.java b/OpenCV/src/main/java/org/opencv/objdetect/CascadeClassifier.java new file mode 100644 index 00000000..462dc921 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/objdetect/CascadeClassifier.java @@ -0,0 +1,413 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.objdetect; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfDouble; +import org.opencv.core.MatOfInt; +import org.opencv.core.MatOfRect; +import org.opencv.core.Size; +import org.opencv.utils.Converters; + +// C++: class CascadeClassifier +//javadoc: CascadeClassifier + +public class CascadeClassifier { + + protected final long nativeObj; + protected CascadeClassifier(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static CascadeClassifier __fromPtr__(long addr) { return new CascadeClassifier(addr); } + + // + // C++: cv::CascadeClassifier::CascadeClassifier(String filename) + // + + //javadoc: CascadeClassifier::CascadeClassifier(filename) + public CascadeClassifier(String filename) + { + + nativeObj = CascadeClassifier_0(filename); + + return; + } + + + // + // C++: cv::CascadeClassifier::CascadeClassifier() + // + + //javadoc: CascadeClassifier::CascadeClassifier() + public CascadeClassifier() + { + + nativeObj = CascadeClassifier_1(); + + return; + } + + + // + // C++: Size cv::CascadeClassifier::getOriginalWindowSize() + // + + //javadoc: CascadeClassifier::getOriginalWindowSize() + public Size getOriginalWindowSize() + { + + Size retVal = new Size(getOriginalWindowSize_0(nativeObj)); + + return retVal; + } + + + // + // C++: static bool cv::CascadeClassifier::convert(String oldcascade, String newcascade) + // + + //javadoc: CascadeClassifier::convert(oldcascade, newcascade) + public static boolean convert(String oldcascade, String newcascade) + { + + boolean retVal = convert_0(oldcascade, newcascade); + + return retVal; + } + + + // + // C++: bool cv::CascadeClassifier::empty() + // + + //javadoc: CascadeClassifier::empty() + public boolean empty() + { + + boolean retVal = empty_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::CascadeClassifier::isOldFormatCascade() + // + + //javadoc: CascadeClassifier::isOldFormatCascade() + public boolean isOldFormatCascade() + { + + boolean retVal = isOldFormatCascade_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::CascadeClassifier::load(String filename) + // + + //javadoc: CascadeClassifier::load(filename) + public boolean load(String filename) + { + + boolean retVal = load_0(nativeObj, filename); + + return retVal; + } + + + // + // C++: bool cv::CascadeClassifier::read(FileNode node) + // + + // Unknown type 'FileNode' (I), skipping the function + + + // + // C++: int cv::CascadeClassifier::getFeatureType() + // + + //javadoc: CascadeClassifier::getFeatureType() + public int getFeatureType() + { + + int retVal = getFeatureType_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::CascadeClassifier::detectMultiScale(Mat image, vector_Rect& objects, double scaleFactor = 1.1, int minNeighbors = 3, int flags = 0, Size minSize = Size(), Size maxSize = Size()) + // + + //javadoc: CascadeClassifier::detectMultiScale(image, objects, scaleFactor, minNeighbors, flags, minSize, maxSize) + public void detectMultiScale(Mat image, MatOfRect objects, double scaleFactor, int minNeighbors, int flags, Size minSize, Size maxSize) + { + Mat objects_mat = objects; + detectMultiScale_0(nativeObj, image.nativeObj, objects_mat.nativeObj, scaleFactor, minNeighbors, flags, minSize.width, minSize.height, maxSize.width, maxSize.height); + + return; + } + + //javadoc: CascadeClassifier::detectMultiScale(image, objects, scaleFactor, minNeighbors, flags, minSize) + public void detectMultiScale(Mat image, MatOfRect objects, double scaleFactor, int minNeighbors, int flags, Size minSize) + { + Mat objects_mat = objects; + detectMultiScale_1(nativeObj, image.nativeObj, objects_mat.nativeObj, scaleFactor, minNeighbors, flags, minSize.width, minSize.height); + + return; + } + + //javadoc: CascadeClassifier::detectMultiScale(image, objects, scaleFactor, minNeighbors, flags) + public void detectMultiScale(Mat image, MatOfRect objects, double scaleFactor, int minNeighbors, int flags) + { + Mat objects_mat = objects; + detectMultiScale_2(nativeObj, image.nativeObj, objects_mat.nativeObj, scaleFactor, minNeighbors, flags); + + return; + } + + //javadoc: CascadeClassifier::detectMultiScale(image, objects, scaleFactor, minNeighbors) + public void detectMultiScale(Mat image, MatOfRect objects, double scaleFactor, int minNeighbors) + { + Mat objects_mat = objects; + detectMultiScale_3(nativeObj, image.nativeObj, objects_mat.nativeObj, scaleFactor, minNeighbors); + + return; + } + + //javadoc: CascadeClassifier::detectMultiScale(image, objects, scaleFactor) + public void detectMultiScale(Mat image, MatOfRect objects, double scaleFactor) + { + Mat objects_mat = objects; + detectMultiScale_4(nativeObj, image.nativeObj, objects_mat.nativeObj, scaleFactor); + + return; + } + + //javadoc: CascadeClassifier::detectMultiScale(image, objects) + public void detectMultiScale(Mat image, MatOfRect objects) + { + Mat objects_mat = objects; + detectMultiScale_5(nativeObj, image.nativeObj, objects_mat.nativeObj); + + return; + } + + + // + // C++: void cv::CascadeClassifier::detectMultiScale(Mat image, vector_Rect& objects, vector_int& numDetections, double scaleFactor = 1.1, int minNeighbors = 3, int flags = 0, Size minSize = Size(), Size maxSize = Size()) + // + + //javadoc: CascadeClassifier::detectMultiScale2(image, objects, numDetections, scaleFactor, minNeighbors, flags, minSize, maxSize) + public void detectMultiScale2(Mat image, MatOfRect objects, MatOfInt numDetections, double scaleFactor, int minNeighbors, int flags, Size minSize, Size maxSize) + { + Mat objects_mat = objects; + Mat numDetections_mat = numDetections; + detectMultiScale2_0(nativeObj, image.nativeObj, objects_mat.nativeObj, numDetections_mat.nativeObj, scaleFactor, minNeighbors, flags, minSize.width, minSize.height, maxSize.width, maxSize.height); + + return; + } + + //javadoc: CascadeClassifier::detectMultiScale2(image, objects, numDetections, scaleFactor, minNeighbors, flags, minSize) + public void detectMultiScale2(Mat image, MatOfRect objects, MatOfInt numDetections, double scaleFactor, int minNeighbors, int flags, Size minSize) + { + Mat objects_mat = objects; + Mat numDetections_mat = numDetections; + detectMultiScale2_1(nativeObj, image.nativeObj, objects_mat.nativeObj, numDetections_mat.nativeObj, scaleFactor, minNeighbors, flags, minSize.width, minSize.height); + + return; + } + + //javadoc: CascadeClassifier::detectMultiScale2(image, objects, numDetections, scaleFactor, minNeighbors, flags) + public void detectMultiScale2(Mat image, MatOfRect objects, MatOfInt numDetections, double scaleFactor, int minNeighbors, int flags) + { + Mat objects_mat = objects; + Mat numDetections_mat = numDetections; + detectMultiScale2_2(nativeObj, image.nativeObj, objects_mat.nativeObj, numDetections_mat.nativeObj, scaleFactor, minNeighbors, flags); + + return; + } + + //javadoc: CascadeClassifier::detectMultiScale2(image, objects, numDetections, scaleFactor, minNeighbors) + public void detectMultiScale2(Mat image, MatOfRect objects, MatOfInt numDetections, double scaleFactor, int minNeighbors) + { + Mat objects_mat = objects; + Mat numDetections_mat = numDetections; + detectMultiScale2_3(nativeObj, image.nativeObj, objects_mat.nativeObj, numDetections_mat.nativeObj, scaleFactor, minNeighbors); + + return; + } + + //javadoc: CascadeClassifier::detectMultiScale2(image, objects, numDetections, scaleFactor) + public void detectMultiScale2(Mat image, MatOfRect objects, MatOfInt numDetections, double scaleFactor) + { + Mat objects_mat = objects; + Mat numDetections_mat = numDetections; + detectMultiScale2_4(nativeObj, image.nativeObj, objects_mat.nativeObj, numDetections_mat.nativeObj, scaleFactor); + + return; + } + + //javadoc: CascadeClassifier::detectMultiScale2(image, objects, numDetections) + public void detectMultiScale2(Mat image, MatOfRect objects, MatOfInt numDetections) + { + Mat objects_mat = objects; + Mat numDetections_mat = numDetections; + detectMultiScale2_5(nativeObj, image.nativeObj, objects_mat.nativeObj, numDetections_mat.nativeObj); + + return; + } + + + // + // C++: void cv::CascadeClassifier::detectMultiScale(Mat image, vector_Rect& objects, vector_int& rejectLevels, vector_double& levelWeights, double scaleFactor = 1.1, int minNeighbors = 3, int flags = 0, Size minSize = Size(), Size maxSize = Size(), bool outputRejectLevels = false) + // + + //javadoc: CascadeClassifier::detectMultiScale3(image, objects, rejectLevels, levelWeights, scaleFactor, minNeighbors, flags, minSize, maxSize, outputRejectLevels) + public void detectMultiScale3(Mat image, MatOfRect objects, MatOfInt rejectLevels, MatOfDouble levelWeights, double scaleFactor, int minNeighbors, int flags, Size minSize, Size maxSize, boolean outputRejectLevels) + { + Mat objects_mat = objects; + Mat rejectLevels_mat = rejectLevels; + Mat levelWeights_mat = levelWeights; + detectMultiScale3_0(nativeObj, image.nativeObj, objects_mat.nativeObj, rejectLevels_mat.nativeObj, levelWeights_mat.nativeObj, scaleFactor, minNeighbors, flags, minSize.width, minSize.height, maxSize.width, maxSize.height, outputRejectLevels); + + return; + } + + //javadoc: CascadeClassifier::detectMultiScale3(image, objects, rejectLevels, levelWeights, scaleFactor, minNeighbors, flags, minSize, maxSize) + public void detectMultiScale3(Mat image, MatOfRect objects, MatOfInt rejectLevels, MatOfDouble levelWeights, double scaleFactor, int minNeighbors, int flags, Size minSize, Size maxSize) + { + Mat objects_mat = objects; + Mat rejectLevels_mat = rejectLevels; + Mat levelWeights_mat = levelWeights; + detectMultiScale3_1(nativeObj, image.nativeObj, objects_mat.nativeObj, rejectLevels_mat.nativeObj, levelWeights_mat.nativeObj, scaleFactor, minNeighbors, flags, minSize.width, minSize.height, maxSize.width, maxSize.height); + + return; + } + + //javadoc: CascadeClassifier::detectMultiScale3(image, objects, rejectLevels, levelWeights, scaleFactor, minNeighbors, flags, minSize) + public void detectMultiScale3(Mat image, MatOfRect objects, MatOfInt rejectLevels, MatOfDouble levelWeights, double scaleFactor, int minNeighbors, int flags, Size minSize) + { + Mat objects_mat = objects; + Mat rejectLevels_mat = rejectLevels; + Mat levelWeights_mat = levelWeights; + detectMultiScale3_2(nativeObj, image.nativeObj, objects_mat.nativeObj, rejectLevels_mat.nativeObj, levelWeights_mat.nativeObj, scaleFactor, minNeighbors, flags, minSize.width, minSize.height); + + return; + } + + //javadoc: CascadeClassifier::detectMultiScale3(image, objects, rejectLevels, levelWeights, scaleFactor, minNeighbors, flags) + public void detectMultiScale3(Mat image, MatOfRect objects, MatOfInt rejectLevels, MatOfDouble levelWeights, double scaleFactor, int minNeighbors, int flags) + { + Mat objects_mat = objects; + Mat rejectLevels_mat = rejectLevels; + Mat levelWeights_mat = levelWeights; + detectMultiScale3_3(nativeObj, image.nativeObj, objects_mat.nativeObj, rejectLevels_mat.nativeObj, levelWeights_mat.nativeObj, scaleFactor, minNeighbors, flags); + + return; + } + + //javadoc: CascadeClassifier::detectMultiScale3(image, objects, rejectLevels, levelWeights, scaleFactor, minNeighbors) + public void detectMultiScale3(Mat image, MatOfRect objects, MatOfInt rejectLevels, MatOfDouble levelWeights, double scaleFactor, int minNeighbors) + { + Mat objects_mat = objects; + Mat rejectLevels_mat = rejectLevels; + Mat levelWeights_mat = levelWeights; + detectMultiScale3_4(nativeObj, image.nativeObj, objects_mat.nativeObj, rejectLevels_mat.nativeObj, levelWeights_mat.nativeObj, scaleFactor, minNeighbors); + + return; + } + + //javadoc: CascadeClassifier::detectMultiScale3(image, objects, rejectLevels, levelWeights, scaleFactor) + public void detectMultiScale3(Mat image, MatOfRect objects, MatOfInt rejectLevels, MatOfDouble levelWeights, double scaleFactor) + { + Mat objects_mat = objects; + Mat rejectLevels_mat = rejectLevels; + Mat levelWeights_mat = levelWeights; + detectMultiScale3_5(nativeObj, image.nativeObj, objects_mat.nativeObj, rejectLevels_mat.nativeObj, levelWeights_mat.nativeObj, scaleFactor); + + return; + } + + //javadoc: CascadeClassifier::detectMultiScale3(image, objects, rejectLevels, levelWeights) + public void detectMultiScale3(Mat image, MatOfRect objects, MatOfInt rejectLevels, MatOfDouble levelWeights) + { + Mat objects_mat = objects; + Mat rejectLevels_mat = rejectLevels; + Mat levelWeights_mat = levelWeights; + detectMultiScale3_6(nativeObj, image.nativeObj, objects_mat.nativeObj, rejectLevels_mat.nativeObj, levelWeights_mat.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: cv::CascadeClassifier::CascadeClassifier(String filename) + private static native long CascadeClassifier_0(String filename); + + // C++: cv::CascadeClassifier::CascadeClassifier() + private static native long CascadeClassifier_1(); + + // C++: Size cv::CascadeClassifier::getOriginalWindowSize() + private static native double[] getOriginalWindowSize_0(long nativeObj); + + // C++: static bool cv::CascadeClassifier::convert(String oldcascade, String newcascade) + private static native boolean convert_0(String oldcascade, String newcascade); + + // C++: bool cv::CascadeClassifier::empty() + private static native boolean empty_0(long nativeObj); + + // C++: bool cv::CascadeClassifier::isOldFormatCascade() + private static native boolean isOldFormatCascade_0(long nativeObj); + + // C++: bool cv::CascadeClassifier::load(String filename) + private static native boolean load_0(long nativeObj, String filename); + + // C++: int cv::CascadeClassifier::getFeatureType() + private static native int getFeatureType_0(long nativeObj); + + // C++: void cv::CascadeClassifier::detectMultiScale(Mat image, vector_Rect& objects, double scaleFactor = 1.1, int minNeighbors = 3, int flags = 0, Size minSize = Size(), Size maxSize = Size()) + private static native void detectMultiScale_0(long nativeObj, long image_nativeObj, long objects_mat_nativeObj, double scaleFactor, int minNeighbors, int flags, double minSize_width, double minSize_height, double maxSize_width, double maxSize_height); + private static native void detectMultiScale_1(long nativeObj, long image_nativeObj, long objects_mat_nativeObj, double scaleFactor, int minNeighbors, int flags, double minSize_width, double minSize_height); + private static native void detectMultiScale_2(long nativeObj, long image_nativeObj, long objects_mat_nativeObj, double scaleFactor, int minNeighbors, int flags); + private static native void detectMultiScale_3(long nativeObj, long image_nativeObj, long objects_mat_nativeObj, double scaleFactor, int minNeighbors); + private static native void detectMultiScale_4(long nativeObj, long image_nativeObj, long objects_mat_nativeObj, double scaleFactor); + private static native void detectMultiScale_5(long nativeObj, long image_nativeObj, long objects_mat_nativeObj); + + // C++: void cv::CascadeClassifier::detectMultiScale(Mat image, vector_Rect& objects, vector_int& numDetections, double scaleFactor = 1.1, int minNeighbors = 3, int flags = 0, Size minSize = Size(), Size maxSize = Size()) + private static native void detectMultiScale2_0(long nativeObj, long image_nativeObj, long objects_mat_nativeObj, long numDetections_mat_nativeObj, double scaleFactor, int minNeighbors, int flags, double minSize_width, double minSize_height, double maxSize_width, double maxSize_height); + private static native void detectMultiScale2_1(long nativeObj, long image_nativeObj, long objects_mat_nativeObj, long numDetections_mat_nativeObj, double scaleFactor, int minNeighbors, int flags, double minSize_width, double minSize_height); + private static native void detectMultiScale2_2(long nativeObj, long image_nativeObj, long objects_mat_nativeObj, long numDetections_mat_nativeObj, double scaleFactor, int minNeighbors, int flags); + private static native void detectMultiScale2_3(long nativeObj, long image_nativeObj, long objects_mat_nativeObj, long numDetections_mat_nativeObj, double scaleFactor, int minNeighbors); + private static native void detectMultiScale2_4(long nativeObj, long image_nativeObj, long objects_mat_nativeObj, long numDetections_mat_nativeObj, double scaleFactor); + private static native void detectMultiScale2_5(long nativeObj, long image_nativeObj, long objects_mat_nativeObj, long numDetections_mat_nativeObj); + + // C++: void cv::CascadeClassifier::detectMultiScale(Mat image, vector_Rect& objects, vector_int& rejectLevels, vector_double& levelWeights, double scaleFactor = 1.1, int minNeighbors = 3, int flags = 0, Size minSize = Size(), Size maxSize = Size(), bool outputRejectLevels = false) + private static native void detectMultiScale3_0(long nativeObj, long image_nativeObj, long objects_mat_nativeObj, long rejectLevels_mat_nativeObj, long levelWeights_mat_nativeObj, double scaleFactor, int minNeighbors, int flags, double minSize_width, double minSize_height, double maxSize_width, double maxSize_height, boolean outputRejectLevels); + private static native void detectMultiScale3_1(long nativeObj, long image_nativeObj, long objects_mat_nativeObj, long rejectLevels_mat_nativeObj, long levelWeights_mat_nativeObj, double scaleFactor, int minNeighbors, int flags, double minSize_width, double minSize_height, double maxSize_width, double maxSize_height); + private static native void detectMultiScale3_2(long nativeObj, long image_nativeObj, long objects_mat_nativeObj, long rejectLevels_mat_nativeObj, long levelWeights_mat_nativeObj, double scaleFactor, int minNeighbors, int flags, double minSize_width, double minSize_height); + private static native void detectMultiScale3_3(long nativeObj, long image_nativeObj, long objects_mat_nativeObj, long rejectLevels_mat_nativeObj, long levelWeights_mat_nativeObj, double scaleFactor, int minNeighbors, int flags); + private static native void detectMultiScale3_4(long nativeObj, long image_nativeObj, long objects_mat_nativeObj, long rejectLevels_mat_nativeObj, long levelWeights_mat_nativeObj, double scaleFactor, int minNeighbors); + private static native void detectMultiScale3_5(long nativeObj, long image_nativeObj, long objects_mat_nativeObj, long rejectLevels_mat_nativeObj, long levelWeights_mat_nativeObj, double scaleFactor); + private static native void detectMultiScale3_6(long nativeObj, long image_nativeObj, long objects_mat_nativeObj, long rejectLevels_mat_nativeObj, long levelWeights_mat_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/objdetect/HOGDescriptor.java b/OpenCV/src/main/java/org/opencv/objdetect/HOGDescriptor.java new file mode 100644 index 00000000..b507eeba --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/objdetect/HOGDescriptor.java @@ -0,0 +1,786 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.objdetect; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfDouble; +import org.opencv.core.MatOfFloat; +import org.opencv.core.MatOfPoint; +import org.opencv.core.MatOfRect; +import org.opencv.core.Size; +import org.opencv.utils.Converters; + +// C++: class HOGDescriptor +//javadoc: HOGDescriptor + +public class HOGDescriptor { + + protected final long nativeObj; + protected HOGDescriptor(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static HOGDescriptor __fromPtr__(long addr) { return new HOGDescriptor(addr); } + + // C++: enum DescriptorStorageFormat + public static final int + DESCR_FORMAT_COL_BY_COL = 0, + DESCR_FORMAT_ROW_BY_ROW = 1; + + + // C++: enum + public static final int + DEFAULT_NLEVELS = 64; + + + // C++: enum HistogramNormType + public static final int + L2Hys = 0; + + + // + // C++: cv::HOGDescriptor::HOGDescriptor(Size _winSize, Size _blockSize, Size _blockStride, Size _cellSize, int _nbins, int _derivAperture = 1, double _winSigma = -1, HOGDescriptor_HistogramNormType _histogramNormType = HOGDescriptor::L2Hys, double _L2HysThreshold = 0.2, bool _gammaCorrection = false, int _nlevels = HOGDescriptor::DEFAULT_NLEVELS, bool _signedGradient = false) + // + + //javadoc: HOGDescriptor::HOGDescriptor(_winSize, _blockSize, _blockStride, _cellSize, _nbins, _derivAperture, _winSigma, _histogramNormType, _L2HysThreshold, _gammaCorrection, _nlevels, _signedGradient) + public HOGDescriptor(Size _winSize, Size _blockSize, Size _blockStride, Size _cellSize, int _nbins, int _derivAperture, double _winSigma, int _histogramNormType, double _L2HysThreshold, boolean _gammaCorrection, int _nlevels, boolean _signedGradient) + { + + nativeObj = HOGDescriptor_0(_winSize.width, _winSize.height, _blockSize.width, _blockSize.height, _blockStride.width, _blockStride.height, _cellSize.width, _cellSize.height, _nbins, _derivAperture, _winSigma, _histogramNormType, _L2HysThreshold, _gammaCorrection, _nlevels, _signedGradient); + + return; + } + + //javadoc: HOGDescriptor::HOGDescriptor(_winSize, _blockSize, _blockStride, _cellSize, _nbins, _derivAperture, _winSigma, _histogramNormType, _L2HysThreshold, _gammaCorrection, _nlevels) + public HOGDescriptor(Size _winSize, Size _blockSize, Size _blockStride, Size _cellSize, int _nbins, int _derivAperture, double _winSigma, int _histogramNormType, double _L2HysThreshold, boolean _gammaCorrection, int _nlevels) + { + + nativeObj = HOGDescriptor_1(_winSize.width, _winSize.height, _blockSize.width, _blockSize.height, _blockStride.width, _blockStride.height, _cellSize.width, _cellSize.height, _nbins, _derivAperture, _winSigma, _histogramNormType, _L2HysThreshold, _gammaCorrection, _nlevels); + + return; + } + + //javadoc: HOGDescriptor::HOGDescriptor(_winSize, _blockSize, _blockStride, _cellSize, _nbins, _derivAperture, _winSigma, _histogramNormType, _L2HysThreshold, _gammaCorrection) + public HOGDescriptor(Size _winSize, Size _blockSize, Size _blockStride, Size _cellSize, int _nbins, int _derivAperture, double _winSigma, int _histogramNormType, double _L2HysThreshold, boolean _gammaCorrection) + { + + nativeObj = HOGDescriptor_2(_winSize.width, _winSize.height, _blockSize.width, _blockSize.height, _blockStride.width, _blockStride.height, _cellSize.width, _cellSize.height, _nbins, _derivAperture, _winSigma, _histogramNormType, _L2HysThreshold, _gammaCorrection); + + return; + } + + //javadoc: HOGDescriptor::HOGDescriptor(_winSize, _blockSize, _blockStride, _cellSize, _nbins, _derivAperture, _winSigma, _histogramNormType, _L2HysThreshold) + public HOGDescriptor(Size _winSize, Size _blockSize, Size _blockStride, Size _cellSize, int _nbins, int _derivAperture, double _winSigma, int _histogramNormType, double _L2HysThreshold) + { + + nativeObj = HOGDescriptor_3(_winSize.width, _winSize.height, _blockSize.width, _blockSize.height, _blockStride.width, _blockStride.height, _cellSize.width, _cellSize.height, _nbins, _derivAperture, _winSigma, _histogramNormType, _L2HysThreshold); + + return; + } + + //javadoc: HOGDescriptor::HOGDescriptor(_winSize, _blockSize, _blockStride, _cellSize, _nbins, _derivAperture, _winSigma, _histogramNormType) + public HOGDescriptor(Size _winSize, Size _blockSize, Size _blockStride, Size _cellSize, int _nbins, int _derivAperture, double _winSigma, int _histogramNormType) + { + + nativeObj = HOGDescriptor_4(_winSize.width, _winSize.height, _blockSize.width, _blockSize.height, _blockStride.width, _blockStride.height, _cellSize.width, _cellSize.height, _nbins, _derivAperture, _winSigma, _histogramNormType); + + return; + } + + //javadoc: HOGDescriptor::HOGDescriptor(_winSize, _blockSize, _blockStride, _cellSize, _nbins, _derivAperture, _winSigma) + public HOGDescriptor(Size _winSize, Size _blockSize, Size _blockStride, Size _cellSize, int _nbins, int _derivAperture, double _winSigma) + { + + nativeObj = HOGDescriptor_5(_winSize.width, _winSize.height, _blockSize.width, _blockSize.height, _blockStride.width, _blockStride.height, _cellSize.width, _cellSize.height, _nbins, _derivAperture, _winSigma); + + return; + } + + //javadoc: HOGDescriptor::HOGDescriptor(_winSize, _blockSize, _blockStride, _cellSize, _nbins, _derivAperture) + public HOGDescriptor(Size _winSize, Size _blockSize, Size _blockStride, Size _cellSize, int _nbins, int _derivAperture) + { + + nativeObj = HOGDescriptor_6(_winSize.width, _winSize.height, _blockSize.width, _blockSize.height, _blockStride.width, _blockStride.height, _cellSize.width, _cellSize.height, _nbins, _derivAperture); + + return; + } + + //javadoc: HOGDescriptor::HOGDescriptor(_winSize, _blockSize, _blockStride, _cellSize, _nbins) + public HOGDescriptor(Size _winSize, Size _blockSize, Size _blockStride, Size _cellSize, int _nbins) + { + + nativeObj = HOGDescriptor_7(_winSize.width, _winSize.height, _blockSize.width, _blockSize.height, _blockStride.width, _blockStride.height, _cellSize.width, _cellSize.height, _nbins); + + return; + } + + + // + // C++: cv::HOGDescriptor::HOGDescriptor(String filename) + // + + //javadoc: HOGDescriptor::HOGDescriptor(filename) + public HOGDescriptor(String filename) + { + + nativeObj = HOGDescriptor_8(filename); + + return; + } + + + // + // C++: cv::HOGDescriptor::HOGDescriptor() + // + + //javadoc: HOGDescriptor::HOGDescriptor() + public HOGDescriptor() + { + + nativeObj = HOGDescriptor_9(); + + return; + } + + + // + // C++: bool cv::HOGDescriptor::checkDetectorSize() + // + + //javadoc: HOGDescriptor::checkDetectorSize() + public boolean checkDetectorSize() + { + + boolean retVal = checkDetectorSize_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::HOGDescriptor::load(String filename, String objname = String()) + // + + //javadoc: HOGDescriptor::load(filename, objname) + public boolean load(String filename, String objname) + { + + boolean retVal = load_0(nativeObj, filename, objname); + + return retVal; + } + + //javadoc: HOGDescriptor::load(filename) + public boolean load(String filename) + { + + boolean retVal = load_1(nativeObj, filename); + + return retVal; + } + + + // + // C++: double cv::HOGDescriptor::getWinSigma() + // + + //javadoc: HOGDescriptor::getWinSigma() + public double getWinSigma() + { + + double retVal = getWinSigma_0(nativeObj); + + return retVal; + } + + + // + // C++: size_t cv::HOGDescriptor::getDescriptorSize() + // + + //javadoc: HOGDescriptor::getDescriptorSize() + public long getDescriptorSize() + { + + long retVal = getDescriptorSize_0(nativeObj); + + return retVal; + } + + + // + // C++: static vector_float cv::HOGDescriptor::getDaimlerPeopleDetector() + // + + //javadoc: HOGDescriptor::getDaimlerPeopleDetector() + public static MatOfFloat getDaimlerPeopleDetector() + { + + MatOfFloat retVal = MatOfFloat.fromNativeAddr(getDaimlerPeopleDetector_0()); + + return retVal; + } + + + // + // C++: static vector_float cv::HOGDescriptor::getDefaultPeopleDetector() + // + + //javadoc: HOGDescriptor::getDefaultPeopleDetector() + public static MatOfFloat getDefaultPeopleDetector() + { + + MatOfFloat retVal = MatOfFloat.fromNativeAddr(getDefaultPeopleDetector_0()); + + return retVal; + } + + + // + // C++: void cv::HOGDescriptor::compute(Mat img, vector_float& descriptors, Size winStride = Size(), Size padding = Size(), vector_Point locations = std::vector()) + // + + //javadoc: HOGDescriptor::compute(img, descriptors, winStride, padding, locations) + public void compute(Mat img, MatOfFloat descriptors, Size winStride, Size padding, MatOfPoint locations) + { + Mat descriptors_mat = descriptors; + Mat locations_mat = locations; + compute_0(nativeObj, img.nativeObj, descriptors_mat.nativeObj, winStride.width, winStride.height, padding.width, padding.height, locations_mat.nativeObj); + + return; + } + + //javadoc: HOGDescriptor::compute(img, descriptors, winStride, padding) + public void compute(Mat img, MatOfFloat descriptors, Size winStride, Size padding) + { + Mat descriptors_mat = descriptors; + compute_1(nativeObj, img.nativeObj, descriptors_mat.nativeObj, winStride.width, winStride.height, padding.width, padding.height); + + return; + } + + //javadoc: HOGDescriptor::compute(img, descriptors, winStride) + public void compute(Mat img, MatOfFloat descriptors, Size winStride) + { + Mat descriptors_mat = descriptors; + compute_2(nativeObj, img.nativeObj, descriptors_mat.nativeObj, winStride.width, winStride.height); + + return; + } + + //javadoc: HOGDescriptor::compute(img, descriptors) + public void compute(Mat img, MatOfFloat descriptors) + { + Mat descriptors_mat = descriptors; + compute_3(nativeObj, img.nativeObj, descriptors_mat.nativeObj); + + return; + } + + + // + // C++: void cv::HOGDescriptor::computeGradient(Mat img, Mat& grad, Mat& angleOfs, Size paddingTL = Size(), Size paddingBR = Size()) + // + + //javadoc: HOGDescriptor::computeGradient(img, grad, angleOfs, paddingTL, paddingBR) + public void computeGradient(Mat img, Mat grad, Mat angleOfs, Size paddingTL, Size paddingBR) + { + + computeGradient_0(nativeObj, img.nativeObj, grad.nativeObj, angleOfs.nativeObj, paddingTL.width, paddingTL.height, paddingBR.width, paddingBR.height); + + return; + } + + //javadoc: HOGDescriptor::computeGradient(img, grad, angleOfs, paddingTL) + public void computeGradient(Mat img, Mat grad, Mat angleOfs, Size paddingTL) + { + + computeGradient_1(nativeObj, img.nativeObj, grad.nativeObj, angleOfs.nativeObj, paddingTL.width, paddingTL.height); + + return; + } + + //javadoc: HOGDescriptor::computeGradient(img, grad, angleOfs) + public void computeGradient(Mat img, Mat grad, Mat angleOfs) + { + + computeGradient_2(nativeObj, img.nativeObj, grad.nativeObj, angleOfs.nativeObj); + + return; + } + + + // + // C++: void cv::HOGDescriptor::detect(Mat img, vector_Point& foundLocations, vector_double& weights, double hitThreshold = 0, Size winStride = Size(), Size padding = Size(), vector_Point searchLocations = std::vector()) + // + + //javadoc: HOGDescriptor::detect(img, foundLocations, weights, hitThreshold, winStride, padding, searchLocations) + public void detect(Mat img, MatOfPoint foundLocations, MatOfDouble weights, double hitThreshold, Size winStride, Size padding, MatOfPoint searchLocations) + { + Mat foundLocations_mat = foundLocations; + Mat weights_mat = weights; + Mat searchLocations_mat = searchLocations; + detect_0(nativeObj, img.nativeObj, foundLocations_mat.nativeObj, weights_mat.nativeObj, hitThreshold, winStride.width, winStride.height, padding.width, padding.height, searchLocations_mat.nativeObj); + + return; + } + + //javadoc: HOGDescriptor::detect(img, foundLocations, weights, hitThreshold, winStride, padding) + public void detect(Mat img, MatOfPoint foundLocations, MatOfDouble weights, double hitThreshold, Size winStride, Size padding) + { + Mat foundLocations_mat = foundLocations; + Mat weights_mat = weights; + detect_1(nativeObj, img.nativeObj, foundLocations_mat.nativeObj, weights_mat.nativeObj, hitThreshold, winStride.width, winStride.height, padding.width, padding.height); + + return; + } + + //javadoc: HOGDescriptor::detect(img, foundLocations, weights, hitThreshold, winStride) + public void detect(Mat img, MatOfPoint foundLocations, MatOfDouble weights, double hitThreshold, Size winStride) + { + Mat foundLocations_mat = foundLocations; + Mat weights_mat = weights; + detect_2(nativeObj, img.nativeObj, foundLocations_mat.nativeObj, weights_mat.nativeObj, hitThreshold, winStride.width, winStride.height); + + return; + } + + //javadoc: HOGDescriptor::detect(img, foundLocations, weights, hitThreshold) + public void detect(Mat img, MatOfPoint foundLocations, MatOfDouble weights, double hitThreshold) + { + Mat foundLocations_mat = foundLocations; + Mat weights_mat = weights; + detect_3(nativeObj, img.nativeObj, foundLocations_mat.nativeObj, weights_mat.nativeObj, hitThreshold); + + return; + } + + //javadoc: HOGDescriptor::detect(img, foundLocations, weights) + public void detect(Mat img, MatOfPoint foundLocations, MatOfDouble weights) + { + Mat foundLocations_mat = foundLocations; + Mat weights_mat = weights; + detect_4(nativeObj, img.nativeObj, foundLocations_mat.nativeObj, weights_mat.nativeObj); + + return; + } + + + // + // C++: void cv::HOGDescriptor::detectMultiScale(Mat img, vector_Rect& foundLocations, vector_double& foundWeights, double hitThreshold = 0, Size winStride = Size(), Size padding = Size(), double scale = 1.05, double finalThreshold = 2.0, bool useMeanshiftGrouping = false) + // + + //javadoc: HOGDescriptor::detectMultiScale(img, foundLocations, foundWeights, hitThreshold, winStride, padding, scale, finalThreshold, useMeanshiftGrouping) + public void detectMultiScale(Mat img, MatOfRect foundLocations, MatOfDouble foundWeights, double hitThreshold, Size winStride, Size padding, double scale, double finalThreshold, boolean useMeanshiftGrouping) + { + Mat foundLocations_mat = foundLocations; + Mat foundWeights_mat = foundWeights; + detectMultiScale_0(nativeObj, img.nativeObj, foundLocations_mat.nativeObj, foundWeights_mat.nativeObj, hitThreshold, winStride.width, winStride.height, padding.width, padding.height, scale, finalThreshold, useMeanshiftGrouping); + + return; + } + + //javadoc: HOGDescriptor::detectMultiScale(img, foundLocations, foundWeights, hitThreshold, winStride, padding, scale, finalThreshold) + public void detectMultiScale(Mat img, MatOfRect foundLocations, MatOfDouble foundWeights, double hitThreshold, Size winStride, Size padding, double scale, double finalThreshold) + { + Mat foundLocations_mat = foundLocations; + Mat foundWeights_mat = foundWeights; + detectMultiScale_1(nativeObj, img.nativeObj, foundLocations_mat.nativeObj, foundWeights_mat.nativeObj, hitThreshold, winStride.width, winStride.height, padding.width, padding.height, scale, finalThreshold); + + return; + } + + //javadoc: HOGDescriptor::detectMultiScale(img, foundLocations, foundWeights, hitThreshold, winStride, padding, scale) + public void detectMultiScale(Mat img, MatOfRect foundLocations, MatOfDouble foundWeights, double hitThreshold, Size winStride, Size padding, double scale) + { + Mat foundLocations_mat = foundLocations; + Mat foundWeights_mat = foundWeights; + detectMultiScale_2(nativeObj, img.nativeObj, foundLocations_mat.nativeObj, foundWeights_mat.nativeObj, hitThreshold, winStride.width, winStride.height, padding.width, padding.height, scale); + + return; + } + + //javadoc: HOGDescriptor::detectMultiScale(img, foundLocations, foundWeights, hitThreshold, winStride, padding) + public void detectMultiScale(Mat img, MatOfRect foundLocations, MatOfDouble foundWeights, double hitThreshold, Size winStride, Size padding) + { + Mat foundLocations_mat = foundLocations; + Mat foundWeights_mat = foundWeights; + detectMultiScale_3(nativeObj, img.nativeObj, foundLocations_mat.nativeObj, foundWeights_mat.nativeObj, hitThreshold, winStride.width, winStride.height, padding.width, padding.height); + + return; + } + + //javadoc: HOGDescriptor::detectMultiScale(img, foundLocations, foundWeights, hitThreshold, winStride) + public void detectMultiScale(Mat img, MatOfRect foundLocations, MatOfDouble foundWeights, double hitThreshold, Size winStride) + { + Mat foundLocations_mat = foundLocations; + Mat foundWeights_mat = foundWeights; + detectMultiScale_4(nativeObj, img.nativeObj, foundLocations_mat.nativeObj, foundWeights_mat.nativeObj, hitThreshold, winStride.width, winStride.height); + + return; + } + + //javadoc: HOGDescriptor::detectMultiScale(img, foundLocations, foundWeights, hitThreshold) + public void detectMultiScale(Mat img, MatOfRect foundLocations, MatOfDouble foundWeights, double hitThreshold) + { + Mat foundLocations_mat = foundLocations; + Mat foundWeights_mat = foundWeights; + detectMultiScale_5(nativeObj, img.nativeObj, foundLocations_mat.nativeObj, foundWeights_mat.nativeObj, hitThreshold); + + return; + } + + //javadoc: HOGDescriptor::detectMultiScale(img, foundLocations, foundWeights) + public void detectMultiScale(Mat img, MatOfRect foundLocations, MatOfDouble foundWeights) + { + Mat foundLocations_mat = foundLocations; + Mat foundWeights_mat = foundWeights; + detectMultiScale_6(nativeObj, img.nativeObj, foundLocations_mat.nativeObj, foundWeights_mat.nativeObj); + + return; + } + + + // + // C++: void cv::HOGDescriptor::save(String filename, String objname = String()) + // + + //javadoc: HOGDescriptor::save(filename, objname) + public void save(String filename, String objname) + { + + save_0(nativeObj, filename, objname); + + return; + } + + //javadoc: HOGDescriptor::save(filename) + public void save(String filename) + { + + save_1(nativeObj, filename); + + return; + } + + + // + // C++: void cv::HOGDescriptor::setSVMDetector(Mat svmdetector) + // + + //javadoc: HOGDescriptor::setSVMDetector(svmdetector) + public void setSVMDetector(Mat svmdetector) + { + + setSVMDetector_0(nativeObj, svmdetector.nativeObj); + + return; + } + + + // + // C++: Size HOGDescriptor::winSize + // + + //javadoc: HOGDescriptor::get_winSize() + public Size get_winSize() + { + + Size retVal = new Size(get_winSize_0(nativeObj)); + + return retVal; + } + + + // + // C++: Size HOGDescriptor::blockSize + // + + //javadoc: HOGDescriptor::get_blockSize() + public Size get_blockSize() + { + + Size retVal = new Size(get_blockSize_0(nativeObj)); + + return retVal; + } + + + // + // C++: Size HOGDescriptor::blockStride + // + + //javadoc: HOGDescriptor::get_blockStride() + public Size get_blockStride() + { + + Size retVal = new Size(get_blockStride_0(nativeObj)); + + return retVal; + } + + + // + // C++: Size HOGDescriptor::cellSize + // + + //javadoc: HOGDescriptor::get_cellSize() + public Size get_cellSize() + { + + Size retVal = new Size(get_cellSize_0(nativeObj)); + + return retVal; + } + + + // + // C++: int HOGDescriptor::nbins + // + + //javadoc: HOGDescriptor::get_nbins() + public int get_nbins() + { + + int retVal = get_nbins_0(nativeObj); + + return retVal; + } + + + // + // C++: int HOGDescriptor::derivAperture + // + + //javadoc: HOGDescriptor::get_derivAperture() + public int get_derivAperture() + { + + int retVal = get_derivAperture_0(nativeObj); + + return retVal; + } + + + // + // C++: double HOGDescriptor::winSigma + // + + //javadoc: HOGDescriptor::get_winSigma() + public double get_winSigma() + { + + double retVal = get_winSigma_0(nativeObj); + + return retVal; + } + + + // + // C++: HOGDescriptor_HistogramNormType HOGDescriptor::histogramNormType + // + + //javadoc: HOGDescriptor::get_histogramNormType() + public int get_histogramNormType() + { + + int retVal = get_histogramNormType_0(nativeObj); + + return retVal; + } + + + // + // C++: double HOGDescriptor::L2HysThreshold + // + + //javadoc: HOGDescriptor::get_L2HysThreshold() + public double get_L2HysThreshold() + { + + double retVal = get_L2HysThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: bool HOGDescriptor::gammaCorrection + // + + //javadoc: HOGDescriptor::get_gammaCorrection() + public boolean get_gammaCorrection() + { + + boolean retVal = get_gammaCorrection_0(nativeObj); + + return retVal; + } + + + // + // C++: vector_float HOGDescriptor::svmDetector + // + + //javadoc: HOGDescriptor::get_svmDetector() + public MatOfFloat get_svmDetector() + { + + MatOfFloat retVal = MatOfFloat.fromNativeAddr(get_svmDetector_0(nativeObj)); + + return retVal; + } + + + // + // C++: int HOGDescriptor::nlevels + // + + //javadoc: HOGDescriptor::get_nlevels() + public int get_nlevels() + { + + int retVal = get_nlevels_0(nativeObj); + + return retVal; + } + + + // + // C++: bool HOGDescriptor::signedGradient + // + + //javadoc: HOGDescriptor::get_signedGradient() + public boolean get_signedGradient() + { + + boolean retVal = get_signedGradient_0(nativeObj); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: cv::HOGDescriptor::HOGDescriptor(Size _winSize, Size _blockSize, Size _blockStride, Size _cellSize, int _nbins, int _derivAperture = 1, double _winSigma = -1, HOGDescriptor_HistogramNormType _histogramNormType = HOGDescriptor::L2Hys, double _L2HysThreshold = 0.2, bool _gammaCorrection = false, int _nlevels = HOGDescriptor::DEFAULT_NLEVELS, bool _signedGradient = false) + private static native long HOGDescriptor_0(double _winSize_width, double _winSize_height, double _blockSize_width, double _blockSize_height, double _blockStride_width, double _blockStride_height, double _cellSize_width, double _cellSize_height, int _nbins, int _derivAperture, double _winSigma, int _histogramNormType, double _L2HysThreshold, boolean _gammaCorrection, int _nlevels, boolean _signedGradient); + private static native long HOGDescriptor_1(double _winSize_width, double _winSize_height, double _blockSize_width, double _blockSize_height, double _blockStride_width, double _blockStride_height, double _cellSize_width, double _cellSize_height, int _nbins, int _derivAperture, double _winSigma, int _histogramNormType, double _L2HysThreshold, boolean _gammaCorrection, int _nlevels); + private static native long HOGDescriptor_2(double _winSize_width, double _winSize_height, double _blockSize_width, double _blockSize_height, double _blockStride_width, double _blockStride_height, double _cellSize_width, double _cellSize_height, int _nbins, int _derivAperture, double _winSigma, int _histogramNormType, double _L2HysThreshold, boolean _gammaCorrection); + private static native long HOGDescriptor_3(double _winSize_width, double _winSize_height, double _blockSize_width, double _blockSize_height, double _blockStride_width, double _blockStride_height, double _cellSize_width, double _cellSize_height, int _nbins, int _derivAperture, double _winSigma, int _histogramNormType, double _L2HysThreshold); + private static native long HOGDescriptor_4(double _winSize_width, double _winSize_height, double _blockSize_width, double _blockSize_height, double _blockStride_width, double _blockStride_height, double _cellSize_width, double _cellSize_height, int _nbins, int _derivAperture, double _winSigma, int _histogramNormType); + private static native long HOGDescriptor_5(double _winSize_width, double _winSize_height, double _blockSize_width, double _blockSize_height, double _blockStride_width, double _blockStride_height, double _cellSize_width, double _cellSize_height, int _nbins, int _derivAperture, double _winSigma); + private static native long HOGDescriptor_6(double _winSize_width, double _winSize_height, double _blockSize_width, double _blockSize_height, double _blockStride_width, double _blockStride_height, double _cellSize_width, double _cellSize_height, int _nbins, int _derivAperture); + private static native long HOGDescriptor_7(double _winSize_width, double _winSize_height, double _blockSize_width, double _blockSize_height, double _blockStride_width, double _blockStride_height, double _cellSize_width, double _cellSize_height, int _nbins); + + // C++: cv::HOGDescriptor::HOGDescriptor(String filename) + private static native long HOGDescriptor_8(String filename); + + // C++: cv::HOGDescriptor::HOGDescriptor() + private static native long HOGDescriptor_9(); + + // C++: bool cv::HOGDescriptor::checkDetectorSize() + private static native boolean checkDetectorSize_0(long nativeObj); + + // C++: bool cv::HOGDescriptor::load(String filename, String objname = String()) + private static native boolean load_0(long nativeObj, String filename, String objname); + private static native boolean load_1(long nativeObj, String filename); + + // C++: double cv::HOGDescriptor::getWinSigma() + private static native double getWinSigma_0(long nativeObj); + + // C++: size_t cv::HOGDescriptor::getDescriptorSize() + private static native long getDescriptorSize_0(long nativeObj); + + // C++: static vector_float cv::HOGDescriptor::getDaimlerPeopleDetector() + private static native long getDaimlerPeopleDetector_0(); + + // C++: static vector_float cv::HOGDescriptor::getDefaultPeopleDetector() + private static native long getDefaultPeopleDetector_0(); + + // C++: void cv::HOGDescriptor::compute(Mat img, vector_float& descriptors, Size winStride = Size(), Size padding = Size(), vector_Point locations = std::vector()) + private static native void compute_0(long nativeObj, long img_nativeObj, long descriptors_mat_nativeObj, double winStride_width, double winStride_height, double padding_width, double padding_height, long locations_mat_nativeObj); + private static native void compute_1(long nativeObj, long img_nativeObj, long descriptors_mat_nativeObj, double winStride_width, double winStride_height, double padding_width, double padding_height); + private static native void compute_2(long nativeObj, long img_nativeObj, long descriptors_mat_nativeObj, double winStride_width, double winStride_height); + private static native void compute_3(long nativeObj, long img_nativeObj, long descriptors_mat_nativeObj); + + // C++: void cv::HOGDescriptor::computeGradient(Mat img, Mat& grad, Mat& angleOfs, Size paddingTL = Size(), Size paddingBR = Size()) + private static native void computeGradient_0(long nativeObj, long img_nativeObj, long grad_nativeObj, long angleOfs_nativeObj, double paddingTL_width, double paddingTL_height, double paddingBR_width, double paddingBR_height); + private static native void computeGradient_1(long nativeObj, long img_nativeObj, long grad_nativeObj, long angleOfs_nativeObj, double paddingTL_width, double paddingTL_height); + private static native void computeGradient_2(long nativeObj, long img_nativeObj, long grad_nativeObj, long angleOfs_nativeObj); + + // C++: void cv::HOGDescriptor::detect(Mat img, vector_Point& foundLocations, vector_double& weights, double hitThreshold = 0, Size winStride = Size(), Size padding = Size(), vector_Point searchLocations = std::vector()) + private static native void detect_0(long nativeObj, long img_nativeObj, long foundLocations_mat_nativeObj, long weights_mat_nativeObj, double hitThreshold, double winStride_width, double winStride_height, double padding_width, double padding_height, long searchLocations_mat_nativeObj); + private static native void detect_1(long nativeObj, long img_nativeObj, long foundLocations_mat_nativeObj, long weights_mat_nativeObj, double hitThreshold, double winStride_width, double winStride_height, double padding_width, double padding_height); + private static native void detect_2(long nativeObj, long img_nativeObj, long foundLocations_mat_nativeObj, long weights_mat_nativeObj, double hitThreshold, double winStride_width, double winStride_height); + private static native void detect_3(long nativeObj, long img_nativeObj, long foundLocations_mat_nativeObj, long weights_mat_nativeObj, double hitThreshold); + private static native void detect_4(long nativeObj, long img_nativeObj, long foundLocations_mat_nativeObj, long weights_mat_nativeObj); + + // C++: void cv::HOGDescriptor::detectMultiScale(Mat img, vector_Rect& foundLocations, vector_double& foundWeights, double hitThreshold = 0, Size winStride = Size(), Size padding = Size(), double scale = 1.05, double finalThreshold = 2.0, bool useMeanshiftGrouping = false) + private static native void detectMultiScale_0(long nativeObj, long img_nativeObj, long foundLocations_mat_nativeObj, long foundWeights_mat_nativeObj, double hitThreshold, double winStride_width, double winStride_height, double padding_width, double padding_height, double scale, double finalThreshold, boolean useMeanshiftGrouping); + private static native void detectMultiScale_1(long nativeObj, long img_nativeObj, long foundLocations_mat_nativeObj, long foundWeights_mat_nativeObj, double hitThreshold, double winStride_width, double winStride_height, double padding_width, double padding_height, double scale, double finalThreshold); + private static native void detectMultiScale_2(long nativeObj, long img_nativeObj, long foundLocations_mat_nativeObj, long foundWeights_mat_nativeObj, double hitThreshold, double winStride_width, double winStride_height, double padding_width, double padding_height, double scale); + private static native void detectMultiScale_3(long nativeObj, long img_nativeObj, long foundLocations_mat_nativeObj, long foundWeights_mat_nativeObj, double hitThreshold, double winStride_width, double winStride_height, double padding_width, double padding_height); + private static native void detectMultiScale_4(long nativeObj, long img_nativeObj, long foundLocations_mat_nativeObj, long foundWeights_mat_nativeObj, double hitThreshold, double winStride_width, double winStride_height); + private static native void detectMultiScale_5(long nativeObj, long img_nativeObj, long foundLocations_mat_nativeObj, long foundWeights_mat_nativeObj, double hitThreshold); + private static native void detectMultiScale_6(long nativeObj, long img_nativeObj, long foundLocations_mat_nativeObj, long foundWeights_mat_nativeObj); + + // C++: void cv::HOGDescriptor::save(String filename, String objname = String()) + private static native void save_0(long nativeObj, String filename, String objname); + private static native void save_1(long nativeObj, String filename); + + // C++: void cv::HOGDescriptor::setSVMDetector(Mat svmdetector) + private static native void setSVMDetector_0(long nativeObj, long svmdetector_nativeObj); + + // C++: Size HOGDescriptor::winSize + private static native double[] get_winSize_0(long nativeObj); + + // C++: Size HOGDescriptor::blockSize + private static native double[] get_blockSize_0(long nativeObj); + + // C++: Size HOGDescriptor::blockStride + private static native double[] get_blockStride_0(long nativeObj); + + // C++: Size HOGDescriptor::cellSize + private static native double[] get_cellSize_0(long nativeObj); + + // C++: int HOGDescriptor::nbins + private static native int get_nbins_0(long nativeObj); + + // C++: int HOGDescriptor::derivAperture + private static native int get_derivAperture_0(long nativeObj); + + // C++: double HOGDescriptor::winSigma + private static native double get_winSigma_0(long nativeObj); + + // C++: HOGDescriptor_HistogramNormType HOGDescriptor::histogramNormType + private static native int get_histogramNormType_0(long nativeObj); + + // C++: double HOGDescriptor::L2HysThreshold + private static native double get_L2HysThreshold_0(long nativeObj); + + // C++: bool HOGDescriptor::gammaCorrection + private static native boolean get_gammaCorrection_0(long nativeObj); + + // C++: vector_float HOGDescriptor::svmDetector + private static native long get_svmDetector_0(long nativeObj); + + // C++: int HOGDescriptor::nlevels + private static native int get_nlevels_0(long nativeObj); + + // C++: bool HOGDescriptor::signedGradient + private static native boolean get_signedGradient_0(long nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/objdetect/Objdetect.java b/OpenCV/src/main/java/org/opencv/objdetect/Objdetect.java new file mode 100644 index 00000000..97a8f79d --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/objdetect/Objdetect.java @@ -0,0 +1,65 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.objdetect; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfInt; +import org.opencv.core.MatOfRect; +import org.opencv.utils.Converters; + +// C++: class Objdetect +//javadoc: Objdetect + +public class Objdetect { + + // C++: enum + public static final int + CASCADE_DO_CANNY_PRUNING = 1, + CASCADE_SCALE_IMAGE = 2, + CASCADE_FIND_BIGGEST_OBJECT = 4, + CASCADE_DO_ROUGH_SEARCH = 8; + + + // C++: enum ObjectStatus + public static final int + DetectionBasedTracker_DETECTED_NOT_SHOWN_YET = 0, + DetectionBasedTracker_DETECTED = 1, + DetectionBasedTracker_DETECTED_TEMPORARY_LOST = 2, + DetectionBasedTracker_WRONG_OBJECT = 3; + + + // + // C++: void cv::groupRectangles(vector_Rect& rectList, vector_int& weights, int groupThreshold, double eps = 0.2) + // + + //javadoc: groupRectangles(rectList, weights, groupThreshold, eps) + public static void groupRectangles(MatOfRect rectList, MatOfInt weights, int groupThreshold, double eps) + { + Mat rectList_mat = rectList; + Mat weights_mat = weights; + groupRectangles_0(rectList_mat.nativeObj, weights_mat.nativeObj, groupThreshold, eps); + + return; + } + + //javadoc: groupRectangles(rectList, weights, groupThreshold) + public static void groupRectangles(MatOfRect rectList, MatOfInt weights, int groupThreshold) + { + Mat rectList_mat = rectList; + Mat weights_mat = weights; + groupRectangles_1(rectList_mat.nativeObj, weights_mat.nativeObj, groupThreshold); + + return; + } + + + + + // C++: void cv::groupRectangles(vector_Rect& rectList, vector_int& weights, int groupThreshold, double eps = 0.2) + private static native void groupRectangles_0(long rectList_mat_nativeObj, long weights_mat_nativeObj, int groupThreshold, double eps); + private static native void groupRectangles_1(long rectList_mat_nativeObj, long weights_mat_nativeObj, int groupThreshold); + +} diff --git a/OpenCV/src/main/java/org/opencv/objdetect/QRCodeDetector.java b/OpenCV/src/main/java/org/opencv/objdetect/QRCodeDetector.java new file mode 100644 index 00000000..67c2a6a5 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/objdetect/QRCodeDetector.java @@ -0,0 +1,164 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.objdetect; + +import java.lang.String; +import org.opencv.core.Mat; + +// C++: class QRCodeDetector +//javadoc: QRCodeDetector + +public class QRCodeDetector { + + protected final long nativeObj; + protected QRCodeDetector(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static QRCodeDetector __fromPtr__(long addr) { return new QRCodeDetector(addr); } + + // + // C++: cv::QRCodeDetector::QRCodeDetector() + // + + //javadoc: QRCodeDetector::QRCodeDetector() + public QRCodeDetector() + { + + nativeObj = QRCodeDetector_0(); + + return; + } + + + // + // C++: bool cv::QRCodeDetector::detect(Mat img, Mat& points) + // + + //javadoc: QRCodeDetector::detect(img, points) + public boolean detect(Mat img, Mat points) + { + + boolean retVal = detect_0(nativeObj, img.nativeObj, points.nativeObj); + + return retVal; + } + + + // + // C++: string cv::QRCodeDetector::decode(Mat img, Mat points, Mat& straight_qrcode = Mat()) + // + + //javadoc: QRCodeDetector::decode(img, points, straight_qrcode) + public String decode(Mat img, Mat points, Mat straight_qrcode) + { + + String retVal = decode_0(nativeObj, img.nativeObj, points.nativeObj, straight_qrcode.nativeObj); + + return retVal; + } + + //javadoc: QRCodeDetector::decode(img, points) + public String decode(Mat img, Mat points) + { + + String retVal = decode_1(nativeObj, img.nativeObj, points.nativeObj); + + return retVal; + } + + + // + // C++: string cv::QRCodeDetector::detectAndDecode(Mat img, Mat& points = Mat(), Mat& straight_qrcode = Mat()) + // + + //javadoc: QRCodeDetector::detectAndDecode(img, points, straight_qrcode) + public String detectAndDecode(Mat img, Mat points, Mat straight_qrcode) + { + + String retVal = detectAndDecode_0(nativeObj, img.nativeObj, points.nativeObj, straight_qrcode.nativeObj); + + return retVal; + } + + //javadoc: QRCodeDetector::detectAndDecode(img, points) + public String detectAndDecode(Mat img, Mat points) + { + + String retVal = detectAndDecode_1(nativeObj, img.nativeObj, points.nativeObj); + + return retVal; + } + + //javadoc: QRCodeDetector::detectAndDecode(img) + public String detectAndDecode(Mat img) + { + + String retVal = detectAndDecode_2(nativeObj, img.nativeObj); + + return retVal; + } + + + // + // C++: void cv::QRCodeDetector::setEpsX(double epsX) + // + + //javadoc: QRCodeDetector::setEpsX(epsX) + public void setEpsX(double epsX) + { + + setEpsX_0(nativeObj, epsX); + + return; + } + + + // + // C++: void cv::QRCodeDetector::setEpsY(double epsY) + // + + //javadoc: QRCodeDetector::setEpsY(epsY) + public void setEpsY(double epsY) + { + + setEpsY_0(nativeObj, epsY); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: cv::QRCodeDetector::QRCodeDetector() + private static native long QRCodeDetector_0(); + + // C++: bool cv::QRCodeDetector::detect(Mat img, Mat& points) + private static native boolean detect_0(long nativeObj, long img_nativeObj, long points_nativeObj); + + // C++: string cv::QRCodeDetector::decode(Mat img, Mat points, Mat& straight_qrcode = Mat()) + private static native String decode_0(long nativeObj, long img_nativeObj, long points_nativeObj, long straight_qrcode_nativeObj); + private static native String decode_1(long nativeObj, long img_nativeObj, long points_nativeObj); + + // C++: string cv::QRCodeDetector::detectAndDecode(Mat img, Mat& points = Mat(), Mat& straight_qrcode = Mat()) + private static native String detectAndDecode_0(long nativeObj, long img_nativeObj, long points_nativeObj, long straight_qrcode_nativeObj); + private static native String detectAndDecode_1(long nativeObj, long img_nativeObj, long points_nativeObj); + private static native String detectAndDecode_2(long nativeObj, long img_nativeObj); + + // C++: void cv::QRCodeDetector::setEpsX(double epsX) + private static native void setEpsX_0(long nativeObj, double epsX); + + // C++: void cv::QRCodeDetector::setEpsY(double epsY) + private static native void setEpsY_0(long nativeObj, double epsY); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/osgi/OpenCVInterface.java b/OpenCV/src/main/java/org/opencv/osgi/OpenCVInterface.java new file mode 100644 index 00000000..83ffee1a --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/osgi/OpenCVInterface.java @@ -0,0 +1,8 @@ +package org.opencv.osgi; + +/** + * Dummy interface to allow some integration testing within OSGi implementation. + */ +public interface OpenCVInterface +{ +} diff --git a/OpenCV/src/main/java/org/opencv/osgi/OpenCVNativeLoader.java b/OpenCV/src/main/java/org/opencv/osgi/OpenCVNativeLoader.java new file mode 100644 index 00000000..bffc2ad4 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/osgi/OpenCVNativeLoader.java @@ -0,0 +1,18 @@ +package org.opencv.osgi; + +import java.util.logging.Level; +import java.util.logging.Logger; + +/** + * This class is intended to provide a convenient way to load OpenCV's native + * library from the Java bundle. If Blueprint is enabled in the OSGi container + * this class will be instantiated automatically and the init() method called + * loading the native library. + */ +public class OpenCVNativeLoader implements OpenCVInterface { + + public void init() { + System.loadLibrary("opencv_java4"); + Logger.getLogger("org.opencv.osgi").log(Level.INFO, "Successfully loaded OpenCV native library."); + } +} diff --git a/OpenCV/src/main/java/org/opencv/phase_unwrapping/HistogramPhaseUnwrapping.java b/OpenCV/src/main/java/org/opencv/phase_unwrapping/HistogramPhaseUnwrapping.java new file mode 100644 index 00000000..9cc61b17 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/phase_unwrapping/HistogramPhaseUnwrapping.java @@ -0,0 +1,46 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.phase_unwrapping; + +import org.opencv.core.Mat; +import org.opencv.phase_unwrapping.PhaseUnwrapping; + +// C++: class HistogramPhaseUnwrapping +//javadoc: HistogramPhaseUnwrapping + +public class HistogramPhaseUnwrapping extends PhaseUnwrapping { + + protected HistogramPhaseUnwrapping(long addr) { super(addr); } + + // internal usage only + public static HistogramPhaseUnwrapping __fromPtr__(long addr) { return new HistogramPhaseUnwrapping(addr); } + + // + // C++: void cv::phase_unwrapping::HistogramPhaseUnwrapping::getInverseReliabilityMap(Mat& reliabilityMap) + // + + //javadoc: HistogramPhaseUnwrapping::getInverseReliabilityMap(reliabilityMap) + public void getInverseReliabilityMap(Mat reliabilityMap) + { + + getInverseReliabilityMap_0(nativeObj, reliabilityMap.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::phase_unwrapping::HistogramPhaseUnwrapping::getInverseReliabilityMap(Mat& reliabilityMap) + private static native void getInverseReliabilityMap_0(long nativeObj, long reliabilityMap_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/phase_unwrapping/PhaseUnwrapping.java b/OpenCV/src/main/java/org/opencv/phase_unwrapping/PhaseUnwrapping.java new file mode 100644 index 00000000..ae259dd2 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/phase_unwrapping/PhaseUnwrapping.java @@ -0,0 +1,56 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.phase_unwrapping; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class PhaseUnwrapping +//javadoc: PhaseUnwrapping + +public class PhaseUnwrapping extends Algorithm { + + protected PhaseUnwrapping(long addr) { super(addr); } + + // internal usage only + public static PhaseUnwrapping __fromPtr__(long addr) { return new PhaseUnwrapping(addr); } + + // + // C++: void cv::phase_unwrapping::PhaseUnwrapping::unwrapPhaseMap(Mat wrappedPhaseMap, Mat& unwrappedPhaseMap, Mat shadowMask = Mat()) + // + + //javadoc: PhaseUnwrapping::unwrapPhaseMap(wrappedPhaseMap, unwrappedPhaseMap, shadowMask) + public void unwrapPhaseMap(Mat wrappedPhaseMap, Mat unwrappedPhaseMap, Mat shadowMask) + { + + unwrapPhaseMap_0(nativeObj, wrappedPhaseMap.nativeObj, unwrappedPhaseMap.nativeObj, shadowMask.nativeObj); + + return; + } + + //javadoc: PhaseUnwrapping::unwrapPhaseMap(wrappedPhaseMap, unwrappedPhaseMap) + public void unwrapPhaseMap(Mat wrappedPhaseMap, Mat unwrappedPhaseMap) + { + + unwrapPhaseMap_1(nativeObj, wrappedPhaseMap.nativeObj, unwrappedPhaseMap.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::phase_unwrapping::PhaseUnwrapping::unwrapPhaseMap(Mat wrappedPhaseMap, Mat& unwrappedPhaseMap, Mat shadowMask = Mat()) + private static native void unwrapPhaseMap_0(long nativeObj, long wrappedPhaseMap_nativeObj, long unwrappedPhaseMap_nativeObj, long shadowMask_nativeObj); + private static native void unwrapPhaseMap_1(long nativeObj, long wrappedPhaseMap_nativeObj, long unwrappedPhaseMap_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/phase_unwrapping/Phase_unwrapping.java b/OpenCV/src/main/java/org/opencv/phase_unwrapping/Phase_unwrapping.java new file mode 100644 index 00000000..d9891959 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/phase_unwrapping/Phase_unwrapping.java @@ -0,0 +1,15 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.phase_unwrapping; + + + +// C++: class Phase_unwrapping +//javadoc: Phase_unwrapping + +public class Phase_unwrapping { + + + +} diff --git a/OpenCV/src/main/java/org/opencv/photo/AlignExposures.java b/OpenCV/src/main/java/org/opencv/photo/AlignExposures.java new file mode 100644 index 00000000..a50870a0 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/photo/AlignExposures.java @@ -0,0 +1,50 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.photo; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.utils.Converters; + +// C++: class AlignExposures +//javadoc: AlignExposures + +public class AlignExposures extends Algorithm { + + protected AlignExposures(long addr) { super(addr); } + + // internal usage only + public static AlignExposures __fromPtr__(long addr) { return new AlignExposures(addr); } + + // + // C++: void cv::AlignExposures::process(vector_Mat src, vector_Mat dst, Mat times, Mat response) + // + + //javadoc: AlignExposures::process(src, dst, times, response) + public void process(List src, List dst, Mat times, Mat response) + { + Mat src_mat = Converters.vector_Mat_to_Mat(src); + Mat dst_mat = Converters.vector_Mat_to_Mat(dst); + process_0(nativeObj, src_mat.nativeObj, dst_mat.nativeObj, times.nativeObj, response.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::AlignExposures::process(vector_Mat src, vector_Mat dst, Mat times, Mat response) + private static native void process_0(long nativeObj, long src_mat_nativeObj, long dst_mat_nativeObj, long times_nativeObj, long response_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/photo/AlignMTB.java b/OpenCV/src/main/java/org/opencv/photo/AlignMTB.java new file mode 100644 index 00000000..69e8de58 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/photo/AlignMTB.java @@ -0,0 +1,222 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.photo; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.Point; +import org.opencv.photo.AlignExposures; +import org.opencv.utils.Converters; + +// C++: class AlignMTB +//javadoc: AlignMTB + +public class AlignMTB extends AlignExposures { + + protected AlignMTB(long addr) { super(addr); } + + // internal usage only + public static AlignMTB __fromPtr__(long addr) { return new AlignMTB(addr); } + + // + // C++: Point cv::AlignMTB::calculateShift(Mat img0, Mat img1) + // + + //javadoc: AlignMTB::calculateShift(img0, img1) + public Point calculateShift(Mat img0, Mat img1) + { + + Point retVal = new Point(calculateShift_0(nativeObj, img0.nativeObj, img1.nativeObj)); + + return retVal; + } + + + // + // C++: bool cv::AlignMTB::getCut() + // + + //javadoc: AlignMTB::getCut() + public boolean getCut() + { + + boolean retVal = getCut_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::AlignMTB::getExcludeRange() + // + + //javadoc: AlignMTB::getExcludeRange() + public int getExcludeRange() + { + + int retVal = getExcludeRange_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::AlignMTB::getMaxBits() + // + + //javadoc: AlignMTB::getMaxBits() + public int getMaxBits() + { + + int retVal = getMaxBits_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::AlignMTB::computeBitmaps(Mat img, Mat& tb, Mat& eb) + // + + //javadoc: AlignMTB::computeBitmaps(img, tb, eb) + public void computeBitmaps(Mat img, Mat tb, Mat eb) + { + + computeBitmaps_0(nativeObj, img.nativeObj, tb.nativeObj, eb.nativeObj); + + return; + } + + + // + // C++: void cv::AlignMTB::process(vector_Mat src, vector_Mat dst, Mat times, Mat response) + // + + //javadoc: AlignMTB::process(src, dst, times, response) + public void process(List src, List dst, Mat times, Mat response) + { + Mat src_mat = Converters.vector_Mat_to_Mat(src); + Mat dst_mat = Converters.vector_Mat_to_Mat(dst); + process_0(nativeObj, src_mat.nativeObj, dst_mat.nativeObj, times.nativeObj, response.nativeObj); + + return; + } + + + // + // C++: void cv::AlignMTB::process(vector_Mat src, vector_Mat dst) + // + + //javadoc: AlignMTB::process(src, dst) + public void process(List src, List dst) + { + Mat src_mat = Converters.vector_Mat_to_Mat(src); + Mat dst_mat = Converters.vector_Mat_to_Mat(dst); + process_1(nativeObj, src_mat.nativeObj, dst_mat.nativeObj); + + return; + } + + + // + // C++: void cv::AlignMTB::setCut(bool value) + // + + //javadoc: AlignMTB::setCut(value) + public void setCut(boolean value) + { + + setCut_0(nativeObj, value); + + return; + } + + + // + // C++: void cv::AlignMTB::setExcludeRange(int exclude_range) + // + + //javadoc: AlignMTB::setExcludeRange(exclude_range) + public void setExcludeRange(int exclude_range) + { + + setExcludeRange_0(nativeObj, exclude_range); + + return; + } + + + // + // C++: void cv::AlignMTB::setMaxBits(int max_bits) + // + + //javadoc: AlignMTB::setMaxBits(max_bits) + public void setMaxBits(int max_bits) + { + + setMaxBits_0(nativeObj, max_bits); + + return; + } + + + // + // C++: void cv::AlignMTB::shiftMat(Mat src, Mat& dst, Point shift) + // + + //javadoc: AlignMTB::shiftMat(src, dst, shift) + public void shiftMat(Mat src, Mat dst, Point shift) + { + + shiftMat_0(nativeObj, src.nativeObj, dst.nativeObj, shift.x, shift.y); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: Point cv::AlignMTB::calculateShift(Mat img0, Mat img1) + private static native double[] calculateShift_0(long nativeObj, long img0_nativeObj, long img1_nativeObj); + + // C++: bool cv::AlignMTB::getCut() + private static native boolean getCut_0(long nativeObj); + + // C++: int cv::AlignMTB::getExcludeRange() + private static native int getExcludeRange_0(long nativeObj); + + // C++: int cv::AlignMTB::getMaxBits() + private static native int getMaxBits_0(long nativeObj); + + // C++: void cv::AlignMTB::computeBitmaps(Mat img, Mat& tb, Mat& eb) + private static native void computeBitmaps_0(long nativeObj, long img_nativeObj, long tb_nativeObj, long eb_nativeObj); + + // C++: void cv::AlignMTB::process(vector_Mat src, vector_Mat dst, Mat times, Mat response) + private static native void process_0(long nativeObj, long src_mat_nativeObj, long dst_mat_nativeObj, long times_nativeObj, long response_nativeObj); + + // C++: void cv::AlignMTB::process(vector_Mat src, vector_Mat dst) + private static native void process_1(long nativeObj, long src_mat_nativeObj, long dst_mat_nativeObj); + + // C++: void cv::AlignMTB::setCut(bool value) + private static native void setCut_0(long nativeObj, boolean value); + + // C++: void cv::AlignMTB::setExcludeRange(int exclude_range) + private static native void setExcludeRange_0(long nativeObj, int exclude_range); + + // C++: void cv::AlignMTB::setMaxBits(int max_bits) + private static native void setMaxBits_0(long nativeObj, int max_bits); + + // C++: void cv::AlignMTB::shiftMat(Mat src, Mat& dst, Point shift) + private static native void shiftMat_0(long nativeObj, long src_nativeObj, long dst_nativeObj, double shift_x, double shift_y); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/photo/CalibrateCRF.java b/OpenCV/src/main/java/org/opencv/photo/CalibrateCRF.java new file mode 100644 index 00000000..53d7501d --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/photo/CalibrateCRF.java @@ -0,0 +1,49 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.photo; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.utils.Converters; + +// C++: class CalibrateCRF +//javadoc: CalibrateCRF + +public class CalibrateCRF extends Algorithm { + + protected CalibrateCRF(long addr) { super(addr); } + + // internal usage only + public static CalibrateCRF __fromPtr__(long addr) { return new CalibrateCRF(addr); } + + // + // C++: void cv::CalibrateCRF::process(vector_Mat src, Mat& dst, Mat times) + // + + //javadoc: CalibrateCRF::process(src, dst, times) + public void process(List src, Mat dst, Mat times) + { + Mat src_mat = Converters.vector_Mat_to_Mat(src); + process_0(nativeObj, src_mat.nativeObj, dst.nativeObj, times.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::CalibrateCRF::process(vector_Mat src, Mat& dst, Mat times) + private static native void process_0(long nativeObj, long src_mat_nativeObj, long dst_nativeObj, long times_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/photo/CalibrateDebevec.java b/OpenCV/src/main/java/org/opencv/photo/CalibrateDebevec.java new file mode 100644 index 00000000..4411d000 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/photo/CalibrateDebevec.java @@ -0,0 +1,130 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.photo; + +import org.opencv.photo.CalibrateCRF; + +// C++: class CalibrateDebevec +//javadoc: CalibrateDebevec + +public class CalibrateDebevec extends CalibrateCRF { + + protected CalibrateDebevec(long addr) { super(addr); } + + // internal usage only + public static CalibrateDebevec __fromPtr__(long addr) { return new CalibrateDebevec(addr); } + + // + // C++: bool cv::CalibrateDebevec::getRandom() + // + + //javadoc: CalibrateDebevec::getRandom() + public boolean getRandom() + { + + boolean retVal = getRandom_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::CalibrateDebevec::getLambda() + // + + //javadoc: CalibrateDebevec::getLambda() + public float getLambda() + { + + float retVal = getLambda_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::CalibrateDebevec::getSamples() + // + + //javadoc: CalibrateDebevec::getSamples() + public int getSamples() + { + + int retVal = getSamples_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::CalibrateDebevec::setLambda(float lambda) + // + + //javadoc: CalibrateDebevec::setLambda(lambda) + public void setLambda(float lambda) + { + + setLambda_0(nativeObj, lambda); + + return; + } + + + // + // C++: void cv::CalibrateDebevec::setRandom(bool random) + // + + //javadoc: CalibrateDebevec::setRandom(random) + public void setRandom(boolean random) + { + + setRandom_0(nativeObj, random); + + return; + } + + + // + // C++: void cv::CalibrateDebevec::setSamples(int samples) + // + + //javadoc: CalibrateDebevec::setSamples(samples) + public void setSamples(int samples) + { + + setSamples_0(nativeObj, samples); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: bool cv::CalibrateDebevec::getRandom() + private static native boolean getRandom_0(long nativeObj); + + // C++: float cv::CalibrateDebevec::getLambda() + private static native float getLambda_0(long nativeObj); + + // C++: int cv::CalibrateDebevec::getSamples() + private static native int getSamples_0(long nativeObj); + + // C++: void cv::CalibrateDebevec::setLambda(float lambda) + private static native void setLambda_0(long nativeObj, float lambda); + + // C++: void cv::CalibrateDebevec::setRandom(bool random) + private static native void setRandom_0(long nativeObj, boolean random); + + // C++: void cv::CalibrateDebevec::setSamples(int samples) + private static native void setSamples_0(long nativeObj, int samples); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/photo/CalibrateRobertson.java b/OpenCV/src/main/java/org/opencv/photo/CalibrateRobertson.java new file mode 100644 index 00000000..5cd0d9a3 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/photo/CalibrateRobertson.java @@ -0,0 +1,114 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.photo; + +import org.opencv.core.Mat; +import org.opencv.photo.CalibrateCRF; + +// C++: class CalibrateRobertson +//javadoc: CalibrateRobertson + +public class CalibrateRobertson extends CalibrateCRF { + + protected CalibrateRobertson(long addr) { super(addr); } + + // internal usage only + public static CalibrateRobertson __fromPtr__(long addr) { return new CalibrateRobertson(addr); } + + // + // C++: Mat cv::CalibrateRobertson::getRadiance() + // + + //javadoc: CalibrateRobertson::getRadiance() + public Mat getRadiance() + { + + Mat retVal = new Mat(getRadiance_0(nativeObj)); + + return retVal; + } + + + // + // C++: float cv::CalibrateRobertson::getThreshold() + // + + //javadoc: CalibrateRobertson::getThreshold() + public float getThreshold() + { + + float retVal = getThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::CalibrateRobertson::getMaxIter() + // + + //javadoc: CalibrateRobertson::getMaxIter() + public int getMaxIter() + { + + int retVal = getMaxIter_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::CalibrateRobertson::setMaxIter(int max_iter) + // + + //javadoc: CalibrateRobertson::setMaxIter(max_iter) + public void setMaxIter(int max_iter) + { + + setMaxIter_0(nativeObj, max_iter); + + return; + } + + + // + // C++: void cv::CalibrateRobertson::setThreshold(float threshold) + // + + //javadoc: CalibrateRobertson::setThreshold(threshold) + public void setThreshold(float threshold) + { + + setThreshold_0(nativeObj, threshold); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: Mat cv::CalibrateRobertson::getRadiance() + private static native long getRadiance_0(long nativeObj); + + // C++: float cv::CalibrateRobertson::getThreshold() + private static native float getThreshold_0(long nativeObj); + + // C++: int cv::CalibrateRobertson::getMaxIter() + private static native int getMaxIter_0(long nativeObj); + + // C++: void cv::CalibrateRobertson::setMaxIter(int max_iter) + private static native void setMaxIter_0(long nativeObj, int max_iter); + + // C++: void cv::CalibrateRobertson::setThreshold(float threshold) + private static native void setThreshold_0(long nativeObj, float threshold); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/photo/MergeDebevec.java b/OpenCV/src/main/java/org/opencv/photo/MergeDebevec.java new file mode 100644 index 00000000..8ac00d11 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/photo/MergeDebevec.java @@ -0,0 +1,66 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.photo; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.photo.MergeExposures; +import org.opencv.utils.Converters; + +// C++: class MergeDebevec +//javadoc: MergeDebevec + +public class MergeDebevec extends MergeExposures { + + protected MergeDebevec(long addr) { super(addr); } + + // internal usage only + public static MergeDebevec __fromPtr__(long addr) { return new MergeDebevec(addr); } + + // + // C++: void cv::MergeDebevec::process(vector_Mat src, Mat& dst, Mat times, Mat response) + // + + //javadoc: MergeDebevec::process(src, dst, times, response) + public void process(List src, Mat dst, Mat times, Mat response) + { + Mat src_mat = Converters.vector_Mat_to_Mat(src); + process_0(nativeObj, src_mat.nativeObj, dst.nativeObj, times.nativeObj, response.nativeObj); + + return; + } + + + // + // C++: void cv::MergeDebevec::process(vector_Mat src, Mat& dst, Mat times) + // + + //javadoc: MergeDebevec::process(src, dst, times) + public void process(List src, Mat dst, Mat times) + { + Mat src_mat = Converters.vector_Mat_to_Mat(src); + process_1(nativeObj, src_mat.nativeObj, dst.nativeObj, times.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::MergeDebevec::process(vector_Mat src, Mat& dst, Mat times, Mat response) + private static native void process_0(long nativeObj, long src_mat_nativeObj, long dst_nativeObj, long times_nativeObj, long response_nativeObj); + + // C++: void cv::MergeDebevec::process(vector_Mat src, Mat& dst, Mat times) + private static native void process_1(long nativeObj, long src_mat_nativeObj, long dst_nativeObj, long times_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/photo/MergeExposures.java b/OpenCV/src/main/java/org/opencv/photo/MergeExposures.java new file mode 100644 index 00000000..68ba61fc --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/photo/MergeExposures.java @@ -0,0 +1,49 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.photo; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.utils.Converters; + +// C++: class MergeExposures +//javadoc: MergeExposures + +public class MergeExposures extends Algorithm { + + protected MergeExposures(long addr) { super(addr); } + + // internal usage only + public static MergeExposures __fromPtr__(long addr) { return new MergeExposures(addr); } + + // + // C++: void cv::MergeExposures::process(vector_Mat src, Mat& dst, Mat times, Mat response) + // + + //javadoc: MergeExposures::process(src, dst, times, response) + public void process(List src, Mat dst, Mat times, Mat response) + { + Mat src_mat = Converters.vector_Mat_to_Mat(src); + process_0(nativeObj, src_mat.nativeObj, dst.nativeObj, times.nativeObj, response.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::MergeExposures::process(vector_Mat src, Mat& dst, Mat times, Mat response) + private static native void process_0(long nativeObj, long src_mat_nativeObj, long dst_nativeObj, long times_nativeObj, long response_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/photo/MergeMertens.java b/OpenCV/src/main/java/org/opencv/photo/MergeMertens.java new file mode 100644 index 00000000..fd9e85b3 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/photo/MergeMertens.java @@ -0,0 +1,168 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.photo; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.photo.MergeExposures; +import org.opencv.utils.Converters; + +// C++: class MergeMertens +//javadoc: MergeMertens + +public class MergeMertens extends MergeExposures { + + protected MergeMertens(long addr) { super(addr); } + + // internal usage only + public static MergeMertens __fromPtr__(long addr) { return new MergeMertens(addr); } + + // + // C++: float cv::MergeMertens::getContrastWeight() + // + + //javadoc: MergeMertens::getContrastWeight() + public float getContrastWeight() + { + + float retVal = getContrastWeight_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::MergeMertens::getExposureWeight() + // + + //javadoc: MergeMertens::getExposureWeight() + public float getExposureWeight() + { + + float retVal = getExposureWeight_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::MergeMertens::getSaturationWeight() + // + + //javadoc: MergeMertens::getSaturationWeight() + public float getSaturationWeight() + { + + float retVal = getSaturationWeight_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::MergeMertens::process(vector_Mat src, Mat& dst, Mat times, Mat response) + // + + //javadoc: MergeMertens::process(src, dst, times, response) + public void process(List src, Mat dst, Mat times, Mat response) + { + Mat src_mat = Converters.vector_Mat_to_Mat(src); + process_0(nativeObj, src_mat.nativeObj, dst.nativeObj, times.nativeObj, response.nativeObj); + + return; + } + + + // + // C++: void cv::MergeMertens::process(vector_Mat src, Mat& dst) + // + + //javadoc: MergeMertens::process(src, dst) + public void process(List src, Mat dst) + { + Mat src_mat = Converters.vector_Mat_to_Mat(src); + process_1(nativeObj, src_mat.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::MergeMertens::setContrastWeight(float contrast_weiht) + // + + //javadoc: MergeMertens::setContrastWeight(contrast_weiht) + public void setContrastWeight(float contrast_weiht) + { + + setContrastWeight_0(nativeObj, contrast_weiht); + + return; + } + + + // + // C++: void cv::MergeMertens::setExposureWeight(float exposure_weight) + // + + //javadoc: MergeMertens::setExposureWeight(exposure_weight) + public void setExposureWeight(float exposure_weight) + { + + setExposureWeight_0(nativeObj, exposure_weight); + + return; + } + + + // + // C++: void cv::MergeMertens::setSaturationWeight(float saturation_weight) + // + + //javadoc: MergeMertens::setSaturationWeight(saturation_weight) + public void setSaturationWeight(float saturation_weight) + { + + setSaturationWeight_0(nativeObj, saturation_weight); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: float cv::MergeMertens::getContrastWeight() + private static native float getContrastWeight_0(long nativeObj); + + // C++: float cv::MergeMertens::getExposureWeight() + private static native float getExposureWeight_0(long nativeObj); + + // C++: float cv::MergeMertens::getSaturationWeight() + private static native float getSaturationWeight_0(long nativeObj); + + // C++: void cv::MergeMertens::process(vector_Mat src, Mat& dst, Mat times, Mat response) + private static native void process_0(long nativeObj, long src_mat_nativeObj, long dst_nativeObj, long times_nativeObj, long response_nativeObj); + + // C++: void cv::MergeMertens::process(vector_Mat src, Mat& dst) + private static native void process_1(long nativeObj, long src_mat_nativeObj, long dst_nativeObj); + + // C++: void cv::MergeMertens::setContrastWeight(float contrast_weiht) + private static native void setContrastWeight_0(long nativeObj, float contrast_weiht); + + // C++: void cv::MergeMertens::setExposureWeight(float exposure_weight) + private static native void setExposureWeight_0(long nativeObj, float exposure_weight); + + // C++: void cv::MergeMertens::setSaturationWeight(float saturation_weight) + private static native void setSaturationWeight_0(long nativeObj, float saturation_weight); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/photo/MergeRobertson.java b/OpenCV/src/main/java/org/opencv/photo/MergeRobertson.java new file mode 100644 index 00000000..536907d2 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/photo/MergeRobertson.java @@ -0,0 +1,66 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.photo; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.photo.MergeExposures; +import org.opencv.utils.Converters; + +// C++: class MergeRobertson +//javadoc: MergeRobertson + +public class MergeRobertson extends MergeExposures { + + protected MergeRobertson(long addr) { super(addr); } + + // internal usage only + public static MergeRobertson __fromPtr__(long addr) { return new MergeRobertson(addr); } + + // + // C++: void cv::MergeRobertson::process(vector_Mat src, Mat& dst, Mat times, Mat response) + // + + //javadoc: MergeRobertson::process(src, dst, times, response) + public void process(List src, Mat dst, Mat times, Mat response) + { + Mat src_mat = Converters.vector_Mat_to_Mat(src); + process_0(nativeObj, src_mat.nativeObj, dst.nativeObj, times.nativeObj, response.nativeObj); + + return; + } + + + // + // C++: void cv::MergeRobertson::process(vector_Mat src, Mat& dst, Mat times) + // + + //javadoc: MergeRobertson::process(src, dst, times) + public void process(List src, Mat dst, Mat times) + { + Mat src_mat = Converters.vector_Mat_to_Mat(src); + process_1(nativeObj, src_mat.nativeObj, dst.nativeObj, times.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::MergeRobertson::process(vector_Mat src, Mat& dst, Mat times, Mat response) + private static native void process_0(long nativeObj, long src_mat_nativeObj, long dst_nativeObj, long times_nativeObj, long response_nativeObj); + + // C++: void cv::MergeRobertson::process(vector_Mat src, Mat& dst, Mat times) + private static native void process_1(long nativeObj, long src_mat_nativeObj, long dst_nativeObj, long times_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/photo/Photo.java b/OpenCV/src/main/java/org/opencv/photo/Photo.java new file mode 100644 index 00000000..94832c05 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/photo/Photo.java @@ -0,0 +1,1125 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.photo; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfFloat; +import org.opencv.core.Point; +import org.opencv.photo.AlignMTB; +import org.opencv.photo.CalibrateDebevec; +import org.opencv.photo.CalibrateRobertson; +import org.opencv.photo.MergeDebevec; +import org.opencv.photo.MergeMertens; +import org.opencv.photo.MergeRobertson; +import org.opencv.photo.Tonemap; +import org.opencv.photo.TonemapDrago; +import org.opencv.photo.TonemapMantiuk; +import org.opencv.photo.TonemapReinhard; +import org.opencv.utils.Converters; + +// C++: class Photo +//javadoc: Photo + +public class Photo { + + // C++: enum + public static final int + INPAINT_NS = 0, + INPAINT_TELEA = 1, + LDR_SIZE = 256, + NORMAL_CLONE = 1, + MIXED_CLONE = 2, + MONOCHROME_TRANSFER = 3, + RECURS_FILTER = 1, + NORMCONV_FILTER = 2; + + + // + // C++: Ptr_AlignMTB cv::createAlignMTB(int max_bits = 6, int exclude_range = 4, bool cut = true) + // + + //javadoc: createAlignMTB(max_bits, exclude_range, cut) + public static AlignMTB createAlignMTB(int max_bits, int exclude_range, boolean cut) + { + + AlignMTB retVal = AlignMTB.__fromPtr__(createAlignMTB_0(max_bits, exclude_range, cut)); + + return retVal; + } + + //javadoc: createAlignMTB(max_bits, exclude_range) + public static AlignMTB createAlignMTB(int max_bits, int exclude_range) + { + + AlignMTB retVal = AlignMTB.__fromPtr__(createAlignMTB_1(max_bits, exclude_range)); + + return retVal; + } + + //javadoc: createAlignMTB(max_bits) + public static AlignMTB createAlignMTB(int max_bits) + { + + AlignMTB retVal = AlignMTB.__fromPtr__(createAlignMTB_2(max_bits)); + + return retVal; + } + + //javadoc: createAlignMTB() + public static AlignMTB createAlignMTB() + { + + AlignMTB retVal = AlignMTB.__fromPtr__(createAlignMTB_3()); + + return retVal; + } + + + // + // C++: Ptr_CalibrateDebevec cv::createCalibrateDebevec(int samples = 70, float lambda = 10.0f, bool random = false) + // + + //javadoc: createCalibrateDebevec(samples, lambda, random) + public static CalibrateDebevec createCalibrateDebevec(int samples, float lambda, boolean random) + { + + CalibrateDebevec retVal = CalibrateDebevec.__fromPtr__(createCalibrateDebevec_0(samples, lambda, random)); + + return retVal; + } + + //javadoc: createCalibrateDebevec(samples, lambda) + public static CalibrateDebevec createCalibrateDebevec(int samples, float lambda) + { + + CalibrateDebevec retVal = CalibrateDebevec.__fromPtr__(createCalibrateDebevec_1(samples, lambda)); + + return retVal; + } + + //javadoc: createCalibrateDebevec(samples) + public static CalibrateDebevec createCalibrateDebevec(int samples) + { + + CalibrateDebevec retVal = CalibrateDebevec.__fromPtr__(createCalibrateDebevec_2(samples)); + + return retVal; + } + + //javadoc: createCalibrateDebevec() + public static CalibrateDebevec createCalibrateDebevec() + { + + CalibrateDebevec retVal = CalibrateDebevec.__fromPtr__(createCalibrateDebevec_3()); + + return retVal; + } + + + // + // C++: Ptr_CalibrateRobertson cv::createCalibrateRobertson(int max_iter = 30, float threshold = 0.01f) + // + + //javadoc: createCalibrateRobertson(max_iter, threshold) + public static CalibrateRobertson createCalibrateRobertson(int max_iter, float threshold) + { + + CalibrateRobertson retVal = CalibrateRobertson.__fromPtr__(createCalibrateRobertson_0(max_iter, threshold)); + + return retVal; + } + + //javadoc: createCalibrateRobertson(max_iter) + public static CalibrateRobertson createCalibrateRobertson(int max_iter) + { + + CalibrateRobertson retVal = CalibrateRobertson.__fromPtr__(createCalibrateRobertson_1(max_iter)); + + return retVal; + } + + //javadoc: createCalibrateRobertson() + public static CalibrateRobertson createCalibrateRobertson() + { + + CalibrateRobertson retVal = CalibrateRobertson.__fromPtr__(createCalibrateRobertson_2()); + + return retVal; + } + + + // + // C++: Ptr_MergeDebevec cv::createMergeDebevec() + // + + //javadoc: createMergeDebevec() + public static MergeDebevec createMergeDebevec() + { + + MergeDebevec retVal = MergeDebevec.__fromPtr__(createMergeDebevec_0()); + + return retVal; + } + + + // + // C++: Ptr_MergeMertens cv::createMergeMertens(float contrast_weight = 1.0f, float saturation_weight = 1.0f, float exposure_weight = 0.0f) + // + + //javadoc: createMergeMertens(contrast_weight, saturation_weight, exposure_weight) + public static MergeMertens createMergeMertens(float contrast_weight, float saturation_weight, float exposure_weight) + { + + MergeMertens retVal = MergeMertens.__fromPtr__(createMergeMertens_0(contrast_weight, saturation_weight, exposure_weight)); + + return retVal; + } + + //javadoc: createMergeMertens(contrast_weight, saturation_weight) + public static MergeMertens createMergeMertens(float contrast_weight, float saturation_weight) + { + + MergeMertens retVal = MergeMertens.__fromPtr__(createMergeMertens_1(contrast_weight, saturation_weight)); + + return retVal; + } + + //javadoc: createMergeMertens(contrast_weight) + public static MergeMertens createMergeMertens(float contrast_weight) + { + + MergeMertens retVal = MergeMertens.__fromPtr__(createMergeMertens_2(contrast_weight)); + + return retVal; + } + + //javadoc: createMergeMertens() + public static MergeMertens createMergeMertens() + { + + MergeMertens retVal = MergeMertens.__fromPtr__(createMergeMertens_3()); + + return retVal; + } + + + // + // C++: Ptr_MergeRobertson cv::createMergeRobertson() + // + + //javadoc: createMergeRobertson() + public static MergeRobertson createMergeRobertson() + { + + MergeRobertson retVal = MergeRobertson.__fromPtr__(createMergeRobertson_0()); + + return retVal; + } + + + // + // C++: Ptr_Tonemap cv::createTonemap(float gamma = 1.0f) + // + + //javadoc: createTonemap(gamma) + public static Tonemap createTonemap(float gamma) + { + + Tonemap retVal = Tonemap.__fromPtr__(createTonemap_0(gamma)); + + return retVal; + } + + //javadoc: createTonemap() + public static Tonemap createTonemap() + { + + Tonemap retVal = Tonemap.__fromPtr__(createTonemap_1()); + + return retVal; + } + + + // + // C++: Ptr_TonemapDrago cv::createTonemapDrago(float gamma = 1.0f, float saturation = 1.0f, float bias = 0.85f) + // + + //javadoc: createTonemapDrago(gamma, saturation, bias) + public static TonemapDrago createTonemapDrago(float gamma, float saturation, float bias) + { + + TonemapDrago retVal = TonemapDrago.__fromPtr__(createTonemapDrago_0(gamma, saturation, bias)); + + return retVal; + } + + //javadoc: createTonemapDrago(gamma, saturation) + public static TonemapDrago createTonemapDrago(float gamma, float saturation) + { + + TonemapDrago retVal = TonemapDrago.__fromPtr__(createTonemapDrago_1(gamma, saturation)); + + return retVal; + } + + //javadoc: createTonemapDrago(gamma) + public static TonemapDrago createTonemapDrago(float gamma) + { + + TonemapDrago retVal = TonemapDrago.__fromPtr__(createTonemapDrago_2(gamma)); + + return retVal; + } + + //javadoc: createTonemapDrago() + public static TonemapDrago createTonemapDrago() + { + + TonemapDrago retVal = TonemapDrago.__fromPtr__(createTonemapDrago_3()); + + return retVal; + } + + + // + // C++: Ptr_TonemapMantiuk cv::createTonemapMantiuk(float gamma = 1.0f, float scale = 0.7f, float saturation = 1.0f) + // + + //javadoc: createTonemapMantiuk(gamma, scale, saturation) + public static TonemapMantiuk createTonemapMantiuk(float gamma, float scale, float saturation) + { + + TonemapMantiuk retVal = TonemapMantiuk.__fromPtr__(createTonemapMantiuk_0(gamma, scale, saturation)); + + return retVal; + } + + //javadoc: createTonemapMantiuk(gamma, scale) + public static TonemapMantiuk createTonemapMantiuk(float gamma, float scale) + { + + TonemapMantiuk retVal = TonemapMantiuk.__fromPtr__(createTonemapMantiuk_1(gamma, scale)); + + return retVal; + } + + //javadoc: createTonemapMantiuk(gamma) + public static TonemapMantiuk createTonemapMantiuk(float gamma) + { + + TonemapMantiuk retVal = TonemapMantiuk.__fromPtr__(createTonemapMantiuk_2(gamma)); + + return retVal; + } + + //javadoc: createTonemapMantiuk() + public static TonemapMantiuk createTonemapMantiuk() + { + + TonemapMantiuk retVal = TonemapMantiuk.__fromPtr__(createTonemapMantiuk_3()); + + return retVal; + } + + + // + // C++: Ptr_TonemapReinhard cv::createTonemapReinhard(float gamma = 1.0f, float intensity = 0.0f, float light_adapt = 1.0f, float color_adapt = 0.0f) + // + + //javadoc: createTonemapReinhard(gamma, intensity, light_adapt, color_adapt) + public static TonemapReinhard createTonemapReinhard(float gamma, float intensity, float light_adapt, float color_adapt) + { + + TonemapReinhard retVal = TonemapReinhard.__fromPtr__(createTonemapReinhard_0(gamma, intensity, light_adapt, color_adapt)); + + return retVal; + } + + //javadoc: createTonemapReinhard(gamma, intensity, light_adapt) + public static TonemapReinhard createTonemapReinhard(float gamma, float intensity, float light_adapt) + { + + TonemapReinhard retVal = TonemapReinhard.__fromPtr__(createTonemapReinhard_1(gamma, intensity, light_adapt)); + + return retVal; + } + + //javadoc: createTonemapReinhard(gamma, intensity) + public static TonemapReinhard createTonemapReinhard(float gamma, float intensity) + { + + TonemapReinhard retVal = TonemapReinhard.__fromPtr__(createTonemapReinhard_2(gamma, intensity)); + + return retVal; + } + + //javadoc: createTonemapReinhard(gamma) + public static TonemapReinhard createTonemapReinhard(float gamma) + { + + TonemapReinhard retVal = TonemapReinhard.__fromPtr__(createTonemapReinhard_3(gamma)); + + return retVal; + } + + //javadoc: createTonemapReinhard() + public static TonemapReinhard createTonemapReinhard() + { + + TonemapReinhard retVal = TonemapReinhard.__fromPtr__(createTonemapReinhard_4()); + + return retVal; + } + + + // + // C++: void cv::colorChange(Mat src, Mat mask, Mat& dst, float red_mul = 1.0f, float green_mul = 1.0f, float blue_mul = 1.0f) + // + + //javadoc: colorChange(src, mask, dst, red_mul, green_mul, blue_mul) + public static void colorChange(Mat src, Mat mask, Mat dst, float red_mul, float green_mul, float blue_mul) + { + + colorChange_0(src.nativeObj, mask.nativeObj, dst.nativeObj, red_mul, green_mul, blue_mul); + + return; + } + + //javadoc: colorChange(src, mask, dst, red_mul, green_mul) + public static void colorChange(Mat src, Mat mask, Mat dst, float red_mul, float green_mul) + { + + colorChange_1(src.nativeObj, mask.nativeObj, dst.nativeObj, red_mul, green_mul); + + return; + } + + //javadoc: colorChange(src, mask, dst, red_mul) + public static void colorChange(Mat src, Mat mask, Mat dst, float red_mul) + { + + colorChange_2(src.nativeObj, mask.nativeObj, dst.nativeObj, red_mul); + + return; + } + + //javadoc: colorChange(src, mask, dst) + public static void colorChange(Mat src, Mat mask, Mat dst) + { + + colorChange_3(src.nativeObj, mask.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::decolor(Mat src, Mat& grayscale, Mat& color_boost) + // + + //javadoc: decolor(src, grayscale, color_boost) + public static void decolor(Mat src, Mat grayscale, Mat color_boost) + { + + decolor_0(src.nativeObj, grayscale.nativeObj, color_boost.nativeObj); + + return; + } + + + // + // C++: void cv::denoise_TVL1(vector_Mat observations, Mat result, double lambda = 1.0, int niters = 30) + // + + //javadoc: denoise_TVL1(observations, result, lambda, niters) + public static void denoise_TVL1(List observations, Mat result, double lambda, int niters) + { + Mat observations_mat = Converters.vector_Mat_to_Mat(observations); + denoise_TVL1_0(observations_mat.nativeObj, result.nativeObj, lambda, niters); + + return; + } + + //javadoc: denoise_TVL1(observations, result, lambda) + public static void denoise_TVL1(List observations, Mat result, double lambda) + { + Mat observations_mat = Converters.vector_Mat_to_Mat(observations); + denoise_TVL1_1(observations_mat.nativeObj, result.nativeObj, lambda); + + return; + } + + //javadoc: denoise_TVL1(observations, result) + public static void denoise_TVL1(List observations, Mat result) + { + Mat observations_mat = Converters.vector_Mat_to_Mat(observations); + denoise_TVL1_2(observations_mat.nativeObj, result.nativeObj); + + return; + } + + + // + // C++: void cv::detailEnhance(Mat src, Mat& dst, float sigma_s = 10, float sigma_r = 0.15f) + // + + //javadoc: detailEnhance(src, dst, sigma_s, sigma_r) + public static void detailEnhance(Mat src, Mat dst, float sigma_s, float sigma_r) + { + + detailEnhance_0(src.nativeObj, dst.nativeObj, sigma_s, sigma_r); + + return; + } + + //javadoc: detailEnhance(src, dst, sigma_s) + public static void detailEnhance(Mat src, Mat dst, float sigma_s) + { + + detailEnhance_1(src.nativeObj, dst.nativeObj, sigma_s); + + return; + } + + //javadoc: detailEnhance(src, dst) + public static void detailEnhance(Mat src, Mat dst) + { + + detailEnhance_2(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::edgePreservingFilter(Mat src, Mat& dst, int flags = 1, float sigma_s = 60, float sigma_r = 0.4f) + // + + //javadoc: edgePreservingFilter(src, dst, flags, sigma_s, sigma_r) + public static void edgePreservingFilter(Mat src, Mat dst, int flags, float sigma_s, float sigma_r) + { + + edgePreservingFilter_0(src.nativeObj, dst.nativeObj, flags, sigma_s, sigma_r); + + return; + } + + //javadoc: edgePreservingFilter(src, dst, flags, sigma_s) + public static void edgePreservingFilter(Mat src, Mat dst, int flags, float sigma_s) + { + + edgePreservingFilter_1(src.nativeObj, dst.nativeObj, flags, sigma_s); + + return; + } + + //javadoc: edgePreservingFilter(src, dst, flags) + public static void edgePreservingFilter(Mat src, Mat dst, int flags) + { + + edgePreservingFilter_2(src.nativeObj, dst.nativeObj, flags); + + return; + } + + //javadoc: edgePreservingFilter(src, dst) + public static void edgePreservingFilter(Mat src, Mat dst) + { + + edgePreservingFilter_3(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::fastNlMeansDenoising(Mat src, Mat& dst, float h = 3, int templateWindowSize = 7, int searchWindowSize = 21) + // + + //javadoc: fastNlMeansDenoising(src, dst, h, templateWindowSize, searchWindowSize) + public static void fastNlMeansDenoising(Mat src, Mat dst, float h, int templateWindowSize, int searchWindowSize) + { + + fastNlMeansDenoising_0(src.nativeObj, dst.nativeObj, h, templateWindowSize, searchWindowSize); + + return; + } + + //javadoc: fastNlMeansDenoising(src, dst, h, templateWindowSize) + public static void fastNlMeansDenoising(Mat src, Mat dst, float h, int templateWindowSize) + { + + fastNlMeansDenoising_1(src.nativeObj, dst.nativeObj, h, templateWindowSize); + + return; + } + + //javadoc: fastNlMeansDenoising(src, dst, h) + public static void fastNlMeansDenoising(Mat src, Mat dst, float h) + { + + fastNlMeansDenoising_2(src.nativeObj, dst.nativeObj, h); + + return; + } + + //javadoc: fastNlMeansDenoising(src, dst) + public static void fastNlMeansDenoising(Mat src, Mat dst) + { + + fastNlMeansDenoising_3(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::fastNlMeansDenoising(Mat src, Mat& dst, vector_float h, int templateWindowSize = 7, int searchWindowSize = 21, int normType = NORM_L2) + // + + //javadoc: fastNlMeansDenoising(src, dst, h, templateWindowSize, searchWindowSize, normType) + public static void fastNlMeansDenoising(Mat src, Mat dst, MatOfFloat h, int templateWindowSize, int searchWindowSize, int normType) + { + Mat h_mat = h; + fastNlMeansDenoising_4(src.nativeObj, dst.nativeObj, h_mat.nativeObj, templateWindowSize, searchWindowSize, normType); + + return; + } + + //javadoc: fastNlMeansDenoising(src, dst, h, templateWindowSize, searchWindowSize) + public static void fastNlMeansDenoising(Mat src, Mat dst, MatOfFloat h, int templateWindowSize, int searchWindowSize) + { + Mat h_mat = h; + fastNlMeansDenoising_5(src.nativeObj, dst.nativeObj, h_mat.nativeObj, templateWindowSize, searchWindowSize); + + return; + } + + //javadoc: fastNlMeansDenoising(src, dst, h, templateWindowSize) + public static void fastNlMeansDenoising(Mat src, Mat dst, MatOfFloat h, int templateWindowSize) + { + Mat h_mat = h; + fastNlMeansDenoising_6(src.nativeObj, dst.nativeObj, h_mat.nativeObj, templateWindowSize); + + return; + } + + //javadoc: fastNlMeansDenoising(src, dst, h) + public static void fastNlMeansDenoising(Mat src, Mat dst, MatOfFloat h) + { + Mat h_mat = h; + fastNlMeansDenoising_7(src.nativeObj, dst.nativeObj, h_mat.nativeObj); + + return; + } + + + // + // C++: void cv::fastNlMeansDenoisingColored(Mat src, Mat& dst, float h = 3, float hColor = 3, int templateWindowSize = 7, int searchWindowSize = 21) + // + + //javadoc: fastNlMeansDenoisingColored(src, dst, h, hColor, templateWindowSize, searchWindowSize) + public static void fastNlMeansDenoisingColored(Mat src, Mat dst, float h, float hColor, int templateWindowSize, int searchWindowSize) + { + + fastNlMeansDenoisingColored_0(src.nativeObj, dst.nativeObj, h, hColor, templateWindowSize, searchWindowSize); + + return; + } + + //javadoc: fastNlMeansDenoisingColored(src, dst, h, hColor, templateWindowSize) + public static void fastNlMeansDenoisingColored(Mat src, Mat dst, float h, float hColor, int templateWindowSize) + { + + fastNlMeansDenoisingColored_1(src.nativeObj, dst.nativeObj, h, hColor, templateWindowSize); + + return; + } + + //javadoc: fastNlMeansDenoisingColored(src, dst, h, hColor) + public static void fastNlMeansDenoisingColored(Mat src, Mat dst, float h, float hColor) + { + + fastNlMeansDenoisingColored_2(src.nativeObj, dst.nativeObj, h, hColor); + + return; + } + + //javadoc: fastNlMeansDenoisingColored(src, dst, h) + public static void fastNlMeansDenoisingColored(Mat src, Mat dst, float h) + { + + fastNlMeansDenoisingColored_3(src.nativeObj, dst.nativeObj, h); + + return; + } + + //javadoc: fastNlMeansDenoisingColored(src, dst) + public static void fastNlMeansDenoisingColored(Mat src, Mat dst) + { + + fastNlMeansDenoisingColored_4(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::fastNlMeansDenoisingColoredMulti(vector_Mat srcImgs, Mat& dst, int imgToDenoiseIndex, int temporalWindowSize, float h = 3, float hColor = 3, int templateWindowSize = 7, int searchWindowSize = 21) + // + + //javadoc: fastNlMeansDenoisingColoredMulti(srcImgs, dst, imgToDenoiseIndex, temporalWindowSize, h, hColor, templateWindowSize, searchWindowSize) + public static void fastNlMeansDenoisingColoredMulti(List srcImgs, Mat dst, int imgToDenoiseIndex, int temporalWindowSize, float h, float hColor, int templateWindowSize, int searchWindowSize) + { + Mat srcImgs_mat = Converters.vector_Mat_to_Mat(srcImgs); + fastNlMeansDenoisingColoredMulti_0(srcImgs_mat.nativeObj, dst.nativeObj, imgToDenoiseIndex, temporalWindowSize, h, hColor, templateWindowSize, searchWindowSize); + + return; + } + + //javadoc: fastNlMeansDenoisingColoredMulti(srcImgs, dst, imgToDenoiseIndex, temporalWindowSize, h, hColor, templateWindowSize) + public static void fastNlMeansDenoisingColoredMulti(List srcImgs, Mat dst, int imgToDenoiseIndex, int temporalWindowSize, float h, float hColor, int templateWindowSize) + { + Mat srcImgs_mat = Converters.vector_Mat_to_Mat(srcImgs); + fastNlMeansDenoisingColoredMulti_1(srcImgs_mat.nativeObj, dst.nativeObj, imgToDenoiseIndex, temporalWindowSize, h, hColor, templateWindowSize); + + return; + } + + //javadoc: fastNlMeansDenoisingColoredMulti(srcImgs, dst, imgToDenoiseIndex, temporalWindowSize, h, hColor) + public static void fastNlMeansDenoisingColoredMulti(List srcImgs, Mat dst, int imgToDenoiseIndex, int temporalWindowSize, float h, float hColor) + { + Mat srcImgs_mat = Converters.vector_Mat_to_Mat(srcImgs); + fastNlMeansDenoisingColoredMulti_2(srcImgs_mat.nativeObj, dst.nativeObj, imgToDenoiseIndex, temporalWindowSize, h, hColor); + + return; + } + + //javadoc: fastNlMeansDenoisingColoredMulti(srcImgs, dst, imgToDenoiseIndex, temporalWindowSize, h) + public static void fastNlMeansDenoisingColoredMulti(List srcImgs, Mat dst, int imgToDenoiseIndex, int temporalWindowSize, float h) + { + Mat srcImgs_mat = Converters.vector_Mat_to_Mat(srcImgs); + fastNlMeansDenoisingColoredMulti_3(srcImgs_mat.nativeObj, dst.nativeObj, imgToDenoiseIndex, temporalWindowSize, h); + + return; + } + + //javadoc: fastNlMeansDenoisingColoredMulti(srcImgs, dst, imgToDenoiseIndex, temporalWindowSize) + public static void fastNlMeansDenoisingColoredMulti(List srcImgs, Mat dst, int imgToDenoiseIndex, int temporalWindowSize) + { + Mat srcImgs_mat = Converters.vector_Mat_to_Mat(srcImgs); + fastNlMeansDenoisingColoredMulti_4(srcImgs_mat.nativeObj, dst.nativeObj, imgToDenoiseIndex, temporalWindowSize); + + return; + } + + + // + // C++: void cv::fastNlMeansDenoisingMulti(vector_Mat srcImgs, Mat& dst, int imgToDenoiseIndex, int temporalWindowSize, float h = 3, int templateWindowSize = 7, int searchWindowSize = 21) + // + + //javadoc: fastNlMeansDenoisingMulti(srcImgs, dst, imgToDenoiseIndex, temporalWindowSize, h, templateWindowSize, searchWindowSize) + public static void fastNlMeansDenoisingMulti(List srcImgs, Mat dst, int imgToDenoiseIndex, int temporalWindowSize, float h, int templateWindowSize, int searchWindowSize) + { + Mat srcImgs_mat = Converters.vector_Mat_to_Mat(srcImgs); + fastNlMeansDenoisingMulti_0(srcImgs_mat.nativeObj, dst.nativeObj, imgToDenoiseIndex, temporalWindowSize, h, templateWindowSize, searchWindowSize); + + return; + } + + //javadoc: fastNlMeansDenoisingMulti(srcImgs, dst, imgToDenoiseIndex, temporalWindowSize, h, templateWindowSize) + public static void fastNlMeansDenoisingMulti(List srcImgs, Mat dst, int imgToDenoiseIndex, int temporalWindowSize, float h, int templateWindowSize) + { + Mat srcImgs_mat = Converters.vector_Mat_to_Mat(srcImgs); + fastNlMeansDenoisingMulti_1(srcImgs_mat.nativeObj, dst.nativeObj, imgToDenoiseIndex, temporalWindowSize, h, templateWindowSize); + + return; + } + + //javadoc: fastNlMeansDenoisingMulti(srcImgs, dst, imgToDenoiseIndex, temporalWindowSize, h) + public static void fastNlMeansDenoisingMulti(List srcImgs, Mat dst, int imgToDenoiseIndex, int temporalWindowSize, float h) + { + Mat srcImgs_mat = Converters.vector_Mat_to_Mat(srcImgs); + fastNlMeansDenoisingMulti_2(srcImgs_mat.nativeObj, dst.nativeObj, imgToDenoiseIndex, temporalWindowSize, h); + + return; + } + + //javadoc: fastNlMeansDenoisingMulti(srcImgs, dst, imgToDenoiseIndex, temporalWindowSize) + public static void fastNlMeansDenoisingMulti(List srcImgs, Mat dst, int imgToDenoiseIndex, int temporalWindowSize) + { + Mat srcImgs_mat = Converters.vector_Mat_to_Mat(srcImgs); + fastNlMeansDenoisingMulti_3(srcImgs_mat.nativeObj, dst.nativeObj, imgToDenoiseIndex, temporalWindowSize); + + return; + } + + + // + // C++: void cv::fastNlMeansDenoisingMulti(vector_Mat srcImgs, Mat& dst, int imgToDenoiseIndex, int temporalWindowSize, vector_float h, int templateWindowSize = 7, int searchWindowSize = 21, int normType = NORM_L2) + // + + //javadoc: fastNlMeansDenoisingMulti(srcImgs, dst, imgToDenoiseIndex, temporalWindowSize, h, templateWindowSize, searchWindowSize, normType) + public static void fastNlMeansDenoisingMulti(List srcImgs, Mat dst, int imgToDenoiseIndex, int temporalWindowSize, MatOfFloat h, int templateWindowSize, int searchWindowSize, int normType) + { + Mat srcImgs_mat = Converters.vector_Mat_to_Mat(srcImgs); + Mat h_mat = h; + fastNlMeansDenoisingMulti_4(srcImgs_mat.nativeObj, dst.nativeObj, imgToDenoiseIndex, temporalWindowSize, h_mat.nativeObj, templateWindowSize, searchWindowSize, normType); + + return; + } + + //javadoc: fastNlMeansDenoisingMulti(srcImgs, dst, imgToDenoiseIndex, temporalWindowSize, h, templateWindowSize, searchWindowSize) + public static void fastNlMeansDenoisingMulti(List srcImgs, Mat dst, int imgToDenoiseIndex, int temporalWindowSize, MatOfFloat h, int templateWindowSize, int searchWindowSize) + { + Mat srcImgs_mat = Converters.vector_Mat_to_Mat(srcImgs); + Mat h_mat = h; + fastNlMeansDenoisingMulti_5(srcImgs_mat.nativeObj, dst.nativeObj, imgToDenoiseIndex, temporalWindowSize, h_mat.nativeObj, templateWindowSize, searchWindowSize); + + return; + } + + //javadoc: fastNlMeansDenoisingMulti(srcImgs, dst, imgToDenoiseIndex, temporalWindowSize, h, templateWindowSize) + public static void fastNlMeansDenoisingMulti(List srcImgs, Mat dst, int imgToDenoiseIndex, int temporalWindowSize, MatOfFloat h, int templateWindowSize) + { + Mat srcImgs_mat = Converters.vector_Mat_to_Mat(srcImgs); + Mat h_mat = h; + fastNlMeansDenoisingMulti_6(srcImgs_mat.nativeObj, dst.nativeObj, imgToDenoiseIndex, temporalWindowSize, h_mat.nativeObj, templateWindowSize); + + return; + } + + //javadoc: fastNlMeansDenoisingMulti(srcImgs, dst, imgToDenoiseIndex, temporalWindowSize, h) + public static void fastNlMeansDenoisingMulti(List srcImgs, Mat dst, int imgToDenoiseIndex, int temporalWindowSize, MatOfFloat h) + { + Mat srcImgs_mat = Converters.vector_Mat_to_Mat(srcImgs); + Mat h_mat = h; + fastNlMeansDenoisingMulti_7(srcImgs_mat.nativeObj, dst.nativeObj, imgToDenoiseIndex, temporalWindowSize, h_mat.nativeObj); + + return; + } + + + // + // C++: void cv::illuminationChange(Mat src, Mat mask, Mat& dst, float alpha = 0.2f, float beta = 0.4f) + // + + //javadoc: illuminationChange(src, mask, dst, alpha, beta) + public static void illuminationChange(Mat src, Mat mask, Mat dst, float alpha, float beta) + { + + illuminationChange_0(src.nativeObj, mask.nativeObj, dst.nativeObj, alpha, beta); + + return; + } + + //javadoc: illuminationChange(src, mask, dst, alpha) + public static void illuminationChange(Mat src, Mat mask, Mat dst, float alpha) + { + + illuminationChange_1(src.nativeObj, mask.nativeObj, dst.nativeObj, alpha); + + return; + } + + //javadoc: illuminationChange(src, mask, dst) + public static void illuminationChange(Mat src, Mat mask, Mat dst) + { + + illuminationChange_2(src.nativeObj, mask.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::inpaint(Mat src, Mat inpaintMask, Mat& dst, double inpaintRadius, int flags) + // + + //javadoc: inpaint(src, inpaintMask, dst, inpaintRadius, flags) + public static void inpaint(Mat src, Mat inpaintMask, Mat dst, double inpaintRadius, int flags) + { + + inpaint_0(src.nativeObj, inpaintMask.nativeObj, dst.nativeObj, inpaintRadius, flags); + + return; + } + + + // + // C++: void cv::pencilSketch(Mat src, Mat& dst1, Mat& dst2, float sigma_s = 60, float sigma_r = 0.07f, float shade_factor = 0.02f) + // + + //javadoc: pencilSketch(src, dst1, dst2, sigma_s, sigma_r, shade_factor) + public static void pencilSketch(Mat src, Mat dst1, Mat dst2, float sigma_s, float sigma_r, float shade_factor) + { + + pencilSketch_0(src.nativeObj, dst1.nativeObj, dst2.nativeObj, sigma_s, sigma_r, shade_factor); + + return; + } + + //javadoc: pencilSketch(src, dst1, dst2, sigma_s, sigma_r) + public static void pencilSketch(Mat src, Mat dst1, Mat dst2, float sigma_s, float sigma_r) + { + + pencilSketch_1(src.nativeObj, dst1.nativeObj, dst2.nativeObj, sigma_s, sigma_r); + + return; + } + + //javadoc: pencilSketch(src, dst1, dst2, sigma_s) + public static void pencilSketch(Mat src, Mat dst1, Mat dst2, float sigma_s) + { + + pencilSketch_2(src.nativeObj, dst1.nativeObj, dst2.nativeObj, sigma_s); + + return; + } + + //javadoc: pencilSketch(src, dst1, dst2) + public static void pencilSketch(Mat src, Mat dst1, Mat dst2) + { + + pencilSketch_3(src.nativeObj, dst1.nativeObj, dst2.nativeObj); + + return; + } + + + // + // C++: void cv::seamlessClone(Mat src, Mat dst, Mat mask, Point p, Mat& blend, int flags) + // + + //javadoc: seamlessClone(src, dst, mask, p, blend, flags) + public static void seamlessClone(Mat src, Mat dst, Mat mask, Point p, Mat blend, int flags) + { + + seamlessClone_0(src.nativeObj, dst.nativeObj, mask.nativeObj, p.x, p.y, blend.nativeObj, flags); + + return; + } + + + // + // C++: void cv::stylization(Mat src, Mat& dst, float sigma_s = 60, float sigma_r = 0.45f) + // + + //javadoc: stylization(src, dst, sigma_s, sigma_r) + public static void stylization(Mat src, Mat dst, float sigma_s, float sigma_r) + { + + stylization_0(src.nativeObj, dst.nativeObj, sigma_s, sigma_r); + + return; + } + + //javadoc: stylization(src, dst, sigma_s) + public static void stylization(Mat src, Mat dst, float sigma_s) + { + + stylization_1(src.nativeObj, dst.nativeObj, sigma_s); + + return; + } + + //javadoc: stylization(src, dst) + public static void stylization(Mat src, Mat dst) + { + + stylization_2(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::textureFlattening(Mat src, Mat mask, Mat& dst, float low_threshold = 30, float high_threshold = 45, int kernel_size = 3) + // + + //javadoc: textureFlattening(src, mask, dst, low_threshold, high_threshold, kernel_size) + public static void textureFlattening(Mat src, Mat mask, Mat dst, float low_threshold, float high_threshold, int kernel_size) + { + + textureFlattening_0(src.nativeObj, mask.nativeObj, dst.nativeObj, low_threshold, high_threshold, kernel_size); + + return; + } + + //javadoc: textureFlattening(src, mask, dst, low_threshold, high_threshold) + public static void textureFlattening(Mat src, Mat mask, Mat dst, float low_threshold, float high_threshold) + { + + textureFlattening_1(src.nativeObj, mask.nativeObj, dst.nativeObj, low_threshold, high_threshold); + + return; + } + + //javadoc: textureFlattening(src, mask, dst, low_threshold) + public static void textureFlattening(Mat src, Mat mask, Mat dst, float low_threshold) + { + + textureFlattening_2(src.nativeObj, mask.nativeObj, dst.nativeObj, low_threshold); + + return; + } + + //javadoc: textureFlattening(src, mask, dst) + public static void textureFlattening(Mat src, Mat mask, Mat dst) + { + + textureFlattening_3(src.nativeObj, mask.nativeObj, dst.nativeObj); + + return; + } + + + + + // C++: Ptr_AlignMTB cv::createAlignMTB(int max_bits = 6, int exclude_range = 4, bool cut = true) + private static native long createAlignMTB_0(int max_bits, int exclude_range, boolean cut); + private static native long createAlignMTB_1(int max_bits, int exclude_range); + private static native long createAlignMTB_2(int max_bits); + private static native long createAlignMTB_3(); + + // C++: Ptr_CalibrateDebevec cv::createCalibrateDebevec(int samples = 70, float lambda = 10.0f, bool random = false) + private static native long createCalibrateDebevec_0(int samples, float lambda, boolean random); + private static native long createCalibrateDebevec_1(int samples, float lambda); + private static native long createCalibrateDebevec_2(int samples); + private static native long createCalibrateDebevec_3(); + + // C++: Ptr_CalibrateRobertson cv::createCalibrateRobertson(int max_iter = 30, float threshold = 0.01f) + private static native long createCalibrateRobertson_0(int max_iter, float threshold); + private static native long createCalibrateRobertson_1(int max_iter); + private static native long createCalibrateRobertson_2(); + + // C++: Ptr_MergeDebevec cv::createMergeDebevec() + private static native long createMergeDebevec_0(); + + // C++: Ptr_MergeMertens cv::createMergeMertens(float contrast_weight = 1.0f, float saturation_weight = 1.0f, float exposure_weight = 0.0f) + private static native long createMergeMertens_0(float contrast_weight, float saturation_weight, float exposure_weight); + private static native long createMergeMertens_1(float contrast_weight, float saturation_weight); + private static native long createMergeMertens_2(float contrast_weight); + private static native long createMergeMertens_3(); + + // C++: Ptr_MergeRobertson cv::createMergeRobertson() + private static native long createMergeRobertson_0(); + + // C++: Ptr_Tonemap cv::createTonemap(float gamma = 1.0f) + private static native long createTonemap_0(float gamma); + private static native long createTonemap_1(); + + // C++: Ptr_TonemapDrago cv::createTonemapDrago(float gamma = 1.0f, float saturation = 1.0f, float bias = 0.85f) + private static native long createTonemapDrago_0(float gamma, float saturation, float bias); + private static native long createTonemapDrago_1(float gamma, float saturation); + private static native long createTonemapDrago_2(float gamma); + private static native long createTonemapDrago_3(); + + // C++: Ptr_TonemapMantiuk cv::createTonemapMantiuk(float gamma = 1.0f, float scale = 0.7f, float saturation = 1.0f) + private static native long createTonemapMantiuk_0(float gamma, float scale, float saturation); + private static native long createTonemapMantiuk_1(float gamma, float scale); + private static native long createTonemapMantiuk_2(float gamma); + private static native long createTonemapMantiuk_3(); + + // C++: Ptr_TonemapReinhard cv::createTonemapReinhard(float gamma = 1.0f, float intensity = 0.0f, float light_adapt = 1.0f, float color_adapt = 0.0f) + private static native long createTonemapReinhard_0(float gamma, float intensity, float light_adapt, float color_adapt); + private static native long createTonemapReinhard_1(float gamma, float intensity, float light_adapt); + private static native long createTonemapReinhard_2(float gamma, float intensity); + private static native long createTonemapReinhard_3(float gamma); + private static native long createTonemapReinhard_4(); + + // C++: void cv::colorChange(Mat src, Mat mask, Mat& dst, float red_mul = 1.0f, float green_mul = 1.0f, float blue_mul = 1.0f) + private static native void colorChange_0(long src_nativeObj, long mask_nativeObj, long dst_nativeObj, float red_mul, float green_mul, float blue_mul); + private static native void colorChange_1(long src_nativeObj, long mask_nativeObj, long dst_nativeObj, float red_mul, float green_mul); + private static native void colorChange_2(long src_nativeObj, long mask_nativeObj, long dst_nativeObj, float red_mul); + private static native void colorChange_3(long src_nativeObj, long mask_nativeObj, long dst_nativeObj); + + // C++: void cv::decolor(Mat src, Mat& grayscale, Mat& color_boost) + private static native void decolor_0(long src_nativeObj, long grayscale_nativeObj, long color_boost_nativeObj); + + // C++: void cv::denoise_TVL1(vector_Mat observations, Mat result, double lambda = 1.0, int niters = 30) + private static native void denoise_TVL1_0(long observations_mat_nativeObj, long result_nativeObj, double lambda, int niters); + private static native void denoise_TVL1_1(long observations_mat_nativeObj, long result_nativeObj, double lambda); + private static native void denoise_TVL1_2(long observations_mat_nativeObj, long result_nativeObj); + + // C++: void cv::detailEnhance(Mat src, Mat& dst, float sigma_s = 10, float sigma_r = 0.15f) + private static native void detailEnhance_0(long src_nativeObj, long dst_nativeObj, float sigma_s, float sigma_r); + private static native void detailEnhance_1(long src_nativeObj, long dst_nativeObj, float sigma_s); + private static native void detailEnhance_2(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::edgePreservingFilter(Mat src, Mat& dst, int flags = 1, float sigma_s = 60, float sigma_r = 0.4f) + private static native void edgePreservingFilter_0(long src_nativeObj, long dst_nativeObj, int flags, float sigma_s, float sigma_r); + private static native void edgePreservingFilter_1(long src_nativeObj, long dst_nativeObj, int flags, float sigma_s); + private static native void edgePreservingFilter_2(long src_nativeObj, long dst_nativeObj, int flags); + private static native void edgePreservingFilter_3(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::fastNlMeansDenoising(Mat src, Mat& dst, float h = 3, int templateWindowSize = 7, int searchWindowSize = 21) + private static native void fastNlMeansDenoising_0(long src_nativeObj, long dst_nativeObj, float h, int templateWindowSize, int searchWindowSize); + private static native void fastNlMeansDenoising_1(long src_nativeObj, long dst_nativeObj, float h, int templateWindowSize); + private static native void fastNlMeansDenoising_2(long src_nativeObj, long dst_nativeObj, float h); + private static native void fastNlMeansDenoising_3(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::fastNlMeansDenoising(Mat src, Mat& dst, vector_float h, int templateWindowSize = 7, int searchWindowSize = 21, int normType = NORM_L2) + private static native void fastNlMeansDenoising_4(long src_nativeObj, long dst_nativeObj, long h_mat_nativeObj, int templateWindowSize, int searchWindowSize, int normType); + private static native void fastNlMeansDenoising_5(long src_nativeObj, long dst_nativeObj, long h_mat_nativeObj, int templateWindowSize, int searchWindowSize); + private static native void fastNlMeansDenoising_6(long src_nativeObj, long dst_nativeObj, long h_mat_nativeObj, int templateWindowSize); + private static native void fastNlMeansDenoising_7(long src_nativeObj, long dst_nativeObj, long h_mat_nativeObj); + + // C++: void cv::fastNlMeansDenoisingColored(Mat src, Mat& dst, float h = 3, float hColor = 3, int templateWindowSize = 7, int searchWindowSize = 21) + private static native void fastNlMeansDenoisingColored_0(long src_nativeObj, long dst_nativeObj, float h, float hColor, int templateWindowSize, int searchWindowSize); + private static native void fastNlMeansDenoisingColored_1(long src_nativeObj, long dst_nativeObj, float h, float hColor, int templateWindowSize); + private static native void fastNlMeansDenoisingColored_2(long src_nativeObj, long dst_nativeObj, float h, float hColor); + private static native void fastNlMeansDenoisingColored_3(long src_nativeObj, long dst_nativeObj, float h); + private static native void fastNlMeansDenoisingColored_4(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::fastNlMeansDenoisingColoredMulti(vector_Mat srcImgs, Mat& dst, int imgToDenoiseIndex, int temporalWindowSize, float h = 3, float hColor = 3, int templateWindowSize = 7, int searchWindowSize = 21) + private static native void fastNlMeansDenoisingColoredMulti_0(long srcImgs_mat_nativeObj, long dst_nativeObj, int imgToDenoiseIndex, int temporalWindowSize, float h, float hColor, int templateWindowSize, int searchWindowSize); + private static native void fastNlMeansDenoisingColoredMulti_1(long srcImgs_mat_nativeObj, long dst_nativeObj, int imgToDenoiseIndex, int temporalWindowSize, float h, float hColor, int templateWindowSize); + private static native void fastNlMeansDenoisingColoredMulti_2(long srcImgs_mat_nativeObj, long dst_nativeObj, int imgToDenoiseIndex, int temporalWindowSize, float h, float hColor); + private static native void fastNlMeansDenoisingColoredMulti_3(long srcImgs_mat_nativeObj, long dst_nativeObj, int imgToDenoiseIndex, int temporalWindowSize, float h); + private static native void fastNlMeansDenoisingColoredMulti_4(long srcImgs_mat_nativeObj, long dst_nativeObj, int imgToDenoiseIndex, int temporalWindowSize); + + // C++: void cv::fastNlMeansDenoisingMulti(vector_Mat srcImgs, Mat& dst, int imgToDenoiseIndex, int temporalWindowSize, float h = 3, int templateWindowSize = 7, int searchWindowSize = 21) + private static native void fastNlMeansDenoisingMulti_0(long srcImgs_mat_nativeObj, long dst_nativeObj, int imgToDenoiseIndex, int temporalWindowSize, float h, int templateWindowSize, int searchWindowSize); + private static native void fastNlMeansDenoisingMulti_1(long srcImgs_mat_nativeObj, long dst_nativeObj, int imgToDenoiseIndex, int temporalWindowSize, float h, int templateWindowSize); + private static native void fastNlMeansDenoisingMulti_2(long srcImgs_mat_nativeObj, long dst_nativeObj, int imgToDenoiseIndex, int temporalWindowSize, float h); + private static native void fastNlMeansDenoisingMulti_3(long srcImgs_mat_nativeObj, long dst_nativeObj, int imgToDenoiseIndex, int temporalWindowSize); + + // C++: void cv::fastNlMeansDenoisingMulti(vector_Mat srcImgs, Mat& dst, int imgToDenoiseIndex, int temporalWindowSize, vector_float h, int templateWindowSize = 7, int searchWindowSize = 21, int normType = NORM_L2) + private static native void fastNlMeansDenoisingMulti_4(long srcImgs_mat_nativeObj, long dst_nativeObj, int imgToDenoiseIndex, int temporalWindowSize, long h_mat_nativeObj, int templateWindowSize, int searchWindowSize, int normType); + private static native void fastNlMeansDenoisingMulti_5(long srcImgs_mat_nativeObj, long dst_nativeObj, int imgToDenoiseIndex, int temporalWindowSize, long h_mat_nativeObj, int templateWindowSize, int searchWindowSize); + private static native void fastNlMeansDenoisingMulti_6(long srcImgs_mat_nativeObj, long dst_nativeObj, int imgToDenoiseIndex, int temporalWindowSize, long h_mat_nativeObj, int templateWindowSize); + private static native void fastNlMeansDenoisingMulti_7(long srcImgs_mat_nativeObj, long dst_nativeObj, int imgToDenoiseIndex, int temporalWindowSize, long h_mat_nativeObj); + + // C++: void cv::illuminationChange(Mat src, Mat mask, Mat& dst, float alpha = 0.2f, float beta = 0.4f) + private static native void illuminationChange_0(long src_nativeObj, long mask_nativeObj, long dst_nativeObj, float alpha, float beta); + private static native void illuminationChange_1(long src_nativeObj, long mask_nativeObj, long dst_nativeObj, float alpha); + private static native void illuminationChange_2(long src_nativeObj, long mask_nativeObj, long dst_nativeObj); + + // C++: void cv::inpaint(Mat src, Mat inpaintMask, Mat& dst, double inpaintRadius, int flags) + private static native void inpaint_0(long src_nativeObj, long inpaintMask_nativeObj, long dst_nativeObj, double inpaintRadius, int flags); + + // C++: void cv::pencilSketch(Mat src, Mat& dst1, Mat& dst2, float sigma_s = 60, float sigma_r = 0.07f, float shade_factor = 0.02f) + private static native void pencilSketch_0(long src_nativeObj, long dst1_nativeObj, long dst2_nativeObj, float sigma_s, float sigma_r, float shade_factor); + private static native void pencilSketch_1(long src_nativeObj, long dst1_nativeObj, long dst2_nativeObj, float sigma_s, float sigma_r); + private static native void pencilSketch_2(long src_nativeObj, long dst1_nativeObj, long dst2_nativeObj, float sigma_s); + private static native void pencilSketch_3(long src_nativeObj, long dst1_nativeObj, long dst2_nativeObj); + + // C++: void cv::seamlessClone(Mat src, Mat dst, Mat mask, Point p, Mat& blend, int flags) + private static native void seamlessClone_0(long src_nativeObj, long dst_nativeObj, long mask_nativeObj, double p_x, double p_y, long blend_nativeObj, int flags); + + // C++: void cv::stylization(Mat src, Mat& dst, float sigma_s = 60, float sigma_r = 0.45f) + private static native void stylization_0(long src_nativeObj, long dst_nativeObj, float sigma_s, float sigma_r); + private static native void stylization_1(long src_nativeObj, long dst_nativeObj, float sigma_s); + private static native void stylization_2(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::textureFlattening(Mat src, Mat mask, Mat& dst, float low_threshold = 30, float high_threshold = 45, int kernel_size = 3) + private static native void textureFlattening_0(long src_nativeObj, long mask_nativeObj, long dst_nativeObj, float low_threshold, float high_threshold, int kernel_size); + private static native void textureFlattening_1(long src_nativeObj, long mask_nativeObj, long dst_nativeObj, float low_threshold, float high_threshold); + private static native void textureFlattening_2(long src_nativeObj, long mask_nativeObj, long dst_nativeObj, float low_threshold); + private static native void textureFlattening_3(long src_nativeObj, long mask_nativeObj, long dst_nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/photo/Tonemap.java b/OpenCV/src/main/java/org/opencv/photo/Tonemap.java new file mode 100644 index 00000000..e816a034 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/photo/Tonemap.java @@ -0,0 +1,80 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.photo; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class Tonemap +//javadoc: Tonemap + +public class Tonemap extends Algorithm { + + protected Tonemap(long addr) { super(addr); } + + // internal usage only + public static Tonemap __fromPtr__(long addr) { return new Tonemap(addr); } + + // + // C++: float cv::Tonemap::getGamma() + // + + //javadoc: Tonemap::getGamma() + public float getGamma() + { + + float retVal = getGamma_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::Tonemap::process(Mat src, Mat& dst) + // + + //javadoc: Tonemap::process(src, dst) + public void process(Mat src, Mat dst) + { + + process_0(nativeObj, src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::Tonemap::setGamma(float gamma) + // + + //javadoc: Tonemap::setGamma(gamma) + public void setGamma(float gamma) + { + + setGamma_0(nativeObj, gamma); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: float cv::Tonemap::getGamma() + private static native float getGamma_0(long nativeObj); + + // C++: void cv::Tonemap::process(Mat src, Mat& dst) + private static native void process_0(long nativeObj, long src_nativeObj, long dst_nativeObj); + + // C++: void cv::Tonemap::setGamma(float gamma) + private static native void setGamma_0(long nativeObj, float gamma); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/photo/TonemapDrago.java b/OpenCV/src/main/java/org/opencv/photo/TonemapDrago.java new file mode 100644 index 00000000..15d2ef2b --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/photo/TonemapDrago.java @@ -0,0 +1,96 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.photo; + +import org.opencv.photo.Tonemap; + +// C++: class TonemapDrago +//javadoc: TonemapDrago + +public class TonemapDrago extends Tonemap { + + protected TonemapDrago(long addr) { super(addr); } + + // internal usage only + public static TonemapDrago __fromPtr__(long addr) { return new TonemapDrago(addr); } + + // + // C++: float cv::TonemapDrago::getBias() + // + + //javadoc: TonemapDrago::getBias() + public float getBias() + { + + float retVal = getBias_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::TonemapDrago::getSaturation() + // + + //javadoc: TonemapDrago::getSaturation() + public float getSaturation() + { + + float retVal = getSaturation_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::TonemapDrago::setBias(float bias) + // + + //javadoc: TonemapDrago::setBias(bias) + public void setBias(float bias) + { + + setBias_0(nativeObj, bias); + + return; + } + + + // + // C++: void cv::TonemapDrago::setSaturation(float saturation) + // + + //javadoc: TonemapDrago::setSaturation(saturation) + public void setSaturation(float saturation) + { + + setSaturation_0(nativeObj, saturation); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: float cv::TonemapDrago::getBias() + private static native float getBias_0(long nativeObj); + + // C++: float cv::TonemapDrago::getSaturation() + private static native float getSaturation_0(long nativeObj); + + // C++: void cv::TonemapDrago::setBias(float bias) + private static native void setBias_0(long nativeObj, float bias); + + // C++: void cv::TonemapDrago::setSaturation(float saturation) + private static native void setSaturation_0(long nativeObj, float saturation); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/photo/TonemapMantiuk.java b/OpenCV/src/main/java/org/opencv/photo/TonemapMantiuk.java new file mode 100644 index 00000000..49f24a75 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/photo/TonemapMantiuk.java @@ -0,0 +1,96 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.photo; + +import org.opencv.photo.Tonemap; + +// C++: class TonemapMantiuk +//javadoc: TonemapMantiuk + +public class TonemapMantiuk extends Tonemap { + + protected TonemapMantiuk(long addr) { super(addr); } + + // internal usage only + public static TonemapMantiuk __fromPtr__(long addr) { return new TonemapMantiuk(addr); } + + // + // C++: float cv::TonemapMantiuk::getSaturation() + // + + //javadoc: TonemapMantiuk::getSaturation() + public float getSaturation() + { + + float retVal = getSaturation_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::TonemapMantiuk::getScale() + // + + //javadoc: TonemapMantiuk::getScale() + public float getScale() + { + + float retVal = getScale_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::TonemapMantiuk::setSaturation(float saturation) + // + + //javadoc: TonemapMantiuk::setSaturation(saturation) + public void setSaturation(float saturation) + { + + setSaturation_0(nativeObj, saturation); + + return; + } + + + // + // C++: void cv::TonemapMantiuk::setScale(float scale) + // + + //javadoc: TonemapMantiuk::setScale(scale) + public void setScale(float scale) + { + + setScale_0(nativeObj, scale); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: float cv::TonemapMantiuk::getSaturation() + private static native float getSaturation_0(long nativeObj); + + // C++: float cv::TonemapMantiuk::getScale() + private static native float getScale_0(long nativeObj); + + // C++: void cv::TonemapMantiuk::setSaturation(float saturation) + private static native void setSaturation_0(long nativeObj, float saturation); + + // C++: void cv::TonemapMantiuk::setScale(float scale) + private static native void setScale_0(long nativeObj, float scale); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/photo/TonemapReinhard.java b/OpenCV/src/main/java/org/opencv/photo/TonemapReinhard.java new file mode 100644 index 00000000..354e233f --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/photo/TonemapReinhard.java @@ -0,0 +1,130 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.photo; + +import org.opencv.photo.Tonemap; + +// C++: class TonemapReinhard +//javadoc: TonemapReinhard + +public class TonemapReinhard extends Tonemap { + + protected TonemapReinhard(long addr) { super(addr); } + + // internal usage only + public static TonemapReinhard __fromPtr__(long addr) { return new TonemapReinhard(addr); } + + // + // C++: float cv::TonemapReinhard::getColorAdaptation() + // + + //javadoc: TonemapReinhard::getColorAdaptation() + public float getColorAdaptation() + { + + float retVal = getColorAdaptation_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::TonemapReinhard::getIntensity() + // + + //javadoc: TonemapReinhard::getIntensity() + public float getIntensity() + { + + float retVal = getIntensity_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::TonemapReinhard::getLightAdaptation() + // + + //javadoc: TonemapReinhard::getLightAdaptation() + public float getLightAdaptation() + { + + float retVal = getLightAdaptation_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::TonemapReinhard::setColorAdaptation(float color_adapt) + // + + //javadoc: TonemapReinhard::setColorAdaptation(color_adapt) + public void setColorAdaptation(float color_adapt) + { + + setColorAdaptation_0(nativeObj, color_adapt); + + return; + } + + + // + // C++: void cv::TonemapReinhard::setIntensity(float intensity) + // + + //javadoc: TonemapReinhard::setIntensity(intensity) + public void setIntensity(float intensity) + { + + setIntensity_0(nativeObj, intensity); + + return; + } + + + // + // C++: void cv::TonemapReinhard::setLightAdaptation(float light_adapt) + // + + //javadoc: TonemapReinhard::setLightAdaptation(light_adapt) + public void setLightAdaptation(float light_adapt) + { + + setLightAdaptation_0(nativeObj, light_adapt); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: float cv::TonemapReinhard::getColorAdaptation() + private static native float getColorAdaptation_0(long nativeObj); + + // C++: float cv::TonemapReinhard::getIntensity() + private static native float getIntensity_0(long nativeObj); + + // C++: float cv::TonemapReinhard::getLightAdaptation() + private static native float getLightAdaptation_0(long nativeObj); + + // C++: void cv::TonemapReinhard::setColorAdaptation(float color_adapt) + private static native void setColorAdaptation_0(long nativeObj, float color_adapt); + + // C++: void cv::TonemapReinhard::setIntensity(float intensity) + private static native void setIntensity_0(long nativeObj, float intensity); + + // C++: void cv::TonemapReinhard::setLightAdaptation(float light_adapt) + private static native void setLightAdaptation_0(long nativeObj, float light_adapt); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/plot/Plot.java b/OpenCV/src/main/java/org/opencv/plot/Plot.java new file mode 100644 index 00000000..0256e297 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/plot/Plot.java @@ -0,0 +1,15 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.plot; + + + +// C++: class Plot +//javadoc: Plot + +public class Plot { + + + +} diff --git a/OpenCV/src/main/java/org/opencv/plot/Plot2d.java b/OpenCV/src/main/java/org/opencv/plot/Plot2d.java new file mode 100644 index 00000000..a2340491 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/plot/Plot2d.java @@ -0,0 +1,371 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.plot; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.core.Scalar; +import org.opencv.plot.Plot2d; + +// C++: class Plot2d +//javadoc: Plot2d + +public class Plot2d extends Algorithm { + + protected Plot2d(long addr) { super(addr); } + + // internal usage only + public static Plot2d __fromPtr__(long addr) { return new Plot2d(addr); } + + // + // C++: static Ptr_Plot2d cv::plot::Plot2d::create(Mat data) + // + + //javadoc: Plot2d::create(data) + public static Plot2d create(Mat data) + { + + Plot2d retVal = Plot2d.__fromPtr__(create_0(data.nativeObj)); + + return retVal; + } + + + // + // C++: static Ptr_Plot2d cv::plot::Plot2d::create(Mat dataX, Mat dataY) + // + + //javadoc: Plot2d::create(dataX, dataY) + public static Plot2d create(Mat dataX, Mat dataY) + { + + Plot2d retVal = Plot2d.__fromPtr__(create_1(dataX.nativeObj, dataY.nativeObj)); + + return retVal; + } + + + // + // C++: void cv::plot::Plot2d::render(Mat& _plotResult) + // + + //javadoc: Plot2d::render(_plotResult) + public void render(Mat _plotResult) + { + + render_0(nativeObj, _plotResult.nativeObj); + + return; + } + + + // + // C++: void cv::plot::Plot2d::setGridLinesNumber(int gridLinesNumber) + // + + //javadoc: Plot2d::setGridLinesNumber(gridLinesNumber) + public void setGridLinesNumber(int gridLinesNumber) + { + + setGridLinesNumber_0(nativeObj, gridLinesNumber); + + return; + } + + + // + // C++: void cv::plot::Plot2d::setInvertOrientation(bool _invertOrientation) + // + + //javadoc: Plot2d::setInvertOrientation(_invertOrientation) + public void setInvertOrientation(boolean _invertOrientation) + { + + setInvertOrientation_0(nativeObj, _invertOrientation); + + return; + } + + + // + // C++: void cv::plot::Plot2d::setMaxX(double _plotMaxX) + // + + //javadoc: Plot2d::setMaxX(_plotMaxX) + public void setMaxX(double _plotMaxX) + { + + setMaxX_0(nativeObj, _plotMaxX); + + return; + } + + + // + // C++: void cv::plot::Plot2d::setMaxY(double _plotMaxY) + // + + //javadoc: Plot2d::setMaxY(_plotMaxY) + public void setMaxY(double _plotMaxY) + { + + setMaxY_0(nativeObj, _plotMaxY); + + return; + } + + + // + // C++: void cv::plot::Plot2d::setMinX(double _plotMinX) + // + + //javadoc: Plot2d::setMinX(_plotMinX) + public void setMinX(double _plotMinX) + { + + setMinX_0(nativeObj, _plotMinX); + + return; + } + + + // + // C++: void cv::plot::Plot2d::setMinY(double _plotMinY) + // + + //javadoc: Plot2d::setMinY(_plotMinY) + public void setMinY(double _plotMinY) + { + + setMinY_0(nativeObj, _plotMinY); + + return; + } + + + // + // C++: void cv::plot::Plot2d::setNeedPlotLine(bool _needPlotLine) + // + + //javadoc: Plot2d::setNeedPlotLine(_needPlotLine) + public void setNeedPlotLine(boolean _needPlotLine) + { + + setNeedPlotLine_0(nativeObj, _needPlotLine); + + return; + } + + + // + // C++: void cv::plot::Plot2d::setPlotAxisColor(Scalar _plotAxisColor) + // + + //javadoc: Plot2d::setPlotAxisColor(_plotAxisColor) + public void setPlotAxisColor(Scalar _plotAxisColor) + { + + setPlotAxisColor_0(nativeObj, _plotAxisColor.val[0], _plotAxisColor.val[1], _plotAxisColor.val[2], _plotAxisColor.val[3]); + + return; + } + + + // + // C++: void cv::plot::Plot2d::setPlotBackgroundColor(Scalar _plotBackgroundColor) + // + + //javadoc: Plot2d::setPlotBackgroundColor(_plotBackgroundColor) + public void setPlotBackgroundColor(Scalar _plotBackgroundColor) + { + + setPlotBackgroundColor_0(nativeObj, _plotBackgroundColor.val[0], _plotBackgroundColor.val[1], _plotBackgroundColor.val[2], _plotBackgroundColor.val[3]); + + return; + } + + + // + // C++: void cv::plot::Plot2d::setPlotGridColor(Scalar _plotGridColor) + // + + //javadoc: Plot2d::setPlotGridColor(_plotGridColor) + public void setPlotGridColor(Scalar _plotGridColor) + { + + setPlotGridColor_0(nativeObj, _plotGridColor.val[0], _plotGridColor.val[1], _plotGridColor.val[2], _plotGridColor.val[3]); + + return; + } + + + // + // C++: void cv::plot::Plot2d::setPlotLineColor(Scalar _plotLineColor) + // + + //javadoc: Plot2d::setPlotLineColor(_plotLineColor) + public void setPlotLineColor(Scalar _plotLineColor) + { + + setPlotLineColor_0(nativeObj, _plotLineColor.val[0], _plotLineColor.val[1], _plotLineColor.val[2], _plotLineColor.val[3]); + + return; + } + + + // + // C++: void cv::plot::Plot2d::setPlotLineWidth(int _plotLineWidth) + // + + //javadoc: Plot2d::setPlotLineWidth(_plotLineWidth) + public void setPlotLineWidth(int _plotLineWidth) + { + + setPlotLineWidth_0(nativeObj, _plotLineWidth); + + return; + } + + + // + // C++: void cv::plot::Plot2d::setPlotSize(int _plotSizeWidth, int _plotSizeHeight) + // + + //javadoc: Plot2d::setPlotSize(_plotSizeWidth, _plotSizeHeight) + public void setPlotSize(int _plotSizeWidth, int _plotSizeHeight) + { + + setPlotSize_0(nativeObj, _plotSizeWidth, _plotSizeHeight); + + return; + } + + + // + // C++: void cv::plot::Plot2d::setPlotTextColor(Scalar _plotTextColor) + // + + //javadoc: Plot2d::setPlotTextColor(_plotTextColor) + public void setPlotTextColor(Scalar _plotTextColor) + { + + setPlotTextColor_0(nativeObj, _plotTextColor.val[0], _plotTextColor.val[1], _plotTextColor.val[2], _plotTextColor.val[3]); + + return; + } + + + // + // C++: void cv::plot::Plot2d::setPointIdxToPrint(int pointIdx) + // + + //javadoc: Plot2d::setPointIdxToPrint(pointIdx) + public void setPointIdxToPrint(int pointIdx) + { + + setPointIdxToPrint_0(nativeObj, pointIdx); + + return; + } + + + // + // C++: void cv::plot::Plot2d::setShowGrid(bool needShowGrid) + // + + //javadoc: Plot2d::setShowGrid(needShowGrid) + public void setShowGrid(boolean needShowGrid) + { + + setShowGrid_0(nativeObj, needShowGrid); + + return; + } + + + // + // C++: void cv::plot::Plot2d::setShowText(bool needShowText) + // + + //javadoc: Plot2d::setShowText(needShowText) + public void setShowText(boolean needShowText) + { + + setShowText_0(nativeObj, needShowText); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_Plot2d cv::plot::Plot2d::create(Mat data) + private static native long create_0(long data_nativeObj); + + // C++: static Ptr_Plot2d cv::plot::Plot2d::create(Mat dataX, Mat dataY) + private static native long create_1(long dataX_nativeObj, long dataY_nativeObj); + + // C++: void cv::plot::Plot2d::render(Mat& _plotResult) + private static native void render_0(long nativeObj, long _plotResult_nativeObj); + + // C++: void cv::plot::Plot2d::setGridLinesNumber(int gridLinesNumber) + private static native void setGridLinesNumber_0(long nativeObj, int gridLinesNumber); + + // C++: void cv::plot::Plot2d::setInvertOrientation(bool _invertOrientation) + private static native void setInvertOrientation_0(long nativeObj, boolean _invertOrientation); + + // C++: void cv::plot::Plot2d::setMaxX(double _plotMaxX) + private static native void setMaxX_0(long nativeObj, double _plotMaxX); + + // C++: void cv::plot::Plot2d::setMaxY(double _plotMaxY) + private static native void setMaxY_0(long nativeObj, double _plotMaxY); + + // C++: void cv::plot::Plot2d::setMinX(double _plotMinX) + private static native void setMinX_0(long nativeObj, double _plotMinX); + + // C++: void cv::plot::Plot2d::setMinY(double _plotMinY) + private static native void setMinY_0(long nativeObj, double _plotMinY); + + // C++: void cv::plot::Plot2d::setNeedPlotLine(bool _needPlotLine) + private static native void setNeedPlotLine_0(long nativeObj, boolean _needPlotLine); + + // C++: void cv::plot::Plot2d::setPlotAxisColor(Scalar _plotAxisColor) + private static native void setPlotAxisColor_0(long nativeObj, double _plotAxisColor_val0, double _plotAxisColor_val1, double _plotAxisColor_val2, double _plotAxisColor_val3); + + // C++: void cv::plot::Plot2d::setPlotBackgroundColor(Scalar _plotBackgroundColor) + private static native void setPlotBackgroundColor_0(long nativeObj, double _plotBackgroundColor_val0, double _plotBackgroundColor_val1, double _plotBackgroundColor_val2, double _plotBackgroundColor_val3); + + // C++: void cv::plot::Plot2d::setPlotGridColor(Scalar _plotGridColor) + private static native void setPlotGridColor_0(long nativeObj, double _plotGridColor_val0, double _plotGridColor_val1, double _plotGridColor_val2, double _plotGridColor_val3); + + // C++: void cv::plot::Plot2d::setPlotLineColor(Scalar _plotLineColor) + private static native void setPlotLineColor_0(long nativeObj, double _plotLineColor_val0, double _plotLineColor_val1, double _plotLineColor_val2, double _plotLineColor_val3); + + // C++: void cv::plot::Plot2d::setPlotLineWidth(int _plotLineWidth) + private static native void setPlotLineWidth_0(long nativeObj, int _plotLineWidth); + + // C++: void cv::plot::Plot2d::setPlotSize(int _plotSizeWidth, int _plotSizeHeight) + private static native void setPlotSize_0(long nativeObj, int _plotSizeWidth, int _plotSizeHeight); + + // C++: void cv::plot::Plot2d::setPlotTextColor(Scalar _plotTextColor) + private static native void setPlotTextColor_0(long nativeObj, double _plotTextColor_val0, double _plotTextColor_val1, double _plotTextColor_val2, double _plotTextColor_val3); + + // C++: void cv::plot::Plot2d::setPointIdxToPrint(int pointIdx) + private static native void setPointIdxToPrint_0(long nativeObj, int pointIdx); + + // C++: void cv::plot::Plot2d::setShowGrid(bool needShowGrid) + private static native void setShowGrid_0(long nativeObj, boolean needShowGrid); + + // C++: void cv::plot::Plot2d::setShowText(bool needShowText) + private static native void setShowText_0(long nativeObj, boolean needShowText); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/structured_light/GrayCodePattern.java b/OpenCV/src/main/java/org/opencv/structured_light/GrayCodePattern.java new file mode 100644 index 00000000..f8df6ba9 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/structured_light/GrayCodePattern.java @@ -0,0 +1,137 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.structured_light; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.Point; +import org.opencv.structured_light.GrayCodePattern; +import org.opencv.structured_light.StructuredLightPattern; +import org.opencv.utils.Converters; + +// C++: class GrayCodePattern +//javadoc: GrayCodePattern + +public class GrayCodePattern extends StructuredLightPattern { + + protected GrayCodePattern(long addr) { super(addr); } + + // internal usage only + public static GrayCodePattern __fromPtr__(long addr) { return new GrayCodePattern(addr); } + + // + // C++: static Ptr_GrayCodePattern cv::structured_light::GrayCodePattern::create(int width, int height) + // + + //javadoc: GrayCodePattern::create(width, height) + public static GrayCodePattern create(int width, int height) + { + + GrayCodePattern retVal = GrayCodePattern.__fromPtr__(create_0(width, height)); + + return retVal; + } + + + // + // C++: bool cv::structured_light::GrayCodePattern::getProjPixel(vector_Mat patternImages, int x, int y, Point& projPix) + // + + //javadoc: GrayCodePattern::getProjPixel(patternImages, x, y, projPix) + public boolean getProjPixel(List patternImages, int x, int y, Point projPix) + { + Mat patternImages_mat = Converters.vector_Mat_to_Mat(patternImages); + double[] projPix_out = new double[2]; + boolean retVal = getProjPixel_0(nativeObj, patternImages_mat.nativeObj, x, y, projPix_out); + if(projPix!=null){ projPix.x = projPix_out[0]; projPix.y = projPix_out[1]; } + return retVal; + } + + + // + // C++: size_t cv::structured_light::GrayCodePattern::getNumberOfPatternImages() + // + + //javadoc: GrayCodePattern::getNumberOfPatternImages() + public long getNumberOfPatternImages() + { + + long retVal = getNumberOfPatternImages_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::structured_light::GrayCodePattern::getImagesForShadowMasks(Mat& blackImage, Mat& whiteImage) + // + + //javadoc: GrayCodePattern::getImagesForShadowMasks(blackImage, whiteImage) + public void getImagesForShadowMasks(Mat blackImage, Mat whiteImage) + { + + getImagesForShadowMasks_0(nativeObj, blackImage.nativeObj, whiteImage.nativeObj); + + return; + } + + + // + // C++: void cv::structured_light::GrayCodePattern::setBlackThreshold(size_t value) + // + + //javadoc: GrayCodePattern::setBlackThreshold(value) + public void setBlackThreshold(long value) + { + + setBlackThreshold_0(nativeObj, value); + + return; + } + + + // + // C++: void cv::structured_light::GrayCodePattern::setWhiteThreshold(size_t value) + // + + //javadoc: GrayCodePattern::setWhiteThreshold(value) + public void setWhiteThreshold(long value) + { + + setWhiteThreshold_0(nativeObj, value); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_GrayCodePattern cv::structured_light::GrayCodePattern::create(int width, int height) + private static native long create_0(int width, int height); + + // C++: bool cv::structured_light::GrayCodePattern::getProjPixel(vector_Mat patternImages, int x, int y, Point& projPix) + private static native boolean getProjPixel_0(long nativeObj, long patternImages_mat_nativeObj, int x, int y, double[] projPix_out); + + // C++: size_t cv::structured_light::GrayCodePattern::getNumberOfPatternImages() + private static native long getNumberOfPatternImages_0(long nativeObj); + + // C++: void cv::structured_light::GrayCodePattern::getImagesForShadowMasks(Mat& blackImage, Mat& whiteImage) + private static native void getImagesForShadowMasks_0(long nativeObj, long blackImage_nativeObj, long whiteImage_nativeObj); + + // C++: void cv::structured_light::GrayCodePattern::setBlackThreshold(size_t value) + private static native void setBlackThreshold_0(long nativeObj, long value); + + // C++: void cv::structured_light::GrayCodePattern::setWhiteThreshold(size_t value) + private static native void setWhiteThreshold_0(long nativeObj, long value); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/structured_light/Params.java b/OpenCV/src/main/java/org/opencv/structured_light/Params.java new file mode 100644 index 00000000..a3897faa --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/structured_light/Params.java @@ -0,0 +1,48 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.structured_light; + + + +// C++: class Params +//javadoc: Params + +public class Params { + + protected final long nativeObj; + protected Params(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static Params __fromPtr__(long addr) { return new Params(addr); } + + // + // C++: cv::structured_light::SinusoidalPattern::Params::Params() + // + + //javadoc: Params::Params() + public Params() + { + + nativeObj = Params_0(); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: cv::structured_light::SinusoidalPattern::Params::Params() + private static native long Params_0(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/structured_light/SinusoidalPattern.java b/OpenCV/src/main/java/org/opencv/structured_light/SinusoidalPattern.java new file mode 100644 index 00000000..ea61e67a --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/structured_light/SinusoidalPattern.java @@ -0,0 +1,150 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.structured_light; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.Size; +import org.opencv.structured_light.SinusoidalPattern; +import org.opencv.structured_light.StructuredLightPattern; +import org.opencv.utils.Converters; + +// C++: class SinusoidalPattern +//javadoc: SinusoidalPattern + +public class SinusoidalPattern extends StructuredLightPattern { + + protected SinusoidalPattern(long addr) { super(addr); } + + // internal usage only + public static SinusoidalPattern __fromPtr__(long addr) { return new SinusoidalPattern(addr); } + + // + // C++: static Ptr_SinusoidalPattern cv::structured_light::SinusoidalPattern::create(Ptr_SinusoidalPattern_Params parameters = makePtr()) + // + + //javadoc: SinusoidalPattern::create() + public static SinusoidalPattern create() + { + + SinusoidalPattern retVal = SinusoidalPattern.__fromPtr__(create_0()); + + return retVal; + } + + + // + // C++: void cv::structured_light::SinusoidalPattern::computeDataModulationTerm(vector_Mat patternImages, Mat& dataModulationTerm, Mat shadowMask) + // + + //javadoc: SinusoidalPattern::computeDataModulationTerm(patternImages, dataModulationTerm, shadowMask) + public void computeDataModulationTerm(List patternImages, Mat dataModulationTerm, Mat shadowMask) + { + Mat patternImages_mat = Converters.vector_Mat_to_Mat(patternImages); + computeDataModulationTerm_0(nativeObj, patternImages_mat.nativeObj, dataModulationTerm.nativeObj, shadowMask.nativeObj); + + return; + } + + + // + // C++: void cv::structured_light::SinusoidalPattern::computePhaseMap(vector_Mat patternImages, Mat& wrappedPhaseMap, Mat& shadowMask = Mat(), Mat fundamental = Mat()) + // + + //javadoc: SinusoidalPattern::computePhaseMap(patternImages, wrappedPhaseMap, shadowMask, fundamental) + public void computePhaseMap(List patternImages, Mat wrappedPhaseMap, Mat shadowMask, Mat fundamental) + { + Mat patternImages_mat = Converters.vector_Mat_to_Mat(patternImages); + computePhaseMap_0(nativeObj, patternImages_mat.nativeObj, wrappedPhaseMap.nativeObj, shadowMask.nativeObj, fundamental.nativeObj); + + return; + } + + //javadoc: SinusoidalPattern::computePhaseMap(patternImages, wrappedPhaseMap, shadowMask) + public void computePhaseMap(List patternImages, Mat wrappedPhaseMap, Mat shadowMask) + { + Mat patternImages_mat = Converters.vector_Mat_to_Mat(patternImages); + computePhaseMap_1(nativeObj, patternImages_mat.nativeObj, wrappedPhaseMap.nativeObj, shadowMask.nativeObj); + + return; + } + + //javadoc: SinusoidalPattern::computePhaseMap(patternImages, wrappedPhaseMap) + public void computePhaseMap(List patternImages, Mat wrappedPhaseMap) + { + Mat patternImages_mat = Converters.vector_Mat_to_Mat(patternImages); + computePhaseMap_2(nativeObj, patternImages_mat.nativeObj, wrappedPhaseMap.nativeObj); + + return; + } + + + // + // C++: void cv::structured_light::SinusoidalPattern::findProCamMatches(Mat projUnwrappedPhaseMap, Mat camUnwrappedPhaseMap, vector_Mat& matches) + // + + //javadoc: SinusoidalPattern::findProCamMatches(projUnwrappedPhaseMap, camUnwrappedPhaseMap, matches) + public void findProCamMatches(Mat projUnwrappedPhaseMap, Mat camUnwrappedPhaseMap, List matches) + { + Mat matches_mat = new Mat(); + findProCamMatches_0(nativeObj, projUnwrappedPhaseMap.nativeObj, camUnwrappedPhaseMap.nativeObj, matches_mat.nativeObj); + Converters.Mat_to_vector_Mat(matches_mat, matches); + matches_mat.release(); + return; + } + + + // + // C++: void cv::structured_light::SinusoidalPattern::unwrapPhaseMap(vector_Mat wrappedPhaseMap, Mat& unwrappedPhaseMap, Size camSize, Mat shadowMask = Mat()) + // + + //javadoc: SinusoidalPattern::unwrapPhaseMap(wrappedPhaseMap, unwrappedPhaseMap, camSize, shadowMask) + public void unwrapPhaseMap(List wrappedPhaseMap, Mat unwrappedPhaseMap, Size camSize, Mat shadowMask) + { + Mat wrappedPhaseMap_mat = Converters.vector_Mat_to_Mat(wrappedPhaseMap); + unwrapPhaseMap_0(nativeObj, wrappedPhaseMap_mat.nativeObj, unwrappedPhaseMap.nativeObj, camSize.width, camSize.height, shadowMask.nativeObj); + + return; + } + + //javadoc: SinusoidalPattern::unwrapPhaseMap(wrappedPhaseMap, unwrappedPhaseMap, camSize) + public void unwrapPhaseMap(List wrappedPhaseMap, Mat unwrappedPhaseMap, Size camSize) + { + Mat wrappedPhaseMap_mat = Converters.vector_Mat_to_Mat(wrappedPhaseMap); + unwrapPhaseMap_1(nativeObj, wrappedPhaseMap_mat.nativeObj, unwrappedPhaseMap.nativeObj, camSize.width, camSize.height); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_SinusoidalPattern cv::structured_light::SinusoidalPattern::create(Ptr_SinusoidalPattern_Params parameters = makePtr()) + private static native long create_0(); + + // C++: void cv::structured_light::SinusoidalPattern::computeDataModulationTerm(vector_Mat patternImages, Mat& dataModulationTerm, Mat shadowMask) + private static native void computeDataModulationTerm_0(long nativeObj, long patternImages_mat_nativeObj, long dataModulationTerm_nativeObj, long shadowMask_nativeObj); + + // C++: void cv::structured_light::SinusoidalPattern::computePhaseMap(vector_Mat patternImages, Mat& wrappedPhaseMap, Mat& shadowMask = Mat(), Mat fundamental = Mat()) + private static native void computePhaseMap_0(long nativeObj, long patternImages_mat_nativeObj, long wrappedPhaseMap_nativeObj, long shadowMask_nativeObj, long fundamental_nativeObj); + private static native void computePhaseMap_1(long nativeObj, long patternImages_mat_nativeObj, long wrappedPhaseMap_nativeObj, long shadowMask_nativeObj); + private static native void computePhaseMap_2(long nativeObj, long patternImages_mat_nativeObj, long wrappedPhaseMap_nativeObj); + + // C++: void cv::structured_light::SinusoidalPattern::findProCamMatches(Mat projUnwrappedPhaseMap, Mat camUnwrappedPhaseMap, vector_Mat& matches) + private static native void findProCamMatches_0(long nativeObj, long projUnwrappedPhaseMap_nativeObj, long camUnwrappedPhaseMap_nativeObj, long matches_mat_nativeObj); + + // C++: void cv::structured_light::SinusoidalPattern::unwrapPhaseMap(vector_Mat wrappedPhaseMap, Mat& unwrappedPhaseMap, Size camSize, Mat shadowMask = Mat()) + private static native void unwrapPhaseMap_0(long nativeObj, long wrappedPhaseMap_mat_nativeObj, long unwrappedPhaseMap_nativeObj, double camSize_width, double camSize_height, long shadowMask_nativeObj); + private static native void unwrapPhaseMap_1(long nativeObj, long wrappedPhaseMap_mat_nativeObj, long unwrappedPhaseMap_nativeObj, double camSize_width, double camSize_height); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/structured_light/StructuredLightPattern.java b/OpenCV/src/main/java/org/opencv/structured_light/StructuredLightPattern.java new file mode 100644 index 00000000..2770ea03 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/structured_light/StructuredLightPattern.java @@ -0,0 +1,57 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.structured_light; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.utils.Converters; + +// C++: class StructuredLightPattern +//javadoc: StructuredLightPattern + +public class StructuredLightPattern extends Algorithm { + + protected StructuredLightPattern(long addr) { super(addr); } + + // internal usage only + public static StructuredLightPattern __fromPtr__(long addr) { return new StructuredLightPattern(addr); } + + // + // C++: bool cv::structured_light::StructuredLightPattern::decode(vector_vector_Mat patternImages, Mat& disparityMap, vector_Mat blackImages = vector_Mat(), vector_Mat whiteImages = vector_Mat(), int flags = DECODE_3D_UNDERWORLD) + // + + // Unknown type 'vector_vector_Mat' (I), skipping the function + + + // + // C++: bool cv::structured_light::StructuredLightPattern::generate(vector_Mat& patternImages) + // + + //javadoc: StructuredLightPattern::generate(patternImages) + public boolean generate(List patternImages) + { + Mat patternImages_mat = new Mat(); + boolean retVal = generate_0(nativeObj, patternImages_mat.nativeObj); + Converters.Mat_to_vector_Mat(patternImages_mat, patternImages); + patternImages_mat.release(); + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: bool cv::structured_light::StructuredLightPattern::generate(vector_Mat& patternImages) + private static native boolean generate_0(long nativeObj, long patternImages_mat_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/structured_light/Structured_light.java b/OpenCV/src/main/java/org/opencv/structured_light/Structured_light.java new file mode 100644 index 00000000..46fcad78 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/structured_light/Structured_light.java @@ -0,0 +1,23 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.structured_light; + + + +// C++: class Structured_light +//javadoc: Structured_light + +public class Structured_light { + + // C++: enum + public static final int + DECODE_3D_UNDERWORLD = 0, + FTP = 0, + PSP = 1, + FAPS = 2; + + + + +} diff --git a/OpenCV/src/main/java/org/opencv/text/BaseOCR.java b/OpenCV/src/main/java/org/opencv/text/BaseOCR.java new file mode 100644 index 00000000..6c75f77b --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/text/BaseOCR.java @@ -0,0 +1,31 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.text; + + + +// C++: class BaseOCR +//javadoc: BaseOCR + +public class BaseOCR { + + protected final long nativeObj; + protected BaseOCR(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static BaseOCR __fromPtr__(long addr) { return new BaseOCR(addr); } + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/text/Callback.java b/OpenCV/src/main/java/org/opencv/text/Callback.java new file mode 100644 index 00000000..93af62b7 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/text/Callback.java @@ -0,0 +1,31 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.text; + + + +// C++: class Callback +//javadoc: Callback + +public class Callback { + + protected final long nativeObj; + protected Callback(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static Callback __fromPtr__(long addr) { return new Callback(addr); } + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/text/ClassifierCallback.java b/OpenCV/src/main/java/org/opencv/text/ClassifierCallback.java new file mode 100644 index 00000000..e8fede44 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/text/ClassifierCallback.java @@ -0,0 +1,31 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.text; + + + +// C++: class ClassifierCallback +//javadoc: ClassifierCallback + +public class ClassifierCallback { + + protected final long nativeObj; + protected ClassifierCallback(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static ClassifierCallback __fromPtr__(long addr) { return new ClassifierCallback(addr); } + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/text/ERFilter.java b/OpenCV/src/main/java/org/opencv/text/ERFilter.java new file mode 100644 index 00000000..f907ffb5 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/text/ERFilter.java @@ -0,0 +1,28 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.text; + +import org.opencv.core.Algorithm; + +// C++: class ERFilter +//javadoc: ERFilter + +public class ERFilter extends Algorithm { + + protected ERFilter(long addr) { super(addr); } + + // internal usage only + public static ERFilter __fromPtr__(long addr) { return new ERFilter(addr); } + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/text/OCRBeamSearchDecoder.java b/OpenCV/src/main/java/org/opencv/text/OCRBeamSearchDecoder.java new file mode 100644 index 00000000..3812cc93 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/text/OCRBeamSearchDecoder.java @@ -0,0 +1,129 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.text; + +import java.lang.String; +import org.opencv.core.Mat; +import org.opencv.text.BaseOCR; +import org.opencv.text.OCRBeamSearchDecoder; + +// C++: class OCRBeamSearchDecoder +//javadoc: OCRBeamSearchDecoder + +public class OCRBeamSearchDecoder extends BaseOCR { + + protected OCRBeamSearchDecoder(long addr) { super(addr); } + + // internal usage only + public static OCRBeamSearchDecoder __fromPtr__(long addr) { return new OCRBeamSearchDecoder(addr); } + + // + // C++: static Ptr_OCRBeamSearchDecoder cv::text::OCRBeamSearchDecoder::create(Ptr_OCRBeamSearchDecoder_ClassifierCallback classifier, String vocabulary, Mat transition_probabilities_table, Mat emission_probabilities_table, int mode = OCR_DECODER_VITERBI, int beam_size = 500) + // + + // Unknown type 'Ptr_OCRBeamSearchDecoder_ClassifierCallback' (I), skipping the function + + + // + // C++: static Ptr_OCRBeamSearchDecoder cv::text::OCRBeamSearchDecoder::create(String filename, String vocabulary, Mat transition_probabilities_table, Mat emission_probabilities_table, int mode = OCR_DECODER_VITERBI, int beam_size = 500) + // + + //javadoc: OCRBeamSearchDecoder::create(filename, vocabulary, transition_probabilities_table, emission_probabilities_table, mode, beam_size) + public static OCRBeamSearchDecoder create(String filename, String vocabulary, Mat transition_probabilities_table, Mat emission_probabilities_table, int mode, int beam_size) + { + + OCRBeamSearchDecoder retVal = OCRBeamSearchDecoder.__fromPtr__(create_0(filename, vocabulary, transition_probabilities_table.nativeObj, emission_probabilities_table.nativeObj, mode, beam_size)); + + return retVal; + } + + //javadoc: OCRBeamSearchDecoder::create(filename, vocabulary, transition_probabilities_table, emission_probabilities_table, mode) + public static OCRBeamSearchDecoder create(String filename, String vocabulary, Mat transition_probabilities_table, Mat emission_probabilities_table, int mode) + { + + OCRBeamSearchDecoder retVal = OCRBeamSearchDecoder.__fromPtr__(create_1(filename, vocabulary, transition_probabilities_table.nativeObj, emission_probabilities_table.nativeObj, mode)); + + return retVal; + } + + //javadoc: OCRBeamSearchDecoder::create(filename, vocabulary, transition_probabilities_table, emission_probabilities_table) + public static OCRBeamSearchDecoder create(String filename, String vocabulary, Mat transition_probabilities_table, Mat emission_probabilities_table) + { + + OCRBeamSearchDecoder retVal = OCRBeamSearchDecoder.__fromPtr__(create_2(filename, vocabulary, transition_probabilities_table.nativeObj, emission_probabilities_table.nativeObj)); + + return retVal; + } + + + // + // C++: String cv::text::OCRBeamSearchDecoder::run(Mat image, Mat mask, int min_confidence, int component_level = 0) + // + + //javadoc: OCRBeamSearchDecoder::run(image, mask, min_confidence, component_level) + public String run(Mat image, Mat mask, int min_confidence, int component_level) + { + + String retVal = run_0(nativeObj, image.nativeObj, mask.nativeObj, min_confidence, component_level); + + return retVal; + } + + //javadoc: OCRBeamSearchDecoder::run(image, mask, min_confidence) + public String run(Mat image, Mat mask, int min_confidence) + { + + String retVal = run_1(nativeObj, image.nativeObj, mask.nativeObj, min_confidence); + + return retVal; + } + + + // + // C++: String cv::text::OCRBeamSearchDecoder::run(Mat image, int min_confidence, int component_level = 0) + // + + //javadoc: OCRBeamSearchDecoder::run(image, min_confidence, component_level) + public String run(Mat image, int min_confidence, int component_level) + { + + String retVal = run_2(nativeObj, image.nativeObj, min_confidence, component_level); + + return retVal; + } + + //javadoc: OCRBeamSearchDecoder::run(image, min_confidence) + public String run(Mat image, int min_confidence) + { + + String retVal = run_3(nativeObj, image.nativeObj, min_confidence); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_OCRBeamSearchDecoder cv::text::OCRBeamSearchDecoder::create(String filename, String vocabulary, Mat transition_probabilities_table, Mat emission_probabilities_table, int mode = OCR_DECODER_VITERBI, int beam_size = 500) + private static native long create_0(String filename, String vocabulary, long transition_probabilities_table_nativeObj, long emission_probabilities_table_nativeObj, int mode, int beam_size); + private static native long create_1(String filename, String vocabulary, long transition_probabilities_table_nativeObj, long emission_probabilities_table_nativeObj, int mode); + private static native long create_2(String filename, String vocabulary, long transition_probabilities_table_nativeObj, long emission_probabilities_table_nativeObj); + + // C++: String cv::text::OCRBeamSearchDecoder::run(Mat image, Mat mask, int min_confidence, int component_level = 0) + private static native String run_0(long nativeObj, long image_nativeObj, long mask_nativeObj, int min_confidence, int component_level); + private static native String run_1(long nativeObj, long image_nativeObj, long mask_nativeObj, int min_confidence); + + // C++: String cv::text::OCRBeamSearchDecoder::run(Mat image, int min_confidence, int component_level = 0) + private static native String run_2(long nativeObj, long image_nativeObj, int min_confidence, int component_level); + private static native String run_3(long nativeObj, long image_nativeObj, int min_confidence); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/text/OCRHMMDecoder.java b/OpenCV/src/main/java/org/opencv/text/OCRHMMDecoder.java new file mode 100644 index 00000000..feb79271 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/text/OCRHMMDecoder.java @@ -0,0 +1,129 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.text; + +import java.lang.String; +import org.opencv.core.Mat; +import org.opencv.text.BaseOCR; +import org.opencv.text.OCRHMMDecoder; + +// C++: class OCRHMMDecoder +//javadoc: OCRHMMDecoder + +public class OCRHMMDecoder extends BaseOCR { + + protected OCRHMMDecoder(long addr) { super(addr); } + + // internal usage only + public static OCRHMMDecoder __fromPtr__(long addr) { return new OCRHMMDecoder(addr); } + + // + // C++: static Ptr_OCRHMMDecoder cv::text::OCRHMMDecoder::create(Ptr_OCRHMMDecoder_ClassifierCallback classifier, String vocabulary, Mat transition_probabilities_table, Mat emission_probabilities_table, int mode = OCR_DECODER_VITERBI) + // + + // Unknown type 'Ptr_OCRHMMDecoder_ClassifierCallback' (I), skipping the function + + + // + // C++: static Ptr_OCRHMMDecoder cv::text::OCRHMMDecoder::create(String filename, String vocabulary, Mat transition_probabilities_table, Mat emission_probabilities_table, int mode = OCR_DECODER_VITERBI, int classifier = OCR_KNN_CLASSIFIER) + // + + //javadoc: OCRHMMDecoder::create(filename, vocabulary, transition_probabilities_table, emission_probabilities_table, mode, classifier) + public static OCRHMMDecoder create(String filename, String vocabulary, Mat transition_probabilities_table, Mat emission_probabilities_table, int mode, int classifier) + { + + OCRHMMDecoder retVal = OCRHMMDecoder.__fromPtr__(create_0(filename, vocabulary, transition_probabilities_table.nativeObj, emission_probabilities_table.nativeObj, mode, classifier)); + + return retVal; + } + + //javadoc: OCRHMMDecoder::create(filename, vocabulary, transition_probabilities_table, emission_probabilities_table, mode) + public static OCRHMMDecoder create(String filename, String vocabulary, Mat transition_probabilities_table, Mat emission_probabilities_table, int mode) + { + + OCRHMMDecoder retVal = OCRHMMDecoder.__fromPtr__(create_1(filename, vocabulary, transition_probabilities_table.nativeObj, emission_probabilities_table.nativeObj, mode)); + + return retVal; + } + + //javadoc: OCRHMMDecoder::create(filename, vocabulary, transition_probabilities_table, emission_probabilities_table) + public static OCRHMMDecoder create(String filename, String vocabulary, Mat transition_probabilities_table, Mat emission_probabilities_table) + { + + OCRHMMDecoder retVal = OCRHMMDecoder.__fromPtr__(create_2(filename, vocabulary, transition_probabilities_table.nativeObj, emission_probabilities_table.nativeObj)); + + return retVal; + } + + + // + // C++: String cv::text::OCRHMMDecoder::run(Mat image, Mat mask, int min_confidence, int component_level = 0) + // + + //javadoc: OCRHMMDecoder::run(image, mask, min_confidence, component_level) + public String run(Mat image, Mat mask, int min_confidence, int component_level) + { + + String retVal = run_0(nativeObj, image.nativeObj, mask.nativeObj, min_confidence, component_level); + + return retVal; + } + + //javadoc: OCRHMMDecoder::run(image, mask, min_confidence) + public String run(Mat image, Mat mask, int min_confidence) + { + + String retVal = run_1(nativeObj, image.nativeObj, mask.nativeObj, min_confidence); + + return retVal; + } + + + // + // C++: String cv::text::OCRHMMDecoder::run(Mat image, int min_confidence, int component_level = 0) + // + + //javadoc: OCRHMMDecoder::run(image, min_confidence, component_level) + public String run(Mat image, int min_confidence, int component_level) + { + + String retVal = run_2(nativeObj, image.nativeObj, min_confidence, component_level); + + return retVal; + } + + //javadoc: OCRHMMDecoder::run(image, min_confidence) + public String run(Mat image, int min_confidence) + { + + String retVal = run_3(nativeObj, image.nativeObj, min_confidence); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_OCRHMMDecoder cv::text::OCRHMMDecoder::create(String filename, String vocabulary, Mat transition_probabilities_table, Mat emission_probabilities_table, int mode = OCR_DECODER_VITERBI, int classifier = OCR_KNN_CLASSIFIER) + private static native long create_0(String filename, String vocabulary, long transition_probabilities_table_nativeObj, long emission_probabilities_table_nativeObj, int mode, int classifier); + private static native long create_1(String filename, String vocabulary, long transition_probabilities_table_nativeObj, long emission_probabilities_table_nativeObj, int mode); + private static native long create_2(String filename, String vocabulary, long transition_probabilities_table_nativeObj, long emission_probabilities_table_nativeObj); + + // C++: String cv::text::OCRHMMDecoder::run(Mat image, Mat mask, int min_confidence, int component_level = 0) + private static native String run_0(long nativeObj, long image_nativeObj, long mask_nativeObj, int min_confidence, int component_level); + private static native String run_1(long nativeObj, long image_nativeObj, long mask_nativeObj, int min_confidence); + + // C++: String cv::text::OCRHMMDecoder::run(Mat image, int min_confidence, int component_level = 0) + private static native String run_2(long nativeObj, long image_nativeObj, int min_confidence, int component_level); + private static native String run_3(long nativeObj, long image_nativeObj, int min_confidence); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/text/OCRTesseract.java b/OpenCV/src/main/java/org/opencv/text/OCRTesseract.java new file mode 100644 index 00000000..b328809d --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/text/OCRTesseract.java @@ -0,0 +1,169 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.text; + +import java.lang.String; +import org.opencv.core.Mat; +import org.opencv.text.BaseOCR; +import org.opencv.text.OCRTesseract; + +// C++: class OCRTesseract +//javadoc: OCRTesseract + +public class OCRTesseract extends BaseOCR { + + protected OCRTesseract(long addr) { super(addr); } + + // internal usage only + public static OCRTesseract __fromPtr__(long addr) { return new OCRTesseract(addr); } + + // + // C++: static Ptr_OCRTesseract cv::text::OCRTesseract::create(c_string datapath = 0, c_string language = 0, c_string char_whitelist = 0, int oem = OEM_DEFAULT, int psmode = PSM_AUTO) + // + + //javadoc: OCRTesseract::create(datapath, language, char_whitelist, oem, psmode) + public static OCRTesseract create(String datapath, String language, String char_whitelist, int oem, int psmode) + { + + OCRTesseract retVal = OCRTesseract.__fromPtr__(create_0(datapath, language, char_whitelist, oem, psmode)); + + return retVal; + } + + //javadoc: OCRTesseract::create(datapath, language, char_whitelist, oem) + public static OCRTesseract create(String datapath, String language, String char_whitelist, int oem) + { + + OCRTesseract retVal = OCRTesseract.__fromPtr__(create_1(datapath, language, char_whitelist, oem)); + + return retVal; + } + + //javadoc: OCRTesseract::create(datapath, language, char_whitelist) + public static OCRTesseract create(String datapath, String language, String char_whitelist) + { + + OCRTesseract retVal = OCRTesseract.__fromPtr__(create_2(datapath, language, char_whitelist)); + + return retVal; + } + + //javadoc: OCRTesseract::create(datapath, language) + public static OCRTesseract create(String datapath, String language) + { + + OCRTesseract retVal = OCRTesseract.__fromPtr__(create_3(datapath, language)); + + return retVal; + } + + //javadoc: OCRTesseract::create(datapath) + public static OCRTesseract create(String datapath) + { + + OCRTesseract retVal = OCRTesseract.__fromPtr__(create_4(datapath)); + + return retVal; + } + + //javadoc: OCRTesseract::create() + public static OCRTesseract create() + { + + OCRTesseract retVal = OCRTesseract.__fromPtr__(create_5()); + + return retVal; + } + + + // + // C++: String cv::text::OCRTesseract::run(Mat image, Mat mask, int min_confidence, int component_level = 0) + // + + //javadoc: OCRTesseract::run(image, mask, min_confidence, component_level) + public String run(Mat image, Mat mask, int min_confidence, int component_level) + { + + String retVal = run_0(nativeObj, image.nativeObj, mask.nativeObj, min_confidence, component_level); + + return retVal; + } + + //javadoc: OCRTesseract::run(image, mask, min_confidence) + public String run(Mat image, Mat mask, int min_confidence) + { + + String retVal = run_1(nativeObj, image.nativeObj, mask.nativeObj, min_confidence); + + return retVal; + } + + + // + // C++: String cv::text::OCRTesseract::run(Mat image, int min_confidence, int component_level = 0) + // + + //javadoc: OCRTesseract::run(image, min_confidence, component_level) + public String run(Mat image, int min_confidence, int component_level) + { + + String retVal = run_2(nativeObj, image.nativeObj, min_confidence, component_level); + + return retVal; + } + + //javadoc: OCRTesseract::run(image, min_confidence) + public String run(Mat image, int min_confidence) + { + + String retVal = run_3(nativeObj, image.nativeObj, min_confidence); + + return retVal; + } + + + // + // C++: void cv::text::OCRTesseract::setWhiteList(String char_whitelist) + // + + //javadoc: OCRTesseract::setWhiteList(char_whitelist) + public void setWhiteList(String char_whitelist) + { + + setWhiteList_0(nativeObj, char_whitelist); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_OCRTesseract cv::text::OCRTesseract::create(c_string datapath = 0, c_string language = 0, c_string char_whitelist = 0, int oem = OEM_DEFAULT, int psmode = PSM_AUTO) + private static native long create_0(String datapath, String language, String char_whitelist, int oem, int psmode); + private static native long create_1(String datapath, String language, String char_whitelist, int oem); + private static native long create_2(String datapath, String language, String char_whitelist); + private static native long create_3(String datapath, String language); + private static native long create_4(String datapath); + private static native long create_5(); + + // C++: String cv::text::OCRTesseract::run(Mat image, Mat mask, int min_confidence, int component_level = 0) + private static native String run_0(long nativeObj, long image_nativeObj, long mask_nativeObj, int min_confidence, int component_level); + private static native String run_1(long nativeObj, long image_nativeObj, long mask_nativeObj, int min_confidence); + + // C++: String cv::text::OCRTesseract::run(Mat image, int min_confidence, int component_level = 0) + private static native String run_2(long nativeObj, long image_nativeObj, int min_confidence, int component_level); + private static native String run_3(long nativeObj, long image_nativeObj, int min_confidence); + + // C++: void cv::text::OCRTesseract::setWhiteList(String char_whitelist) + private static native void setWhiteList_0(long nativeObj, String char_whitelist); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/text/Text.java b/OpenCV/src/main/java/org/opencv/text/Text.java new file mode 100644 index 00000000..cb0945b4 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/text/Text.java @@ -0,0 +1,396 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.text; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfPoint; +import org.opencv.core.MatOfRect; +import org.opencv.text.ERFilter; +import org.opencv.utils.Converters; + +// C++: class Text +//javadoc: Text + +public class Text { + + // C++: enum decoder_mode + public static final int + OCR_DECODER_VITERBI = 0; + + + // C++: enum erGrouping_Modes + public static final int + ERGROUPING_ORIENTATION_HORIZ = 0, + ERGROUPING_ORIENTATION_ANY = 1; + + + // C++: enum page_seg_mode + public static final int + PSM_OSD_ONLY = 0, + PSM_AUTO_OSD = 1, + PSM_AUTO_ONLY = 2, + PSM_AUTO = 3, + PSM_SINGLE_COLUMN = 4, + PSM_SINGLE_BLOCK_VERT_TEXT = 5, + PSM_SINGLE_BLOCK = 6, + PSM_SINGLE_LINE = 7, + PSM_SINGLE_WORD = 8, + PSM_CIRCLE_WORD = 9, + PSM_SINGLE_CHAR = 10; + + + // C++: enum classifier_type + public static final int + OCR_KNN_CLASSIFIER = 0, + OCR_CNN_CLASSIFIER = 1; + + + // C++: enum + public static final int + ERFILTER_NM_RGBLGrad = 0, + ERFILTER_NM_IHSGrad = 1, + OCR_LEVEL_WORD = 0, + OCR_LEVEL_TEXTLINE = 1; + + + // C++: enum ocr_engine_mode + public static final int + OEM_TESSERACT_ONLY = 0, + OEM_CUBE_ONLY = 1, + OEM_TESSERACT_CUBE_COMBINED = 2, + OEM_DEFAULT = 3; + + + // + // C++: Mat cv::text::createOCRHMMTransitionsTable(String vocabulary, vector_String lexicon) + // + + //javadoc: createOCRHMMTransitionsTable(vocabulary, lexicon) + public static Mat createOCRHMMTransitionsTable(String vocabulary, List lexicon) + { + + Mat retVal = new Mat(createOCRHMMTransitionsTable_0(vocabulary, lexicon)); + + return retVal; + } + + + // + // C++: Ptr_ERFilter cv::text::createERFilterNM1(Ptr_ERFilter_Callback cb, int thresholdDelta = 1, float minArea = (float)0.00025, float maxArea = (float)0.13, float minProbability = (float)0.4, bool nonMaxSuppression = true, float minProbabilityDiff = (float)0.1) + // + + // Unknown type 'Ptr_ERFilter_Callback' (I), skipping the function + + + // + // C++: Ptr_ERFilter cv::text::createERFilterNM1(String filename, int thresholdDelta = 1, float minArea = (float)0.00025, float maxArea = (float)0.13, float minProbability = (float)0.4, bool nonMaxSuppression = true, float minProbabilityDiff = (float)0.1) + // + + //javadoc: createERFilterNM1(filename, thresholdDelta, minArea, maxArea, minProbability, nonMaxSuppression, minProbabilityDiff) + public static ERFilter createERFilterNM1(String filename, int thresholdDelta, float minArea, float maxArea, float minProbability, boolean nonMaxSuppression, float minProbabilityDiff) + { + + ERFilter retVal = ERFilter.__fromPtr__(createERFilterNM1_0(filename, thresholdDelta, minArea, maxArea, minProbability, nonMaxSuppression, minProbabilityDiff)); + + return retVal; + } + + //javadoc: createERFilterNM1(filename, thresholdDelta, minArea, maxArea, minProbability, nonMaxSuppression) + public static ERFilter createERFilterNM1(String filename, int thresholdDelta, float minArea, float maxArea, float minProbability, boolean nonMaxSuppression) + { + + ERFilter retVal = ERFilter.__fromPtr__(createERFilterNM1_1(filename, thresholdDelta, minArea, maxArea, minProbability, nonMaxSuppression)); + + return retVal; + } + + //javadoc: createERFilterNM1(filename, thresholdDelta, minArea, maxArea, minProbability) + public static ERFilter createERFilterNM1(String filename, int thresholdDelta, float minArea, float maxArea, float minProbability) + { + + ERFilter retVal = ERFilter.__fromPtr__(createERFilterNM1_2(filename, thresholdDelta, minArea, maxArea, minProbability)); + + return retVal; + } + + //javadoc: createERFilterNM1(filename, thresholdDelta, minArea, maxArea) + public static ERFilter createERFilterNM1(String filename, int thresholdDelta, float minArea, float maxArea) + { + + ERFilter retVal = ERFilter.__fromPtr__(createERFilterNM1_3(filename, thresholdDelta, minArea, maxArea)); + + return retVal; + } + + //javadoc: createERFilterNM1(filename, thresholdDelta, minArea) + public static ERFilter createERFilterNM1(String filename, int thresholdDelta, float minArea) + { + + ERFilter retVal = ERFilter.__fromPtr__(createERFilterNM1_4(filename, thresholdDelta, minArea)); + + return retVal; + } + + //javadoc: createERFilterNM1(filename, thresholdDelta) + public static ERFilter createERFilterNM1(String filename, int thresholdDelta) + { + + ERFilter retVal = ERFilter.__fromPtr__(createERFilterNM1_5(filename, thresholdDelta)); + + return retVal; + } + + //javadoc: createERFilterNM1(filename) + public static ERFilter createERFilterNM1(String filename) + { + + ERFilter retVal = ERFilter.__fromPtr__(createERFilterNM1_6(filename)); + + return retVal; + } + + + // + // C++: Ptr_ERFilter cv::text::createERFilterNM2(Ptr_ERFilter_Callback cb, float minProbability = (float)0.3) + // + + // Unknown type 'Ptr_ERFilter_Callback' (I), skipping the function + + + // + // C++: Ptr_ERFilter cv::text::createERFilterNM2(String filename, float minProbability = (float)0.3) + // + + //javadoc: createERFilterNM2(filename, minProbability) + public static ERFilter createERFilterNM2(String filename, float minProbability) + { + + ERFilter retVal = ERFilter.__fromPtr__(createERFilterNM2_0(filename, minProbability)); + + return retVal; + } + + //javadoc: createERFilterNM2(filename) + public static ERFilter createERFilterNM2(String filename) + { + + ERFilter retVal = ERFilter.__fromPtr__(createERFilterNM2_1(filename)); + + return retVal; + } + + + // + // C++: Ptr_ERFilter_Callback cv::text::loadClassifierNM1(String filename) + // + + // Return type 'Ptr_ERFilter_Callback' is not supported, skipping the function + + + // + // C++: Ptr_ERFilter_Callback cv::text::loadClassifierNM2(String filename) + // + + // Return type 'Ptr_ERFilter_Callback' is not supported, skipping the function + + + // + // C++: Ptr_OCRBeamSearchDecoder_ClassifierCallback cv::text::loadOCRBeamSearchClassifierCNN(String filename) + // + + // Return type 'Ptr_OCRBeamSearchDecoder_ClassifierCallback' is not supported, skipping the function + + + // + // C++: Ptr_OCRHMMDecoder_ClassifierCallback cv::text::loadOCRHMMClassifier(String filename, int classifier) + // + + // Return type 'Ptr_OCRHMMDecoder_ClassifierCallback' is not supported, skipping the function + + + // + // C++: Ptr_OCRHMMDecoder_ClassifierCallback cv::text::loadOCRHMMClassifierCNN(String filename) + // + + // Return type 'Ptr_OCRHMMDecoder_ClassifierCallback' is not supported, skipping the function + + + // + // C++: Ptr_OCRHMMDecoder_ClassifierCallback cv::text::loadOCRHMMClassifierNM(String filename) + // + + // Return type 'Ptr_OCRHMMDecoder_ClassifierCallback' is not supported, skipping the function + + + // + // C++: void cv::text::computeNMChannels(Mat _src, vector_Mat& _channels, int _mode = ERFILTER_NM_RGBLGrad) + // + + //javadoc: computeNMChannels(_src, _channels, _mode) + public static void computeNMChannels(Mat _src, List _channels, int _mode) + { + Mat _channels_mat = new Mat(); + computeNMChannels_0(_src.nativeObj, _channels_mat.nativeObj, _mode); + Converters.Mat_to_vector_Mat(_channels_mat, _channels); + _channels_mat.release(); + return; + } + + //javadoc: computeNMChannels(_src, _channels) + public static void computeNMChannels(Mat _src, List _channels) + { + Mat _channels_mat = new Mat(); + computeNMChannels_1(_src.nativeObj, _channels_mat.nativeObj); + Converters.Mat_to_vector_Mat(_channels_mat, _channels); + _channels_mat.release(); + return; + } + + + // + // C++: void cv::text::detectRegions(Mat image, Ptr_ERFilter er_filter1, Ptr_ERFilter er_filter2, vector_Rect& groups_rects, int method = ERGROUPING_ORIENTATION_HORIZ, String filename = String(), float minProbability = (float)0.5) + // + + //javadoc: detectRegions(image, er_filter1, er_filter2, groups_rects, method, filename, minProbability) + public static void detectRegions(Mat image, ERFilter er_filter1, ERFilter er_filter2, MatOfRect groups_rects, int method, String filename, float minProbability) + { + Mat groups_rects_mat = groups_rects; + detectRegions_0(image.nativeObj, er_filter1.getNativeObjAddr(), er_filter2.getNativeObjAddr(), groups_rects_mat.nativeObj, method, filename, minProbability); + + return; + } + + //javadoc: detectRegions(image, er_filter1, er_filter2, groups_rects, method, filename) + public static void detectRegions(Mat image, ERFilter er_filter1, ERFilter er_filter2, MatOfRect groups_rects, int method, String filename) + { + Mat groups_rects_mat = groups_rects; + detectRegions_1(image.nativeObj, er_filter1.getNativeObjAddr(), er_filter2.getNativeObjAddr(), groups_rects_mat.nativeObj, method, filename); + + return; + } + + //javadoc: detectRegions(image, er_filter1, er_filter2, groups_rects, method) + public static void detectRegions(Mat image, ERFilter er_filter1, ERFilter er_filter2, MatOfRect groups_rects, int method) + { + Mat groups_rects_mat = groups_rects; + detectRegions_2(image.nativeObj, er_filter1.getNativeObjAddr(), er_filter2.getNativeObjAddr(), groups_rects_mat.nativeObj, method); + + return; + } + + //javadoc: detectRegions(image, er_filter1, er_filter2, groups_rects) + public static void detectRegions(Mat image, ERFilter er_filter1, ERFilter er_filter2, MatOfRect groups_rects) + { + Mat groups_rects_mat = groups_rects; + detectRegions_3(image.nativeObj, er_filter1.getNativeObjAddr(), er_filter2.getNativeObjAddr(), groups_rects_mat.nativeObj); + + return; + } + + + // + // C++: void cv::text::detectRegions(Mat image, Ptr_ERFilter er_filter1, Ptr_ERFilter er_filter2, vector_vector_Point& regions) + // + + //javadoc: detectRegions(image, er_filter1, er_filter2, regions) + public static void detectRegions(Mat image, ERFilter er_filter1, ERFilter er_filter2, List regions) + { + Mat regions_mat = new Mat(); + detectRegions_4(image.nativeObj, er_filter1.getNativeObjAddr(), er_filter2.getNativeObjAddr(), regions_mat.nativeObj); + Converters.Mat_to_vector_vector_Point(regions_mat, regions); + regions_mat.release(); + return; + } + + + // + // C++: void cv::text::erGrouping(Mat image, Mat channel, vector_vector_Point regions, vector_Rect& groups_rects, int method = ERGROUPING_ORIENTATION_HORIZ, String filename = String(), float minProbablity = (float)0.5) + // + + //javadoc: erGrouping(image, channel, regions, groups_rects, method, filename, minProbablity) + public static void erGrouping(Mat image, Mat channel, List regions, MatOfRect groups_rects, int method, String filename, float minProbablity) + { + List regions_tmplm = new ArrayList((regions != null) ? regions.size() : 0); + Mat regions_mat = Converters.vector_vector_Point_to_Mat(regions, regions_tmplm); + Mat groups_rects_mat = groups_rects; + erGrouping_0(image.nativeObj, channel.nativeObj, regions_mat.nativeObj, groups_rects_mat.nativeObj, method, filename, minProbablity); + + return; + } + + //javadoc: erGrouping(image, channel, regions, groups_rects, method, filename) + public static void erGrouping(Mat image, Mat channel, List regions, MatOfRect groups_rects, int method, String filename) + { + List regions_tmplm = new ArrayList((regions != null) ? regions.size() : 0); + Mat regions_mat = Converters.vector_vector_Point_to_Mat(regions, regions_tmplm); + Mat groups_rects_mat = groups_rects; + erGrouping_1(image.nativeObj, channel.nativeObj, regions_mat.nativeObj, groups_rects_mat.nativeObj, method, filename); + + return; + } + + //javadoc: erGrouping(image, channel, regions, groups_rects, method) + public static void erGrouping(Mat image, Mat channel, List regions, MatOfRect groups_rects, int method) + { + List regions_tmplm = new ArrayList((regions != null) ? regions.size() : 0); + Mat regions_mat = Converters.vector_vector_Point_to_Mat(regions, regions_tmplm); + Mat groups_rects_mat = groups_rects; + erGrouping_2(image.nativeObj, channel.nativeObj, regions_mat.nativeObj, groups_rects_mat.nativeObj, method); + + return; + } + + //javadoc: erGrouping(image, channel, regions, groups_rects) + public static void erGrouping(Mat image, Mat channel, List regions, MatOfRect groups_rects) + { + List regions_tmplm = new ArrayList((regions != null) ? regions.size() : 0); + Mat regions_mat = Converters.vector_vector_Point_to_Mat(regions, regions_tmplm); + Mat groups_rects_mat = groups_rects; + erGrouping_3(image.nativeObj, channel.nativeObj, regions_mat.nativeObj, groups_rects_mat.nativeObj); + + return; + } + + + + + // C++: Mat cv::text::createOCRHMMTransitionsTable(String vocabulary, vector_String lexicon) + private static native long createOCRHMMTransitionsTable_0(String vocabulary, List lexicon); + + // C++: Ptr_ERFilter cv::text::createERFilterNM1(String filename, int thresholdDelta = 1, float minArea = (float)0.00025, float maxArea = (float)0.13, float minProbability = (float)0.4, bool nonMaxSuppression = true, float minProbabilityDiff = (float)0.1) + private static native long createERFilterNM1_0(String filename, int thresholdDelta, float minArea, float maxArea, float minProbability, boolean nonMaxSuppression, float minProbabilityDiff); + private static native long createERFilterNM1_1(String filename, int thresholdDelta, float minArea, float maxArea, float minProbability, boolean nonMaxSuppression); + private static native long createERFilterNM1_2(String filename, int thresholdDelta, float minArea, float maxArea, float minProbability); + private static native long createERFilterNM1_3(String filename, int thresholdDelta, float minArea, float maxArea); + private static native long createERFilterNM1_4(String filename, int thresholdDelta, float minArea); + private static native long createERFilterNM1_5(String filename, int thresholdDelta); + private static native long createERFilterNM1_6(String filename); + + // C++: Ptr_ERFilter cv::text::createERFilterNM2(String filename, float minProbability = (float)0.3) + private static native long createERFilterNM2_0(String filename, float minProbability); + private static native long createERFilterNM2_1(String filename); + + // C++: void cv::text::computeNMChannels(Mat _src, vector_Mat& _channels, int _mode = ERFILTER_NM_RGBLGrad) + private static native void computeNMChannels_0(long _src_nativeObj, long _channels_mat_nativeObj, int _mode); + private static native void computeNMChannels_1(long _src_nativeObj, long _channels_mat_nativeObj); + + // C++: void cv::text::detectRegions(Mat image, Ptr_ERFilter er_filter1, Ptr_ERFilter er_filter2, vector_Rect& groups_rects, int method = ERGROUPING_ORIENTATION_HORIZ, String filename = String(), float minProbability = (float)0.5) + private static native void detectRegions_0(long image_nativeObj, long er_filter1_nativeObj, long er_filter2_nativeObj, long groups_rects_mat_nativeObj, int method, String filename, float minProbability); + private static native void detectRegions_1(long image_nativeObj, long er_filter1_nativeObj, long er_filter2_nativeObj, long groups_rects_mat_nativeObj, int method, String filename); + private static native void detectRegions_2(long image_nativeObj, long er_filter1_nativeObj, long er_filter2_nativeObj, long groups_rects_mat_nativeObj, int method); + private static native void detectRegions_3(long image_nativeObj, long er_filter1_nativeObj, long er_filter2_nativeObj, long groups_rects_mat_nativeObj); + + // C++: void cv::text::detectRegions(Mat image, Ptr_ERFilter er_filter1, Ptr_ERFilter er_filter2, vector_vector_Point& regions) + private static native void detectRegions_4(long image_nativeObj, long er_filter1_nativeObj, long er_filter2_nativeObj, long regions_mat_nativeObj); + + // C++: void cv::text::erGrouping(Mat image, Mat channel, vector_vector_Point regions, vector_Rect& groups_rects, int method = ERGROUPING_ORIENTATION_HORIZ, String filename = String(), float minProbablity = (float)0.5) + private static native void erGrouping_0(long image_nativeObj, long channel_nativeObj, long regions_mat_nativeObj, long groups_rects_mat_nativeObj, int method, String filename, float minProbablity); + private static native void erGrouping_1(long image_nativeObj, long channel_nativeObj, long regions_mat_nativeObj, long groups_rects_mat_nativeObj, int method, String filename); + private static native void erGrouping_2(long image_nativeObj, long channel_nativeObj, long regions_mat_nativeObj, long groups_rects_mat_nativeObj, int method); + private static native void erGrouping_3(long image_nativeObj, long channel_nativeObj, long regions_mat_nativeObj, long groups_rects_mat_nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/text/TextDetector.java b/OpenCV/src/main/java/org/opencv/text/TextDetector.java new file mode 100644 index 00000000..967a456e --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/text/TextDetector.java @@ -0,0 +1,54 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.text; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfFloat; +import org.opencv.core.MatOfRect; +import org.opencv.utils.Converters; + +// C++: class TextDetector +//javadoc: TextDetector + +public class TextDetector { + + protected final long nativeObj; + protected TextDetector(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static TextDetector __fromPtr__(long addr) { return new TextDetector(addr); } + + // + // C++: void cv::text::TextDetector::detect(Mat inputImage, vector_Rect& Bbox, vector_float& confidence) + // + + //javadoc: TextDetector::detect(inputImage, Bbox, confidence) + public void detect(Mat inputImage, MatOfRect Bbox, MatOfFloat confidence) + { + Mat Bbox_mat = Bbox; + Mat confidence_mat = confidence; + detect_0(nativeObj, inputImage.nativeObj, Bbox_mat.nativeObj, confidence_mat.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::text::TextDetector::detect(Mat inputImage, vector_Rect& Bbox, vector_float& confidence) + private static native void detect_0(long nativeObj, long inputImage_nativeObj, long Bbox_mat_nativeObj, long confidence_mat_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/text/TextDetectorCNN.java b/OpenCV/src/main/java/org/opencv/text/TextDetectorCNN.java new file mode 100644 index 00000000..b6983506 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/text/TextDetectorCNN.java @@ -0,0 +1,71 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.text; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfFloat; +import org.opencv.core.MatOfRect; +import org.opencv.text.TextDetector; +import org.opencv.text.TextDetectorCNN; +import org.opencv.utils.Converters; + +// C++: class TextDetectorCNN +//javadoc: TextDetectorCNN + +public class TextDetectorCNN extends TextDetector { + + protected TextDetectorCNN(long addr) { super(addr); } + + // internal usage only + public static TextDetectorCNN __fromPtr__(long addr) { return new TextDetectorCNN(addr); } + + // + // C++: static Ptr_TextDetectorCNN cv::text::TextDetectorCNN::create(String modelArchFilename, String modelWeightsFilename) + // + + //javadoc: TextDetectorCNN::create(modelArchFilename, modelWeightsFilename) + public static TextDetectorCNN create(String modelArchFilename, String modelWeightsFilename) + { + + TextDetectorCNN retVal = TextDetectorCNN.__fromPtr__(create_0(modelArchFilename, modelWeightsFilename)); + + return retVal; + } + + + // + // C++: void cv::text::TextDetectorCNN::detect(Mat inputImage, vector_Rect& Bbox, vector_float& confidence) + // + + //javadoc: TextDetectorCNN::detect(inputImage, Bbox, confidence) + public void detect(Mat inputImage, MatOfRect Bbox, MatOfFloat confidence) + { + Mat Bbox_mat = Bbox; + Mat confidence_mat = confidence; + detect_0(nativeObj, inputImage.nativeObj, Bbox_mat.nativeObj, confidence_mat.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_TextDetectorCNN cv::text::TextDetectorCNN::create(String modelArchFilename, String modelWeightsFilename) + private static native long create_0(String modelArchFilename, String modelWeightsFilename); + + // C++: void cv::text::TextDetectorCNN::detect(Mat inputImage, vector_Rect& Bbox, vector_float& confidence) + private static native void detect_0(long nativeObj, long inputImage_nativeObj, long Bbox_mat_nativeObj, long confidence_mat_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/tracking/MultiTracker.java b/OpenCV/src/main/java/org/opencv/tracking/MultiTracker.java new file mode 100644 index 00000000..2d58e3df --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/tracking/MultiTracker.java @@ -0,0 +1,121 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.tracking; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.core.MatOfRect2d; +import org.opencv.core.Rect2d; +import org.opencv.tracking.MultiTracker; +import org.opencv.tracking.Tracker; +import org.opencv.utils.Converters; + +// C++: class MultiTracker +//javadoc: MultiTracker + +public class MultiTracker extends Algorithm { + + protected MultiTracker(long addr) { super(addr); } + + // internal usage only + public static MultiTracker __fromPtr__(long addr) { return new MultiTracker(addr); } + + // + // C++: cv::MultiTracker::MultiTracker() + // + + //javadoc: MultiTracker::MultiTracker() + public MultiTracker() + { + + super( MultiTracker_0() ); + + return; + } + + + // + // C++: static Ptr_MultiTracker cv::MultiTracker::create() + // + + //javadoc: MultiTracker::create() + public static MultiTracker create() + { + + MultiTracker retVal = MultiTracker.__fromPtr__(create_0()); + + return retVal; + } + + + // + // C++: bool cv::MultiTracker::add(Ptr_Tracker newTracker, Mat image, Rect2d boundingBox) + // + + //javadoc: MultiTracker::add(newTracker, image, boundingBox) + public boolean add(Tracker newTracker, Mat image, Rect2d boundingBox) + { + + boolean retVal = add_0(nativeObj, newTracker.getNativeObjAddr(), image.nativeObj, boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height); + + return retVal; + } + + + // + // C++: bool cv::MultiTracker::update(Mat image, vector_Rect2d& boundingBox) + // + + //javadoc: MultiTracker::update(image, boundingBox) + public boolean update(Mat image, MatOfRect2d boundingBox) + { + Mat boundingBox_mat = boundingBox; + boolean retVal = update_0(nativeObj, image.nativeObj, boundingBox_mat.nativeObj); + + return retVal; + } + + + // + // C++: vector_Rect2d cv::MultiTracker::getObjects() + // + + //javadoc: MultiTracker::getObjects() + public MatOfRect2d getObjects() + { + + MatOfRect2d retVal = MatOfRect2d.fromNativeAddr(getObjects_0(nativeObj)); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: cv::MultiTracker::MultiTracker() + private static native long MultiTracker_0(); + + // C++: static Ptr_MultiTracker cv::MultiTracker::create() + private static native long create_0(); + + // C++: bool cv::MultiTracker::add(Ptr_Tracker newTracker, Mat image, Rect2d boundingBox) + private static native boolean add_0(long nativeObj, long newTracker_nativeObj, long image_nativeObj, double boundingBox_x, double boundingBox_y, double boundingBox_width, double boundingBox_height); + + // C++: bool cv::MultiTracker::update(Mat image, vector_Rect2d& boundingBox) + private static native boolean update_0(long nativeObj, long image_nativeObj, long boundingBox_mat_nativeObj); + + // C++: vector_Rect2d cv::MultiTracker::getObjects() + private static native long getObjects_0(long nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/tracking/Tracker.java b/OpenCV/src/main/java/org/opencv/tracking/Tracker.java new file mode 100644 index 00000000..24f0a9a0 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/tracking/Tracker.java @@ -0,0 +1,64 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.tracking; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.core.Rect2d; + +// C++: class Tracker +//javadoc: Tracker + +public class Tracker extends Algorithm { + + protected Tracker(long addr) { super(addr); } + + // internal usage only + public static Tracker __fromPtr__(long addr) { return new Tracker(addr); } + + // + // C++: bool cv::Tracker::init(Mat image, Rect2d boundingBox) + // + + //javadoc: Tracker::init(image, boundingBox) + public boolean init(Mat image, Rect2d boundingBox) + { + + boolean retVal = init_0(nativeObj, image.nativeObj, boundingBox.x, boundingBox.y, boundingBox.width, boundingBox.height); + + return retVal; + } + + + // + // C++: bool cv::Tracker::update(Mat image, Rect2d& boundingBox) + // + + //javadoc: Tracker::update(image, boundingBox) + public boolean update(Mat image, Rect2d boundingBox) + { + double[] boundingBox_out = new double[4]; + boolean retVal = update_0(nativeObj, image.nativeObj, boundingBox_out); + if(boundingBox!=null){ boundingBox.x = boundingBox_out[0]; boundingBox.y = boundingBox_out[1]; boundingBox.width = boundingBox_out[2]; boundingBox.height = boundingBox_out[3]; } + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: bool cv::Tracker::init(Mat image, Rect2d boundingBox) + private static native boolean init_0(long nativeObj, long image_nativeObj, double boundingBox_x, double boundingBox_y, double boundingBox_width, double boundingBox_height); + + // C++: bool cv::Tracker::update(Mat image, Rect2d& boundingBox) + private static native boolean update_0(long nativeObj, long image_nativeObj, double[] boundingBox_out); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/tracking/TrackerBoosting.java b/OpenCV/src/main/java/org/opencv/tracking/TrackerBoosting.java new file mode 100644 index 00000000..67688811 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/tracking/TrackerBoosting.java @@ -0,0 +1,46 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.tracking; + +import org.opencv.tracking.Tracker; +import org.opencv.tracking.TrackerBoosting; + +// C++: class TrackerBoosting +//javadoc: TrackerBoosting + +public class TrackerBoosting extends Tracker { + + protected TrackerBoosting(long addr) { super(addr); } + + // internal usage only + public static TrackerBoosting __fromPtr__(long addr) { return new TrackerBoosting(addr); } + + // + // C++: static Ptr_TrackerBoosting cv::TrackerBoosting::create() + // + + //javadoc: TrackerBoosting::create() + public static TrackerBoosting create() + { + + TrackerBoosting retVal = TrackerBoosting.__fromPtr__(create_0()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_TrackerBoosting cv::TrackerBoosting::create() + private static native long create_0(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/tracking/TrackerCSRT.java b/OpenCV/src/main/java/org/opencv/tracking/TrackerCSRT.java new file mode 100644 index 00000000..ab679894 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/tracking/TrackerCSRT.java @@ -0,0 +1,64 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.tracking; + +import org.opencv.core.Mat; +import org.opencv.tracking.Tracker; +import org.opencv.tracking.TrackerCSRT; + +// C++: class TrackerCSRT +//javadoc: TrackerCSRT + +public class TrackerCSRT extends Tracker { + + protected TrackerCSRT(long addr) { super(addr); } + + // internal usage only + public static TrackerCSRT __fromPtr__(long addr) { return new TrackerCSRT(addr); } + + // + // C++: static Ptr_TrackerCSRT cv::TrackerCSRT::create() + // + + //javadoc: TrackerCSRT::create() + public static TrackerCSRT create() + { + + TrackerCSRT retVal = TrackerCSRT.__fromPtr__(create_0()); + + return retVal; + } + + + // + // C++: void cv::TrackerCSRT::setInitialMask(Mat mask) + // + + //javadoc: TrackerCSRT::setInitialMask(mask) + public void setInitialMask(Mat mask) + { + + setInitialMask_0(nativeObj, mask.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_TrackerCSRT cv::TrackerCSRT::create() + private static native long create_0(); + + // C++: void cv::TrackerCSRT::setInitialMask(Mat mask) + private static native void setInitialMask_0(long nativeObj, long mask_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/tracking/TrackerGOTURN.java b/OpenCV/src/main/java/org/opencv/tracking/TrackerGOTURN.java new file mode 100644 index 00000000..148dcdc4 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/tracking/TrackerGOTURN.java @@ -0,0 +1,46 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.tracking; + +import org.opencv.tracking.Tracker; +import org.opencv.tracking.TrackerGOTURN; + +// C++: class TrackerGOTURN +//javadoc: TrackerGOTURN + +public class TrackerGOTURN extends Tracker { + + protected TrackerGOTURN(long addr) { super(addr); } + + // internal usage only + public static TrackerGOTURN __fromPtr__(long addr) { return new TrackerGOTURN(addr); } + + // + // C++: static Ptr_TrackerGOTURN cv::TrackerGOTURN::create() + // + + //javadoc: TrackerGOTURN::create() + public static TrackerGOTURN create() + { + + TrackerGOTURN retVal = TrackerGOTURN.__fromPtr__(create_0()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_TrackerGOTURN cv::TrackerGOTURN::create() + private static native long create_0(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/tracking/TrackerKCF.java b/OpenCV/src/main/java/org/opencv/tracking/TrackerKCF.java new file mode 100644 index 00000000..fe08a197 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/tracking/TrackerKCF.java @@ -0,0 +1,53 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.tracking; + +import org.opencv.tracking.Tracker; +import org.opencv.tracking.TrackerKCF; + +// C++: class TrackerKCF +//javadoc: TrackerKCF + +public class TrackerKCF extends Tracker { + + protected TrackerKCF(long addr) { super(addr); } + + // internal usage only + public static TrackerKCF __fromPtr__(long addr) { return new TrackerKCF(addr); } + + // C++: enum MODE + public static final int + GRAY = (1 << 0), + CN = (1 << 1), + CUSTOM = (1 << 2); + + + // + // C++: static Ptr_TrackerKCF cv::TrackerKCF::create() + // + + //javadoc: TrackerKCF::create() + public static TrackerKCF create() + { + + TrackerKCF retVal = TrackerKCF.__fromPtr__(create_0()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_TrackerKCF cv::TrackerKCF::create() + private static native long create_0(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/tracking/TrackerMIL.java b/OpenCV/src/main/java/org/opencv/tracking/TrackerMIL.java new file mode 100644 index 00000000..a116da42 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/tracking/TrackerMIL.java @@ -0,0 +1,46 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.tracking; + +import org.opencv.tracking.Tracker; +import org.opencv.tracking.TrackerMIL; + +// C++: class TrackerMIL +//javadoc: TrackerMIL + +public class TrackerMIL extends Tracker { + + protected TrackerMIL(long addr) { super(addr); } + + // internal usage only + public static TrackerMIL __fromPtr__(long addr) { return new TrackerMIL(addr); } + + // + // C++: static Ptr_TrackerMIL cv::TrackerMIL::create() + // + + //javadoc: TrackerMIL::create() + public static TrackerMIL create() + { + + TrackerMIL retVal = TrackerMIL.__fromPtr__(create_0()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_TrackerMIL cv::TrackerMIL::create() + private static native long create_0(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/tracking/TrackerMOSSE.java b/OpenCV/src/main/java/org/opencv/tracking/TrackerMOSSE.java new file mode 100644 index 00000000..45b55777 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/tracking/TrackerMOSSE.java @@ -0,0 +1,46 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.tracking; + +import org.opencv.tracking.Tracker; +import org.opencv.tracking.TrackerMOSSE; + +// C++: class TrackerMOSSE +//javadoc: TrackerMOSSE + +public class TrackerMOSSE extends Tracker { + + protected TrackerMOSSE(long addr) { super(addr); } + + // internal usage only + public static TrackerMOSSE __fromPtr__(long addr) { return new TrackerMOSSE(addr); } + + // + // C++: static Ptr_TrackerMOSSE cv::TrackerMOSSE::create() + // + + //javadoc: TrackerMOSSE::create() + public static TrackerMOSSE create() + { + + TrackerMOSSE retVal = TrackerMOSSE.__fromPtr__(create_0()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_TrackerMOSSE cv::TrackerMOSSE::create() + private static native long create_0(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/tracking/TrackerMedianFlow.java b/OpenCV/src/main/java/org/opencv/tracking/TrackerMedianFlow.java new file mode 100644 index 00000000..ed50b1c6 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/tracking/TrackerMedianFlow.java @@ -0,0 +1,46 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.tracking; + +import org.opencv.tracking.Tracker; +import org.opencv.tracking.TrackerMedianFlow; + +// C++: class TrackerMedianFlow +//javadoc: TrackerMedianFlow + +public class TrackerMedianFlow extends Tracker { + + protected TrackerMedianFlow(long addr) { super(addr); } + + // internal usage only + public static TrackerMedianFlow __fromPtr__(long addr) { return new TrackerMedianFlow(addr); } + + // + // C++: static Ptr_TrackerMedianFlow cv::TrackerMedianFlow::create() + // + + //javadoc: TrackerMedianFlow::create() + public static TrackerMedianFlow create() + { + + TrackerMedianFlow retVal = TrackerMedianFlow.__fromPtr__(create_0()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_TrackerMedianFlow cv::TrackerMedianFlow::create() + private static native long create_0(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/tracking/TrackerTLD.java b/OpenCV/src/main/java/org/opencv/tracking/TrackerTLD.java new file mode 100644 index 00000000..cf73b7e2 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/tracking/TrackerTLD.java @@ -0,0 +1,46 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.tracking; + +import org.opencv.tracking.Tracker; +import org.opencv.tracking.TrackerTLD; + +// C++: class TrackerTLD +//javadoc: TrackerTLD + +public class TrackerTLD extends Tracker { + + protected TrackerTLD(long addr) { super(addr); } + + // internal usage only + public static TrackerTLD __fromPtr__(long addr) { return new TrackerTLD(addr); } + + // + // C++: static Ptr_TrackerTLD cv::TrackerTLD::create() + // + + //javadoc: TrackerTLD::create() + public static TrackerTLD create() + { + + TrackerTLD retVal = TrackerTLD.__fromPtr__(create_0()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_TrackerTLD cv::TrackerTLD::create() + private static native long create_0(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/tracking/Tracking.java b/OpenCV/src/main/java/org/opencv/tracking/Tracking.java new file mode 100644 index 00000000..4f68aafe --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/tracking/Tracking.java @@ -0,0 +1,34 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.tracking; + + + +// C++: class Tracking +//javadoc: Tracking + +public class Tracking { + + // C++: enum + public static final int + TrackerSamplerCSC_MODE_INIT_POS = 1, + TrackerSamplerCSC_MODE_INIT_NEG = 2, + TrackerSamplerCSC_MODE_TRACK_POS = 3, + TrackerSamplerCSC_MODE_TRACK_NEG = 4, + TrackerSamplerCSC_MODE_DETECT = 5, + TrackerSamplerCS_MODE_POSITIVE = 1, + TrackerSamplerCS_MODE_NEGATIVE = 2, + TrackerSamplerCS_MODE_CLASSIFY = 3; + + + // C++: enum FeatureType + public static final int + CvFeatureParams_HAAR = 0, + CvFeatureParams_LBP = 1, + CvFeatureParams_HOG = 2; + + + + +} diff --git a/OpenCV/src/main/java/org/opencv/utils/Converters.java b/OpenCV/src/main/java/org/opencv/utils/Converters.java new file mode 100644 index 00000000..94675da1 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/utils/Converters.java @@ -0,0 +1,812 @@ +package org.opencv.utils; + +import java.util.ArrayList; +import java.util.List; + +import org.opencv.core.CvType; +import org.opencv.core.Mat; +import org.opencv.core.MatOfByte; +import org.opencv.core.MatOfDMatch; +import org.opencv.core.MatOfKeyPoint; +import org.opencv.core.MatOfPoint; +import org.opencv.core.MatOfPoint2f; +import org.opencv.core.MatOfPoint3f; +import org.opencv.core.Point; +import org.opencv.core.Point3; +import org.opencv.core.Size; +import org.opencv.core.Rect; +import org.opencv.core.RotatedRect; +import org.opencv.core.Rect2d; +import org.opencv.core.DMatch; +import org.opencv.core.KeyPoint; + +public class Converters { + + public static Mat vector_Point_to_Mat(List pts) { + return vector_Point_to_Mat(pts, CvType.CV_32S); + } + + public static Mat vector_Point2f_to_Mat(List pts) { + return vector_Point_to_Mat(pts, CvType.CV_32F); + } + + public static Mat vector_Point2d_to_Mat(List pts) { + return vector_Point_to_Mat(pts, CvType.CV_64F); + } + + public static Mat vector_Point_to_Mat(List pts, int typeDepth) { + Mat res; + int count = (pts != null) ? pts.size() : 0; + if (count > 0) { + switch (typeDepth) { + case CvType.CV_32S: { + res = new Mat(count, 1, CvType.CV_32SC2); + int[] buff = new int[count * 2]; + for (int i = 0; i < count; i++) { + Point p = pts.get(i); + buff[i * 2] = (int) p.x; + buff[i * 2 + 1] = (int) p.y; + } + res.put(0, 0, buff); + } + break; + + case CvType.CV_32F: { + res = new Mat(count, 1, CvType.CV_32FC2); + float[] buff = new float[count * 2]; + for (int i = 0; i < count; i++) { + Point p = pts.get(i); + buff[i * 2] = (float) p.x; + buff[i * 2 + 1] = (float) p.y; + } + res.put(0, 0, buff); + } + break; + + case CvType.CV_64F: { + res = new Mat(count, 1, CvType.CV_64FC2); + double[] buff = new double[count * 2]; + for (int i = 0; i < count; i++) { + Point p = pts.get(i); + buff[i * 2] = p.x; + buff[i * 2 + 1] = p.y; + } + res.put(0, 0, buff); + } + break; + + default: + throw new IllegalArgumentException("'typeDepth' can be CV_32S, CV_32F or CV_64F"); + } + } else { + res = new Mat(); + } + return res; + } + + public static Mat vector_Point3i_to_Mat(List pts) { + return vector_Point3_to_Mat(pts, CvType.CV_32S); + } + + public static Mat vector_Point3f_to_Mat(List pts) { + return vector_Point3_to_Mat(pts, CvType.CV_32F); + } + + public static Mat vector_Point3d_to_Mat(List pts) { + return vector_Point3_to_Mat(pts, CvType.CV_64F); + } + + public static Mat vector_Point3_to_Mat(List pts, int typeDepth) { + Mat res; + int count = (pts != null) ? pts.size() : 0; + if (count > 0) { + switch (typeDepth) { + case CvType.CV_32S: { + res = new Mat(count, 1, CvType.CV_32SC3); + int[] buff = new int[count * 3]; + for (int i = 0; i < count; i++) { + Point3 p = pts.get(i); + buff[i * 3] = (int) p.x; + buff[i * 3 + 1] = (int) p.y; + buff[i * 3 + 2] = (int) p.z; + } + res.put(0, 0, buff); + } + break; + + case CvType.CV_32F: { + res = new Mat(count, 1, CvType.CV_32FC3); + float[] buff = new float[count * 3]; + for (int i = 0; i < count; i++) { + Point3 p = pts.get(i); + buff[i * 3] = (float) p.x; + buff[i * 3 + 1] = (float) p.y; + buff[i * 3 + 2] = (float) p.z; + } + res.put(0, 0, buff); + } + break; + + case CvType.CV_64F: { + res = new Mat(count, 1, CvType.CV_64FC3); + double[] buff = new double[count * 3]; + for (int i = 0; i < count; i++) { + Point3 p = pts.get(i); + buff[i * 3] = p.x; + buff[i * 3 + 1] = p.y; + buff[i * 3 + 2] = p.z; + } + res.put(0, 0, buff); + } + break; + + default: + throw new IllegalArgumentException("'typeDepth' can be CV_32S, CV_32F or CV_64F"); + } + } else { + res = new Mat(); + } + return res; + } + + public static void Mat_to_vector_Point2f(Mat m, List pts) { + Mat_to_vector_Point(m, pts); + } + + public static void Mat_to_vector_Point2d(Mat m, List pts) { + Mat_to_vector_Point(m, pts); + } + + public static void Mat_to_vector_Point(Mat m, List pts) { + if (pts == null) + throw new IllegalArgumentException("Output List can't be null"); + int count = m.rows(); + int type = m.type(); + if (m.cols() != 1) + throw new IllegalArgumentException("Input Mat should have one column\n" + m); + + pts.clear(); + if (type == CvType.CV_32SC2) { + int[] buff = new int[2 * count]; + m.get(0, 0, buff); + for (int i = 0; i < count; i++) { + pts.add(new Point(buff[i * 2], buff[i * 2 + 1])); + } + } else if (type == CvType.CV_32FC2) { + float[] buff = new float[2 * count]; + m.get(0, 0, buff); + for (int i = 0; i < count; i++) { + pts.add(new Point(buff[i * 2], buff[i * 2 + 1])); + } + } else if (type == CvType.CV_64FC2) { + double[] buff = new double[2 * count]; + m.get(0, 0, buff); + for (int i = 0; i < count; i++) { + pts.add(new Point(buff[i * 2], buff[i * 2 + 1])); + } + } else { + throw new IllegalArgumentException( + "Input Mat should be of CV_32SC2, CV_32FC2 or CV_64FC2 type\n" + m); + } + } + + public static void Mat_to_vector_Point3i(Mat m, List pts) { + Mat_to_vector_Point3(m, pts); + } + + public static void Mat_to_vector_Point3f(Mat m, List pts) { + Mat_to_vector_Point3(m, pts); + } + + public static void Mat_to_vector_Point3d(Mat m, List pts) { + Mat_to_vector_Point3(m, pts); + } + + public static void Mat_to_vector_Point3(Mat m, List pts) { + if (pts == null) + throw new IllegalArgumentException("Output List can't be null"); + int count = m.rows(); + int type = m.type(); + if (m.cols() != 1) + throw new IllegalArgumentException("Input Mat should have one column\n" + m); + + pts.clear(); + if (type == CvType.CV_32SC3) { + int[] buff = new int[3 * count]; + m.get(0, 0, buff); + for (int i = 0; i < count; i++) { + pts.add(new Point3(buff[i * 3], buff[i * 3 + 1], buff[i * 3 + 2])); + } + } else if (type == CvType.CV_32FC3) { + float[] buff = new float[3 * count]; + m.get(0, 0, buff); + for (int i = 0; i < count; i++) { + pts.add(new Point3(buff[i * 3], buff[i * 3 + 1], buff[i * 3 + 2])); + } + } else if (type == CvType.CV_64FC3) { + double[] buff = new double[3 * count]; + m.get(0, 0, buff); + for (int i = 0; i < count; i++) { + pts.add(new Point3(buff[i * 3], buff[i * 3 + 1], buff[i * 3 + 2])); + } + } else { + throw new IllegalArgumentException( + "Input Mat should be of CV_32SC3, CV_32FC3 or CV_64FC3 type\n" + m); + } + } + + public static Mat vector_Mat_to_Mat(List mats) { + Mat res; + int count = (mats != null) ? mats.size() : 0; + if (count > 0) { + res = new Mat(count, 1, CvType.CV_32SC2); + int[] buff = new int[count * 2]; + for (int i = 0; i < count; i++) { + long addr = mats.get(i).nativeObj; + buff[i * 2] = (int) (addr >> 32); + buff[i * 2 + 1] = (int) (addr & 0xffffffff); + } + res.put(0, 0, buff); + } else { + res = new Mat(); + } + return res; + } + + public static void Mat_to_vector_Mat(Mat m, List mats) { + if (mats == null) + throw new IllegalArgumentException("mats == null"); + int count = m.rows(); + if (CvType.CV_32SC2 != m.type() || m.cols() != 1) + throw new IllegalArgumentException( + "CvType.CV_32SC2 != m.type() || m.cols()!=1\n" + m); + + mats.clear(); + int[] buff = new int[count * 2]; + m.get(0, 0, buff); + for (int i = 0; i < count; i++) { + long addr = (((long) buff[i * 2]) << 32) | (((long) buff[i * 2 + 1]) & 0xffffffffL); + mats.add(new Mat(addr)); + } + } + + public static Mat vector_float_to_Mat(List fs) { + Mat res; + int count = (fs != null) ? fs.size() : 0; + if (count > 0) { + res = new Mat(count, 1, CvType.CV_32FC1); + float[] buff = new float[count]; + for (int i = 0; i < count; i++) { + float f = fs.get(i); + buff[i] = f; + } + res.put(0, 0, buff); + } else { + res = new Mat(); + } + return res; + } + + public static void Mat_to_vector_float(Mat m, List fs) { + if (fs == null) + throw new IllegalArgumentException("fs == null"); + int count = m.rows(); + if (CvType.CV_32FC1 != m.type() || m.cols() != 1) + throw new IllegalArgumentException( + "CvType.CV_32FC1 != m.type() || m.cols()!=1\n" + m); + + fs.clear(); + float[] buff = new float[count]; + m.get(0, 0, buff); + for (int i = 0; i < count; i++) { + fs.add(buff[i]); + } + } + + public static Mat vector_uchar_to_Mat(List bs) { + Mat res; + int count = (bs != null) ? bs.size() : 0; + if (count > 0) { + res = new Mat(count, 1, CvType.CV_8UC1); + byte[] buff = new byte[count]; + for (int i = 0; i < count; i++) { + byte b = bs.get(i); + buff[i] = b; + } + res.put(0, 0, buff); + } else { + res = new Mat(); + } + return res; + } + + public static void Mat_to_vector_uchar(Mat m, List us) { + if (us == null) + throw new IllegalArgumentException("Output List can't be null"); + int count = m.rows(); + if (CvType.CV_8UC1 != m.type() || m.cols() != 1) + throw new IllegalArgumentException( + "CvType.CV_8UC1 != m.type() || m.cols()!=1\n" + m); + + us.clear(); + byte[] buff = new byte[count]; + m.get(0, 0, buff); + for (int i = 0; i < count; i++) { + us.add(buff[i]); + } + } + + public static Mat vector_char_to_Mat(List bs) { + Mat res; + int count = (bs != null) ? bs.size() : 0; + if (count > 0) { + res = new Mat(count, 1, CvType.CV_8SC1); + byte[] buff = new byte[count]; + for (int i = 0; i < count; i++) { + byte b = bs.get(i); + buff[i] = b; + } + res.put(0, 0, buff); + } else { + res = new Mat(); + } + return res; + } + + public static Mat vector_int_to_Mat(List is) { + Mat res; + int count = (is != null) ? is.size() : 0; + if (count > 0) { + res = new Mat(count, 1, CvType.CV_32SC1); + int[] buff = new int[count]; + for (int i = 0; i < count; i++) { + int v = is.get(i); + buff[i] = v; + } + res.put(0, 0, buff); + } else { + res = new Mat(); + } + return res; + } + + public static void Mat_to_vector_int(Mat m, List is) { + if (is == null) + throw new IllegalArgumentException("is == null"); + int count = m.rows(); + if (CvType.CV_32SC1 != m.type() || m.cols() != 1) + throw new IllegalArgumentException( + "CvType.CV_32SC1 != m.type() || m.cols()!=1\n" + m); + + is.clear(); + int[] buff = new int[count]; + m.get(0, 0, buff); + for (int i = 0; i < count; i++) { + is.add(buff[i]); + } + } + + public static void Mat_to_vector_char(Mat m, List bs) { + if (bs == null) + throw new IllegalArgumentException("Output List can't be null"); + int count = m.rows(); + if (CvType.CV_8SC1 != m.type() || m.cols() != 1) + throw new IllegalArgumentException( + "CvType.CV_8SC1 != m.type() || m.cols()!=1\n" + m); + + bs.clear(); + byte[] buff = new byte[count]; + m.get(0, 0, buff); + for (int i = 0; i < count; i++) { + bs.add(buff[i]); + } + } + + public static Mat vector_Rect_to_Mat(List rs) { + Mat res; + int count = (rs != null) ? rs.size() : 0; + if (count > 0) { + res = new Mat(count, 1, CvType.CV_32SC4); + int[] buff = new int[4 * count]; + for (int i = 0; i < count; i++) { + Rect r = rs.get(i); + buff[4 * i] = r.x; + buff[4 * i + 1] = r.y; + buff[4 * i + 2] = r.width; + buff[4 * i + 3] = r.height; + } + res.put(0, 0, buff); + } else { + res = new Mat(); + } + return res; + } + + public static void Mat_to_vector_Rect(Mat m, List rs) { + if (rs == null) + throw new IllegalArgumentException("rs == null"); + int count = m.rows(); + if (CvType.CV_32SC4 != m.type() || m.cols() != 1) + throw new IllegalArgumentException( + "CvType.CV_32SC4 != m.type() || m.rows()!=1\n" + m); + + rs.clear(); + int[] buff = new int[4 * count]; + m.get(0, 0, buff); + for (int i = 0; i < count; i++) { + rs.add(new Rect(buff[4 * i], buff[4 * i + 1], buff[4 * i + 2], buff[4 * i + 3])); + } + } + + public static Mat vector_Rect2d_to_Mat(List rs) { + Mat res; + int count = (rs != null) ? rs.size() : 0; + if (count > 0) { + res = new Mat(count, 1, CvType.CV_64FC4); + double[] buff = new double[4 * count]; + for (int i = 0; i < count; i++) { + Rect2d r = rs.get(i); + buff[4 * i] = r.x; + buff[4 * i + 1] = r.y; + buff[4 * i + 2] = r.width; + buff[4 * i + 3] = r.height; + } + res.put(0, 0, buff); + } else { + res = new Mat(); + } + return res; + } + + public static void Mat_to_vector_Rect2d(Mat m, List rs) { + if (rs == null) + throw new IllegalArgumentException("rs == null"); + int count = m.rows(); + if (CvType.CV_64FC4 != m.type() || m.cols() != 1) + throw new IllegalArgumentException( + "CvType.CV_64FC4 != m.type() || m.rows()!=1\n" + m); + + rs.clear(); + double[] buff = new double[4 * count]; + m.get(0, 0, buff); + for (int i = 0; i < count; i++) { + rs.add(new Rect2d(buff[4 * i], buff[4 * i + 1], buff[4 * i + 2], buff[4 * i + 3])); + } + } + + public static Mat vector_KeyPoint_to_Mat(List kps) { + Mat res; + int count = (kps != null) ? kps.size() : 0; + if (count > 0) { + res = new Mat(count, 1, CvType.CV_64FC(7)); + double[] buff = new double[count * 7]; + for (int i = 0; i < count; i++) { + KeyPoint kp = kps.get(i); + buff[7 * i] = kp.pt.x; + buff[7 * i + 1] = kp.pt.y; + buff[7 * i + 2] = kp.size; + buff[7 * i + 3] = kp.angle; + buff[7 * i + 4] = kp.response; + buff[7 * i + 5] = kp.octave; + buff[7 * i + 6] = kp.class_id; + } + res.put(0, 0, buff); + } else { + res = new Mat(); + } + return res; + } + + public static void Mat_to_vector_KeyPoint(Mat m, List kps) { + if (kps == null) + throw new IllegalArgumentException("Output List can't be null"); + int count = m.rows(); + if (CvType.CV_64FC(7) != m.type() || m.cols() != 1) + throw new IllegalArgumentException( + "CvType.CV_64FC(7) != m.type() || m.cols()!=1\n" + m); + + kps.clear(); + double[] buff = new double[7 * count]; + m.get(0, 0, buff); + for (int i = 0; i < count; i++) { + kps.add(new KeyPoint((float) buff[7 * i], (float) buff[7 * i + 1], (float) buff[7 * i + 2], (float) buff[7 * i + 3], + (float) buff[7 * i + 4], (int) buff[7 * i + 5], (int) buff[7 * i + 6])); + } + } + + // vector_vector_Point + public static Mat vector_vector_Point_to_Mat(List pts, List mats) { + Mat res; + int lCount = (pts != null) ? pts.size() : 0; + if (lCount > 0) { + for (MatOfPoint vpt : pts) + mats.add(vpt); + res = vector_Mat_to_Mat(mats); + } else { + res = new Mat(); + } + return res; + } + + public static void Mat_to_vector_vector_Point(Mat m, List pts) { + if (pts == null) + throw new IllegalArgumentException("Output List can't be null"); + + if (m == null) + throw new IllegalArgumentException("Input Mat can't be null"); + + List mats = new ArrayList(m.rows()); + Mat_to_vector_Mat(m, mats); + for (Mat mi : mats) { + MatOfPoint pt = new MatOfPoint(mi); + pts.add(pt); + mi.release(); + } + mats.clear(); + } + + // vector_vector_Point2f + public static void Mat_to_vector_vector_Point2f(Mat m, List pts) { + if (pts == null) + throw new IllegalArgumentException("Output List can't be null"); + + if (m == null) + throw new IllegalArgumentException("Input Mat can't be null"); + + List mats = new ArrayList(m.rows()); + Mat_to_vector_Mat(m, mats); + for (Mat mi : mats) { + MatOfPoint2f pt = new MatOfPoint2f(mi); + pts.add(pt); + mi.release(); + } + mats.clear(); + } + + // vector_vector_Point2f + public static Mat vector_vector_Point2f_to_Mat(List pts, List mats) { + Mat res; + int lCount = (pts != null) ? pts.size() : 0; + if (lCount > 0) { + for (MatOfPoint2f vpt : pts) + mats.add(vpt); + res = vector_Mat_to_Mat(mats); + } else { + res = new Mat(); + } + return res; + } + + // vector_vector_Point3f + public static void Mat_to_vector_vector_Point3f(Mat m, List pts) { + if (pts == null) + throw new IllegalArgumentException("Output List can't be null"); + + if (m == null) + throw new IllegalArgumentException("Input Mat can't be null"); + + List mats = new ArrayList(m.rows()); + Mat_to_vector_Mat(m, mats); + for (Mat mi : mats) { + MatOfPoint3f pt = new MatOfPoint3f(mi); + pts.add(pt); + mi.release(); + } + mats.clear(); + } + + // vector_vector_Point3f + public static Mat vector_vector_Point3f_to_Mat(List pts, List mats) { + Mat res; + int lCount = (pts != null) ? pts.size() : 0; + if (lCount > 0) { + for (MatOfPoint3f vpt : pts) + mats.add(vpt); + res = vector_Mat_to_Mat(mats); + } else { + res = new Mat(); + } + return res; + } + + // vector_vector_KeyPoint + public static Mat vector_vector_KeyPoint_to_Mat(List kps, List mats) { + Mat res; + int lCount = (kps != null) ? kps.size() : 0; + if (lCount > 0) { + for (MatOfKeyPoint vkp : kps) + mats.add(vkp); + res = vector_Mat_to_Mat(mats); + } else { + res = new Mat(); + } + return res; + } + + public static void Mat_to_vector_vector_KeyPoint(Mat m, List kps) { + if (kps == null) + throw new IllegalArgumentException("Output List can't be null"); + + if (m == null) + throw new IllegalArgumentException("Input Mat can't be null"); + + List mats = new ArrayList(m.rows()); + Mat_to_vector_Mat(m, mats); + for (Mat mi : mats) { + MatOfKeyPoint vkp = new MatOfKeyPoint(mi); + kps.add(vkp); + mi.release(); + } + mats.clear(); + } + + public static Mat vector_double_to_Mat(List ds) { + Mat res; + int count = (ds != null) ? ds.size() : 0; + if (count > 0) { + res = new Mat(count, 1, CvType.CV_64FC1); + double[] buff = new double[count]; + for (int i = 0; i < count; i++) { + double v = ds.get(i); + buff[i] = v; + } + res.put(0, 0, buff); + } else { + res = new Mat(); + } + return res; + } + + public static void Mat_to_vector_double(Mat m, List ds) { + if (ds == null) + throw new IllegalArgumentException("ds == null"); + int count = m.rows(); + if (CvType.CV_64FC1 != m.type() || m.cols() != 1) + throw new IllegalArgumentException( + "CvType.CV_64FC1 != m.type() || m.cols()!=1\n" + m); + + ds.clear(); + double[] buff = new double[count]; + m.get(0, 0, buff); + for (int i = 0; i < count; i++) { + ds.add(buff[i]); + } + } + + public static Mat vector_DMatch_to_Mat(List matches) { + Mat res; + int count = (matches != null) ? matches.size() : 0; + if (count > 0) { + res = new Mat(count, 1, CvType.CV_64FC4); + double[] buff = new double[count * 4]; + for (int i = 0; i < count; i++) { + DMatch m = matches.get(i); + buff[4 * i] = m.queryIdx; + buff[4 * i + 1] = m.trainIdx; + buff[4 * i + 2] = m.imgIdx; + buff[4 * i + 3] = m.distance; + } + res.put(0, 0, buff); + } else { + res = new Mat(); + } + return res; + } + + public static void Mat_to_vector_DMatch(Mat m, List matches) { + if (matches == null) + throw new IllegalArgumentException("Output List can't be null"); + int count = m.rows(); + if (CvType.CV_64FC4 != m.type() || m.cols() != 1) + throw new IllegalArgumentException( + "CvType.CV_64FC4 != m.type() || m.cols()!=1\n" + m); + + matches.clear(); + double[] buff = new double[4 * count]; + m.get(0, 0, buff); + for (int i = 0; i < count; i++) { + matches.add(new DMatch((int) buff[4 * i], (int) buff[4 * i + 1], (int) buff[4 * i + 2], (float) buff[4 * i + 3])); + } + } + + // vector_vector_DMatch + public static Mat vector_vector_DMatch_to_Mat(List lvdm, List mats) { + Mat res; + int lCount = (lvdm != null) ? lvdm.size() : 0; + if (lCount > 0) { + for (MatOfDMatch vdm : lvdm) + mats.add(vdm); + res = vector_Mat_to_Mat(mats); + } else { + res = new Mat(); + } + return res; + } + + public static void Mat_to_vector_vector_DMatch(Mat m, List lvdm) { + if (lvdm == null) + throw new IllegalArgumentException("Output List can't be null"); + + if (m == null) + throw new IllegalArgumentException("Input Mat can't be null"); + + List mats = new ArrayList(m.rows()); + Mat_to_vector_Mat(m, mats); + lvdm.clear(); + for (Mat mi : mats) { + MatOfDMatch vdm = new MatOfDMatch(mi); + lvdm.add(vdm); + mi.release(); + } + mats.clear(); + } + + // vector_vector_char + public static Mat vector_vector_char_to_Mat(List lvb, List mats) { + Mat res; + int lCount = (lvb != null) ? lvb.size() : 0; + if (lCount > 0) { + for (MatOfByte vb : lvb) + mats.add(vb); + res = vector_Mat_to_Mat(mats); + } else { + res = new Mat(); + } + return res; + } + + public static void Mat_to_vector_vector_char(Mat m, List> llb) { + if (llb == null) + throw new IllegalArgumentException("Output List can't be null"); + + if (m == null) + throw new IllegalArgumentException("Input Mat can't be null"); + + List mats = new ArrayList(m.rows()); + Mat_to_vector_Mat(m, mats); + for (Mat mi : mats) { + List lb = new ArrayList(); + Mat_to_vector_char(mi, lb); + llb.add(lb); + mi.release(); + } + mats.clear(); + } + + public static Mat vector_RotatedRect_to_Mat(List rs) { + Mat res; + int count = (rs != null) ? rs.size() : 0; + if (count > 0) { + res = new Mat(count, 1, CvType.CV_32FC(5)); + float[] buff = new float[5 * count]; + for (int i = 0; i < count; i++) { + RotatedRect r = rs.get(i); + buff[5 * i] = (float)r.center.x; + buff[5 * i + 1] = (float)r.center.y; + buff[5 * i + 2] = (float)r.size.width; + buff[5 * i + 3] = (float)r.size.height; + buff[5 * i + 4] = (float)r.angle; + } + res.put(0, 0, buff); + } else { + res = new Mat(); + } + return res; + } + + public static void Mat_to_vector_RotatedRect(Mat m, List rs) { + if (rs == null) + throw new IllegalArgumentException("rs == null"); + int count = m.rows(); + if (CvType.CV_32FC(5) != m.type() || m.cols() != 1) + throw new IllegalArgumentException( + "CvType.CV_32FC5 != m.type() || m.rows()!=1\n" + m); + + rs.clear(); + float[] buff = new float[5 * count]; + m.get(0, 0, buff); + for (int i = 0; i < count; i++) { + rs.add(new RotatedRect(new Point(buff[5 * i], buff[5 * i + 1]), new Size(buff[5 * i + 2], buff[5 * i + 3]), buff[5 * i + 4])); + } + } +} diff --git a/OpenCV/src/main/java/org/opencv/video/BackgroundSubtractor.java b/OpenCV/src/main/java/org/opencv/video/BackgroundSubtractor.java new file mode 100644 index 00000000..88b67245 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/video/BackgroundSubtractor.java @@ -0,0 +1,73 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.video; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class BackgroundSubtractor +//javadoc: BackgroundSubtractor + +public class BackgroundSubtractor extends Algorithm { + + protected BackgroundSubtractor(long addr) { super(addr); } + + // internal usage only + public static BackgroundSubtractor __fromPtr__(long addr) { return new BackgroundSubtractor(addr); } + + // + // C++: void cv::BackgroundSubtractor::apply(Mat image, Mat& fgmask, double learningRate = -1) + // + + //javadoc: BackgroundSubtractor::apply(image, fgmask, learningRate) + public void apply(Mat image, Mat fgmask, double learningRate) + { + + apply_0(nativeObj, image.nativeObj, fgmask.nativeObj, learningRate); + + return; + } + + //javadoc: BackgroundSubtractor::apply(image, fgmask) + public void apply(Mat image, Mat fgmask) + { + + apply_1(nativeObj, image.nativeObj, fgmask.nativeObj); + + return; + } + + + // + // C++: void cv::BackgroundSubtractor::getBackgroundImage(Mat& backgroundImage) + // + + //javadoc: BackgroundSubtractor::getBackgroundImage(backgroundImage) + public void getBackgroundImage(Mat backgroundImage) + { + + getBackgroundImage_0(nativeObj, backgroundImage.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::BackgroundSubtractor::apply(Mat image, Mat& fgmask, double learningRate = -1) + private static native void apply_0(long nativeObj, long image_nativeObj, long fgmask_nativeObj, double learningRate); + private static native void apply_1(long nativeObj, long image_nativeObj, long fgmask_nativeObj); + + // C++: void cv::BackgroundSubtractor::getBackgroundImage(Mat& backgroundImage) + private static native void getBackgroundImage_0(long nativeObj, long backgroundImage_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/video/BackgroundSubtractorKNN.java b/OpenCV/src/main/java/org/opencv/video/BackgroundSubtractorKNN.java new file mode 100644 index 00000000..fa6028b7 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/video/BackgroundSubtractorKNN.java @@ -0,0 +1,266 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.video; + +import org.opencv.video.BackgroundSubtractor; + +// C++: class BackgroundSubtractorKNN +//javadoc: BackgroundSubtractorKNN + +public class BackgroundSubtractorKNN extends BackgroundSubtractor { + + protected BackgroundSubtractorKNN(long addr) { super(addr); } + + // internal usage only + public static BackgroundSubtractorKNN __fromPtr__(long addr) { return new BackgroundSubtractorKNN(addr); } + + // + // C++: bool cv::BackgroundSubtractorKNN::getDetectShadows() + // + + //javadoc: BackgroundSubtractorKNN::getDetectShadows() + public boolean getDetectShadows() + { + + boolean retVal = getDetectShadows_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::BackgroundSubtractorKNN::getDist2Threshold() + // + + //javadoc: BackgroundSubtractorKNN::getDist2Threshold() + public double getDist2Threshold() + { + + double retVal = getDist2Threshold_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::BackgroundSubtractorKNN::getShadowThreshold() + // + + //javadoc: BackgroundSubtractorKNN::getShadowThreshold() + public double getShadowThreshold() + { + + double retVal = getShadowThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::BackgroundSubtractorKNN::getHistory() + // + + //javadoc: BackgroundSubtractorKNN::getHistory() + public int getHistory() + { + + int retVal = getHistory_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::BackgroundSubtractorKNN::getNSamples() + // + + //javadoc: BackgroundSubtractorKNN::getNSamples() + public int getNSamples() + { + + int retVal = getNSamples_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::BackgroundSubtractorKNN::getShadowValue() + // + + //javadoc: BackgroundSubtractorKNN::getShadowValue() + public int getShadowValue() + { + + int retVal = getShadowValue_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::BackgroundSubtractorKNN::getkNNSamples() + // + + //javadoc: BackgroundSubtractorKNN::getkNNSamples() + public int getkNNSamples() + { + + int retVal = getkNNSamples_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::BackgroundSubtractorKNN::setDetectShadows(bool detectShadows) + // + + //javadoc: BackgroundSubtractorKNN::setDetectShadows(detectShadows) + public void setDetectShadows(boolean detectShadows) + { + + setDetectShadows_0(nativeObj, detectShadows); + + return; + } + + + // + // C++: void cv::BackgroundSubtractorKNN::setDist2Threshold(double _dist2Threshold) + // + + //javadoc: BackgroundSubtractorKNN::setDist2Threshold(_dist2Threshold) + public void setDist2Threshold(double _dist2Threshold) + { + + setDist2Threshold_0(nativeObj, _dist2Threshold); + + return; + } + + + // + // C++: void cv::BackgroundSubtractorKNN::setHistory(int history) + // + + //javadoc: BackgroundSubtractorKNN::setHistory(history) + public void setHistory(int history) + { + + setHistory_0(nativeObj, history); + + return; + } + + + // + // C++: void cv::BackgroundSubtractorKNN::setNSamples(int _nN) + // + + //javadoc: BackgroundSubtractorKNN::setNSamples(_nN) + public void setNSamples(int _nN) + { + + setNSamples_0(nativeObj, _nN); + + return; + } + + + // + // C++: void cv::BackgroundSubtractorKNN::setShadowThreshold(double threshold) + // + + //javadoc: BackgroundSubtractorKNN::setShadowThreshold(threshold) + public void setShadowThreshold(double threshold) + { + + setShadowThreshold_0(nativeObj, threshold); + + return; + } + + + // + // C++: void cv::BackgroundSubtractorKNN::setShadowValue(int value) + // + + //javadoc: BackgroundSubtractorKNN::setShadowValue(value) + public void setShadowValue(int value) + { + + setShadowValue_0(nativeObj, value); + + return; + } + + + // + // C++: void cv::BackgroundSubtractorKNN::setkNNSamples(int _nkNN) + // + + //javadoc: BackgroundSubtractorKNN::setkNNSamples(_nkNN) + public void setkNNSamples(int _nkNN) + { + + setkNNSamples_0(nativeObj, _nkNN); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: bool cv::BackgroundSubtractorKNN::getDetectShadows() + private static native boolean getDetectShadows_0(long nativeObj); + + // C++: double cv::BackgroundSubtractorKNN::getDist2Threshold() + private static native double getDist2Threshold_0(long nativeObj); + + // C++: double cv::BackgroundSubtractorKNN::getShadowThreshold() + private static native double getShadowThreshold_0(long nativeObj); + + // C++: int cv::BackgroundSubtractorKNN::getHistory() + private static native int getHistory_0(long nativeObj); + + // C++: int cv::BackgroundSubtractorKNN::getNSamples() + private static native int getNSamples_0(long nativeObj); + + // C++: int cv::BackgroundSubtractorKNN::getShadowValue() + private static native int getShadowValue_0(long nativeObj); + + // C++: int cv::BackgroundSubtractorKNN::getkNNSamples() + private static native int getkNNSamples_0(long nativeObj); + + // C++: void cv::BackgroundSubtractorKNN::setDetectShadows(bool detectShadows) + private static native void setDetectShadows_0(long nativeObj, boolean detectShadows); + + // C++: void cv::BackgroundSubtractorKNN::setDist2Threshold(double _dist2Threshold) + private static native void setDist2Threshold_0(long nativeObj, double _dist2Threshold); + + // C++: void cv::BackgroundSubtractorKNN::setHistory(int history) + private static native void setHistory_0(long nativeObj, int history); + + // C++: void cv::BackgroundSubtractorKNN::setNSamples(int _nN) + private static native void setNSamples_0(long nativeObj, int _nN); + + // C++: void cv::BackgroundSubtractorKNN::setShadowThreshold(double threshold) + private static native void setShadowThreshold_0(long nativeObj, double threshold); + + // C++: void cv::BackgroundSubtractorKNN::setShadowValue(int value) + private static native void setShadowValue_0(long nativeObj, int value); + + // C++: void cv::BackgroundSubtractorKNN::setkNNSamples(int _nkNN) + private static native void setkNNSamples_0(long nativeObj, int _nkNN); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/video/BackgroundSubtractorMOG2.java b/OpenCV/src/main/java/org/opencv/video/BackgroundSubtractorMOG2.java new file mode 100644 index 00000000..47170403 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/video/BackgroundSubtractorMOG2.java @@ -0,0 +1,464 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.video; + +import org.opencv.core.Mat; +import org.opencv.video.BackgroundSubtractor; + +// C++: class BackgroundSubtractorMOG2 +//javadoc: BackgroundSubtractorMOG2 + +public class BackgroundSubtractorMOG2 extends BackgroundSubtractor { + + protected BackgroundSubtractorMOG2(long addr) { super(addr); } + + // internal usage only + public static BackgroundSubtractorMOG2 __fromPtr__(long addr) { return new BackgroundSubtractorMOG2(addr); } + + // + // C++: bool cv::BackgroundSubtractorMOG2::getDetectShadows() + // + + //javadoc: BackgroundSubtractorMOG2::getDetectShadows() + public boolean getDetectShadows() + { + + boolean retVal = getDetectShadows_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::BackgroundSubtractorMOG2::getBackgroundRatio() + // + + //javadoc: BackgroundSubtractorMOG2::getBackgroundRatio() + public double getBackgroundRatio() + { + + double retVal = getBackgroundRatio_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::BackgroundSubtractorMOG2::getComplexityReductionThreshold() + // + + //javadoc: BackgroundSubtractorMOG2::getComplexityReductionThreshold() + public double getComplexityReductionThreshold() + { + + double retVal = getComplexityReductionThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::BackgroundSubtractorMOG2::getShadowThreshold() + // + + //javadoc: BackgroundSubtractorMOG2::getShadowThreshold() + public double getShadowThreshold() + { + + double retVal = getShadowThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::BackgroundSubtractorMOG2::getVarInit() + // + + //javadoc: BackgroundSubtractorMOG2::getVarInit() + public double getVarInit() + { + + double retVal = getVarInit_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::BackgroundSubtractorMOG2::getVarMax() + // + + //javadoc: BackgroundSubtractorMOG2::getVarMax() + public double getVarMax() + { + + double retVal = getVarMax_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::BackgroundSubtractorMOG2::getVarMin() + // + + //javadoc: BackgroundSubtractorMOG2::getVarMin() + public double getVarMin() + { + + double retVal = getVarMin_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::BackgroundSubtractorMOG2::getVarThreshold() + // + + //javadoc: BackgroundSubtractorMOG2::getVarThreshold() + public double getVarThreshold() + { + + double retVal = getVarThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::BackgroundSubtractorMOG2::getVarThresholdGen() + // + + //javadoc: BackgroundSubtractorMOG2::getVarThresholdGen() + public double getVarThresholdGen() + { + + double retVal = getVarThresholdGen_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::BackgroundSubtractorMOG2::getHistory() + // + + //javadoc: BackgroundSubtractorMOG2::getHistory() + public int getHistory() + { + + int retVal = getHistory_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::BackgroundSubtractorMOG2::getNMixtures() + // + + //javadoc: BackgroundSubtractorMOG2::getNMixtures() + public int getNMixtures() + { + + int retVal = getNMixtures_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::BackgroundSubtractorMOG2::getShadowValue() + // + + //javadoc: BackgroundSubtractorMOG2::getShadowValue() + public int getShadowValue() + { + + int retVal = getShadowValue_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::BackgroundSubtractorMOG2::apply(Mat image, Mat& fgmask, double learningRate = -1) + // + + //javadoc: BackgroundSubtractorMOG2::apply(image, fgmask, learningRate) + public void apply(Mat image, Mat fgmask, double learningRate) + { + + apply_0(nativeObj, image.nativeObj, fgmask.nativeObj, learningRate); + + return; + } + + //javadoc: BackgroundSubtractorMOG2::apply(image, fgmask) + public void apply(Mat image, Mat fgmask) + { + + apply_1(nativeObj, image.nativeObj, fgmask.nativeObj); + + return; + } + + + // + // C++: void cv::BackgroundSubtractorMOG2::setBackgroundRatio(double ratio) + // + + //javadoc: BackgroundSubtractorMOG2::setBackgroundRatio(ratio) + public void setBackgroundRatio(double ratio) + { + + setBackgroundRatio_0(nativeObj, ratio); + + return; + } + + + // + // C++: void cv::BackgroundSubtractorMOG2::setComplexityReductionThreshold(double ct) + // + + //javadoc: BackgroundSubtractorMOG2::setComplexityReductionThreshold(ct) + public void setComplexityReductionThreshold(double ct) + { + + setComplexityReductionThreshold_0(nativeObj, ct); + + return; + } + + + // + // C++: void cv::BackgroundSubtractorMOG2::setDetectShadows(bool detectShadows) + // + + //javadoc: BackgroundSubtractorMOG2::setDetectShadows(detectShadows) + public void setDetectShadows(boolean detectShadows) + { + + setDetectShadows_0(nativeObj, detectShadows); + + return; + } + + + // + // C++: void cv::BackgroundSubtractorMOG2::setHistory(int history) + // + + //javadoc: BackgroundSubtractorMOG2::setHistory(history) + public void setHistory(int history) + { + + setHistory_0(nativeObj, history); + + return; + } + + + // + // C++: void cv::BackgroundSubtractorMOG2::setNMixtures(int nmixtures) + // + + //javadoc: BackgroundSubtractorMOG2::setNMixtures(nmixtures) + public void setNMixtures(int nmixtures) + { + + setNMixtures_0(nativeObj, nmixtures); + + return; + } + + + // + // C++: void cv::BackgroundSubtractorMOG2::setShadowThreshold(double threshold) + // + + //javadoc: BackgroundSubtractorMOG2::setShadowThreshold(threshold) + public void setShadowThreshold(double threshold) + { + + setShadowThreshold_0(nativeObj, threshold); + + return; + } + + + // + // C++: void cv::BackgroundSubtractorMOG2::setShadowValue(int value) + // + + //javadoc: BackgroundSubtractorMOG2::setShadowValue(value) + public void setShadowValue(int value) + { + + setShadowValue_0(nativeObj, value); + + return; + } + + + // + // C++: void cv::BackgroundSubtractorMOG2::setVarInit(double varInit) + // + + //javadoc: BackgroundSubtractorMOG2::setVarInit(varInit) + public void setVarInit(double varInit) + { + + setVarInit_0(nativeObj, varInit); + + return; + } + + + // + // C++: void cv::BackgroundSubtractorMOG2::setVarMax(double varMax) + // + + //javadoc: BackgroundSubtractorMOG2::setVarMax(varMax) + public void setVarMax(double varMax) + { + + setVarMax_0(nativeObj, varMax); + + return; + } + + + // + // C++: void cv::BackgroundSubtractorMOG2::setVarMin(double varMin) + // + + //javadoc: BackgroundSubtractorMOG2::setVarMin(varMin) + public void setVarMin(double varMin) + { + + setVarMin_0(nativeObj, varMin); + + return; + } + + + // + // C++: void cv::BackgroundSubtractorMOG2::setVarThreshold(double varThreshold) + // + + //javadoc: BackgroundSubtractorMOG2::setVarThreshold(varThreshold) + public void setVarThreshold(double varThreshold) + { + + setVarThreshold_0(nativeObj, varThreshold); + + return; + } + + + // + // C++: void cv::BackgroundSubtractorMOG2::setVarThresholdGen(double varThresholdGen) + // + + //javadoc: BackgroundSubtractorMOG2::setVarThresholdGen(varThresholdGen) + public void setVarThresholdGen(double varThresholdGen) + { + + setVarThresholdGen_0(nativeObj, varThresholdGen); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: bool cv::BackgroundSubtractorMOG2::getDetectShadows() + private static native boolean getDetectShadows_0(long nativeObj); + + // C++: double cv::BackgroundSubtractorMOG2::getBackgroundRatio() + private static native double getBackgroundRatio_0(long nativeObj); + + // C++: double cv::BackgroundSubtractorMOG2::getComplexityReductionThreshold() + private static native double getComplexityReductionThreshold_0(long nativeObj); + + // C++: double cv::BackgroundSubtractorMOG2::getShadowThreshold() + private static native double getShadowThreshold_0(long nativeObj); + + // C++: double cv::BackgroundSubtractorMOG2::getVarInit() + private static native double getVarInit_0(long nativeObj); + + // C++: double cv::BackgroundSubtractorMOG2::getVarMax() + private static native double getVarMax_0(long nativeObj); + + // C++: double cv::BackgroundSubtractorMOG2::getVarMin() + private static native double getVarMin_0(long nativeObj); + + // C++: double cv::BackgroundSubtractorMOG2::getVarThreshold() + private static native double getVarThreshold_0(long nativeObj); + + // C++: double cv::BackgroundSubtractorMOG2::getVarThresholdGen() + private static native double getVarThresholdGen_0(long nativeObj); + + // C++: int cv::BackgroundSubtractorMOG2::getHistory() + private static native int getHistory_0(long nativeObj); + + // C++: int cv::BackgroundSubtractorMOG2::getNMixtures() + private static native int getNMixtures_0(long nativeObj); + + // C++: int cv::BackgroundSubtractorMOG2::getShadowValue() + private static native int getShadowValue_0(long nativeObj); + + // C++: void cv::BackgroundSubtractorMOG2::apply(Mat image, Mat& fgmask, double learningRate = -1) + private static native void apply_0(long nativeObj, long image_nativeObj, long fgmask_nativeObj, double learningRate); + private static native void apply_1(long nativeObj, long image_nativeObj, long fgmask_nativeObj); + + // C++: void cv::BackgroundSubtractorMOG2::setBackgroundRatio(double ratio) + private static native void setBackgroundRatio_0(long nativeObj, double ratio); + + // C++: void cv::BackgroundSubtractorMOG2::setComplexityReductionThreshold(double ct) + private static native void setComplexityReductionThreshold_0(long nativeObj, double ct); + + // C++: void cv::BackgroundSubtractorMOG2::setDetectShadows(bool detectShadows) + private static native void setDetectShadows_0(long nativeObj, boolean detectShadows); + + // C++: void cv::BackgroundSubtractorMOG2::setHistory(int history) + private static native void setHistory_0(long nativeObj, int history); + + // C++: void cv::BackgroundSubtractorMOG2::setNMixtures(int nmixtures) + private static native void setNMixtures_0(long nativeObj, int nmixtures); + + // C++: void cv::BackgroundSubtractorMOG2::setShadowThreshold(double threshold) + private static native void setShadowThreshold_0(long nativeObj, double threshold); + + // C++: void cv::BackgroundSubtractorMOG2::setShadowValue(int value) + private static native void setShadowValue_0(long nativeObj, int value); + + // C++: void cv::BackgroundSubtractorMOG2::setVarInit(double varInit) + private static native void setVarInit_0(long nativeObj, double varInit); + + // C++: void cv::BackgroundSubtractorMOG2::setVarMax(double varMax) + private static native void setVarMax_0(long nativeObj, double varMax); + + // C++: void cv::BackgroundSubtractorMOG2::setVarMin(double varMin) + private static native void setVarMin_0(long nativeObj, double varMin); + + // C++: void cv::BackgroundSubtractorMOG2::setVarThreshold(double varThreshold) + private static native void setVarThreshold_0(long nativeObj, double varThreshold); + + // C++: void cv::BackgroundSubtractorMOG2::setVarThresholdGen(double varThresholdGen) + private static native void setVarThresholdGen_0(long nativeObj, double varThresholdGen); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/video/DISOpticalFlow.java b/OpenCV/src/main/java/org/opencv/video/DISOpticalFlow.java new file mode 100644 index 00000000..88baa8d1 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/video/DISOpticalFlow.java @@ -0,0 +1,403 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.video; + +import org.opencv.video.DISOpticalFlow; +import org.opencv.video.DenseOpticalFlow; + +// C++: class DISOpticalFlow +//javadoc: DISOpticalFlow + +public class DISOpticalFlow extends DenseOpticalFlow { + + protected DISOpticalFlow(long addr) { super(addr); } + + // internal usage only + public static DISOpticalFlow __fromPtr__(long addr) { return new DISOpticalFlow(addr); } + + // C++: enum + public static final int + PRESET_ULTRAFAST = 0, + PRESET_FAST = 1, + PRESET_MEDIUM = 2; + + + // + // C++: static Ptr_DISOpticalFlow cv::DISOpticalFlow::create(int preset = DISOpticalFlow::PRESET_FAST) + // + + //javadoc: DISOpticalFlow::create(preset) + public static DISOpticalFlow create(int preset) + { + + DISOpticalFlow retVal = DISOpticalFlow.__fromPtr__(create_0(preset)); + + return retVal; + } + + //javadoc: DISOpticalFlow::create() + public static DISOpticalFlow create() + { + + DISOpticalFlow retVal = DISOpticalFlow.__fromPtr__(create_1()); + + return retVal; + } + + + // + // C++: bool cv::DISOpticalFlow::getUseMeanNormalization() + // + + //javadoc: DISOpticalFlow::getUseMeanNormalization() + public boolean getUseMeanNormalization() + { + + boolean retVal = getUseMeanNormalization_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::DISOpticalFlow::getUseSpatialPropagation() + // + + //javadoc: DISOpticalFlow::getUseSpatialPropagation() + public boolean getUseSpatialPropagation() + { + + boolean retVal = getUseSpatialPropagation_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::DISOpticalFlow::getVariationalRefinementAlpha() + // + + //javadoc: DISOpticalFlow::getVariationalRefinementAlpha() + public float getVariationalRefinementAlpha() + { + + float retVal = getVariationalRefinementAlpha_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::DISOpticalFlow::getVariationalRefinementDelta() + // + + //javadoc: DISOpticalFlow::getVariationalRefinementDelta() + public float getVariationalRefinementDelta() + { + + float retVal = getVariationalRefinementDelta_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::DISOpticalFlow::getVariationalRefinementGamma() + // + + //javadoc: DISOpticalFlow::getVariationalRefinementGamma() + public float getVariationalRefinementGamma() + { + + float retVal = getVariationalRefinementGamma_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::DISOpticalFlow::getFinestScale() + // + + //javadoc: DISOpticalFlow::getFinestScale() + public int getFinestScale() + { + + int retVal = getFinestScale_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::DISOpticalFlow::getGradientDescentIterations() + // + + //javadoc: DISOpticalFlow::getGradientDescentIterations() + public int getGradientDescentIterations() + { + + int retVal = getGradientDescentIterations_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::DISOpticalFlow::getPatchSize() + // + + //javadoc: DISOpticalFlow::getPatchSize() + public int getPatchSize() + { + + int retVal = getPatchSize_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::DISOpticalFlow::getPatchStride() + // + + //javadoc: DISOpticalFlow::getPatchStride() + public int getPatchStride() + { + + int retVal = getPatchStride_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::DISOpticalFlow::getVariationalRefinementIterations() + // + + //javadoc: DISOpticalFlow::getVariationalRefinementIterations() + public int getVariationalRefinementIterations() + { + + int retVal = getVariationalRefinementIterations_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::DISOpticalFlow::setFinestScale(int val) + // + + //javadoc: DISOpticalFlow::setFinestScale(val) + public void setFinestScale(int val) + { + + setFinestScale_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::DISOpticalFlow::setGradientDescentIterations(int val) + // + + //javadoc: DISOpticalFlow::setGradientDescentIterations(val) + public void setGradientDescentIterations(int val) + { + + setGradientDescentIterations_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::DISOpticalFlow::setPatchSize(int val) + // + + //javadoc: DISOpticalFlow::setPatchSize(val) + public void setPatchSize(int val) + { + + setPatchSize_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::DISOpticalFlow::setPatchStride(int val) + // + + //javadoc: DISOpticalFlow::setPatchStride(val) + public void setPatchStride(int val) + { + + setPatchStride_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::DISOpticalFlow::setUseMeanNormalization(bool val) + // + + //javadoc: DISOpticalFlow::setUseMeanNormalization(val) + public void setUseMeanNormalization(boolean val) + { + + setUseMeanNormalization_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::DISOpticalFlow::setUseSpatialPropagation(bool val) + // + + //javadoc: DISOpticalFlow::setUseSpatialPropagation(val) + public void setUseSpatialPropagation(boolean val) + { + + setUseSpatialPropagation_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::DISOpticalFlow::setVariationalRefinementAlpha(float val) + // + + //javadoc: DISOpticalFlow::setVariationalRefinementAlpha(val) + public void setVariationalRefinementAlpha(float val) + { + + setVariationalRefinementAlpha_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::DISOpticalFlow::setVariationalRefinementDelta(float val) + // + + //javadoc: DISOpticalFlow::setVariationalRefinementDelta(val) + public void setVariationalRefinementDelta(float val) + { + + setVariationalRefinementDelta_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::DISOpticalFlow::setVariationalRefinementGamma(float val) + // + + //javadoc: DISOpticalFlow::setVariationalRefinementGamma(val) + public void setVariationalRefinementGamma(float val) + { + + setVariationalRefinementGamma_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::DISOpticalFlow::setVariationalRefinementIterations(int val) + // + + //javadoc: DISOpticalFlow::setVariationalRefinementIterations(val) + public void setVariationalRefinementIterations(int val) + { + + setVariationalRefinementIterations_0(nativeObj, val); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_DISOpticalFlow cv::DISOpticalFlow::create(int preset = DISOpticalFlow::PRESET_FAST) + private static native long create_0(int preset); + private static native long create_1(); + + // C++: bool cv::DISOpticalFlow::getUseMeanNormalization() + private static native boolean getUseMeanNormalization_0(long nativeObj); + + // C++: bool cv::DISOpticalFlow::getUseSpatialPropagation() + private static native boolean getUseSpatialPropagation_0(long nativeObj); + + // C++: float cv::DISOpticalFlow::getVariationalRefinementAlpha() + private static native float getVariationalRefinementAlpha_0(long nativeObj); + + // C++: float cv::DISOpticalFlow::getVariationalRefinementDelta() + private static native float getVariationalRefinementDelta_0(long nativeObj); + + // C++: float cv::DISOpticalFlow::getVariationalRefinementGamma() + private static native float getVariationalRefinementGamma_0(long nativeObj); + + // C++: int cv::DISOpticalFlow::getFinestScale() + private static native int getFinestScale_0(long nativeObj); + + // C++: int cv::DISOpticalFlow::getGradientDescentIterations() + private static native int getGradientDescentIterations_0(long nativeObj); + + // C++: int cv::DISOpticalFlow::getPatchSize() + private static native int getPatchSize_0(long nativeObj); + + // C++: int cv::DISOpticalFlow::getPatchStride() + private static native int getPatchStride_0(long nativeObj); + + // C++: int cv::DISOpticalFlow::getVariationalRefinementIterations() + private static native int getVariationalRefinementIterations_0(long nativeObj); + + // C++: void cv::DISOpticalFlow::setFinestScale(int val) + private static native void setFinestScale_0(long nativeObj, int val); + + // C++: void cv::DISOpticalFlow::setGradientDescentIterations(int val) + private static native void setGradientDescentIterations_0(long nativeObj, int val); + + // C++: void cv::DISOpticalFlow::setPatchSize(int val) + private static native void setPatchSize_0(long nativeObj, int val); + + // C++: void cv::DISOpticalFlow::setPatchStride(int val) + private static native void setPatchStride_0(long nativeObj, int val); + + // C++: void cv::DISOpticalFlow::setUseMeanNormalization(bool val) + private static native void setUseMeanNormalization_0(long nativeObj, boolean val); + + // C++: void cv::DISOpticalFlow::setUseSpatialPropagation(bool val) + private static native void setUseSpatialPropagation_0(long nativeObj, boolean val); + + // C++: void cv::DISOpticalFlow::setVariationalRefinementAlpha(float val) + private static native void setVariationalRefinementAlpha_0(long nativeObj, float val); + + // C++: void cv::DISOpticalFlow::setVariationalRefinementDelta(float val) + private static native void setVariationalRefinementDelta_0(long nativeObj, float val); + + // C++: void cv::DISOpticalFlow::setVariationalRefinementGamma(float val) + private static native void setVariationalRefinementGamma_0(long nativeObj, float val); + + // C++: void cv::DISOpticalFlow::setVariationalRefinementIterations(int val) + private static native void setVariationalRefinementIterations_0(long nativeObj, int val); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/video/DenseOpticalFlow.java b/OpenCV/src/main/java/org/opencv/video/DenseOpticalFlow.java new file mode 100644 index 00000000..760534cd --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/video/DenseOpticalFlow.java @@ -0,0 +1,63 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.video; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class DenseOpticalFlow +//javadoc: DenseOpticalFlow + +public class DenseOpticalFlow extends Algorithm { + + protected DenseOpticalFlow(long addr) { super(addr); } + + // internal usage only + public static DenseOpticalFlow __fromPtr__(long addr) { return new DenseOpticalFlow(addr); } + + // + // C++: void cv::DenseOpticalFlow::calc(Mat I0, Mat I1, Mat& flow) + // + + //javadoc: DenseOpticalFlow::calc(I0, I1, flow) + public void calc(Mat I0, Mat I1, Mat flow) + { + + calc_0(nativeObj, I0.nativeObj, I1.nativeObj, flow.nativeObj); + + return; + } + + + // + // C++: void cv::DenseOpticalFlow::collectGarbage() + // + + //javadoc: DenseOpticalFlow::collectGarbage() + public void collectGarbage() + { + + collectGarbage_0(nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::DenseOpticalFlow::calc(Mat I0, Mat I1, Mat& flow) + private static native void calc_0(long nativeObj, long I0_nativeObj, long I1_nativeObj, long flow_nativeObj); + + // C++: void cv::DenseOpticalFlow::collectGarbage() + private static native void collectGarbage_0(long nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/video/FarnebackOpticalFlow.java b/OpenCV/src/main/java/org/opencv/video/FarnebackOpticalFlow.java new file mode 100644 index 00000000..e1c9a4bc --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/video/FarnebackOpticalFlow.java @@ -0,0 +1,398 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.video; + +import org.opencv.video.DenseOpticalFlow; +import org.opencv.video.FarnebackOpticalFlow; + +// C++: class FarnebackOpticalFlow +//javadoc: FarnebackOpticalFlow + +public class FarnebackOpticalFlow extends DenseOpticalFlow { + + protected FarnebackOpticalFlow(long addr) { super(addr); } + + // internal usage only + public static FarnebackOpticalFlow __fromPtr__(long addr) { return new FarnebackOpticalFlow(addr); } + + // + // C++: static Ptr_FarnebackOpticalFlow cv::FarnebackOpticalFlow::create(int numLevels = 5, double pyrScale = 0.5, bool fastPyramids = false, int winSize = 13, int numIters = 10, int polyN = 5, double polySigma = 1.1, int flags = 0) + // + + //javadoc: FarnebackOpticalFlow::create(numLevels, pyrScale, fastPyramids, winSize, numIters, polyN, polySigma, flags) + public static FarnebackOpticalFlow create(int numLevels, double pyrScale, boolean fastPyramids, int winSize, int numIters, int polyN, double polySigma, int flags) + { + + FarnebackOpticalFlow retVal = FarnebackOpticalFlow.__fromPtr__(create_0(numLevels, pyrScale, fastPyramids, winSize, numIters, polyN, polySigma, flags)); + + return retVal; + } + + //javadoc: FarnebackOpticalFlow::create(numLevels, pyrScale, fastPyramids, winSize, numIters, polyN, polySigma) + public static FarnebackOpticalFlow create(int numLevels, double pyrScale, boolean fastPyramids, int winSize, int numIters, int polyN, double polySigma) + { + + FarnebackOpticalFlow retVal = FarnebackOpticalFlow.__fromPtr__(create_1(numLevels, pyrScale, fastPyramids, winSize, numIters, polyN, polySigma)); + + return retVal; + } + + //javadoc: FarnebackOpticalFlow::create(numLevels, pyrScale, fastPyramids, winSize, numIters, polyN) + public static FarnebackOpticalFlow create(int numLevels, double pyrScale, boolean fastPyramids, int winSize, int numIters, int polyN) + { + + FarnebackOpticalFlow retVal = FarnebackOpticalFlow.__fromPtr__(create_2(numLevels, pyrScale, fastPyramids, winSize, numIters, polyN)); + + return retVal; + } + + //javadoc: FarnebackOpticalFlow::create(numLevels, pyrScale, fastPyramids, winSize, numIters) + public static FarnebackOpticalFlow create(int numLevels, double pyrScale, boolean fastPyramids, int winSize, int numIters) + { + + FarnebackOpticalFlow retVal = FarnebackOpticalFlow.__fromPtr__(create_3(numLevels, pyrScale, fastPyramids, winSize, numIters)); + + return retVal; + } + + //javadoc: FarnebackOpticalFlow::create(numLevels, pyrScale, fastPyramids, winSize) + public static FarnebackOpticalFlow create(int numLevels, double pyrScale, boolean fastPyramids, int winSize) + { + + FarnebackOpticalFlow retVal = FarnebackOpticalFlow.__fromPtr__(create_4(numLevels, pyrScale, fastPyramids, winSize)); + + return retVal; + } + + //javadoc: FarnebackOpticalFlow::create(numLevels, pyrScale, fastPyramids) + public static FarnebackOpticalFlow create(int numLevels, double pyrScale, boolean fastPyramids) + { + + FarnebackOpticalFlow retVal = FarnebackOpticalFlow.__fromPtr__(create_5(numLevels, pyrScale, fastPyramids)); + + return retVal; + } + + //javadoc: FarnebackOpticalFlow::create(numLevels, pyrScale) + public static FarnebackOpticalFlow create(int numLevels, double pyrScale) + { + + FarnebackOpticalFlow retVal = FarnebackOpticalFlow.__fromPtr__(create_6(numLevels, pyrScale)); + + return retVal; + } + + //javadoc: FarnebackOpticalFlow::create(numLevels) + public static FarnebackOpticalFlow create(int numLevels) + { + + FarnebackOpticalFlow retVal = FarnebackOpticalFlow.__fromPtr__(create_7(numLevels)); + + return retVal; + } + + //javadoc: FarnebackOpticalFlow::create() + public static FarnebackOpticalFlow create() + { + + FarnebackOpticalFlow retVal = FarnebackOpticalFlow.__fromPtr__(create_8()); + + return retVal; + } + + + // + // C++: bool cv::FarnebackOpticalFlow::getFastPyramids() + // + + //javadoc: FarnebackOpticalFlow::getFastPyramids() + public boolean getFastPyramids() + { + + boolean retVal = getFastPyramids_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::FarnebackOpticalFlow::getPolySigma() + // + + //javadoc: FarnebackOpticalFlow::getPolySigma() + public double getPolySigma() + { + + double retVal = getPolySigma_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::FarnebackOpticalFlow::getPyrScale() + // + + //javadoc: FarnebackOpticalFlow::getPyrScale() + public double getPyrScale() + { + + double retVal = getPyrScale_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::FarnebackOpticalFlow::getFlags() + // + + //javadoc: FarnebackOpticalFlow::getFlags() + public int getFlags() + { + + int retVal = getFlags_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::FarnebackOpticalFlow::getNumIters() + // + + //javadoc: FarnebackOpticalFlow::getNumIters() + public int getNumIters() + { + + int retVal = getNumIters_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::FarnebackOpticalFlow::getNumLevels() + // + + //javadoc: FarnebackOpticalFlow::getNumLevels() + public int getNumLevels() + { + + int retVal = getNumLevels_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::FarnebackOpticalFlow::getPolyN() + // + + //javadoc: FarnebackOpticalFlow::getPolyN() + public int getPolyN() + { + + int retVal = getPolyN_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::FarnebackOpticalFlow::getWinSize() + // + + //javadoc: FarnebackOpticalFlow::getWinSize() + public int getWinSize() + { + + int retVal = getWinSize_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::FarnebackOpticalFlow::setFastPyramids(bool fastPyramids) + // + + //javadoc: FarnebackOpticalFlow::setFastPyramids(fastPyramids) + public void setFastPyramids(boolean fastPyramids) + { + + setFastPyramids_0(nativeObj, fastPyramids); + + return; + } + + + // + // C++: void cv::FarnebackOpticalFlow::setFlags(int flags) + // + + //javadoc: FarnebackOpticalFlow::setFlags(flags) + public void setFlags(int flags) + { + + setFlags_0(nativeObj, flags); + + return; + } + + + // + // C++: void cv::FarnebackOpticalFlow::setNumIters(int numIters) + // + + //javadoc: FarnebackOpticalFlow::setNumIters(numIters) + public void setNumIters(int numIters) + { + + setNumIters_0(nativeObj, numIters); + + return; + } + + + // + // C++: void cv::FarnebackOpticalFlow::setNumLevels(int numLevels) + // + + //javadoc: FarnebackOpticalFlow::setNumLevels(numLevels) + public void setNumLevels(int numLevels) + { + + setNumLevels_0(nativeObj, numLevels); + + return; + } + + + // + // C++: void cv::FarnebackOpticalFlow::setPolyN(int polyN) + // + + //javadoc: FarnebackOpticalFlow::setPolyN(polyN) + public void setPolyN(int polyN) + { + + setPolyN_0(nativeObj, polyN); + + return; + } + + + // + // C++: void cv::FarnebackOpticalFlow::setPolySigma(double polySigma) + // + + //javadoc: FarnebackOpticalFlow::setPolySigma(polySigma) + public void setPolySigma(double polySigma) + { + + setPolySigma_0(nativeObj, polySigma); + + return; + } + + + // + // C++: void cv::FarnebackOpticalFlow::setPyrScale(double pyrScale) + // + + //javadoc: FarnebackOpticalFlow::setPyrScale(pyrScale) + public void setPyrScale(double pyrScale) + { + + setPyrScale_0(nativeObj, pyrScale); + + return; + } + + + // + // C++: void cv::FarnebackOpticalFlow::setWinSize(int winSize) + // + + //javadoc: FarnebackOpticalFlow::setWinSize(winSize) + public void setWinSize(int winSize) + { + + setWinSize_0(nativeObj, winSize); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_FarnebackOpticalFlow cv::FarnebackOpticalFlow::create(int numLevels = 5, double pyrScale = 0.5, bool fastPyramids = false, int winSize = 13, int numIters = 10, int polyN = 5, double polySigma = 1.1, int flags = 0) + private static native long create_0(int numLevels, double pyrScale, boolean fastPyramids, int winSize, int numIters, int polyN, double polySigma, int flags); + private static native long create_1(int numLevels, double pyrScale, boolean fastPyramids, int winSize, int numIters, int polyN, double polySigma); + private static native long create_2(int numLevels, double pyrScale, boolean fastPyramids, int winSize, int numIters, int polyN); + private static native long create_3(int numLevels, double pyrScale, boolean fastPyramids, int winSize, int numIters); + private static native long create_4(int numLevels, double pyrScale, boolean fastPyramids, int winSize); + private static native long create_5(int numLevels, double pyrScale, boolean fastPyramids); + private static native long create_6(int numLevels, double pyrScale); + private static native long create_7(int numLevels); + private static native long create_8(); + + // C++: bool cv::FarnebackOpticalFlow::getFastPyramids() + private static native boolean getFastPyramids_0(long nativeObj); + + // C++: double cv::FarnebackOpticalFlow::getPolySigma() + private static native double getPolySigma_0(long nativeObj); + + // C++: double cv::FarnebackOpticalFlow::getPyrScale() + private static native double getPyrScale_0(long nativeObj); + + // C++: int cv::FarnebackOpticalFlow::getFlags() + private static native int getFlags_0(long nativeObj); + + // C++: int cv::FarnebackOpticalFlow::getNumIters() + private static native int getNumIters_0(long nativeObj); + + // C++: int cv::FarnebackOpticalFlow::getNumLevels() + private static native int getNumLevels_0(long nativeObj); + + // C++: int cv::FarnebackOpticalFlow::getPolyN() + private static native int getPolyN_0(long nativeObj); + + // C++: int cv::FarnebackOpticalFlow::getWinSize() + private static native int getWinSize_0(long nativeObj); + + // C++: void cv::FarnebackOpticalFlow::setFastPyramids(bool fastPyramids) + private static native void setFastPyramids_0(long nativeObj, boolean fastPyramids); + + // C++: void cv::FarnebackOpticalFlow::setFlags(int flags) + private static native void setFlags_0(long nativeObj, int flags); + + // C++: void cv::FarnebackOpticalFlow::setNumIters(int numIters) + private static native void setNumIters_0(long nativeObj, int numIters); + + // C++: void cv::FarnebackOpticalFlow::setNumLevels(int numLevels) + private static native void setNumLevels_0(long nativeObj, int numLevels); + + // C++: void cv::FarnebackOpticalFlow::setPolyN(int polyN) + private static native void setPolyN_0(long nativeObj, int polyN); + + // C++: void cv::FarnebackOpticalFlow::setPolySigma(double polySigma) + private static native void setPolySigma_0(long nativeObj, double polySigma); + + // C++: void cv::FarnebackOpticalFlow::setPyrScale(double pyrScale) + private static native void setPyrScale_0(long nativeObj, double pyrScale); + + // C++: void cv::FarnebackOpticalFlow::setWinSize(int winSize) + private static native void setWinSize_0(long nativeObj, int winSize); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/video/KalmanFilter.java b/OpenCV/src/main/java/org/opencv/video/KalmanFilter.java new file mode 100644 index 00000000..91771b7e --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/video/KalmanFilter.java @@ -0,0 +1,469 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.video; + +import org.opencv.core.Mat; + +// C++: class KalmanFilter +//javadoc: KalmanFilter + +public class KalmanFilter { + + protected final long nativeObj; + protected KalmanFilter(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static KalmanFilter __fromPtr__(long addr) { return new KalmanFilter(addr); } + + // + // C++: cv::KalmanFilter::KalmanFilter(int dynamParams, int measureParams, int controlParams = 0, int type = CV_32F) + // + + //javadoc: KalmanFilter::KalmanFilter(dynamParams, measureParams, controlParams, type) + public KalmanFilter(int dynamParams, int measureParams, int controlParams, int type) + { + + nativeObj = KalmanFilter_0(dynamParams, measureParams, controlParams, type); + + return; + } + + //javadoc: KalmanFilter::KalmanFilter(dynamParams, measureParams, controlParams) + public KalmanFilter(int dynamParams, int measureParams, int controlParams) + { + + nativeObj = KalmanFilter_1(dynamParams, measureParams, controlParams); + + return; + } + + //javadoc: KalmanFilter::KalmanFilter(dynamParams, measureParams) + public KalmanFilter(int dynamParams, int measureParams) + { + + nativeObj = KalmanFilter_2(dynamParams, measureParams); + + return; + } + + + // + // C++: cv::KalmanFilter::KalmanFilter() + // + + //javadoc: KalmanFilter::KalmanFilter() + public KalmanFilter() + { + + nativeObj = KalmanFilter_3(); + + return; + } + + + // + // C++: Mat cv::KalmanFilter::correct(Mat measurement) + // + + //javadoc: KalmanFilter::correct(measurement) + public Mat correct(Mat measurement) + { + + Mat retVal = new Mat(correct_0(nativeObj, measurement.nativeObj)); + + return retVal; + } + + + // + // C++: Mat cv::KalmanFilter::predict(Mat control = Mat()) + // + + //javadoc: KalmanFilter::predict(control) + public Mat predict(Mat control) + { + + Mat retVal = new Mat(predict_0(nativeObj, control.nativeObj)); + + return retVal; + } + + //javadoc: KalmanFilter::predict() + public Mat predict() + { + + Mat retVal = new Mat(predict_1(nativeObj)); + + return retVal; + } + + + // + // C++: Mat KalmanFilter::statePre + // + + //javadoc: KalmanFilter::get_statePre() + public Mat get_statePre() + { + + Mat retVal = new Mat(get_statePre_0(nativeObj)); + + return retVal; + } + + + // + // C++: void KalmanFilter::statePre + // + + //javadoc: KalmanFilter::set_statePre(statePre) + public void set_statePre(Mat statePre) + { + + set_statePre_0(nativeObj, statePre.nativeObj); + + return; + } + + + // + // C++: Mat KalmanFilter::statePost + // + + //javadoc: KalmanFilter::get_statePost() + public Mat get_statePost() + { + + Mat retVal = new Mat(get_statePost_0(nativeObj)); + + return retVal; + } + + + // + // C++: void KalmanFilter::statePost + // + + //javadoc: KalmanFilter::set_statePost(statePost) + public void set_statePost(Mat statePost) + { + + set_statePost_0(nativeObj, statePost.nativeObj); + + return; + } + + + // + // C++: Mat KalmanFilter::transitionMatrix + // + + //javadoc: KalmanFilter::get_transitionMatrix() + public Mat get_transitionMatrix() + { + + Mat retVal = new Mat(get_transitionMatrix_0(nativeObj)); + + return retVal; + } + + + // + // C++: void KalmanFilter::transitionMatrix + // + + //javadoc: KalmanFilter::set_transitionMatrix(transitionMatrix) + public void set_transitionMatrix(Mat transitionMatrix) + { + + set_transitionMatrix_0(nativeObj, transitionMatrix.nativeObj); + + return; + } + + + // + // C++: Mat KalmanFilter::controlMatrix + // + + //javadoc: KalmanFilter::get_controlMatrix() + public Mat get_controlMatrix() + { + + Mat retVal = new Mat(get_controlMatrix_0(nativeObj)); + + return retVal; + } + + + // + // C++: void KalmanFilter::controlMatrix + // + + //javadoc: KalmanFilter::set_controlMatrix(controlMatrix) + public void set_controlMatrix(Mat controlMatrix) + { + + set_controlMatrix_0(nativeObj, controlMatrix.nativeObj); + + return; + } + + + // + // C++: Mat KalmanFilter::measurementMatrix + // + + //javadoc: KalmanFilter::get_measurementMatrix() + public Mat get_measurementMatrix() + { + + Mat retVal = new Mat(get_measurementMatrix_0(nativeObj)); + + return retVal; + } + + + // + // C++: void KalmanFilter::measurementMatrix + // + + //javadoc: KalmanFilter::set_measurementMatrix(measurementMatrix) + public void set_measurementMatrix(Mat measurementMatrix) + { + + set_measurementMatrix_0(nativeObj, measurementMatrix.nativeObj); + + return; + } + + + // + // C++: Mat KalmanFilter::processNoiseCov + // + + //javadoc: KalmanFilter::get_processNoiseCov() + public Mat get_processNoiseCov() + { + + Mat retVal = new Mat(get_processNoiseCov_0(nativeObj)); + + return retVal; + } + + + // + // C++: void KalmanFilter::processNoiseCov + // + + //javadoc: KalmanFilter::set_processNoiseCov(processNoiseCov) + public void set_processNoiseCov(Mat processNoiseCov) + { + + set_processNoiseCov_0(nativeObj, processNoiseCov.nativeObj); + + return; + } + + + // + // C++: Mat KalmanFilter::measurementNoiseCov + // + + //javadoc: KalmanFilter::get_measurementNoiseCov() + public Mat get_measurementNoiseCov() + { + + Mat retVal = new Mat(get_measurementNoiseCov_0(nativeObj)); + + return retVal; + } + + + // + // C++: void KalmanFilter::measurementNoiseCov + // + + //javadoc: KalmanFilter::set_measurementNoiseCov(measurementNoiseCov) + public void set_measurementNoiseCov(Mat measurementNoiseCov) + { + + set_measurementNoiseCov_0(nativeObj, measurementNoiseCov.nativeObj); + + return; + } + + + // + // C++: Mat KalmanFilter::errorCovPre + // + + //javadoc: KalmanFilter::get_errorCovPre() + public Mat get_errorCovPre() + { + + Mat retVal = new Mat(get_errorCovPre_0(nativeObj)); + + return retVal; + } + + + // + // C++: void KalmanFilter::errorCovPre + // + + //javadoc: KalmanFilter::set_errorCovPre(errorCovPre) + public void set_errorCovPre(Mat errorCovPre) + { + + set_errorCovPre_0(nativeObj, errorCovPre.nativeObj); + + return; + } + + + // + // C++: Mat KalmanFilter::gain + // + + //javadoc: KalmanFilter::get_gain() + public Mat get_gain() + { + + Mat retVal = new Mat(get_gain_0(nativeObj)); + + return retVal; + } + + + // + // C++: void KalmanFilter::gain + // + + //javadoc: KalmanFilter::set_gain(gain) + public void set_gain(Mat gain) + { + + set_gain_0(nativeObj, gain.nativeObj); + + return; + } + + + // + // C++: Mat KalmanFilter::errorCovPost + // + + //javadoc: KalmanFilter::get_errorCovPost() + public Mat get_errorCovPost() + { + + Mat retVal = new Mat(get_errorCovPost_0(nativeObj)); + + return retVal; + } + + + // + // C++: void KalmanFilter::errorCovPost + // + + //javadoc: KalmanFilter::set_errorCovPost(errorCovPost) + public void set_errorCovPost(Mat errorCovPost) + { + + set_errorCovPost_0(nativeObj, errorCovPost.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: cv::KalmanFilter::KalmanFilter(int dynamParams, int measureParams, int controlParams = 0, int type = CV_32F) + private static native long KalmanFilter_0(int dynamParams, int measureParams, int controlParams, int type); + private static native long KalmanFilter_1(int dynamParams, int measureParams, int controlParams); + private static native long KalmanFilter_2(int dynamParams, int measureParams); + + // C++: cv::KalmanFilter::KalmanFilter() + private static native long KalmanFilter_3(); + + // C++: Mat cv::KalmanFilter::correct(Mat measurement) + private static native long correct_0(long nativeObj, long measurement_nativeObj); + + // C++: Mat cv::KalmanFilter::predict(Mat control = Mat()) + private static native long predict_0(long nativeObj, long control_nativeObj); + private static native long predict_1(long nativeObj); + + // C++: Mat KalmanFilter::statePre + private static native long get_statePre_0(long nativeObj); + + // C++: void KalmanFilter::statePre + private static native void set_statePre_0(long nativeObj, long statePre_nativeObj); + + // C++: Mat KalmanFilter::statePost + private static native long get_statePost_0(long nativeObj); + + // C++: void KalmanFilter::statePost + private static native void set_statePost_0(long nativeObj, long statePost_nativeObj); + + // C++: Mat KalmanFilter::transitionMatrix + private static native long get_transitionMatrix_0(long nativeObj); + + // C++: void KalmanFilter::transitionMatrix + private static native void set_transitionMatrix_0(long nativeObj, long transitionMatrix_nativeObj); + + // C++: Mat KalmanFilter::controlMatrix + private static native long get_controlMatrix_0(long nativeObj); + + // C++: void KalmanFilter::controlMatrix + private static native void set_controlMatrix_0(long nativeObj, long controlMatrix_nativeObj); + + // C++: Mat KalmanFilter::measurementMatrix + private static native long get_measurementMatrix_0(long nativeObj); + + // C++: void KalmanFilter::measurementMatrix + private static native void set_measurementMatrix_0(long nativeObj, long measurementMatrix_nativeObj); + + // C++: Mat KalmanFilter::processNoiseCov + private static native long get_processNoiseCov_0(long nativeObj); + + // C++: void KalmanFilter::processNoiseCov + private static native void set_processNoiseCov_0(long nativeObj, long processNoiseCov_nativeObj); + + // C++: Mat KalmanFilter::measurementNoiseCov + private static native long get_measurementNoiseCov_0(long nativeObj); + + // C++: void KalmanFilter::measurementNoiseCov + private static native void set_measurementNoiseCov_0(long nativeObj, long measurementNoiseCov_nativeObj); + + // C++: Mat KalmanFilter::errorCovPre + private static native long get_errorCovPre_0(long nativeObj); + + // C++: void KalmanFilter::errorCovPre + private static native void set_errorCovPre_0(long nativeObj, long errorCovPre_nativeObj); + + // C++: Mat KalmanFilter::gain + private static native long get_gain_0(long nativeObj); + + // C++: void KalmanFilter::gain + private static native void set_gain_0(long nativeObj, long gain_nativeObj); + + // C++: Mat KalmanFilter::errorCovPost + private static native long get_errorCovPost_0(long nativeObj); + + // C++: void KalmanFilter::errorCovPost + private static native void set_errorCovPost_0(long nativeObj, long errorCovPost_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/video/SparseOpticalFlow.java b/OpenCV/src/main/java/org/opencv/video/SparseOpticalFlow.java new file mode 100644 index 00000000..dba7b724 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/video/SparseOpticalFlow.java @@ -0,0 +1,56 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.video; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class SparseOpticalFlow +//javadoc: SparseOpticalFlow + +public class SparseOpticalFlow extends Algorithm { + + protected SparseOpticalFlow(long addr) { super(addr); } + + // internal usage only + public static SparseOpticalFlow __fromPtr__(long addr) { return new SparseOpticalFlow(addr); } + + // + // C++: void cv::SparseOpticalFlow::calc(Mat prevImg, Mat nextImg, Mat prevPts, Mat& nextPts, Mat& status, Mat& err = cv::Mat()) + // + + //javadoc: SparseOpticalFlow::calc(prevImg, nextImg, prevPts, nextPts, status, err) + public void calc(Mat prevImg, Mat nextImg, Mat prevPts, Mat nextPts, Mat status, Mat err) + { + + calc_0(nativeObj, prevImg.nativeObj, nextImg.nativeObj, prevPts.nativeObj, nextPts.nativeObj, status.nativeObj, err.nativeObj); + + return; + } + + //javadoc: SparseOpticalFlow::calc(prevImg, nextImg, prevPts, nextPts, status) + public void calc(Mat prevImg, Mat nextImg, Mat prevPts, Mat nextPts, Mat status) + { + + calc_1(nativeObj, prevImg.nativeObj, nextImg.nativeObj, prevPts.nativeObj, nextPts.nativeObj, status.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::SparseOpticalFlow::calc(Mat prevImg, Mat nextImg, Mat prevPts, Mat& nextPts, Mat& status, Mat& err = cv::Mat()) + private static native void calc_0(long nativeObj, long prevImg_nativeObj, long nextImg_nativeObj, long prevPts_nativeObj, long nextPts_nativeObj, long status_nativeObj, long err_nativeObj); + private static native void calc_1(long nativeObj, long prevImg_nativeObj, long nextImg_nativeObj, long prevPts_nativeObj, long nextPts_nativeObj, long status_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/video/SparsePyrLKOpticalFlow.java b/OpenCV/src/main/java/org/opencv/video/SparsePyrLKOpticalFlow.java new file mode 100644 index 00000000..9f1a1228 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/video/SparsePyrLKOpticalFlow.java @@ -0,0 +1,268 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.video; + +import org.opencv.core.Size; +import org.opencv.core.TermCriteria; +import org.opencv.video.SparseOpticalFlow; +import org.opencv.video.SparsePyrLKOpticalFlow; + +// C++: class SparsePyrLKOpticalFlow +//javadoc: SparsePyrLKOpticalFlow + +public class SparsePyrLKOpticalFlow extends SparseOpticalFlow { + + protected SparsePyrLKOpticalFlow(long addr) { super(addr); } + + // internal usage only + public static SparsePyrLKOpticalFlow __fromPtr__(long addr) { return new SparsePyrLKOpticalFlow(addr); } + + // + // C++: static Ptr_SparsePyrLKOpticalFlow cv::SparsePyrLKOpticalFlow::create(Size winSize = Size(21, 21), int maxLevel = 3, TermCriteria crit = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01), int flags = 0, double minEigThreshold = 1e-4) + // + + //javadoc: SparsePyrLKOpticalFlow::create(winSize, maxLevel, crit, flags, minEigThreshold) + public static SparsePyrLKOpticalFlow create(Size winSize, int maxLevel, TermCriteria crit, int flags, double minEigThreshold) + { + + SparsePyrLKOpticalFlow retVal = SparsePyrLKOpticalFlow.__fromPtr__(create_0(winSize.width, winSize.height, maxLevel, crit.type, crit.maxCount, crit.epsilon, flags, minEigThreshold)); + + return retVal; + } + + //javadoc: SparsePyrLKOpticalFlow::create(winSize, maxLevel, crit, flags) + public static SparsePyrLKOpticalFlow create(Size winSize, int maxLevel, TermCriteria crit, int flags) + { + + SparsePyrLKOpticalFlow retVal = SparsePyrLKOpticalFlow.__fromPtr__(create_1(winSize.width, winSize.height, maxLevel, crit.type, crit.maxCount, crit.epsilon, flags)); + + return retVal; + } + + //javadoc: SparsePyrLKOpticalFlow::create(winSize, maxLevel, crit) + public static SparsePyrLKOpticalFlow create(Size winSize, int maxLevel, TermCriteria crit) + { + + SparsePyrLKOpticalFlow retVal = SparsePyrLKOpticalFlow.__fromPtr__(create_2(winSize.width, winSize.height, maxLevel, crit.type, crit.maxCount, crit.epsilon)); + + return retVal; + } + + //javadoc: SparsePyrLKOpticalFlow::create(winSize, maxLevel) + public static SparsePyrLKOpticalFlow create(Size winSize, int maxLevel) + { + + SparsePyrLKOpticalFlow retVal = SparsePyrLKOpticalFlow.__fromPtr__(create_3(winSize.width, winSize.height, maxLevel)); + + return retVal; + } + + //javadoc: SparsePyrLKOpticalFlow::create(winSize) + public static SparsePyrLKOpticalFlow create(Size winSize) + { + + SparsePyrLKOpticalFlow retVal = SparsePyrLKOpticalFlow.__fromPtr__(create_4(winSize.width, winSize.height)); + + return retVal; + } + + //javadoc: SparsePyrLKOpticalFlow::create() + public static SparsePyrLKOpticalFlow create() + { + + SparsePyrLKOpticalFlow retVal = SparsePyrLKOpticalFlow.__fromPtr__(create_5()); + + return retVal; + } + + + // + // C++: Size cv::SparsePyrLKOpticalFlow::getWinSize() + // + + //javadoc: SparsePyrLKOpticalFlow::getWinSize() + public Size getWinSize() + { + + Size retVal = new Size(getWinSize_0(nativeObj)); + + return retVal; + } + + + // + // C++: TermCriteria cv::SparsePyrLKOpticalFlow::getTermCriteria() + // + + //javadoc: SparsePyrLKOpticalFlow::getTermCriteria() + public TermCriteria getTermCriteria() + { + + TermCriteria retVal = new TermCriteria(getTermCriteria_0(nativeObj)); + + return retVal; + } + + + // + // C++: double cv::SparsePyrLKOpticalFlow::getMinEigThreshold() + // + + //javadoc: SparsePyrLKOpticalFlow::getMinEigThreshold() + public double getMinEigThreshold() + { + + double retVal = getMinEigThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::SparsePyrLKOpticalFlow::getFlags() + // + + //javadoc: SparsePyrLKOpticalFlow::getFlags() + public int getFlags() + { + + int retVal = getFlags_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::SparsePyrLKOpticalFlow::getMaxLevel() + // + + //javadoc: SparsePyrLKOpticalFlow::getMaxLevel() + public int getMaxLevel() + { + + int retVal = getMaxLevel_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::SparsePyrLKOpticalFlow::setFlags(int flags) + // + + //javadoc: SparsePyrLKOpticalFlow::setFlags(flags) + public void setFlags(int flags) + { + + setFlags_0(nativeObj, flags); + + return; + } + + + // + // C++: void cv::SparsePyrLKOpticalFlow::setMaxLevel(int maxLevel) + // + + //javadoc: SparsePyrLKOpticalFlow::setMaxLevel(maxLevel) + public void setMaxLevel(int maxLevel) + { + + setMaxLevel_0(nativeObj, maxLevel); + + return; + } + + + // + // C++: void cv::SparsePyrLKOpticalFlow::setMinEigThreshold(double minEigThreshold) + // + + //javadoc: SparsePyrLKOpticalFlow::setMinEigThreshold(minEigThreshold) + public void setMinEigThreshold(double minEigThreshold) + { + + setMinEigThreshold_0(nativeObj, minEigThreshold); + + return; + } + + + // + // C++: void cv::SparsePyrLKOpticalFlow::setTermCriteria(TermCriteria crit) + // + + //javadoc: SparsePyrLKOpticalFlow::setTermCriteria(crit) + public void setTermCriteria(TermCriteria crit) + { + + setTermCriteria_0(nativeObj, crit.type, crit.maxCount, crit.epsilon); + + return; + } + + + // + // C++: void cv::SparsePyrLKOpticalFlow::setWinSize(Size winSize) + // + + //javadoc: SparsePyrLKOpticalFlow::setWinSize(winSize) + public void setWinSize(Size winSize) + { + + setWinSize_0(nativeObj, winSize.width, winSize.height); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_SparsePyrLKOpticalFlow cv::SparsePyrLKOpticalFlow::create(Size winSize = Size(21, 21), int maxLevel = 3, TermCriteria crit = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01), int flags = 0, double minEigThreshold = 1e-4) + private static native long create_0(double winSize_width, double winSize_height, int maxLevel, int crit_type, int crit_maxCount, double crit_epsilon, int flags, double minEigThreshold); + private static native long create_1(double winSize_width, double winSize_height, int maxLevel, int crit_type, int crit_maxCount, double crit_epsilon, int flags); + private static native long create_2(double winSize_width, double winSize_height, int maxLevel, int crit_type, int crit_maxCount, double crit_epsilon); + private static native long create_3(double winSize_width, double winSize_height, int maxLevel); + private static native long create_4(double winSize_width, double winSize_height); + private static native long create_5(); + + // C++: Size cv::SparsePyrLKOpticalFlow::getWinSize() + private static native double[] getWinSize_0(long nativeObj); + + // C++: TermCriteria cv::SparsePyrLKOpticalFlow::getTermCriteria() + private static native double[] getTermCriteria_0(long nativeObj); + + // C++: double cv::SparsePyrLKOpticalFlow::getMinEigThreshold() + private static native double getMinEigThreshold_0(long nativeObj); + + // C++: int cv::SparsePyrLKOpticalFlow::getFlags() + private static native int getFlags_0(long nativeObj); + + // C++: int cv::SparsePyrLKOpticalFlow::getMaxLevel() + private static native int getMaxLevel_0(long nativeObj); + + // C++: void cv::SparsePyrLKOpticalFlow::setFlags(int flags) + private static native void setFlags_0(long nativeObj, int flags); + + // C++: void cv::SparsePyrLKOpticalFlow::setMaxLevel(int maxLevel) + private static native void setMaxLevel_0(long nativeObj, int maxLevel); + + // C++: void cv::SparsePyrLKOpticalFlow::setMinEigThreshold(double minEigThreshold) + private static native void setMinEigThreshold_0(long nativeObj, double minEigThreshold); + + // C++: void cv::SparsePyrLKOpticalFlow::setTermCriteria(TermCriteria crit) + private static native void setTermCriteria_0(long nativeObj, int crit_type, int crit_maxCount, double crit_epsilon); + + // C++: void cv::SparsePyrLKOpticalFlow::setWinSize(Size winSize) + private static native void setWinSize_0(long nativeObj, double winSize_width, double winSize_height); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/video/VariationalRefinement.java b/OpenCV/src/main/java/org/opencv/video/VariationalRefinement.java new file mode 100644 index 00000000..0b2c64a0 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/video/VariationalRefinement.java @@ -0,0 +1,268 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.video; + +import org.opencv.core.Mat; +import org.opencv.video.DenseOpticalFlow; +import org.opencv.video.VariationalRefinement; + +// C++: class VariationalRefinement +//javadoc: VariationalRefinement + +public class VariationalRefinement extends DenseOpticalFlow { + + protected VariationalRefinement(long addr) { super(addr); } + + // internal usage only + public static VariationalRefinement __fromPtr__(long addr) { return new VariationalRefinement(addr); } + + // + // C++: static Ptr_VariationalRefinement cv::VariationalRefinement::create() + // + + //javadoc: VariationalRefinement::create() + public static VariationalRefinement create() + { + + VariationalRefinement retVal = VariationalRefinement.__fromPtr__(create_0()); + + return retVal; + } + + + // + // C++: float cv::VariationalRefinement::getAlpha() + // + + //javadoc: VariationalRefinement::getAlpha() + public float getAlpha() + { + + float retVal = getAlpha_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::VariationalRefinement::getDelta() + // + + //javadoc: VariationalRefinement::getDelta() + public float getDelta() + { + + float retVal = getDelta_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::VariationalRefinement::getGamma() + // + + //javadoc: VariationalRefinement::getGamma() + public float getGamma() + { + + float retVal = getGamma_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::VariationalRefinement::getOmega() + // + + //javadoc: VariationalRefinement::getOmega() + public float getOmega() + { + + float retVal = getOmega_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::VariationalRefinement::getFixedPointIterations() + // + + //javadoc: VariationalRefinement::getFixedPointIterations() + public int getFixedPointIterations() + { + + int retVal = getFixedPointIterations_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::VariationalRefinement::getSorIterations() + // + + //javadoc: VariationalRefinement::getSorIterations() + public int getSorIterations() + { + + int retVal = getSorIterations_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::VariationalRefinement::calcUV(Mat I0, Mat I1, Mat& flow_u, Mat& flow_v) + // + + //javadoc: VariationalRefinement::calcUV(I0, I1, flow_u, flow_v) + public void calcUV(Mat I0, Mat I1, Mat flow_u, Mat flow_v) + { + + calcUV_0(nativeObj, I0.nativeObj, I1.nativeObj, flow_u.nativeObj, flow_v.nativeObj); + + return; + } + + + // + // C++: void cv::VariationalRefinement::setAlpha(float val) + // + + //javadoc: VariationalRefinement::setAlpha(val) + public void setAlpha(float val) + { + + setAlpha_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::VariationalRefinement::setDelta(float val) + // + + //javadoc: VariationalRefinement::setDelta(val) + public void setDelta(float val) + { + + setDelta_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::VariationalRefinement::setFixedPointIterations(int val) + // + + //javadoc: VariationalRefinement::setFixedPointIterations(val) + public void setFixedPointIterations(int val) + { + + setFixedPointIterations_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::VariationalRefinement::setGamma(float val) + // + + //javadoc: VariationalRefinement::setGamma(val) + public void setGamma(float val) + { + + setGamma_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::VariationalRefinement::setOmega(float val) + // + + //javadoc: VariationalRefinement::setOmega(val) + public void setOmega(float val) + { + + setOmega_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::VariationalRefinement::setSorIterations(int val) + // + + //javadoc: VariationalRefinement::setSorIterations(val) + public void setSorIterations(int val) + { + + setSorIterations_0(nativeObj, val); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_VariationalRefinement cv::VariationalRefinement::create() + private static native long create_0(); + + // C++: float cv::VariationalRefinement::getAlpha() + private static native float getAlpha_0(long nativeObj); + + // C++: float cv::VariationalRefinement::getDelta() + private static native float getDelta_0(long nativeObj); + + // C++: float cv::VariationalRefinement::getGamma() + private static native float getGamma_0(long nativeObj); + + // C++: float cv::VariationalRefinement::getOmega() + private static native float getOmega_0(long nativeObj); + + // C++: int cv::VariationalRefinement::getFixedPointIterations() + private static native int getFixedPointIterations_0(long nativeObj); + + // C++: int cv::VariationalRefinement::getSorIterations() + private static native int getSorIterations_0(long nativeObj); + + // C++: void cv::VariationalRefinement::calcUV(Mat I0, Mat I1, Mat& flow_u, Mat& flow_v) + private static native void calcUV_0(long nativeObj, long I0_nativeObj, long I1_nativeObj, long flow_u_nativeObj, long flow_v_nativeObj); + + // C++: void cv::VariationalRefinement::setAlpha(float val) + private static native void setAlpha_0(long nativeObj, float val); + + // C++: void cv::VariationalRefinement::setDelta(float val) + private static native void setDelta_0(long nativeObj, float val); + + // C++: void cv::VariationalRefinement::setFixedPointIterations(int val) + private static native void setFixedPointIterations_0(long nativeObj, int val); + + // C++: void cv::VariationalRefinement::setGamma(float val) + private static native void setGamma_0(long nativeObj, float val); + + // C++: void cv::VariationalRefinement::setOmega(float val) + private static native void setOmega_0(long nativeObj, float val); + + // C++: void cv::VariationalRefinement::setSorIterations(int val) + private static native void setSorIterations_0(long nativeObj, int val); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/video/Video.java b/OpenCV/src/main/java/org/opencv/video/Video.java new file mode 100644 index 00000000..4268a30c --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/video/Video.java @@ -0,0 +1,414 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.video; + +import java.lang.String; +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfByte; +import org.opencv.core.MatOfFloat; +import org.opencv.core.MatOfPoint2f; +import org.opencv.core.Rect; +import org.opencv.core.RotatedRect; +import org.opencv.core.Size; +import org.opencv.core.TermCriteria; +import org.opencv.utils.Converters; +import org.opencv.video.BackgroundSubtractorKNN; +import org.opencv.video.BackgroundSubtractorMOG2; + +// C++: class Video +//javadoc: Video + +public class Video { + + private static final int + CV_LKFLOW_INITIAL_GUESSES = 4, + CV_LKFLOW_GET_MIN_EIGENVALS = 8; + + + // C++: enum + public static final int + OPTFLOW_USE_INITIAL_FLOW = 4, + OPTFLOW_LK_GET_MIN_EIGENVALS = 8, + OPTFLOW_FARNEBACK_GAUSSIAN = 256, + MOTION_TRANSLATION = 0, + MOTION_EUCLIDEAN = 1, + MOTION_AFFINE = 2, + MOTION_HOMOGRAPHY = 3; + + + // + // C++: Mat cv::readOpticalFlow(String path) + // + + //javadoc: readOpticalFlow(path) + public static Mat readOpticalFlow(String path) + { + + Mat retVal = new Mat(readOpticalFlow_0(path)); + + return retVal; + } + + + // + // C++: Ptr_BackgroundSubtractorKNN cv::createBackgroundSubtractorKNN(int history = 500, double dist2Threshold = 400.0, bool detectShadows = true) + // + + //javadoc: createBackgroundSubtractorKNN(history, dist2Threshold, detectShadows) + public static BackgroundSubtractorKNN createBackgroundSubtractorKNN(int history, double dist2Threshold, boolean detectShadows) + { + + BackgroundSubtractorKNN retVal = BackgroundSubtractorKNN.__fromPtr__(createBackgroundSubtractorKNN_0(history, dist2Threshold, detectShadows)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorKNN(history, dist2Threshold) + public static BackgroundSubtractorKNN createBackgroundSubtractorKNN(int history, double dist2Threshold) + { + + BackgroundSubtractorKNN retVal = BackgroundSubtractorKNN.__fromPtr__(createBackgroundSubtractorKNN_1(history, dist2Threshold)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorKNN(history) + public static BackgroundSubtractorKNN createBackgroundSubtractorKNN(int history) + { + + BackgroundSubtractorKNN retVal = BackgroundSubtractorKNN.__fromPtr__(createBackgroundSubtractorKNN_2(history)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorKNN() + public static BackgroundSubtractorKNN createBackgroundSubtractorKNN() + { + + BackgroundSubtractorKNN retVal = BackgroundSubtractorKNN.__fromPtr__(createBackgroundSubtractorKNN_3()); + + return retVal; + } + + + // + // C++: Ptr_BackgroundSubtractorMOG2 cv::createBackgroundSubtractorMOG2(int history = 500, double varThreshold = 16, bool detectShadows = true) + // + + //javadoc: createBackgroundSubtractorMOG2(history, varThreshold, detectShadows) + public static BackgroundSubtractorMOG2 createBackgroundSubtractorMOG2(int history, double varThreshold, boolean detectShadows) + { + + BackgroundSubtractorMOG2 retVal = BackgroundSubtractorMOG2.__fromPtr__(createBackgroundSubtractorMOG2_0(history, varThreshold, detectShadows)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorMOG2(history, varThreshold) + public static BackgroundSubtractorMOG2 createBackgroundSubtractorMOG2(int history, double varThreshold) + { + + BackgroundSubtractorMOG2 retVal = BackgroundSubtractorMOG2.__fromPtr__(createBackgroundSubtractorMOG2_1(history, varThreshold)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorMOG2(history) + public static BackgroundSubtractorMOG2 createBackgroundSubtractorMOG2(int history) + { + + BackgroundSubtractorMOG2 retVal = BackgroundSubtractorMOG2.__fromPtr__(createBackgroundSubtractorMOG2_2(history)); + + return retVal; + } + + //javadoc: createBackgroundSubtractorMOG2() + public static BackgroundSubtractorMOG2 createBackgroundSubtractorMOG2() + { + + BackgroundSubtractorMOG2 retVal = BackgroundSubtractorMOG2.__fromPtr__(createBackgroundSubtractorMOG2_3()); + + return retVal; + } + + + // + // C++: RotatedRect cv::CamShift(Mat probImage, Rect& window, TermCriteria criteria) + // + + //javadoc: CamShift(probImage, window, criteria) + public static RotatedRect CamShift(Mat probImage, Rect window, TermCriteria criteria) + { + double[] window_out = new double[4]; + RotatedRect retVal = new RotatedRect(CamShift_0(probImage.nativeObj, window.x, window.y, window.width, window.height, window_out, criteria.type, criteria.maxCount, criteria.epsilon)); + if(window!=null){ window.x = (int)window_out[0]; window.y = (int)window_out[1]; window.width = (int)window_out[2]; window.height = (int)window_out[3]; } + return retVal; + } + + + // + // C++: bool cv::writeOpticalFlow(String path, Mat flow) + // + + //javadoc: writeOpticalFlow(path, flow) + public static boolean writeOpticalFlow(String path, Mat flow) + { + + boolean retVal = writeOpticalFlow_0(path, flow.nativeObj); + + return retVal; + } + + + // + // C++: double cv::computeECC(Mat templateImage, Mat inputImage, Mat inputMask = Mat()) + // + + //javadoc: computeECC(templateImage, inputImage, inputMask) + public static double computeECC(Mat templateImage, Mat inputImage, Mat inputMask) + { + + double retVal = computeECC_0(templateImage.nativeObj, inputImage.nativeObj, inputMask.nativeObj); + + return retVal; + } + + //javadoc: computeECC(templateImage, inputImage) + public static double computeECC(Mat templateImage, Mat inputImage) + { + + double retVal = computeECC_1(templateImage.nativeObj, inputImage.nativeObj); + + return retVal; + } + + + // + // C++: double cv::findTransformECC(Mat templateImage, Mat inputImage, Mat& warpMatrix, int motionType, TermCriteria criteria, Mat inputMask, int gaussFiltSize) + // + + //javadoc: findTransformECC(templateImage, inputImage, warpMatrix, motionType, criteria, inputMask, gaussFiltSize) + public static double findTransformECC(Mat templateImage, Mat inputImage, Mat warpMatrix, int motionType, TermCriteria criteria, Mat inputMask, int gaussFiltSize) + { + + double retVal = findTransformECC_0(templateImage.nativeObj, inputImage.nativeObj, warpMatrix.nativeObj, motionType, criteria.type, criteria.maxCount, criteria.epsilon, inputMask.nativeObj, gaussFiltSize); + + return retVal; + } + + + // + // C++: int cv::buildOpticalFlowPyramid(Mat img, vector_Mat& pyramid, Size winSize, int maxLevel, bool withDerivatives = true, int pyrBorder = BORDER_REFLECT_101, int derivBorder = BORDER_CONSTANT, bool tryReuseInputImage = true) + // + + //javadoc: buildOpticalFlowPyramid(img, pyramid, winSize, maxLevel, withDerivatives, pyrBorder, derivBorder, tryReuseInputImage) + public static int buildOpticalFlowPyramid(Mat img, List pyramid, Size winSize, int maxLevel, boolean withDerivatives, int pyrBorder, int derivBorder, boolean tryReuseInputImage) + { + Mat pyramid_mat = new Mat(); + int retVal = buildOpticalFlowPyramid_0(img.nativeObj, pyramid_mat.nativeObj, winSize.width, winSize.height, maxLevel, withDerivatives, pyrBorder, derivBorder, tryReuseInputImage); + Converters.Mat_to_vector_Mat(pyramid_mat, pyramid); + pyramid_mat.release(); + return retVal; + } + + //javadoc: buildOpticalFlowPyramid(img, pyramid, winSize, maxLevel, withDerivatives, pyrBorder, derivBorder) + public static int buildOpticalFlowPyramid(Mat img, List pyramid, Size winSize, int maxLevel, boolean withDerivatives, int pyrBorder, int derivBorder) + { + Mat pyramid_mat = new Mat(); + int retVal = buildOpticalFlowPyramid_1(img.nativeObj, pyramid_mat.nativeObj, winSize.width, winSize.height, maxLevel, withDerivatives, pyrBorder, derivBorder); + Converters.Mat_to_vector_Mat(pyramid_mat, pyramid); + pyramid_mat.release(); + return retVal; + } + + //javadoc: buildOpticalFlowPyramid(img, pyramid, winSize, maxLevel, withDerivatives, pyrBorder) + public static int buildOpticalFlowPyramid(Mat img, List pyramid, Size winSize, int maxLevel, boolean withDerivatives, int pyrBorder) + { + Mat pyramid_mat = new Mat(); + int retVal = buildOpticalFlowPyramid_2(img.nativeObj, pyramid_mat.nativeObj, winSize.width, winSize.height, maxLevel, withDerivatives, pyrBorder); + Converters.Mat_to_vector_Mat(pyramid_mat, pyramid); + pyramid_mat.release(); + return retVal; + } + + //javadoc: buildOpticalFlowPyramid(img, pyramid, winSize, maxLevel, withDerivatives) + public static int buildOpticalFlowPyramid(Mat img, List pyramid, Size winSize, int maxLevel, boolean withDerivatives) + { + Mat pyramid_mat = new Mat(); + int retVal = buildOpticalFlowPyramid_3(img.nativeObj, pyramid_mat.nativeObj, winSize.width, winSize.height, maxLevel, withDerivatives); + Converters.Mat_to_vector_Mat(pyramid_mat, pyramid); + pyramid_mat.release(); + return retVal; + } + + //javadoc: buildOpticalFlowPyramid(img, pyramid, winSize, maxLevel) + public static int buildOpticalFlowPyramid(Mat img, List pyramid, Size winSize, int maxLevel) + { + Mat pyramid_mat = new Mat(); + int retVal = buildOpticalFlowPyramid_4(img.nativeObj, pyramid_mat.nativeObj, winSize.width, winSize.height, maxLevel); + Converters.Mat_to_vector_Mat(pyramid_mat, pyramid); + pyramid_mat.release(); + return retVal; + } + + + // + // C++: int cv::meanShift(Mat probImage, Rect& window, TermCriteria criteria) + // + + //javadoc: meanShift(probImage, window, criteria) + public static int meanShift(Mat probImage, Rect window, TermCriteria criteria) + { + double[] window_out = new double[4]; + int retVal = meanShift_0(probImage.nativeObj, window.x, window.y, window.width, window.height, window_out, criteria.type, criteria.maxCount, criteria.epsilon); + if(window!=null){ window.x = (int)window_out[0]; window.y = (int)window_out[1]; window.width = (int)window_out[2]; window.height = (int)window_out[3]; } + return retVal; + } + + + // + // C++: void cv::calcOpticalFlowFarneback(Mat prev, Mat next, Mat& flow, double pyr_scale, int levels, int winsize, int iterations, int poly_n, double poly_sigma, int flags) + // + + //javadoc: calcOpticalFlowFarneback(prev, next, flow, pyr_scale, levels, winsize, iterations, poly_n, poly_sigma, flags) + public static void calcOpticalFlowFarneback(Mat prev, Mat next, Mat flow, double pyr_scale, int levels, int winsize, int iterations, int poly_n, double poly_sigma, int flags) + { + + calcOpticalFlowFarneback_0(prev.nativeObj, next.nativeObj, flow.nativeObj, pyr_scale, levels, winsize, iterations, poly_n, poly_sigma, flags); + + return; + } + + + // + // C++: void cv::calcOpticalFlowPyrLK(Mat prevImg, Mat nextImg, vector_Point2f prevPts, vector_Point2f& nextPts, vector_uchar& status, vector_float& err, Size winSize = Size(21,21), int maxLevel = 3, TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01), int flags = 0, double minEigThreshold = 1e-4) + // + + //javadoc: calcOpticalFlowPyrLK(prevImg, nextImg, prevPts, nextPts, status, err, winSize, maxLevel, criteria, flags, minEigThreshold) + public static void calcOpticalFlowPyrLK(Mat prevImg, Mat nextImg, MatOfPoint2f prevPts, MatOfPoint2f nextPts, MatOfByte status, MatOfFloat err, Size winSize, int maxLevel, TermCriteria criteria, int flags, double minEigThreshold) + { + Mat prevPts_mat = prevPts; + Mat nextPts_mat = nextPts; + Mat status_mat = status; + Mat err_mat = err; + calcOpticalFlowPyrLK_0(prevImg.nativeObj, nextImg.nativeObj, prevPts_mat.nativeObj, nextPts_mat.nativeObj, status_mat.nativeObj, err_mat.nativeObj, winSize.width, winSize.height, maxLevel, criteria.type, criteria.maxCount, criteria.epsilon, flags, minEigThreshold); + + return; + } + + //javadoc: calcOpticalFlowPyrLK(prevImg, nextImg, prevPts, nextPts, status, err, winSize, maxLevel, criteria, flags) + public static void calcOpticalFlowPyrLK(Mat prevImg, Mat nextImg, MatOfPoint2f prevPts, MatOfPoint2f nextPts, MatOfByte status, MatOfFloat err, Size winSize, int maxLevel, TermCriteria criteria, int flags) + { + Mat prevPts_mat = prevPts; + Mat nextPts_mat = nextPts; + Mat status_mat = status; + Mat err_mat = err; + calcOpticalFlowPyrLK_1(prevImg.nativeObj, nextImg.nativeObj, prevPts_mat.nativeObj, nextPts_mat.nativeObj, status_mat.nativeObj, err_mat.nativeObj, winSize.width, winSize.height, maxLevel, criteria.type, criteria.maxCount, criteria.epsilon, flags); + + return; + } + + //javadoc: calcOpticalFlowPyrLK(prevImg, nextImg, prevPts, nextPts, status, err, winSize, maxLevel, criteria) + public static void calcOpticalFlowPyrLK(Mat prevImg, Mat nextImg, MatOfPoint2f prevPts, MatOfPoint2f nextPts, MatOfByte status, MatOfFloat err, Size winSize, int maxLevel, TermCriteria criteria) + { + Mat prevPts_mat = prevPts; + Mat nextPts_mat = nextPts; + Mat status_mat = status; + Mat err_mat = err; + calcOpticalFlowPyrLK_2(prevImg.nativeObj, nextImg.nativeObj, prevPts_mat.nativeObj, nextPts_mat.nativeObj, status_mat.nativeObj, err_mat.nativeObj, winSize.width, winSize.height, maxLevel, criteria.type, criteria.maxCount, criteria.epsilon); + + return; + } + + //javadoc: calcOpticalFlowPyrLK(prevImg, nextImg, prevPts, nextPts, status, err, winSize, maxLevel) + public static void calcOpticalFlowPyrLK(Mat prevImg, Mat nextImg, MatOfPoint2f prevPts, MatOfPoint2f nextPts, MatOfByte status, MatOfFloat err, Size winSize, int maxLevel) + { + Mat prevPts_mat = prevPts; + Mat nextPts_mat = nextPts; + Mat status_mat = status; + Mat err_mat = err; + calcOpticalFlowPyrLK_3(prevImg.nativeObj, nextImg.nativeObj, prevPts_mat.nativeObj, nextPts_mat.nativeObj, status_mat.nativeObj, err_mat.nativeObj, winSize.width, winSize.height, maxLevel); + + return; + } + + //javadoc: calcOpticalFlowPyrLK(prevImg, nextImg, prevPts, nextPts, status, err, winSize) + public static void calcOpticalFlowPyrLK(Mat prevImg, Mat nextImg, MatOfPoint2f prevPts, MatOfPoint2f nextPts, MatOfByte status, MatOfFloat err, Size winSize) + { + Mat prevPts_mat = prevPts; + Mat nextPts_mat = nextPts; + Mat status_mat = status; + Mat err_mat = err; + calcOpticalFlowPyrLK_4(prevImg.nativeObj, nextImg.nativeObj, prevPts_mat.nativeObj, nextPts_mat.nativeObj, status_mat.nativeObj, err_mat.nativeObj, winSize.width, winSize.height); + + return; + } + + //javadoc: calcOpticalFlowPyrLK(prevImg, nextImg, prevPts, nextPts, status, err) + public static void calcOpticalFlowPyrLK(Mat prevImg, Mat nextImg, MatOfPoint2f prevPts, MatOfPoint2f nextPts, MatOfByte status, MatOfFloat err) + { + Mat prevPts_mat = prevPts; + Mat nextPts_mat = nextPts; + Mat status_mat = status; + Mat err_mat = err; + calcOpticalFlowPyrLK_5(prevImg.nativeObj, nextImg.nativeObj, prevPts_mat.nativeObj, nextPts_mat.nativeObj, status_mat.nativeObj, err_mat.nativeObj); + + return; + } + + + + + // C++: Mat cv::readOpticalFlow(String path) + private static native long readOpticalFlow_0(String path); + + // C++: Ptr_BackgroundSubtractorKNN cv::createBackgroundSubtractorKNN(int history = 500, double dist2Threshold = 400.0, bool detectShadows = true) + private static native long createBackgroundSubtractorKNN_0(int history, double dist2Threshold, boolean detectShadows); + private static native long createBackgroundSubtractorKNN_1(int history, double dist2Threshold); + private static native long createBackgroundSubtractorKNN_2(int history); + private static native long createBackgroundSubtractorKNN_3(); + + // C++: Ptr_BackgroundSubtractorMOG2 cv::createBackgroundSubtractorMOG2(int history = 500, double varThreshold = 16, bool detectShadows = true) + private static native long createBackgroundSubtractorMOG2_0(int history, double varThreshold, boolean detectShadows); + private static native long createBackgroundSubtractorMOG2_1(int history, double varThreshold); + private static native long createBackgroundSubtractorMOG2_2(int history); + private static native long createBackgroundSubtractorMOG2_3(); + + // C++: RotatedRect cv::CamShift(Mat probImage, Rect& window, TermCriteria criteria) + private static native double[] CamShift_0(long probImage_nativeObj, int window_x, int window_y, int window_width, int window_height, double[] window_out, int criteria_type, int criteria_maxCount, double criteria_epsilon); + + // C++: bool cv::writeOpticalFlow(String path, Mat flow) + private static native boolean writeOpticalFlow_0(String path, long flow_nativeObj); + + // C++: double cv::computeECC(Mat templateImage, Mat inputImage, Mat inputMask = Mat()) + private static native double computeECC_0(long templateImage_nativeObj, long inputImage_nativeObj, long inputMask_nativeObj); + private static native double computeECC_1(long templateImage_nativeObj, long inputImage_nativeObj); + + // C++: double cv::findTransformECC(Mat templateImage, Mat inputImage, Mat& warpMatrix, int motionType, TermCriteria criteria, Mat inputMask, int gaussFiltSize) + private static native double findTransformECC_0(long templateImage_nativeObj, long inputImage_nativeObj, long warpMatrix_nativeObj, int motionType, int criteria_type, int criteria_maxCount, double criteria_epsilon, long inputMask_nativeObj, int gaussFiltSize); + + // C++: int cv::buildOpticalFlowPyramid(Mat img, vector_Mat& pyramid, Size winSize, int maxLevel, bool withDerivatives = true, int pyrBorder = BORDER_REFLECT_101, int derivBorder = BORDER_CONSTANT, bool tryReuseInputImage = true) + private static native int buildOpticalFlowPyramid_0(long img_nativeObj, long pyramid_mat_nativeObj, double winSize_width, double winSize_height, int maxLevel, boolean withDerivatives, int pyrBorder, int derivBorder, boolean tryReuseInputImage); + private static native int buildOpticalFlowPyramid_1(long img_nativeObj, long pyramid_mat_nativeObj, double winSize_width, double winSize_height, int maxLevel, boolean withDerivatives, int pyrBorder, int derivBorder); + private static native int buildOpticalFlowPyramid_2(long img_nativeObj, long pyramid_mat_nativeObj, double winSize_width, double winSize_height, int maxLevel, boolean withDerivatives, int pyrBorder); + private static native int buildOpticalFlowPyramid_3(long img_nativeObj, long pyramid_mat_nativeObj, double winSize_width, double winSize_height, int maxLevel, boolean withDerivatives); + private static native int buildOpticalFlowPyramid_4(long img_nativeObj, long pyramid_mat_nativeObj, double winSize_width, double winSize_height, int maxLevel); + + // C++: int cv::meanShift(Mat probImage, Rect& window, TermCriteria criteria) + private static native int meanShift_0(long probImage_nativeObj, int window_x, int window_y, int window_width, int window_height, double[] window_out, int criteria_type, int criteria_maxCount, double criteria_epsilon); + + // C++: void cv::calcOpticalFlowFarneback(Mat prev, Mat next, Mat& flow, double pyr_scale, int levels, int winsize, int iterations, int poly_n, double poly_sigma, int flags) + private static native void calcOpticalFlowFarneback_0(long prev_nativeObj, long next_nativeObj, long flow_nativeObj, double pyr_scale, int levels, int winsize, int iterations, int poly_n, double poly_sigma, int flags); + + // C++: void cv::calcOpticalFlowPyrLK(Mat prevImg, Mat nextImg, vector_Point2f prevPts, vector_Point2f& nextPts, vector_uchar& status, vector_float& err, Size winSize = Size(21,21), int maxLevel = 3, TermCriteria criteria = TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 30, 0.01), int flags = 0, double minEigThreshold = 1e-4) + private static native void calcOpticalFlowPyrLK_0(long prevImg_nativeObj, long nextImg_nativeObj, long prevPts_mat_nativeObj, long nextPts_mat_nativeObj, long status_mat_nativeObj, long err_mat_nativeObj, double winSize_width, double winSize_height, int maxLevel, int criteria_type, int criteria_maxCount, double criteria_epsilon, int flags, double minEigThreshold); + private static native void calcOpticalFlowPyrLK_1(long prevImg_nativeObj, long nextImg_nativeObj, long prevPts_mat_nativeObj, long nextPts_mat_nativeObj, long status_mat_nativeObj, long err_mat_nativeObj, double winSize_width, double winSize_height, int maxLevel, int criteria_type, int criteria_maxCount, double criteria_epsilon, int flags); + private static native void calcOpticalFlowPyrLK_2(long prevImg_nativeObj, long nextImg_nativeObj, long prevPts_mat_nativeObj, long nextPts_mat_nativeObj, long status_mat_nativeObj, long err_mat_nativeObj, double winSize_width, double winSize_height, int maxLevel, int criteria_type, int criteria_maxCount, double criteria_epsilon); + private static native void calcOpticalFlowPyrLK_3(long prevImg_nativeObj, long nextImg_nativeObj, long prevPts_mat_nativeObj, long nextPts_mat_nativeObj, long status_mat_nativeObj, long err_mat_nativeObj, double winSize_width, double winSize_height, int maxLevel); + private static native void calcOpticalFlowPyrLK_4(long prevImg_nativeObj, long nextImg_nativeObj, long prevPts_mat_nativeObj, long nextPts_mat_nativeObj, long status_mat_nativeObj, long err_mat_nativeObj, double winSize_width, double winSize_height); + private static native void calcOpticalFlowPyrLK_5(long prevImg_nativeObj, long nextImg_nativeObj, long prevPts_mat_nativeObj, long nextPts_mat_nativeObj, long status_mat_nativeObj, long err_mat_nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/videoio/VideoCapture.java b/OpenCV/src/main/java/org/opencv/videoio/VideoCapture.java new file mode 100644 index 00000000..a7d16892 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/videoio/VideoCapture.java @@ -0,0 +1,337 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.videoio; + +import java.lang.String; +import org.opencv.core.Mat; + +// C++: class VideoCapture +//javadoc: VideoCapture + +public class VideoCapture { + + protected final long nativeObj; + protected VideoCapture(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static VideoCapture __fromPtr__(long addr) { return new VideoCapture(addr); } + + // + // C++: cv::VideoCapture::VideoCapture(String filename, int apiPreference = CAP_ANY) + // + + //javadoc: VideoCapture::VideoCapture(filename, apiPreference) + public VideoCapture(String filename, int apiPreference) + { + + nativeObj = VideoCapture_0(filename, apiPreference); + + return; + } + + //javadoc: VideoCapture::VideoCapture(filename) + public VideoCapture(String filename) + { + + nativeObj = VideoCapture_1(filename); + + return; + } + + + // + // C++: cv::VideoCapture::VideoCapture(int index, int apiPreference = CAP_ANY) + // + + //javadoc: VideoCapture::VideoCapture(index, apiPreference) + public VideoCapture(int index, int apiPreference) + { + + nativeObj = VideoCapture_2(index, apiPreference); + + return; + } + + //javadoc: VideoCapture::VideoCapture(index) + public VideoCapture(int index) + { + + nativeObj = VideoCapture_3(index); + + return; + } + + + // + // C++: cv::VideoCapture::VideoCapture() + // + + //javadoc: VideoCapture::VideoCapture() + public VideoCapture() + { + + nativeObj = VideoCapture_4(); + + return; + } + + + // + // C++: String cv::VideoCapture::getBackendName() + // + + //javadoc: VideoCapture::getBackendName() + public String getBackendName() + { + + String retVal = getBackendName_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::VideoCapture::getExceptionMode() + // + + //javadoc: VideoCapture::getExceptionMode() + public boolean getExceptionMode() + { + + boolean retVal = getExceptionMode_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::VideoCapture::grab() + // + + //javadoc: VideoCapture::grab() + public boolean grab() + { + + boolean retVal = grab_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::VideoCapture::isOpened() + // + + //javadoc: VideoCapture::isOpened() + public boolean isOpened() + { + + boolean retVal = isOpened_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::VideoCapture::open(String filename, int apiPreference = CAP_ANY) + // + + //javadoc: VideoCapture::open(filename, apiPreference) + public boolean open(String filename, int apiPreference) + { + + boolean retVal = open_0(nativeObj, filename, apiPreference); + + return retVal; + } + + //javadoc: VideoCapture::open(filename) + public boolean open(String filename) + { + + boolean retVal = open_1(nativeObj, filename); + + return retVal; + } + + + // + // C++: bool cv::VideoCapture::open(int index, int apiPreference = CAP_ANY) + // + + //javadoc: VideoCapture::open(index, apiPreference) + public boolean open(int index, int apiPreference) + { + + boolean retVal = open_2(nativeObj, index, apiPreference); + + return retVal; + } + + //javadoc: VideoCapture::open(index) + public boolean open(int index) + { + + boolean retVal = open_3(nativeObj, index); + + return retVal; + } + + + // + // C++: bool cv::VideoCapture::read(Mat& image) + // + + //javadoc: VideoCapture::read(image) + public boolean read(Mat image) + { + + boolean retVal = read_0(nativeObj, image.nativeObj); + + return retVal; + } + + + // + // C++: bool cv::VideoCapture::retrieve(Mat& image, int flag = 0) + // + + //javadoc: VideoCapture::retrieve(image, flag) + public boolean retrieve(Mat image, int flag) + { + + boolean retVal = retrieve_0(nativeObj, image.nativeObj, flag); + + return retVal; + } + + //javadoc: VideoCapture::retrieve(image) + public boolean retrieve(Mat image) + { + + boolean retVal = retrieve_1(nativeObj, image.nativeObj); + + return retVal; + } + + + // + // C++: bool cv::VideoCapture::set(int propId, double value) + // + + //javadoc: VideoCapture::set(propId, value) + public boolean set(int propId, double value) + { + + boolean retVal = set_0(nativeObj, propId, value); + + return retVal; + } + + + // + // C++: double cv::VideoCapture::get(int propId) + // + + //javadoc: VideoCapture::get(propId) + public double get(int propId) + { + + double retVal = get_0(nativeObj, propId); + + return retVal; + } + + + // + // C++: void cv::VideoCapture::release() + // + + //javadoc: VideoCapture::release() + public void release() + { + + release_0(nativeObj); + + return; + } + + + // + // C++: void cv::VideoCapture::setExceptionMode(bool enable) + // + + //javadoc: VideoCapture::setExceptionMode(enable) + public void setExceptionMode(boolean enable) + { + + setExceptionMode_0(nativeObj, enable); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: cv::VideoCapture::VideoCapture(String filename, int apiPreference = CAP_ANY) + private static native long VideoCapture_0(String filename, int apiPreference); + private static native long VideoCapture_1(String filename); + + // C++: cv::VideoCapture::VideoCapture(int index, int apiPreference = CAP_ANY) + private static native long VideoCapture_2(int index, int apiPreference); + private static native long VideoCapture_3(int index); + + // C++: cv::VideoCapture::VideoCapture() + private static native long VideoCapture_4(); + + // C++: String cv::VideoCapture::getBackendName() + private static native String getBackendName_0(long nativeObj); + + // C++: bool cv::VideoCapture::getExceptionMode() + private static native boolean getExceptionMode_0(long nativeObj); + + // C++: bool cv::VideoCapture::grab() + private static native boolean grab_0(long nativeObj); + + // C++: bool cv::VideoCapture::isOpened() + private static native boolean isOpened_0(long nativeObj); + + // C++: bool cv::VideoCapture::open(String filename, int apiPreference = CAP_ANY) + private static native boolean open_0(long nativeObj, String filename, int apiPreference); + private static native boolean open_1(long nativeObj, String filename); + + // C++: bool cv::VideoCapture::open(int index, int apiPreference = CAP_ANY) + private static native boolean open_2(long nativeObj, int index, int apiPreference); + private static native boolean open_3(long nativeObj, int index); + + // C++: bool cv::VideoCapture::read(Mat& image) + private static native boolean read_0(long nativeObj, long image_nativeObj); + + // C++: bool cv::VideoCapture::retrieve(Mat& image, int flag = 0) + private static native boolean retrieve_0(long nativeObj, long image_nativeObj, int flag); + private static native boolean retrieve_1(long nativeObj, long image_nativeObj); + + // C++: bool cv::VideoCapture::set(int propId, double value) + private static native boolean set_0(long nativeObj, int propId, double value); + + // C++: double cv::VideoCapture::get(int propId) + private static native double get_0(long nativeObj, int propId); + + // C++: void cv::VideoCapture::release() + private static native void release_0(long nativeObj); + + // C++: void cv::VideoCapture::setExceptionMode(bool enable) + private static native void setExceptionMode_0(long nativeObj, boolean enable); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/videoio/VideoWriter.java b/OpenCV/src/main/java/org/opencv/videoio/VideoWriter.java new file mode 100644 index 00000000..55e66395 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/videoio/VideoWriter.java @@ -0,0 +1,277 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.videoio; + +import java.lang.String; +import org.opencv.core.Mat; +import org.opencv.core.Size; + +// C++: class VideoWriter +//javadoc: VideoWriter + +public class VideoWriter { + + protected final long nativeObj; + protected VideoWriter(long addr) { nativeObj = addr; } + + public long getNativeObjAddr() { return nativeObj; } + + // internal usage only + public static VideoWriter __fromPtr__(long addr) { return new VideoWriter(addr); } + + // + // C++: cv::VideoWriter::VideoWriter(String filename, int apiPreference, int fourcc, double fps, Size frameSize, bool isColor = true) + // + + //javadoc: VideoWriter::VideoWriter(filename, apiPreference, fourcc, fps, frameSize, isColor) + public VideoWriter(String filename, int apiPreference, int fourcc, double fps, Size frameSize, boolean isColor) + { + + nativeObj = VideoWriter_0(filename, apiPreference, fourcc, fps, frameSize.width, frameSize.height, isColor); + + return; + } + + //javadoc: VideoWriter::VideoWriter(filename, apiPreference, fourcc, fps, frameSize) + public VideoWriter(String filename, int apiPreference, int fourcc, double fps, Size frameSize) + { + + nativeObj = VideoWriter_1(filename, apiPreference, fourcc, fps, frameSize.width, frameSize.height); + + return; + } + + + // + // C++: cv::VideoWriter::VideoWriter(String filename, int fourcc, double fps, Size frameSize, bool isColor = true) + // + + //javadoc: VideoWriter::VideoWriter(filename, fourcc, fps, frameSize, isColor) + public VideoWriter(String filename, int fourcc, double fps, Size frameSize, boolean isColor) + { + + nativeObj = VideoWriter_2(filename, fourcc, fps, frameSize.width, frameSize.height, isColor); + + return; + } + + //javadoc: VideoWriter::VideoWriter(filename, fourcc, fps, frameSize) + public VideoWriter(String filename, int fourcc, double fps, Size frameSize) + { + + nativeObj = VideoWriter_3(filename, fourcc, fps, frameSize.width, frameSize.height); + + return; + } + + + // + // C++: cv::VideoWriter::VideoWriter() + // + + //javadoc: VideoWriter::VideoWriter() + public VideoWriter() + { + + nativeObj = VideoWriter_4(); + + return; + } + + + // + // C++: String cv::VideoWriter::getBackendName() + // + + //javadoc: VideoWriter::getBackendName() + public String getBackendName() + { + + String retVal = getBackendName_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::VideoWriter::isOpened() + // + + //javadoc: VideoWriter::isOpened() + public boolean isOpened() + { + + boolean retVal = isOpened_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::VideoWriter::open(String filename, int apiPreference, int fourcc, double fps, Size frameSize, bool isColor = true) + // + + //javadoc: VideoWriter::open(filename, apiPreference, fourcc, fps, frameSize, isColor) + public boolean open(String filename, int apiPreference, int fourcc, double fps, Size frameSize, boolean isColor) + { + + boolean retVal = open_0(nativeObj, filename, apiPreference, fourcc, fps, frameSize.width, frameSize.height, isColor); + + return retVal; + } + + //javadoc: VideoWriter::open(filename, apiPreference, fourcc, fps, frameSize) + public boolean open(String filename, int apiPreference, int fourcc, double fps, Size frameSize) + { + + boolean retVal = open_1(nativeObj, filename, apiPreference, fourcc, fps, frameSize.width, frameSize.height); + + return retVal; + } + + + // + // C++: bool cv::VideoWriter::open(String filename, int fourcc, double fps, Size frameSize, bool isColor = true) + // + + //javadoc: VideoWriter::open(filename, fourcc, fps, frameSize, isColor) + public boolean open(String filename, int fourcc, double fps, Size frameSize, boolean isColor) + { + + boolean retVal = open_2(nativeObj, filename, fourcc, fps, frameSize.width, frameSize.height, isColor); + + return retVal; + } + + //javadoc: VideoWriter::open(filename, fourcc, fps, frameSize) + public boolean open(String filename, int fourcc, double fps, Size frameSize) + { + + boolean retVal = open_3(nativeObj, filename, fourcc, fps, frameSize.width, frameSize.height); + + return retVal; + } + + + // + // C++: bool cv::VideoWriter::set(int propId, double value) + // + + //javadoc: VideoWriter::set(propId, value) + public boolean set(int propId, double value) + { + + boolean retVal = set_0(nativeObj, propId, value); + + return retVal; + } + + + // + // C++: double cv::VideoWriter::get(int propId) + // + + //javadoc: VideoWriter::get(propId) + public double get(int propId) + { + + double retVal = get_0(nativeObj, propId); + + return retVal; + } + + + // + // C++: static int cv::VideoWriter::fourcc(char c1, char c2, char c3, char c4) + // + + //javadoc: VideoWriter::fourcc(c1, c2, c3, c4) + public static int fourcc(char c1, char c2, char c3, char c4) + { + + int retVal = fourcc_0(c1, c2, c3, c4); + + return retVal; + } + + + // + // C++: void cv::VideoWriter::release() + // + + //javadoc: VideoWriter::release() + public void release() + { + + release_0(nativeObj); + + return; + } + + + // + // C++: void cv::VideoWriter::write(Mat image) + // + + //javadoc: VideoWriter::write(image) + public void write(Mat image) + { + + write_0(nativeObj, image.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: cv::VideoWriter::VideoWriter(String filename, int apiPreference, int fourcc, double fps, Size frameSize, bool isColor = true) + private static native long VideoWriter_0(String filename, int apiPreference, int fourcc, double fps, double frameSize_width, double frameSize_height, boolean isColor); + private static native long VideoWriter_1(String filename, int apiPreference, int fourcc, double fps, double frameSize_width, double frameSize_height); + + // C++: cv::VideoWriter::VideoWriter(String filename, int fourcc, double fps, Size frameSize, bool isColor = true) + private static native long VideoWriter_2(String filename, int fourcc, double fps, double frameSize_width, double frameSize_height, boolean isColor); + private static native long VideoWriter_3(String filename, int fourcc, double fps, double frameSize_width, double frameSize_height); + + // C++: cv::VideoWriter::VideoWriter() + private static native long VideoWriter_4(); + + // C++: String cv::VideoWriter::getBackendName() + private static native String getBackendName_0(long nativeObj); + + // C++: bool cv::VideoWriter::isOpened() + private static native boolean isOpened_0(long nativeObj); + + // C++: bool cv::VideoWriter::open(String filename, int apiPreference, int fourcc, double fps, Size frameSize, bool isColor = true) + private static native boolean open_0(long nativeObj, String filename, int apiPreference, int fourcc, double fps, double frameSize_width, double frameSize_height, boolean isColor); + private static native boolean open_1(long nativeObj, String filename, int apiPreference, int fourcc, double fps, double frameSize_width, double frameSize_height); + + // C++: bool cv::VideoWriter::open(String filename, int fourcc, double fps, Size frameSize, bool isColor = true) + private static native boolean open_2(long nativeObj, String filename, int fourcc, double fps, double frameSize_width, double frameSize_height, boolean isColor); + private static native boolean open_3(long nativeObj, String filename, int fourcc, double fps, double frameSize_width, double frameSize_height); + + // C++: bool cv::VideoWriter::set(int propId, double value) + private static native boolean set_0(long nativeObj, int propId, double value); + + // C++: double cv::VideoWriter::get(int propId) + private static native double get_0(long nativeObj, int propId); + + // C++: static int cv::VideoWriter::fourcc(char c1, char c2, char c3, char c4) + private static native int fourcc_0(char c1, char c2, char c3, char c4); + + // C++: void cv::VideoWriter::release() + private static native void release_0(long nativeObj); + + // C++: void cv::VideoWriter::write(Mat image) + private static native void write_0(long nativeObj, long image_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/videoio/Videoio.java b/OpenCV/src/main/java/org/opencv/videoio/Videoio.java new file mode 100644 index 00000000..3b8a0073 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/videoio/Videoio.java @@ -0,0 +1,413 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.videoio; + +import java.lang.String; + +// C++: class Videoio +//javadoc: Videoio + +public class Videoio { + + // C++: enum VideoWriterProperties + public static final int + VIDEOWRITER_PROP_QUALITY = 1, + VIDEOWRITER_PROP_FRAMEBYTES = 2, + VIDEOWRITER_PROP_NSTRIPES = 3; + + + // C++: enum VideoCaptureProperties + public static final int + CAP_PROP_POS_MSEC = 0, + CAP_PROP_POS_FRAMES = 1, + CAP_PROP_POS_AVI_RATIO = 2, + CAP_PROP_FRAME_WIDTH = 3, + CAP_PROP_FRAME_HEIGHT = 4, + CAP_PROP_FPS = 5, + CAP_PROP_FOURCC = 6, + CAP_PROP_FRAME_COUNT = 7, + CAP_PROP_FORMAT = 8, + CAP_PROP_MODE = 9, + CAP_PROP_BRIGHTNESS = 10, + CAP_PROP_CONTRAST = 11, + CAP_PROP_SATURATION = 12, + CAP_PROP_HUE = 13, + CAP_PROP_GAIN = 14, + CAP_PROP_EXPOSURE = 15, + CAP_PROP_CONVERT_RGB = 16, + CAP_PROP_WHITE_BALANCE_BLUE_U = 17, + CAP_PROP_RECTIFICATION = 18, + CAP_PROP_MONOCHROME = 19, + CAP_PROP_SHARPNESS = 20, + CAP_PROP_AUTO_EXPOSURE = 21, + CAP_PROP_GAMMA = 22, + CAP_PROP_TEMPERATURE = 23, + CAP_PROP_TRIGGER = 24, + CAP_PROP_TRIGGER_DELAY = 25, + CAP_PROP_WHITE_BALANCE_RED_V = 26, + CAP_PROP_ZOOM = 27, + CAP_PROP_FOCUS = 28, + CAP_PROP_GUID = 29, + CAP_PROP_ISO_SPEED = 30, + CAP_PROP_BACKLIGHT = 32, + CAP_PROP_PAN = 33, + CAP_PROP_TILT = 34, + CAP_PROP_ROLL = 35, + CAP_PROP_IRIS = 36, + CAP_PROP_SETTINGS = 37, + CAP_PROP_BUFFERSIZE = 38, + CAP_PROP_AUTOFOCUS = 39, + CAP_PROP_SAR_NUM = 40, + CAP_PROP_SAR_DEN = 41, + CAP_PROP_BACKEND = 42, + CAP_PROP_CHANNEL = 43, + CAP_PROP_AUTO_WB = 44, + CAP_PROP_WB_TEMPERATURE = 45; + + + // C++: enum + public static final int + CAP_PROP_DC1394_OFF = -4, + CAP_PROP_DC1394_MODE_MANUAL = -3, + CAP_PROP_DC1394_MODE_AUTO = -2, + CAP_PROP_DC1394_MODE_ONE_PUSH_AUTO = -1, + CAP_PROP_DC1394_MAX = 31, + CAP_OPENNI_DEPTH_GENERATOR = 1 << 31, + CAP_OPENNI_IMAGE_GENERATOR = 1 << 30, + CAP_OPENNI_IR_GENERATOR = 1 << 29, + CAP_OPENNI_GENERATORS_MASK = CAP_OPENNI_DEPTH_GENERATOR + CAP_OPENNI_IMAGE_GENERATOR + CAP_OPENNI_IR_GENERATOR, + CAP_PROP_OPENNI_OUTPUT_MODE = 100, + CAP_PROP_OPENNI_FRAME_MAX_DEPTH = 101, + CAP_PROP_OPENNI_BASELINE = 102, + CAP_PROP_OPENNI_FOCAL_LENGTH = 103, + CAP_PROP_OPENNI_REGISTRATION = 104, + CAP_PROP_OPENNI_REGISTRATION_ON = CAP_PROP_OPENNI_REGISTRATION, + CAP_PROP_OPENNI_APPROX_FRAME_SYNC = 105, + CAP_PROP_OPENNI_MAX_BUFFER_SIZE = 106, + CAP_PROP_OPENNI_CIRCLE_BUFFER = 107, + CAP_PROP_OPENNI_MAX_TIME_DURATION = 108, + CAP_PROP_OPENNI_GENERATOR_PRESENT = 109, + CAP_PROP_OPENNI2_SYNC = 110, + CAP_PROP_OPENNI2_MIRROR = 111, + CAP_OPENNI_IMAGE_GENERATOR_PRESENT = CAP_OPENNI_IMAGE_GENERATOR + CAP_PROP_OPENNI_GENERATOR_PRESENT, + CAP_OPENNI_IMAGE_GENERATOR_OUTPUT_MODE = CAP_OPENNI_IMAGE_GENERATOR + CAP_PROP_OPENNI_OUTPUT_MODE, + CAP_OPENNI_DEPTH_GENERATOR_PRESENT = CAP_OPENNI_DEPTH_GENERATOR + CAP_PROP_OPENNI_GENERATOR_PRESENT, + CAP_OPENNI_DEPTH_GENERATOR_BASELINE = CAP_OPENNI_DEPTH_GENERATOR + CAP_PROP_OPENNI_BASELINE, + CAP_OPENNI_DEPTH_GENERATOR_FOCAL_LENGTH = CAP_OPENNI_DEPTH_GENERATOR + CAP_PROP_OPENNI_FOCAL_LENGTH, + CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION = CAP_OPENNI_DEPTH_GENERATOR + CAP_PROP_OPENNI_REGISTRATION, + CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION_ON = CAP_OPENNI_DEPTH_GENERATOR_REGISTRATION, + CAP_OPENNI_IR_GENERATOR_PRESENT = CAP_OPENNI_IR_GENERATOR + CAP_PROP_OPENNI_GENERATOR_PRESENT, + CAP_OPENNI_DEPTH_MAP = 0, + CAP_OPENNI_POINT_CLOUD_MAP = 1, + CAP_OPENNI_DISPARITY_MAP = 2, + CAP_OPENNI_DISPARITY_MAP_32F = 3, + CAP_OPENNI_VALID_DEPTH_MASK = 4, + CAP_OPENNI_BGR_IMAGE = 5, + CAP_OPENNI_GRAY_IMAGE = 6, + CAP_OPENNI_IR_IMAGE = 7, + CAP_OPENNI_VGA_30HZ = 0, + CAP_OPENNI_SXGA_15HZ = 1, + CAP_OPENNI_SXGA_30HZ = 2, + CAP_OPENNI_QVGA_30HZ = 3, + CAP_OPENNI_QVGA_60HZ = 4, + CAP_PROP_GSTREAMER_QUEUE_LENGTH = 200, + CAP_PROP_PVAPI_MULTICASTIP = 300, + CAP_PROP_PVAPI_FRAMESTARTTRIGGERMODE = 301, + CAP_PROP_PVAPI_DECIMATIONHORIZONTAL = 302, + CAP_PROP_PVAPI_DECIMATIONVERTICAL = 303, + CAP_PROP_PVAPI_BINNINGX = 304, + CAP_PROP_PVAPI_BINNINGY = 305, + CAP_PROP_PVAPI_PIXELFORMAT = 306, + CAP_PVAPI_FSTRIGMODE_FREERUN = 0, + CAP_PVAPI_FSTRIGMODE_SYNCIN1 = 1, + CAP_PVAPI_FSTRIGMODE_SYNCIN2 = 2, + CAP_PVAPI_FSTRIGMODE_FIXEDRATE = 3, + CAP_PVAPI_FSTRIGMODE_SOFTWARE = 4, + CAP_PVAPI_DECIMATION_OFF = 1, + CAP_PVAPI_DECIMATION_2OUTOF4 = 2, + CAP_PVAPI_DECIMATION_2OUTOF8 = 4, + CAP_PVAPI_DECIMATION_2OUTOF16 = 8, + CAP_PVAPI_PIXELFORMAT_MONO8 = 1, + CAP_PVAPI_PIXELFORMAT_MONO16 = 2, + CAP_PVAPI_PIXELFORMAT_BAYER8 = 3, + CAP_PVAPI_PIXELFORMAT_BAYER16 = 4, + CAP_PVAPI_PIXELFORMAT_RGB24 = 5, + CAP_PVAPI_PIXELFORMAT_BGR24 = 6, + CAP_PVAPI_PIXELFORMAT_RGBA32 = 7, + CAP_PVAPI_PIXELFORMAT_BGRA32 = 8, + CAP_PROP_XI_DOWNSAMPLING = 400, + CAP_PROP_XI_DATA_FORMAT = 401, + CAP_PROP_XI_OFFSET_X = 402, + CAP_PROP_XI_OFFSET_Y = 403, + CAP_PROP_XI_TRG_SOURCE = 404, + CAP_PROP_XI_TRG_SOFTWARE = 405, + CAP_PROP_XI_GPI_SELECTOR = 406, + CAP_PROP_XI_GPI_MODE = 407, + CAP_PROP_XI_GPI_LEVEL = 408, + CAP_PROP_XI_GPO_SELECTOR = 409, + CAP_PROP_XI_GPO_MODE = 410, + CAP_PROP_XI_LED_SELECTOR = 411, + CAP_PROP_XI_LED_MODE = 412, + CAP_PROP_XI_MANUAL_WB = 413, + CAP_PROP_XI_AUTO_WB = 414, + CAP_PROP_XI_AEAG = 415, + CAP_PROP_XI_EXP_PRIORITY = 416, + CAP_PROP_XI_AE_MAX_LIMIT = 417, + CAP_PROP_XI_AG_MAX_LIMIT = 418, + CAP_PROP_XI_AEAG_LEVEL = 419, + CAP_PROP_XI_TIMEOUT = 420, + CAP_PROP_XI_EXPOSURE = 421, + CAP_PROP_XI_EXPOSURE_BURST_COUNT = 422, + CAP_PROP_XI_GAIN_SELECTOR = 423, + CAP_PROP_XI_GAIN = 424, + CAP_PROP_XI_DOWNSAMPLING_TYPE = 426, + CAP_PROP_XI_BINNING_SELECTOR = 427, + CAP_PROP_XI_BINNING_VERTICAL = 428, + CAP_PROP_XI_BINNING_HORIZONTAL = 429, + CAP_PROP_XI_BINNING_PATTERN = 430, + CAP_PROP_XI_DECIMATION_SELECTOR = 431, + CAP_PROP_XI_DECIMATION_VERTICAL = 432, + CAP_PROP_XI_DECIMATION_HORIZONTAL = 433, + CAP_PROP_XI_DECIMATION_PATTERN = 434, + CAP_PROP_XI_TEST_PATTERN_GENERATOR_SELECTOR = 587, + CAP_PROP_XI_TEST_PATTERN = 588, + CAP_PROP_XI_IMAGE_DATA_FORMAT = 435, + CAP_PROP_XI_SHUTTER_TYPE = 436, + CAP_PROP_XI_SENSOR_TAPS = 437, + CAP_PROP_XI_AEAG_ROI_OFFSET_X = 439, + CAP_PROP_XI_AEAG_ROI_OFFSET_Y = 440, + CAP_PROP_XI_AEAG_ROI_WIDTH = 441, + CAP_PROP_XI_AEAG_ROI_HEIGHT = 442, + CAP_PROP_XI_BPC = 445, + CAP_PROP_XI_WB_KR = 448, + CAP_PROP_XI_WB_KG = 449, + CAP_PROP_XI_WB_KB = 450, + CAP_PROP_XI_WIDTH = 451, + CAP_PROP_XI_HEIGHT = 452, + CAP_PROP_XI_REGION_SELECTOR = 589, + CAP_PROP_XI_REGION_MODE = 595, + CAP_PROP_XI_LIMIT_BANDWIDTH = 459, + CAP_PROP_XI_SENSOR_DATA_BIT_DEPTH = 460, + CAP_PROP_XI_OUTPUT_DATA_BIT_DEPTH = 461, + CAP_PROP_XI_IMAGE_DATA_BIT_DEPTH = 462, + CAP_PROP_XI_OUTPUT_DATA_PACKING = 463, + CAP_PROP_XI_OUTPUT_DATA_PACKING_TYPE = 464, + CAP_PROP_XI_IS_COOLED = 465, + CAP_PROP_XI_COOLING = 466, + CAP_PROP_XI_TARGET_TEMP = 467, + CAP_PROP_XI_CHIP_TEMP = 468, + CAP_PROP_XI_HOUS_TEMP = 469, + CAP_PROP_XI_HOUS_BACK_SIDE_TEMP = 590, + CAP_PROP_XI_SENSOR_BOARD_TEMP = 596, + CAP_PROP_XI_CMS = 470, + CAP_PROP_XI_APPLY_CMS = 471, + CAP_PROP_XI_IMAGE_IS_COLOR = 474, + CAP_PROP_XI_COLOR_FILTER_ARRAY = 475, + CAP_PROP_XI_GAMMAY = 476, + CAP_PROP_XI_GAMMAC = 477, + CAP_PROP_XI_SHARPNESS = 478, + CAP_PROP_XI_CC_MATRIX_00 = 479, + CAP_PROP_XI_CC_MATRIX_01 = 480, + CAP_PROP_XI_CC_MATRIX_02 = 481, + CAP_PROP_XI_CC_MATRIX_03 = 482, + CAP_PROP_XI_CC_MATRIX_10 = 483, + CAP_PROP_XI_CC_MATRIX_11 = 484, + CAP_PROP_XI_CC_MATRIX_12 = 485, + CAP_PROP_XI_CC_MATRIX_13 = 486, + CAP_PROP_XI_CC_MATRIX_20 = 487, + CAP_PROP_XI_CC_MATRIX_21 = 488, + CAP_PROP_XI_CC_MATRIX_22 = 489, + CAP_PROP_XI_CC_MATRIX_23 = 490, + CAP_PROP_XI_CC_MATRIX_30 = 491, + CAP_PROP_XI_CC_MATRIX_31 = 492, + CAP_PROP_XI_CC_MATRIX_32 = 493, + CAP_PROP_XI_CC_MATRIX_33 = 494, + CAP_PROP_XI_DEFAULT_CC_MATRIX = 495, + CAP_PROP_XI_TRG_SELECTOR = 498, + CAP_PROP_XI_ACQ_FRAME_BURST_COUNT = 499, + CAP_PROP_XI_DEBOUNCE_EN = 507, + CAP_PROP_XI_DEBOUNCE_T0 = 508, + CAP_PROP_XI_DEBOUNCE_T1 = 509, + CAP_PROP_XI_DEBOUNCE_POL = 510, + CAP_PROP_XI_LENS_MODE = 511, + CAP_PROP_XI_LENS_APERTURE_VALUE = 512, + CAP_PROP_XI_LENS_FOCUS_MOVEMENT_VALUE = 513, + CAP_PROP_XI_LENS_FOCUS_MOVE = 514, + CAP_PROP_XI_LENS_FOCUS_DISTANCE = 515, + CAP_PROP_XI_LENS_FOCAL_LENGTH = 516, + CAP_PROP_XI_LENS_FEATURE_SELECTOR = 517, + CAP_PROP_XI_LENS_FEATURE = 518, + CAP_PROP_XI_DEVICE_MODEL_ID = 521, + CAP_PROP_XI_DEVICE_SN = 522, + CAP_PROP_XI_IMAGE_DATA_FORMAT_RGB32_ALPHA = 529, + CAP_PROP_XI_IMAGE_PAYLOAD_SIZE = 530, + CAP_PROP_XI_TRANSPORT_PIXEL_FORMAT = 531, + CAP_PROP_XI_SENSOR_CLOCK_FREQ_HZ = 532, + CAP_PROP_XI_SENSOR_CLOCK_FREQ_INDEX = 533, + CAP_PROP_XI_SENSOR_OUTPUT_CHANNEL_COUNT = 534, + CAP_PROP_XI_FRAMERATE = 535, + CAP_PROP_XI_COUNTER_SELECTOR = 536, + CAP_PROP_XI_COUNTER_VALUE = 537, + CAP_PROP_XI_ACQ_TIMING_MODE = 538, + CAP_PROP_XI_AVAILABLE_BANDWIDTH = 539, + CAP_PROP_XI_BUFFER_POLICY = 540, + CAP_PROP_XI_LUT_EN = 541, + CAP_PROP_XI_LUT_INDEX = 542, + CAP_PROP_XI_LUT_VALUE = 543, + CAP_PROP_XI_TRG_DELAY = 544, + CAP_PROP_XI_TS_RST_MODE = 545, + CAP_PROP_XI_TS_RST_SOURCE = 546, + CAP_PROP_XI_IS_DEVICE_EXIST = 547, + CAP_PROP_XI_ACQ_BUFFER_SIZE = 548, + CAP_PROP_XI_ACQ_BUFFER_SIZE_UNIT = 549, + CAP_PROP_XI_ACQ_TRANSPORT_BUFFER_SIZE = 550, + CAP_PROP_XI_BUFFERS_QUEUE_SIZE = 551, + CAP_PROP_XI_ACQ_TRANSPORT_BUFFER_COMMIT = 552, + CAP_PROP_XI_RECENT_FRAME = 553, + CAP_PROP_XI_DEVICE_RESET = 554, + CAP_PROP_XI_COLUMN_FPN_CORRECTION = 555, + CAP_PROP_XI_ROW_FPN_CORRECTION = 591, + CAP_PROP_XI_SENSOR_MODE = 558, + CAP_PROP_XI_HDR = 559, + CAP_PROP_XI_HDR_KNEEPOINT_COUNT = 560, + CAP_PROP_XI_HDR_T1 = 561, + CAP_PROP_XI_HDR_T2 = 562, + CAP_PROP_XI_KNEEPOINT1 = 563, + CAP_PROP_XI_KNEEPOINT2 = 564, + CAP_PROP_XI_IMAGE_BLACK_LEVEL = 565, + CAP_PROP_XI_HW_REVISION = 571, + CAP_PROP_XI_DEBUG_LEVEL = 572, + CAP_PROP_XI_AUTO_BANDWIDTH_CALCULATION = 573, + CAP_PROP_XI_FFS_FILE_ID = 594, + CAP_PROP_XI_FFS_FILE_SIZE = 580, + CAP_PROP_XI_FREE_FFS_SIZE = 581, + CAP_PROP_XI_USED_FFS_SIZE = 582, + CAP_PROP_XI_FFS_ACCESS_KEY = 583, + CAP_PROP_XI_SENSOR_FEATURE_SELECTOR = 585, + CAP_PROP_XI_SENSOR_FEATURE_VALUE = 586, + CAP_PROP_IOS_DEVICE_FOCUS = 9001, + CAP_PROP_IOS_DEVICE_EXPOSURE = 9002, + CAP_PROP_IOS_DEVICE_FLASH = 9003, + CAP_PROP_IOS_DEVICE_WHITEBALANCE = 9004, + CAP_PROP_IOS_DEVICE_TORCH = 9005, + CAP_PROP_GIGA_FRAME_OFFSET_X = 10001, + CAP_PROP_GIGA_FRAME_OFFSET_Y = 10002, + CAP_PROP_GIGA_FRAME_WIDTH_MAX = 10003, + CAP_PROP_GIGA_FRAME_HEIGH_MAX = 10004, + CAP_PROP_GIGA_FRAME_SENS_WIDTH = 10005, + CAP_PROP_GIGA_FRAME_SENS_HEIGH = 10006, + CAP_PROP_INTELPERC_PROFILE_COUNT = 11001, + CAP_PROP_INTELPERC_PROFILE_IDX = 11002, + CAP_PROP_INTELPERC_DEPTH_LOW_CONFIDENCE_VALUE = 11003, + CAP_PROP_INTELPERC_DEPTH_SATURATION_VALUE = 11004, + CAP_PROP_INTELPERC_DEPTH_CONFIDENCE_THRESHOLD = 11005, + CAP_PROP_INTELPERC_DEPTH_FOCAL_LENGTH_HORZ = 11006, + CAP_PROP_INTELPERC_DEPTH_FOCAL_LENGTH_VERT = 11007, + CAP_INTELPERC_DEPTH_GENERATOR = 1 << 29, + CAP_INTELPERC_IMAGE_GENERATOR = 1 << 28, + CAP_INTELPERC_IR_GENERATOR = 1 << 27, + CAP_INTELPERC_GENERATORS_MASK = CAP_INTELPERC_DEPTH_GENERATOR + CAP_INTELPERC_IMAGE_GENERATOR + CAP_INTELPERC_IR_GENERATOR, + CAP_INTELPERC_DEPTH_MAP = 0, + CAP_INTELPERC_UVDEPTH_MAP = 1, + CAP_INTELPERC_IR_MAP = 2, + CAP_INTELPERC_IMAGE = 3, + CAP_PROP_GPHOTO2_PREVIEW = 17001, + CAP_PROP_GPHOTO2_WIDGET_ENUMERATE = 17002, + CAP_PROP_GPHOTO2_RELOAD_CONFIG = 17003, + CAP_PROP_GPHOTO2_RELOAD_ON_CHANGE = 17004, + CAP_PROP_GPHOTO2_COLLECT_MSGS = 17005, + CAP_PROP_GPHOTO2_FLUSH_MSGS = 17006, + CAP_PROP_SPEED = 17007, + CAP_PROP_APERTURE = 17008, + CAP_PROP_EXPOSUREPROGRAM = 17009, + CAP_PROP_VIEWFINDER = 17010, + CAP_PROP_IMAGES_BASE = 18000, + CAP_PROP_IMAGES_LAST = 19000; + + + // C++: enum VideoCaptureAPIs + public static final int + CAP_ANY = 0, + CAP_VFW = 200, + CAP_V4L = 200, + CAP_V4L2 = CAP_V4L, + CAP_FIREWIRE = 300, + CAP_FIREWARE = CAP_FIREWIRE, + CAP_IEEE1394 = CAP_FIREWIRE, + CAP_DC1394 = CAP_FIREWIRE, + CAP_CMU1394 = CAP_FIREWIRE, + CAP_QT = 500, + CAP_UNICAP = 600, + CAP_DSHOW = 700, + CAP_PVAPI = 800, + CAP_OPENNI = 900, + CAP_OPENNI_ASUS = 910, + CAP_ANDROID = 1000, + CAP_XIAPI = 1100, + CAP_AVFOUNDATION = 1200, + CAP_GIGANETIX = 1300, + CAP_MSMF = 1400, + CAP_WINRT = 1410, + CAP_INTELPERC = 1500, + CAP_REALSENSE = 1500, + CAP_OPENNI2 = 1600, + CAP_OPENNI2_ASUS = 1610, + CAP_GPHOTO2 = 1700, + CAP_GSTREAMER = 1800, + CAP_FFMPEG = 1900, + CAP_IMAGES = 2000, + CAP_ARAVIS = 2100, + CAP_OPENCV_MJPEG = 2200, + CAP_INTEL_MFX = 2300, + CAP_XINE = 2400; + + + // + // C++: String cv::videoio_registry::getBackendName(VideoCaptureAPIs api) + // + + //javadoc: getBackendName(api) + public static String getBackendName(int api) + { + + String retVal = getBackendName_0(api); + + return retVal; + } + + + // + // C++: vector_VideoCaptureAPIs cv::videoio_registry::getBackends() + // + + // Return type 'vector_VideoCaptureAPIs' is not supported, skipping the function + + + // + // C++: vector_VideoCaptureAPIs cv::videoio_registry::getCameraBackends() + // + + // Return type 'vector_VideoCaptureAPIs' is not supported, skipping the function + + + // + // C++: vector_VideoCaptureAPIs cv::videoio_registry::getStreamBackends() + // + + // Return type 'vector_VideoCaptureAPIs' is not supported, skipping the function + + + // + // C++: vector_VideoCaptureAPIs cv::videoio_registry::getWriterBackends() + // + + // Return type 'vector_VideoCaptureAPIs' is not supported, skipping the function + + + + + // C++: String cv::videoio_registry::getBackendName(VideoCaptureAPIs api) + private static native String getBackendName_0(int api); + +} diff --git a/OpenCV/src/main/java/org/opencv/xfeatures2d/BoostDesc.java b/OpenCV/src/main/java/org/opencv/xfeatures2d/BoostDesc.java new file mode 100644 index 00000000..23a6ef3d --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xfeatures2d/BoostDesc.java @@ -0,0 +1,144 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xfeatures2d; + +import org.opencv.features2d.Feature2D; +import org.opencv.xfeatures2d.BoostDesc; + +// C++: class BoostDesc +//javadoc: BoostDesc + +public class BoostDesc extends Feature2D { + + protected BoostDesc(long addr) { super(addr); } + + // internal usage only + public static BoostDesc __fromPtr__(long addr) { return new BoostDesc(addr); } + + // + // C++: static Ptr_BoostDesc cv::xfeatures2d::BoostDesc::create(int desc = BoostDesc::BINBOOST_256, bool use_scale_orientation = true, float scale_factor = 6.25f) + // + + //javadoc: BoostDesc::create(desc, use_scale_orientation, scale_factor) + public static BoostDesc create(int desc, boolean use_scale_orientation, float scale_factor) + { + + BoostDesc retVal = BoostDesc.__fromPtr__(create_0(desc, use_scale_orientation, scale_factor)); + + return retVal; + } + + //javadoc: BoostDesc::create(desc, use_scale_orientation) + public static BoostDesc create(int desc, boolean use_scale_orientation) + { + + BoostDesc retVal = BoostDesc.__fromPtr__(create_1(desc, use_scale_orientation)); + + return retVal; + } + + //javadoc: BoostDesc::create(desc) + public static BoostDesc create(int desc) + { + + BoostDesc retVal = BoostDesc.__fromPtr__(create_2(desc)); + + return retVal; + } + + //javadoc: BoostDesc::create() + public static BoostDesc create() + { + + BoostDesc retVal = BoostDesc.__fromPtr__(create_3()); + + return retVal; + } + + + // + // C++: bool cv::xfeatures2d::BoostDesc::getUseScaleOrientation() + // + + //javadoc: BoostDesc::getUseScaleOrientation() + public boolean getUseScaleOrientation() + { + + boolean retVal = getUseScaleOrientation_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::xfeatures2d::BoostDesc::getScaleFactor() + // + + //javadoc: BoostDesc::getScaleFactor() + public float getScaleFactor() + { + + float retVal = getScaleFactor_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::xfeatures2d::BoostDesc::setScaleFactor(float scale_factor) + // + + //javadoc: BoostDesc::setScaleFactor(scale_factor) + public void setScaleFactor(float scale_factor) + { + + setScaleFactor_0(nativeObj, scale_factor); + + return; + } + + + // + // C++: void cv::xfeatures2d::BoostDesc::setUseScaleOrientation(bool use_scale_orientation) + // + + //javadoc: BoostDesc::setUseScaleOrientation(use_scale_orientation) + public void setUseScaleOrientation(boolean use_scale_orientation) + { + + setUseScaleOrientation_0(nativeObj, use_scale_orientation); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_BoostDesc cv::xfeatures2d::BoostDesc::create(int desc = BoostDesc::BINBOOST_256, bool use_scale_orientation = true, float scale_factor = 6.25f) + private static native long create_0(int desc, boolean use_scale_orientation, float scale_factor); + private static native long create_1(int desc, boolean use_scale_orientation); + private static native long create_2(int desc); + private static native long create_3(); + + // C++: bool cv::xfeatures2d::BoostDesc::getUseScaleOrientation() + private static native boolean getUseScaleOrientation_0(long nativeObj); + + // C++: float cv::xfeatures2d::BoostDesc::getScaleFactor() + private static native float getScaleFactor_0(long nativeObj); + + // C++: void cv::xfeatures2d::BoostDesc::setScaleFactor(float scale_factor) + private static native void setScaleFactor_0(long nativeObj, float scale_factor); + + // C++: void cv::xfeatures2d::BoostDesc::setUseScaleOrientation(bool use_scale_orientation) + private static native void setUseScaleOrientation_0(long nativeObj, boolean use_scale_orientation); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/xfeatures2d/BriefDescriptorExtractor.java b/OpenCV/src/main/java/org/opencv/xfeatures2d/BriefDescriptorExtractor.java new file mode 100644 index 00000000..37d17e60 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xfeatures2d/BriefDescriptorExtractor.java @@ -0,0 +1,66 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xfeatures2d; + +import org.opencv.features2d.Feature2D; +import org.opencv.xfeatures2d.BriefDescriptorExtractor; + +// C++: class BriefDescriptorExtractor +//javadoc: BriefDescriptorExtractor + +public class BriefDescriptorExtractor extends Feature2D { + + protected BriefDescriptorExtractor(long addr) { super(addr); } + + // internal usage only + public static BriefDescriptorExtractor __fromPtr__(long addr) { return new BriefDescriptorExtractor(addr); } + + // + // C++: static Ptr_BriefDescriptorExtractor cv::xfeatures2d::BriefDescriptorExtractor::create(int bytes = 32, bool use_orientation = false) + // + + //javadoc: BriefDescriptorExtractor::create(bytes, use_orientation) + public static BriefDescriptorExtractor create(int bytes, boolean use_orientation) + { + + BriefDescriptorExtractor retVal = BriefDescriptorExtractor.__fromPtr__(create_0(bytes, use_orientation)); + + return retVal; + } + + //javadoc: BriefDescriptorExtractor::create(bytes) + public static BriefDescriptorExtractor create(int bytes) + { + + BriefDescriptorExtractor retVal = BriefDescriptorExtractor.__fromPtr__(create_1(bytes)); + + return retVal; + } + + //javadoc: BriefDescriptorExtractor::create() + public static BriefDescriptorExtractor create() + { + + BriefDescriptorExtractor retVal = BriefDescriptorExtractor.__fromPtr__(create_2()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_BriefDescriptorExtractor cv::xfeatures2d::BriefDescriptorExtractor::create(int bytes = 32, bool use_orientation = false) + private static native long create_0(int bytes, boolean use_orientation); + private static native long create_1(int bytes); + private static native long create_2(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/xfeatures2d/DAISY.java b/OpenCV/src/main/java/org/opencv/xfeatures2d/DAISY.java new file mode 100644 index 00000000..0f394541 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xfeatures2d/DAISY.java @@ -0,0 +1,125 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xfeatures2d; + +import org.opencv.core.Mat; +import org.opencv.features2d.Feature2D; +import org.opencv.xfeatures2d.DAISY; + +// C++: class DAISY +//javadoc: DAISY + +public class DAISY extends Feature2D { + + protected DAISY(long addr) { super(addr); } + + // internal usage only + public static DAISY __fromPtr__(long addr) { return new DAISY(addr); } + + // C++: enum NormalizationType + public static final int + NRM_NONE = 100, + NRM_PARTIAL = 101, + NRM_FULL = 102, + NRM_SIFT = 103; + + + // + // C++: static Ptr_DAISY cv::xfeatures2d::DAISY::create(float radius = 15, int q_radius = 3, int q_theta = 8, int q_hist = 8, DAISY_NormalizationType norm = DAISY::NRM_NONE, Mat H = Mat(), bool interpolation = true, bool use_orientation = false) + // + + //javadoc: DAISY::create(radius, q_radius, q_theta, q_hist, H, interpolation, use_orientation) + public static DAISY create(float radius, int q_radius, int q_theta, int q_hist, Mat H, boolean interpolation, boolean use_orientation) + { + + DAISY retVal = DAISY.__fromPtr__(create_0(radius, q_radius, q_theta, q_hist, H.nativeObj, interpolation, use_orientation)); + + return retVal; + } + + //javadoc: DAISY::create(radius, q_radius, q_theta, q_hist, H, interpolation) + public static DAISY create(float radius, int q_radius, int q_theta, int q_hist, Mat H, boolean interpolation) + { + + DAISY retVal = DAISY.__fromPtr__(create_1(radius, q_radius, q_theta, q_hist, H.nativeObj, interpolation)); + + return retVal; + } + + //javadoc: DAISY::create(radius, q_radius, q_theta, q_hist, H) + public static DAISY create(float radius, int q_radius, int q_theta, int q_hist, Mat H) + { + + DAISY retVal = DAISY.__fromPtr__(create_2(radius, q_radius, q_theta, q_hist, H.nativeObj)); + + return retVal; + } + + //javadoc: DAISY::create(radius, q_radius, q_theta, q_hist) + public static DAISY create(float radius, int q_radius, int q_theta, int q_hist) + { + + DAISY retVal = DAISY.__fromPtr__(create_3(radius, q_radius, q_theta, q_hist)); + + return retVal; + } + + //javadoc: DAISY::create(radius, q_radius, q_theta) + public static DAISY create(float radius, int q_radius, int q_theta) + { + + DAISY retVal = DAISY.__fromPtr__(create_5(radius, q_radius, q_theta)); + + return retVal; + } + + //javadoc: DAISY::create(radius, q_radius) + public static DAISY create(float radius, int q_radius) + { + + DAISY retVal = DAISY.__fromPtr__(create_6(radius, q_radius)); + + return retVal; + } + + //javadoc: DAISY::create(radius) + public static DAISY create(float radius) + { + + DAISY retVal = DAISY.__fromPtr__(create_7(radius)); + + return retVal; + } + + //javadoc: DAISY::create() + public static DAISY create() + { + + DAISY retVal = DAISY.__fromPtr__(create_8()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_DAISY cv::xfeatures2d::DAISY::create(float radius = 15, int q_radius = 3, int q_theta = 8, int q_hist = 8, DAISY_NormalizationType norm = DAISY::NRM_NONE, Mat H = Mat(), bool interpolation = true, bool use_orientation = false) + private static native long create_0(float radius, int q_radius, int q_theta, int q_hist, long H_nativeObj, boolean interpolation, boolean use_orientation); + private static native long create_1(float radius, int q_radius, int q_theta, int q_hist, long H_nativeObj, boolean interpolation); + private static native long create_2(float radius, int q_radius, int q_theta, int q_hist, long H_nativeObj); + private static native long create_3(float radius, int q_radius, int q_theta, int q_hist); + private static native long create_5(float radius, int q_radius, int q_theta); + private static native long create_6(float radius, int q_radius); + private static native long create_7(float radius); + private static native long create_8(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/xfeatures2d/FREAK.java b/OpenCV/src/main/java/org/opencv/xfeatures2d/FREAK.java new file mode 100644 index 00000000..02b57219 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xfeatures2d/FREAK.java @@ -0,0 +1,101 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xfeatures2d; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfInt; +import org.opencv.features2d.Feature2D; +import org.opencv.utils.Converters; +import org.opencv.xfeatures2d.FREAK; + +// C++: class FREAK +//javadoc: FREAK + +public class FREAK extends Feature2D { + + protected FREAK(long addr) { super(addr); } + + // internal usage only + public static FREAK __fromPtr__(long addr) { return new FREAK(addr); } + + // + // C++: static Ptr_FREAK cv::xfeatures2d::FREAK::create(bool orientationNormalized = true, bool scaleNormalized = true, float patternScale = 22.0f, int nOctaves = 4, vector_int selectedPairs = std::vector()) + // + + //javadoc: FREAK::create(orientationNormalized, scaleNormalized, patternScale, nOctaves, selectedPairs) + public static FREAK create(boolean orientationNormalized, boolean scaleNormalized, float patternScale, int nOctaves, MatOfInt selectedPairs) + { + Mat selectedPairs_mat = selectedPairs; + FREAK retVal = FREAK.__fromPtr__(create_0(orientationNormalized, scaleNormalized, patternScale, nOctaves, selectedPairs_mat.nativeObj)); + + return retVal; + } + + //javadoc: FREAK::create(orientationNormalized, scaleNormalized, patternScale, nOctaves) + public static FREAK create(boolean orientationNormalized, boolean scaleNormalized, float patternScale, int nOctaves) + { + + FREAK retVal = FREAK.__fromPtr__(create_1(orientationNormalized, scaleNormalized, patternScale, nOctaves)); + + return retVal; + } + + //javadoc: FREAK::create(orientationNormalized, scaleNormalized, patternScale) + public static FREAK create(boolean orientationNormalized, boolean scaleNormalized, float patternScale) + { + + FREAK retVal = FREAK.__fromPtr__(create_2(orientationNormalized, scaleNormalized, patternScale)); + + return retVal; + } + + //javadoc: FREAK::create(orientationNormalized, scaleNormalized) + public static FREAK create(boolean orientationNormalized, boolean scaleNormalized) + { + + FREAK retVal = FREAK.__fromPtr__(create_3(orientationNormalized, scaleNormalized)); + + return retVal; + } + + //javadoc: FREAK::create(orientationNormalized) + public static FREAK create(boolean orientationNormalized) + { + + FREAK retVal = FREAK.__fromPtr__(create_4(orientationNormalized)); + + return retVal; + } + + //javadoc: FREAK::create() + public static FREAK create() + { + + FREAK retVal = FREAK.__fromPtr__(create_5()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_FREAK cv::xfeatures2d::FREAK::create(bool orientationNormalized = true, bool scaleNormalized = true, float patternScale = 22.0f, int nOctaves = 4, vector_int selectedPairs = std::vector()) + private static native long create_0(boolean orientationNormalized, boolean scaleNormalized, float patternScale, int nOctaves, long selectedPairs_mat_nativeObj); + private static native long create_1(boolean orientationNormalized, boolean scaleNormalized, float patternScale, int nOctaves); + private static native long create_2(boolean orientationNormalized, boolean scaleNormalized, float patternScale); + private static native long create_3(boolean orientationNormalized, boolean scaleNormalized); + private static native long create_4(boolean orientationNormalized); + private static native long create_5(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/xfeatures2d/HarrisLaplaceFeatureDetector.java b/OpenCV/src/main/java/org/opencv/xfeatures2d/HarrisLaplaceFeatureDetector.java new file mode 100644 index 00000000..dcebc294 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xfeatures2d/HarrisLaplaceFeatureDetector.java @@ -0,0 +1,96 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xfeatures2d; + +import org.opencv.features2d.Feature2D; +import org.opencv.xfeatures2d.HarrisLaplaceFeatureDetector; + +// C++: class HarrisLaplaceFeatureDetector +//javadoc: HarrisLaplaceFeatureDetector + +public class HarrisLaplaceFeatureDetector extends Feature2D { + + protected HarrisLaplaceFeatureDetector(long addr) { super(addr); } + + // internal usage only + public static HarrisLaplaceFeatureDetector __fromPtr__(long addr) { return new HarrisLaplaceFeatureDetector(addr); } + + // + // C++: static Ptr_HarrisLaplaceFeatureDetector cv::xfeatures2d::HarrisLaplaceFeatureDetector::create(int numOctaves = 6, float corn_thresh = 0.01f, float DOG_thresh = 0.01f, int maxCorners = 5000, int num_layers = 4) + // + + //javadoc: HarrisLaplaceFeatureDetector::create(numOctaves, corn_thresh, DOG_thresh, maxCorners, num_layers) + public static HarrisLaplaceFeatureDetector create(int numOctaves, float corn_thresh, float DOG_thresh, int maxCorners, int num_layers) + { + + HarrisLaplaceFeatureDetector retVal = HarrisLaplaceFeatureDetector.__fromPtr__(create_0(numOctaves, corn_thresh, DOG_thresh, maxCorners, num_layers)); + + return retVal; + } + + //javadoc: HarrisLaplaceFeatureDetector::create(numOctaves, corn_thresh, DOG_thresh, maxCorners) + public static HarrisLaplaceFeatureDetector create(int numOctaves, float corn_thresh, float DOG_thresh, int maxCorners) + { + + HarrisLaplaceFeatureDetector retVal = HarrisLaplaceFeatureDetector.__fromPtr__(create_1(numOctaves, corn_thresh, DOG_thresh, maxCorners)); + + return retVal; + } + + //javadoc: HarrisLaplaceFeatureDetector::create(numOctaves, corn_thresh, DOG_thresh) + public static HarrisLaplaceFeatureDetector create(int numOctaves, float corn_thresh, float DOG_thresh) + { + + HarrisLaplaceFeatureDetector retVal = HarrisLaplaceFeatureDetector.__fromPtr__(create_2(numOctaves, corn_thresh, DOG_thresh)); + + return retVal; + } + + //javadoc: HarrisLaplaceFeatureDetector::create(numOctaves, corn_thresh) + public static HarrisLaplaceFeatureDetector create(int numOctaves, float corn_thresh) + { + + HarrisLaplaceFeatureDetector retVal = HarrisLaplaceFeatureDetector.__fromPtr__(create_3(numOctaves, corn_thresh)); + + return retVal; + } + + //javadoc: HarrisLaplaceFeatureDetector::create(numOctaves) + public static HarrisLaplaceFeatureDetector create(int numOctaves) + { + + HarrisLaplaceFeatureDetector retVal = HarrisLaplaceFeatureDetector.__fromPtr__(create_4(numOctaves)); + + return retVal; + } + + //javadoc: HarrisLaplaceFeatureDetector::create() + public static HarrisLaplaceFeatureDetector create() + { + + HarrisLaplaceFeatureDetector retVal = HarrisLaplaceFeatureDetector.__fromPtr__(create_5()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_HarrisLaplaceFeatureDetector cv::xfeatures2d::HarrisLaplaceFeatureDetector::create(int numOctaves = 6, float corn_thresh = 0.01f, float DOG_thresh = 0.01f, int maxCorners = 5000, int num_layers = 4) + private static native long create_0(int numOctaves, float corn_thresh, float DOG_thresh, int maxCorners, int num_layers); + private static native long create_1(int numOctaves, float corn_thresh, float DOG_thresh, int maxCorners); + private static native long create_2(int numOctaves, float corn_thresh, float DOG_thresh); + private static native long create_3(int numOctaves, float corn_thresh); + private static native long create_4(int numOctaves); + private static native long create_5(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/xfeatures2d/LATCH.java b/OpenCV/src/main/java/org/opencv/xfeatures2d/LATCH.java new file mode 100644 index 00000000..b74253c2 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xfeatures2d/LATCH.java @@ -0,0 +1,86 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xfeatures2d; + +import org.opencv.features2d.Feature2D; +import org.opencv.xfeatures2d.LATCH; + +// C++: class LATCH +//javadoc: LATCH + +public class LATCH extends Feature2D { + + protected LATCH(long addr) { super(addr); } + + // internal usage only + public static LATCH __fromPtr__(long addr) { return new LATCH(addr); } + + // + // C++: static Ptr_LATCH cv::xfeatures2d::LATCH::create(int bytes = 32, bool rotationInvariance = true, int half_ssd_size = 3, double sigma = 2.0) + // + + //javadoc: LATCH::create(bytes, rotationInvariance, half_ssd_size, sigma) + public static LATCH create(int bytes, boolean rotationInvariance, int half_ssd_size, double sigma) + { + + LATCH retVal = LATCH.__fromPtr__(create_0(bytes, rotationInvariance, half_ssd_size, sigma)); + + return retVal; + } + + //javadoc: LATCH::create(bytes, rotationInvariance, half_ssd_size) + public static LATCH create(int bytes, boolean rotationInvariance, int half_ssd_size) + { + + LATCH retVal = LATCH.__fromPtr__(create_1(bytes, rotationInvariance, half_ssd_size)); + + return retVal; + } + + //javadoc: LATCH::create(bytes, rotationInvariance) + public static LATCH create(int bytes, boolean rotationInvariance) + { + + LATCH retVal = LATCH.__fromPtr__(create_2(bytes, rotationInvariance)); + + return retVal; + } + + //javadoc: LATCH::create(bytes) + public static LATCH create(int bytes) + { + + LATCH retVal = LATCH.__fromPtr__(create_3(bytes)); + + return retVal; + } + + //javadoc: LATCH::create() + public static LATCH create() + { + + LATCH retVal = LATCH.__fromPtr__(create_4()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_LATCH cv::xfeatures2d::LATCH::create(int bytes = 32, bool rotationInvariance = true, int half_ssd_size = 3, double sigma = 2.0) + private static native long create_0(int bytes, boolean rotationInvariance, int half_ssd_size, double sigma); + private static native long create_1(int bytes, boolean rotationInvariance, int half_ssd_size); + private static native long create_2(int bytes, boolean rotationInvariance); + private static native long create_3(int bytes); + private static native long create_4(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/xfeatures2d/LUCID.java b/OpenCV/src/main/java/org/opencv/xfeatures2d/LUCID.java new file mode 100644 index 00000000..f8d90a51 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xfeatures2d/LUCID.java @@ -0,0 +1,66 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xfeatures2d; + +import org.opencv.features2d.Feature2D; +import org.opencv.xfeatures2d.LUCID; + +// C++: class LUCID +//javadoc: LUCID + +public class LUCID extends Feature2D { + + protected LUCID(long addr) { super(addr); } + + // internal usage only + public static LUCID __fromPtr__(long addr) { return new LUCID(addr); } + + // + // C++: static Ptr_LUCID cv::xfeatures2d::LUCID::create(int lucid_kernel = 1, int blur_kernel = 2) + // + + //javadoc: LUCID::create(lucid_kernel, blur_kernel) + public static LUCID create(int lucid_kernel, int blur_kernel) + { + + LUCID retVal = LUCID.__fromPtr__(create_0(lucid_kernel, blur_kernel)); + + return retVal; + } + + //javadoc: LUCID::create(lucid_kernel) + public static LUCID create(int lucid_kernel) + { + + LUCID retVal = LUCID.__fromPtr__(create_1(lucid_kernel)); + + return retVal; + } + + //javadoc: LUCID::create() + public static LUCID create() + { + + LUCID retVal = LUCID.__fromPtr__(create_2()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_LUCID cv::xfeatures2d::LUCID::create(int lucid_kernel = 1, int blur_kernel = 2) + private static native long create_0(int lucid_kernel, int blur_kernel); + private static native long create_1(int lucid_kernel); + private static native long create_2(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/xfeatures2d/MSDDetector.java b/OpenCV/src/main/java/org/opencv/xfeatures2d/MSDDetector.java new file mode 100644 index 00000000..77a9528b --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xfeatures2d/MSDDetector.java @@ -0,0 +1,28 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xfeatures2d; + +import org.opencv.features2d.Feature2D; + +// C++: class MSDDetector +//javadoc: MSDDetector + +public class MSDDetector extends Feature2D { + + protected MSDDetector(long addr) { super(addr); } + + // internal usage only + public static MSDDetector __fromPtr__(long addr) { return new MSDDetector(addr); } + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/xfeatures2d/PCTSignatures.java b/OpenCV/src/main/java/org/opencv/xfeatures2d/PCTSignatures.java new file mode 100644 index 00000000..cf5e57cf --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xfeatures2d/PCTSignatures.java @@ -0,0 +1,912 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xfeatures2d; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.core.MatOfFloat; +import org.opencv.core.MatOfInt; +import org.opencv.core.MatOfPoint2f; +import org.opencv.utils.Converters; +import org.opencv.xfeatures2d.PCTSignatures; + +// C++: class PCTSignatures +//javadoc: PCTSignatures + +public class PCTSignatures extends Algorithm { + + protected PCTSignatures(long addr) { super(addr); } + + // internal usage only + public static PCTSignatures __fromPtr__(long addr) { return new PCTSignatures(addr); } + + // C++: enum PointDistribution + public static final int + UNIFORM = 0, + REGULAR = 1, + NORMAL = 2; + + + // C++: enum SimilarityFunction + public static final int + MINUS = 0, + GAUSSIAN = 1, + HEURISTIC = 2; + + + // C++: enum DistanceFunction + public static final int + L0_25 = 0, + L0_5 = 1, + L1 = 2, + L2 = 3, + L2SQUARED = 4, + L5 = 5, + L_INFINITY = 6; + + + // + // C++: static Ptr_PCTSignatures cv::xfeatures2d::PCTSignatures::create(int initSampleCount = 2000, int initSeedCount = 400, int pointDistribution = 0) + // + + //javadoc: PCTSignatures::create(initSampleCount, initSeedCount, pointDistribution) + public static PCTSignatures create(int initSampleCount, int initSeedCount, int pointDistribution) + { + + PCTSignatures retVal = PCTSignatures.__fromPtr__(create_0(initSampleCount, initSeedCount, pointDistribution)); + + return retVal; + } + + //javadoc: PCTSignatures::create(initSampleCount, initSeedCount) + public static PCTSignatures create(int initSampleCount, int initSeedCount) + { + + PCTSignatures retVal = PCTSignatures.__fromPtr__(create_1(initSampleCount, initSeedCount)); + + return retVal; + } + + //javadoc: PCTSignatures::create(initSampleCount) + public static PCTSignatures create(int initSampleCount) + { + + PCTSignatures retVal = PCTSignatures.__fromPtr__(create_2(initSampleCount)); + + return retVal; + } + + //javadoc: PCTSignatures::create() + public static PCTSignatures create() + { + + PCTSignatures retVal = PCTSignatures.__fromPtr__(create_3()); + + return retVal; + } + + + // + // C++: static Ptr_PCTSignatures cv::xfeatures2d::PCTSignatures::create(vector_Point2f initSamplingPoints, int initSeedCount) + // + + //javadoc: PCTSignatures::create(initSamplingPoints, initSeedCount) + public static PCTSignatures create(MatOfPoint2f initSamplingPoints, int initSeedCount) + { + Mat initSamplingPoints_mat = initSamplingPoints; + PCTSignatures retVal = PCTSignatures.__fromPtr__(create_4(initSamplingPoints_mat.nativeObj, initSeedCount)); + + return retVal; + } + + + // + // C++: static Ptr_PCTSignatures cv::xfeatures2d::PCTSignatures::create(vector_Point2f initSamplingPoints, vector_int initClusterSeedIndexes) + // + + //javadoc: PCTSignatures::create(initSamplingPoints, initClusterSeedIndexes) + public static PCTSignatures create(MatOfPoint2f initSamplingPoints, MatOfInt initClusterSeedIndexes) + { + Mat initSamplingPoints_mat = initSamplingPoints; + Mat initClusterSeedIndexes_mat = initClusterSeedIndexes; + PCTSignatures retVal = PCTSignatures.__fromPtr__(create_5(initSamplingPoints_mat.nativeObj, initClusterSeedIndexes_mat.nativeObj)); + + return retVal; + } + + + // + // C++: float cv::xfeatures2d::PCTSignatures::getDropThreshold() + // + + //javadoc: PCTSignatures::getDropThreshold() + public float getDropThreshold() + { + + float retVal = getDropThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::xfeatures2d::PCTSignatures::getJoiningDistance() + // + + //javadoc: PCTSignatures::getJoiningDistance() + public float getJoiningDistance() + { + + float retVal = getJoiningDistance_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::xfeatures2d::PCTSignatures::getWeightA() + // + + //javadoc: PCTSignatures::getWeightA() + public float getWeightA() + { + + float retVal = getWeightA_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::xfeatures2d::PCTSignatures::getWeightB() + // + + //javadoc: PCTSignatures::getWeightB() + public float getWeightB() + { + + float retVal = getWeightB_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::xfeatures2d::PCTSignatures::getWeightContrast() + // + + //javadoc: PCTSignatures::getWeightContrast() + public float getWeightContrast() + { + + float retVal = getWeightContrast_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::xfeatures2d::PCTSignatures::getWeightEntropy() + // + + //javadoc: PCTSignatures::getWeightEntropy() + public float getWeightEntropy() + { + + float retVal = getWeightEntropy_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::xfeatures2d::PCTSignatures::getWeightL() + // + + //javadoc: PCTSignatures::getWeightL() + public float getWeightL() + { + + float retVal = getWeightL_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::xfeatures2d::PCTSignatures::getWeightX() + // + + //javadoc: PCTSignatures::getWeightX() + public float getWeightX() + { + + float retVal = getWeightX_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::xfeatures2d::PCTSignatures::getWeightY() + // + + //javadoc: PCTSignatures::getWeightY() + public float getWeightY() + { + + float retVal = getWeightY_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::xfeatures2d::PCTSignatures::getClusterMinSize() + // + + //javadoc: PCTSignatures::getClusterMinSize() + public int getClusterMinSize() + { + + int retVal = getClusterMinSize_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::xfeatures2d::PCTSignatures::getDistanceFunction() + // + + //javadoc: PCTSignatures::getDistanceFunction() + public int getDistanceFunction() + { + + int retVal = getDistanceFunction_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::xfeatures2d::PCTSignatures::getGrayscaleBits() + // + + //javadoc: PCTSignatures::getGrayscaleBits() + public int getGrayscaleBits() + { + + int retVal = getGrayscaleBits_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::xfeatures2d::PCTSignatures::getInitSeedCount() + // + + //javadoc: PCTSignatures::getInitSeedCount() + public int getInitSeedCount() + { + + int retVal = getInitSeedCount_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::xfeatures2d::PCTSignatures::getIterationCount() + // + + //javadoc: PCTSignatures::getIterationCount() + public int getIterationCount() + { + + int retVal = getIterationCount_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::xfeatures2d::PCTSignatures::getMaxClustersCount() + // + + //javadoc: PCTSignatures::getMaxClustersCount() + public int getMaxClustersCount() + { + + int retVal = getMaxClustersCount_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::xfeatures2d::PCTSignatures::getSampleCount() + // + + //javadoc: PCTSignatures::getSampleCount() + public int getSampleCount() + { + + int retVal = getSampleCount_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::xfeatures2d::PCTSignatures::getWindowRadius() + // + + //javadoc: PCTSignatures::getWindowRadius() + public int getWindowRadius() + { + + int retVal = getWindowRadius_0(nativeObj); + + return retVal; + } + + + // + // C++: vector_Point2f cv::xfeatures2d::PCTSignatures::getSamplingPoints() + // + + //javadoc: PCTSignatures::getSamplingPoints() + public MatOfPoint2f getSamplingPoints() + { + + MatOfPoint2f retVal = MatOfPoint2f.fromNativeAddr(getSamplingPoints_0(nativeObj)); + + return retVal; + } + + + // + // C++: vector_int cv::xfeatures2d::PCTSignatures::getInitSeedIndexes() + // + + //javadoc: PCTSignatures::getInitSeedIndexes() + public MatOfInt getInitSeedIndexes() + { + + MatOfInt retVal = MatOfInt.fromNativeAddr(getInitSeedIndexes_0(nativeObj)); + + return retVal; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::computeSignature(Mat image, Mat& signature) + // + + //javadoc: PCTSignatures::computeSignature(image, signature) + public void computeSignature(Mat image, Mat signature) + { + + computeSignature_0(nativeObj, image.nativeObj, signature.nativeObj); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::computeSignatures(vector_Mat images, vector_Mat signatures) + // + + //javadoc: PCTSignatures::computeSignatures(images, signatures) + public void computeSignatures(List images, List signatures) + { + Mat images_mat = Converters.vector_Mat_to_Mat(images); + Mat signatures_mat = Converters.vector_Mat_to_Mat(signatures); + computeSignatures_0(nativeObj, images_mat.nativeObj, signatures_mat.nativeObj); + + return; + } + + + // + // C++: static void cv::xfeatures2d::PCTSignatures::drawSignature(Mat source, Mat signature, Mat& result, float radiusToShorterSideRatio = 1.0 / 8, int borderThickness = 1) + // + + //javadoc: PCTSignatures::drawSignature(source, signature, result, radiusToShorterSideRatio, borderThickness) + public static void drawSignature(Mat source, Mat signature, Mat result, float radiusToShorterSideRatio, int borderThickness) + { + + drawSignature_0(source.nativeObj, signature.nativeObj, result.nativeObj, radiusToShorterSideRatio, borderThickness); + + return; + } + + //javadoc: PCTSignatures::drawSignature(source, signature, result, radiusToShorterSideRatio) + public static void drawSignature(Mat source, Mat signature, Mat result, float radiusToShorterSideRatio) + { + + drawSignature_1(source.nativeObj, signature.nativeObj, result.nativeObj, radiusToShorterSideRatio); + + return; + } + + //javadoc: PCTSignatures::drawSignature(source, signature, result) + public static void drawSignature(Mat source, Mat signature, Mat result) + { + + drawSignature_2(source.nativeObj, signature.nativeObj, result.nativeObj); + + return; + } + + + // + // C++: static void cv::xfeatures2d::PCTSignatures::generateInitPoints(vector_Point2f initPoints, int count, int pointDistribution) + // + + //javadoc: PCTSignatures::generateInitPoints(initPoints, count, pointDistribution) + public static void generateInitPoints(MatOfPoint2f initPoints, int count, int pointDistribution) + { + Mat initPoints_mat = initPoints; + generateInitPoints_0(initPoints_mat.nativeObj, count, pointDistribution); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setClusterMinSize(int clusterMinSize) + // + + //javadoc: PCTSignatures::setClusterMinSize(clusterMinSize) + public void setClusterMinSize(int clusterMinSize) + { + + setClusterMinSize_0(nativeObj, clusterMinSize); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setDistanceFunction(int distanceFunction) + // + + //javadoc: PCTSignatures::setDistanceFunction(distanceFunction) + public void setDistanceFunction(int distanceFunction) + { + + setDistanceFunction_0(nativeObj, distanceFunction); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setDropThreshold(float dropThreshold) + // + + //javadoc: PCTSignatures::setDropThreshold(dropThreshold) + public void setDropThreshold(float dropThreshold) + { + + setDropThreshold_0(nativeObj, dropThreshold); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setGrayscaleBits(int grayscaleBits) + // + + //javadoc: PCTSignatures::setGrayscaleBits(grayscaleBits) + public void setGrayscaleBits(int grayscaleBits) + { + + setGrayscaleBits_0(nativeObj, grayscaleBits); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setInitSeedIndexes(vector_int initSeedIndexes) + // + + //javadoc: PCTSignatures::setInitSeedIndexes(initSeedIndexes) + public void setInitSeedIndexes(MatOfInt initSeedIndexes) + { + Mat initSeedIndexes_mat = initSeedIndexes; + setInitSeedIndexes_0(nativeObj, initSeedIndexes_mat.nativeObj); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setIterationCount(int iterationCount) + // + + //javadoc: PCTSignatures::setIterationCount(iterationCount) + public void setIterationCount(int iterationCount) + { + + setIterationCount_0(nativeObj, iterationCount); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setJoiningDistance(float joiningDistance) + // + + //javadoc: PCTSignatures::setJoiningDistance(joiningDistance) + public void setJoiningDistance(float joiningDistance) + { + + setJoiningDistance_0(nativeObj, joiningDistance); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setMaxClustersCount(int maxClustersCount) + // + + //javadoc: PCTSignatures::setMaxClustersCount(maxClustersCount) + public void setMaxClustersCount(int maxClustersCount) + { + + setMaxClustersCount_0(nativeObj, maxClustersCount); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setSamplingPoints(vector_Point2f samplingPoints) + // + + //javadoc: PCTSignatures::setSamplingPoints(samplingPoints) + public void setSamplingPoints(MatOfPoint2f samplingPoints) + { + Mat samplingPoints_mat = samplingPoints; + setSamplingPoints_0(nativeObj, samplingPoints_mat.nativeObj); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setTranslation(int idx, float value) + // + + //javadoc: PCTSignatures::setTranslation(idx, value) + public void setTranslation(int idx, float value) + { + + setTranslation_0(nativeObj, idx, value); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setTranslations(vector_float translations) + // + + //javadoc: PCTSignatures::setTranslations(translations) + public void setTranslations(MatOfFloat translations) + { + Mat translations_mat = translations; + setTranslations_0(nativeObj, translations_mat.nativeObj); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setWeight(int idx, float value) + // + + //javadoc: PCTSignatures::setWeight(idx, value) + public void setWeight(int idx, float value) + { + + setWeight_0(nativeObj, idx, value); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setWeightA(float weight) + // + + //javadoc: PCTSignatures::setWeightA(weight) + public void setWeightA(float weight) + { + + setWeightA_0(nativeObj, weight); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setWeightB(float weight) + // + + //javadoc: PCTSignatures::setWeightB(weight) + public void setWeightB(float weight) + { + + setWeightB_0(nativeObj, weight); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setWeightContrast(float weight) + // + + //javadoc: PCTSignatures::setWeightContrast(weight) + public void setWeightContrast(float weight) + { + + setWeightContrast_0(nativeObj, weight); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setWeightEntropy(float weight) + // + + //javadoc: PCTSignatures::setWeightEntropy(weight) + public void setWeightEntropy(float weight) + { + + setWeightEntropy_0(nativeObj, weight); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setWeightL(float weight) + // + + //javadoc: PCTSignatures::setWeightL(weight) + public void setWeightL(float weight) + { + + setWeightL_0(nativeObj, weight); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setWeightX(float weight) + // + + //javadoc: PCTSignatures::setWeightX(weight) + public void setWeightX(float weight) + { + + setWeightX_0(nativeObj, weight); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setWeightY(float weight) + // + + //javadoc: PCTSignatures::setWeightY(weight) + public void setWeightY(float weight) + { + + setWeightY_0(nativeObj, weight); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setWeights(vector_float weights) + // + + //javadoc: PCTSignatures::setWeights(weights) + public void setWeights(MatOfFloat weights) + { + Mat weights_mat = weights; + setWeights_0(nativeObj, weights_mat.nativeObj); + + return; + } + + + // + // C++: void cv::xfeatures2d::PCTSignatures::setWindowRadius(int radius) + // + + //javadoc: PCTSignatures::setWindowRadius(radius) + public void setWindowRadius(int radius) + { + + setWindowRadius_0(nativeObj, radius); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_PCTSignatures cv::xfeatures2d::PCTSignatures::create(int initSampleCount = 2000, int initSeedCount = 400, int pointDistribution = 0) + private static native long create_0(int initSampleCount, int initSeedCount, int pointDistribution); + private static native long create_1(int initSampleCount, int initSeedCount); + private static native long create_2(int initSampleCount); + private static native long create_3(); + + // C++: static Ptr_PCTSignatures cv::xfeatures2d::PCTSignatures::create(vector_Point2f initSamplingPoints, int initSeedCount) + private static native long create_4(long initSamplingPoints_mat_nativeObj, int initSeedCount); + + // C++: static Ptr_PCTSignatures cv::xfeatures2d::PCTSignatures::create(vector_Point2f initSamplingPoints, vector_int initClusterSeedIndexes) + private static native long create_5(long initSamplingPoints_mat_nativeObj, long initClusterSeedIndexes_mat_nativeObj); + + // C++: float cv::xfeatures2d::PCTSignatures::getDropThreshold() + private static native float getDropThreshold_0(long nativeObj); + + // C++: float cv::xfeatures2d::PCTSignatures::getJoiningDistance() + private static native float getJoiningDistance_0(long nativeObj); + + // C++: float cv::xfeatures2d::PCTSignatures::getWeightA() + private static native float getWeightA_0(long nativeObj); + + // C++: float cv::xfeatures2d::PCTSignatures::getWeightB() + private static native float getWeightB_0(long nativeObj); + + // C++: float cv::xfeatures2d::PCTSignatures::getWeightContrast() + private static native float getWeightContrast_0(long nativeObj); + + // C++: float cv::xfeatures2d::PCTSignatures::getWeightEntropy() + private static native float getWeightEntropy_0(long nativeObj); + + // C++: float cv::xfeatures2d::PCTSignatures::getWeightL() + private static native float getWeightL_0(long nativeObj); + + // C++: float cv::xfeatures2d::PCTSignatures::getWeightX() + private static native float getWeightX_0(long nativeObj); + + // C++: float cv::xfeatures2d::PCTSignatures::getWeightY() + private static native float getWeightY_0(long nativeObj); + + // C++: int cv::xfeatures2d::PCTSignatures::getClusterMinSize() + private static native int getClusterMinSize_0(long nativeObj); + + // C++: int cv::xfeatures2d::PCTSignatures::getDistanceFunction() + private static native int getDistanceFunction_0(long nativeObj); + + // C++: int cv::xfeatures2d::PCTSignatures::getGrayscaleBits() + private static native int getGrayscaleBits_0(long nativeObj); + + // C++: int cv::xfeatures2d::PCTSignatures::getInitSeedCount() + private static native int getInitSeedCount_0(long nativeObj); + + // C++: int cv::xfeatures2d::PCTSignatures::getIterationCount() + private static native int getIterationCount_0(long nativeObj); + + // C++: int cv::xfeatures2d::PCTSignatures::getMaxClustersCount() + private static native int getMaxClustersCount_0(long nativeObj); + + // C++: int cv::xfeatures2d::PCTSignatures::getSampleCount() + private static native int getSampleCount_0(long nativeObj); + + // C++: int cv::xfeatures2d::PCTSignatures::getWindowRadius() + private static native int getWindowRadius_0(long nativeObj); + + // C++: vector_Point2f cv::xfeatures2d::PCTSignatures::getSamplingPoints() + private static native long getSamplingPoints_0(long nativeObj); + + // C++: vector_int cv::xfeatures2d::PCTSignatures::getInitSeedIndexes() + private static native long getInitSeedIndexes_0(long nativeObj); + + // C++: void cv::xfeatures2d::PCTSignatures::computeSignature(Mat image, Mat& signature) + private static native void computeSignature_0(long nativeObj, long image_nativeObj, long signature_nativeObj); + + // C++: void cv::xfeatures2d::PCTSignatures::computeSignatures(vector_Mat images, vector_Mat signatures) + private static native void computeSignatures_0(long nativeObj, long images_mat_nativeObj, long signatures_mat_nativeObj); + + // C++: static void cv::xfeatures2d::PCTSignatures::drawSignature(Mat source, Mat signature, Mat& result, float radiusToShorterSideRatio = 1.0 / 8, int borderThickness = 1) + private static native void drawSignature_0(long source_nativeObj, long signature_nativeObj, long result_nativeObj, float radiusToShorterSideRatio, int borderThickness); + private static native void drawSignature_1(long source_nativeObj, long signature_nativeObj, long result_nativeObj, float radiusToShorterSideRatio); + private static native void drawSignature_2(long source_nativeObj, long signature_nativeObj, long result_nativeObj); + + // C++: static void cv::xfeatures2d::PCTSignatures::generateInitPoints(vector_Point2f initPoints, int count, int pointDistribution) + private static native void generateInitPoints_0(long initPoints_mat_nativeObj, int count, int pointDistribution); + + // C++: void cv::xfeatures2d::PCTSignatures::setClusterMinSize(int clusterMinSize) + private static native void setClusterMinSize_0(long nativeObj, int clusterMinSize); + + // C++: void cv::xfeatures2d::PCTSignatures::setDistanceFunction(int distanceFunction) + private static native void setDistanceFunction_0(long nativeObj, int distanceFunction); + + // C++: void cv::xfeatures2d::PCTSignatures::setDropThreshold(float dropThreshold) + private static native void setDropThreshold_0(long nativeObj, float dropThreshold); + + // C++: void cv::xfeatures2d::PCTSignatures::setGrayscaleBits(int grayscaleBits) + private static native void setGrayscaleBits_0(long nativeObj, int grayscaleBits); + + // C++: void cv::xfeatures2d::PCTSignatures::setInitSeedIndexes(vector_int initSeedIndexes) + private static native void setInitSeedIndexes_0(long nativeObj, long initSeedIndexes_mat_nativeObj); + + // C++: void cv::xfeatures2d::PCTSignatures::setIterationCount(int iterationCount) + private static native void setIterationCount_0(long nativeObj, int iterationCount); + + // C++: void cv::xfeatures2d::PCTSignatures::setJoiningDistance(float joiningDistance) + private static native void setJoiningDistance_0(long nativeObj, float joiningDistance); + + // C++: void cv::xfeatures2d::PCTSignatures::setMaxClustersCount(int maxClustersCount) + private static native void setMaxClustersCount_0(long nativeObj, int maxClustersCount); + + // C++: void cv::xfeatures2d::PCTSignatures::setSamplingPoints(vector_Point2f samplingPoints) + private static native void setSamplingPoints_0(long nativeObj, long samplingPoints_mat_nativeObj); + + // C++: void cv::xfeatures2d::PCTSignatures::setTranslation(int idx, float value) + private static native void setTranslation_0(long nativeObj, int idx, float value); + + // C++: void cv::xfeatures2d::PCTSignatures::setTranslations(vector_float translations) + private static native void setTranslations_0(long nativeObj, long translations_mat_nativeObj); + + // C++: void cv::xfeatures2d::PCTSignatures::setWeight(int idx, float value) + private static native void setWeight_0(long nativeObj, int idx, float value); + + // C++: void cv::xfeatures2d::PCTSignatures::setWeightA(float weight) + private static native void setWeightA_0(long nativeObj, float weight); + + // C++: void cv::xfeatures2d::PCTSignatures::setWeightB(float weight) + private static native void setWeightB_0(long nativeObj, float weight); + + // C++: void cv::xfeatures2d::PCTSignatures::setWeightContrast(float weight) + private static native void setWeightContrast_0(long nativeObj, float weight); + + // C++: void cv::xfeatures2d::PCTSignatures::setWeightEntropy(float weight) + private static native void setWeightEntropy_0(long nativeObj, float weight); + + // C++: void cv::xfeatures2d::PCTSignatures::setWeightL(float weight) + private static native void setWeightL_0(long nativeObj, float weight); + + // C++: void cv::xfeatures2d::PCTSignatures::setWeightX(float weight) + private static native void setWeightX_0(long nativeObj, float weight); + + // C++: void cv::xfeatures2d::PCTSignatures::setWeightY(float weight) + private static native void setWeightY_0(long nativeObj, float weight); + + // C++: void cv::xfeatures2d::PCTSignatures::setWeights(vector_float weights) + private static native void setWeights_0(long nativeObj, long weights_mat_nativeObj); + + // C++: void cv::xfeatures2d::PCTSignatures::setWindowRadius(int radius) + private static native void setWindowRadius_0(long nativeObj, int radius); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/xfeatures2d/PCTSignaturesSQFD.java b/OpenCV/src/main/java/org/opencv/xfeatures2d/PCTSignaturesSQFD.java new file mode 100644 index 00000000..ed98758b --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xfeatures2d/PCTSignaturesSQFD.java @@ -0,0 +1,116 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xfeatures2d; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.core.MatOfFloat; +import org.opencv.utils.Converters; +import org.opencv.xfeatures2d.PCTSignaturesSQFD; + +// C++: class PCTSignaturesSQFD +//javadoc: PCTSignaturesSQFD + +public class PCTSignaturesSQFD extends Algorithm { + + protected PCTSignaturesSQFD(long addr) { super(addr); } + + // internal usage only + public static PCTSignaturesSQFD __fromPtr__(long addr) { return new PCTSignaturesSQFD(addr); } + + // + // C++: static Ptr_PCTSignaturesSQFD cv::xfeatures2d::PCTSignaturesSQFD::create(int distanceFunction = 3, int similarityFunction = 2, float similarityParameter = 1.0f) + // + + //javadoc: PCTSignaturesSQFD::create(distanceFunction, similarityFunction, similarityParameter) + public static PCTSignaturesSQFD create(int distanceFunction, int similarityFunction, float similarityParameter) + { + + PCTSignaturesSQFD retVal = PCTSignaturesSQFD.__fromPtr__(create_0(distanceFunction, similarityFunction, similarityParameter)); + + return retVal; + } + + //javadoc: PCTSignaturesSQFD::create(distanceFunction, similarityFunction) + public static PCTSignaturesSQFD create(int distanceFunction, int similarityFunction) + { + + PCTSignaturesSQFD retVal = PCTSignaturesSQFD.__fromPtr__(create_1(distanceFunction, similarityFunction)); + + return retVal; + } + + //javadoc: PCTSignaturesSQFD::create(distanceFunction) + public static PCTSignaturesSQFD create(int distanceFunction) + { + + PCTSignaturesSQFD retVal = PCTSignaturesSQFD.__fromPtr__(create_2(distanceFunction)); + + return retVal; + } + + //javadoc: PCTSignaturesSQFD::create() + public static PCTSignaturesSQFD create() + { + + PCTSignaturesSQFD retVal = PCTSignaturesSQFD.__fromPtr__(create_3()); + + return retVal; + } + + + // + // C++: float cv::xfeatures2d::PCTSignaturesSQFD::computeQuadraticFormDistance(Mat _signature0, Mat _signature1) + // + + //javadoc: PCTSignaturesSQFD::computeQuadraticFormDistance(_signature0, _signature1) + public float computeQuadraticFormDistance(Mat _signature0, Mat _signature1) + { + + float retVal = computeQuadraticFormDistance_0(nativeObj, _signature0.nativeObj, _signature1.nativeObj); + + return retVal; + } + + + // + // C++: void cv::xfeatures2d::PCTSignaturesSQFD::computeQuadraticFormDistances(Mat sourceSignature, vector_Mat imageSignatures, vector_float distances) + // + + //javadoc: PCTSignaturesSQFD::computeQuadraticFormDistances(sourceSignature, imageSignatures, distances) + public void computeQuadraticFormDistances(Mat sourceSignature, List imageSignatures, MatOfFloat distances) + { + Mat imageSignatures_mat = Converters.vector_Mat_to_Mat(imageSignatures); + Mat distances_mat = distances; + computeQuadraticFormDistances_0(nativeObj, sourceSignature.nativeObj, imageSignatures_mat.nativeObj, distances_mat.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_PCTSignaturesSQFD cv::xfeatures2d::PCTSignaturesSQFD::create(int distanceFunction = 3, int similarityFunction = 2, float similarityParameter = 1.0f) + private static native long create_0(int distanceFunction, int similarityFunction, float similarityParameter); + private static native long create_1(int distanceFunction, int similarityFunction); + private static native long create_2(int distanceFunction); + private static native long create_3(); + + // C++: float cv::xfeatures2d::PCTSignaturesSQFD::computeQuadraticFormDistance(Mat _signature0, Mat _signature1) + private static native float computeQuadraticFormDistance_0(long nativeObj, long _signature0_nativeObj, long _signature1_nativeObj); + + // C++: void cv::xfeatures2d::PCTSignaturesSQFD::computeQuadraticFormDistances(Mat sourceSignature, vector_Mat imageSignatures, vector_float distances) + private static native void computeQuadraticFormDistances_0(long nativeObj, long sourceSignature_nativeObj, long imageSignatures_mat_nativeObj, long distances_mat_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/xfeatures2d/SIFT.java b/OpenCV/src/main/java/org/opencv/xfeatures2d/SIFT.java new file mode 100644 index 00000000..2fad52c5 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xfeatures2d/SIFT.java @@ -0,0 +1,96 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xfeatures2d; + +import org.opencv.features2d.Feature2D; +import org.opencv.xfeatures2d.SIFT; + +// C++: class SIFT +//javadoc: SIFT + +public class SIFT extends Feature2D { + + protected SIFT(long addr) { super(addr); } + + // internal usage only + public static SIFT __fromPtr__(long addr) { return new SIFT(addr); } + + // + // C++: static Ptr_SIFT cv::xfeatures2d::SIFT::create(int nfeatures = 0, int nOctaveLayers = 3, double contrastThreshold = 0.04, double edgeThreshold = 10, double sigma = 1.6) + // + + //javadoc: SIFT::create(nfeatures, nOctaveLayers, contrastThreshold, edgeThreshold, sigma) + public static SIFT create(int nfeatures, int nOctaveLayers, double contrastThreshold, double edgeThreshold, double sigma) + { + + SIFT retVal = SIFT.__fromPtr__(create_0(nfeatures, nOctaveLayers, contrastThreshold, edgeThreshold, sigma)); + + return retVal; + } + + //javadoc: SIFT::create(nfeatures, nOctaveLayers, contrastThreshold, edgeThreshold) + public static SIFT create(int nfeatures, int nOctaveLayers, double contrastThreshold, double edgeThreshold) + { + + SIFT retVal = SIFT.__fromPtr__(create_1(nfeatures, nOctaveLayers, contrastThreshold, edgeThreshold)); + + return retVal; + } + + //javadoc: SIFT::create(nfeatures, nOctaveLayers, contrastThreshold) + public static SIFT create(int nfeatures, int nOctaveLayers, double contrastThreshold) + { + + SIFT retVal = SIFT.__fromPtr__(create_2(nfeatures, nOctaveLayers, contrastThreshold)); + + return retVal; + } + + //javadoc: SIFT::create(nfeatures, nOctaveLayers) + public static SIFT create(int nfeatures, int nOctaveLayers) + { + + SIFT retVal = SIFT.__fromPtr__(create_3(nfeatures, nOctaveLayers)); + + return retVal; + } + + //javadoc: SIFT::create(nfeatures) + public static SIFT create(int nfeatures) + { + + SIFT retVal = SIFT.__fromPtr__(create_4(nfeatures)); + + return retVal; + } + + //javadoc: SIFT::create() + public static SIFT create() + { + + SIFT retVal = SIFT.__fromPtr__(create_5()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_SIFT cv::xfeatures2d::SIFT::create(int nfeatures = 0, int nOctaveLayers = 3, double contrastThreshold = 0.04, double edgeThreshold = 10, double sigma = 1.6) + private static native long create_0(int nfeatures, int nOctaveLayers, double contrastThreshold, double edgeThreshold, double sigma); + private static native long create_1(int nfeatures, int nOctaveLayers, double contrastThreshold, double edgeThreshold); + private static native long create_2(int nfeatures, int nOctaveLayers, double contrastThreshold); + private static native long create_3(int nfeatures, int nOctaveLayers); + private static native long create_4(int nfeatures); + private static native long create_5(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/xfeatures2d/SURF.java b/OpenCV/src/main/java/org/opencv/xfeatures2d/SURF.java new file mode 100644 index 00000000..d9cbd703 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xfeatures2d/SURF.java @@ -0,0 +1,266 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xfeatures2d; + +import org.opencv.features2d.Feature2D; +import org.opencv.xfeatures2d.SURF; + +// C++: class SURF +//javadoc: SURF + +public class SURF extends Feature2D { + + protected SURF(long addr) { super(addr); } + + // internal usage only + public static SURF __fromPtr__(long addr) { return new SURF(addr); } + + // + // C++: static Ptr_SURF cv::xfeatures2d::SURF::create(double hessianThreshold = 100, int nOctaves = 4, int nOctaveLayers = 3, bool extended = false, bool upright = false) + // + + //javadoc: SURF::create(hessianThreshold, nOctaves, nOctaveLayers, extended, upright) + public static SURF create(double hessianThreshold, int nOctaves, int nOctaveLayers, boolean extended, boolean upright) + { + + SURF retVal = SURF.__fromPtr__(create_0(hessianThreshold, nOctaves, nOctaveLayers, extended, upright)); + + return retVal; + } + + //javadoc: SURF::create(hessianThreshold, nOctaves, nOctaveLayers, extended) + public static SURF create(double hessianThreshold, int nOctaves, int nOctaveLayers, boolean extended) + { + + SURF retVal = SURF.__fromPtr__(create_1(hessianThreshold, nOctaves, nOctaveLayers, extended)); + + return retVal; + } + + //javadoc: SURF::create(hessianThreshold, nOctaves, nOctaveLayers) + public static SURF create(double hessianThreshold, int nOctaves, int nOctaveLayers) + { + + SURF retVal = SURF.__fromPtr__(create_2(hessianThreshold, nOctaves, nOctaveLayers)); + + return retVal; + } + + //javadoc: SURF::create(hessianThreshold, nOctaves) + public static SURF create(double hessianThreshold, int nOctaves) + { + + SURF retVal = SURF.__fromPtr__(create_3(hessianThreshold, nOctaves)); + + return retVal; + } + + //javadoc: SURF::create(hessianThreshold) + public static SURF create(double hessianThreshold) + { + + SURF retVal = SURF.__fromPtr__(create_4(hessianThreshold)); + + return retVal; + } + + //javadoc: SURF::create() + public static SURF create() + { + + SURF retVal = SURF.__fromPtr__(create_5()); + + return retVal; + } + + + // + // C++: bool cv::xfeatures2d::SURF::getExtended() + // + + //javadoc: SURF::getExtended() + public boolean getExtended() + { + + boolean retVal = getExtended_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::xfeatures2d::SURF::getUpright() + // + + //javadoc: SURF::getUpright() + public boolean getUpright() + { + + boolean retVal = getUpright_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::xfeatures2d::SURF::getHessianThreshold() + // + + //javadoc: SURF::getHessianThreshold() + public double getHessianThreshold() + { + + double retVal = getHessianThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::xfeatures2d::SURF::getNOctaveLayers() + // + + //javadoc: SURF::getNOctaveLayers() + public int getNOctaveLayers() + { + + int retVal = getNOctaveLayers_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::xfeatures2d::SURF::getNOctaves() + // + + //javadoc: SURF::getNOctaves() + public int getNOctaves() + { + + int retVal = getNOctaves_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::xfeatures2d::SURF::setExtended(bool extended) + // + + //javadoc: SURF::setExtended(extended) + public void setExtended(boolean extended) + { + + setExtended_0(nativeObj, extended); + + return; + } + + + // + // C++: void cv::xfeatures2d::SURF::setHessianThreshold(double hessianThreshold) + // + + //javadoc: SURF::setHessianThreshold(hessianThreshold) + public void setHessianThreshold(double hessianThreshold) + { + + setHessianThreshold_0(nativeObj, hessianThreshold); + + return; + } + + + // + // C++: void cv::xfeatures2d::SURF::setNOctaveLayers(int nOctaveLayers) + // + + //javadoc: SURF::setNOctaveLayers(nOctaveLayers) + public void setNOctaveLayers(int nOctaveLayers) + { + + setNOctaveLayers_0(nativeObj, nOctaveLayers); + + return; + } + + + // + // C++: void cv::xfeatures2d::SURF::setNOctaves(int nOctaves) + // + + //javadoc: SURF::setNOctaves(nOctaves) + public void setNOctaves(int nOctaves) + { + + setNOctaves_0(nativeObj, nOctaves); + + return; + } + + + // + // C++: void cv::xfeatures2d::SURF::setUpright(bool upright) + // + + //javadoc: SURF::setUpright(upright) + public void setUpright(boolean upright) + { + + setUpright_0(nativeObj, upright); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_SURF cv::xfeatures2d::SURF::create(double hessianThreshold = 100, int nOctaves = 4, int nOctaveLayers = 3, bool extended = false, bool upright = false) + private static native long create_0(double hessianThreshold, int nOctaves, int nOctaveLayers, boolean extended, boolean upright); + private static native long create_1(double hessianThreshold, int nOctaves, int nOctaveLayers, boolean extended); + private static native long create_2(double hessianThreshold, int nOctaves, int nOctaveLayers); + private static native long create_3(double hessianThreshold, int nOctaves); + private static native long create_4(double hessianThreshold); + private static native long create_5(); + + // C++: bool cv::xfeatures2d::SURF::getExtended() + private static native boolean getExtended_0(long nativeObj); + + // C++: bool cv::xfeatures2d::SURF::getUpright() + private static native boolean getUpright_0(long nativeObj); + + // C++: double cv::xfeatures2d::SURF::getHessianThreshold() + private static native double getHessianThreshold_0(long nativeObj); + + // C++: int cv::xfeatures2d::SURF::getNOctaveLayers() + private static native int getNOctaveLayers_0(long nativeObj); + + // C++: int cv::xfeatures2d::SURF::getNOctaves() + private static native int getNOctaves_0(long nativeObj); + + // C++: void cv::xfeatures2d::SURF::setExtended(bool extended) + private static native void setExtended_0(long nativeObj, boolean extended); + + // C++: void cv::xfeatures2d::SURF::setHessianThreshold(double hessianThreshold) + private static native void setHessianThreshold_0(long nativeObj, double hessianThreshold); + + // C++: void cv::xfeatures2d::SURF::setNOctaveLayers(int nOctaveLayers) + private static native void setNOctaveLayers_0(long nativeObj, int nOctaveLayers); + + // C++: void cv::xfeatures2d::SURF::setNOctaves(int nOctaves) + private static native void setNOctaves_0(long nativeObj, int nOctaves); + + // C++: void cv::xfeatures2d::SURF::setUpright(bool upright) + private static native void setUpright_0(long nativeObj, boolean upright); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/xfeatures2d/StarDetector.java b/OpenCV/src/main/java/org/opencv/xfeatures2d/StarDetector.java new file mode 100644 index 00000000..52b05ba9 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xfeatures2d/StarDetector.java @@ -0,0 +1,96 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xfeatures2d; + +import org.opencv.features2d.Feature2D; +import org.opencv.xfeatures2d.StarDetector; + +// C++: class StarDetector +//javadoc: StarDetector + +public class StarDetector extends Feature2D { + + protected StarDetector(long addr) { super(addr); } + + // internal usage only + public static StarDetector __fromPtr__(long addr) { return new StarDetector(addr); } + + // + // C++: static Ptr_StarDetector cv::xfeatures2d::StarDetector::create(int maxSize = 45, int responseThreshold = 30, int lineThresholdProjected = 10, int lineThresholdBinarized = 8, int suppressNonmaxSize = 5) + // + + //javadoc: StarDetector::create(maxSize, responseThreshold, lineThresholdProjected, lineThresholdBinarized, suppressNonmaxSize) + public static StarDetector create(int maxSize, int responseThreshold, int lineThresholdProjected, int lineThresholdBinarized, int suppressNonmaxSize) + { + + StarDetector retVal = StarDetector.__fromPtr__(create_0(maxSize, responseThreshold, lineThresholdProjected, lineThresholdBinarized, suppressNonmaxSize)); + + return retVal; + } + + //javadoc: StarDetector::create(maxSize, responseThreshold, lineThresholdProjected, lineThresholdBinarized) + public static StarDetector create(int maxSize, int responseThreshold, int lineThresholdProjected, int lineThresholdBinarized) + { + + StarDetector retVal = StarDetector.__fromPtr__(create_1(maxSize, responseThreshold, lineThresholdProjected, lineThresholdBinarized)); + + return retVal; + } + + //javadoc: StarDetector::create(maxSize, responseThreshold, lineThresholdProjected) + public static StarDetector create(int maxSize, int responseThreshold, int lineThresholdProjected) + { + + StarDetector retVal = StarDetector.__fromPtr__(create_2(maxSize, responseThreshold, lineThresholdProjected)); + + return retVal; + } + + //javadoc: StarDetector::create(maxSize, responseThreshold) + public static StarDetector create(int maxSize, int responseThreshold) + { + + StarDetector retVal = StarDetector.__fromPtr__(create_3(maxSize, responseThreshold)); + + return retVal; + } + + //javadoc: StarDetector::create(maxSize) + public static StarDetector create(int maxSize) + { + + StarDetector retVal = StarDetector.__fromPtr__(create_4(maxSize)); + + return retVal; + } + + //javadoc: StarDetector::create() + public static StarDetector create() + { + + StarDetector retVal = StarDetector.__fromPtr__(create_5()); + + return retVal; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_StarDetector cv::xfeatures2d::StarDetector::create(int maxSize = 45, int responseThreshold = 30, int lineThresholdProjected = 10, int lineThresholdBinarized = 8, int suppressNonmaxSize = 5) + private static native long create_0(int maxSize, int responseThreshold, int lineThresholdProjected, int lineThresholdBinarized, int suppressNonmaxSize); + private static native long create_1(int maxSize, int responseThreshold, int lineThresholdProjected, int lineThresholdBinarized); + private static native long create_2(int maxSize, int responseThreshold, int lineThresholdProjected); + private static native long create_3(int maxSize, int responseThreshold); + private static native long create_4(int maxSize); + private static native long create_5(); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/xfeatures2d/VGG.java b/OpenCV/src/main/java/org/opencv/xfeatures2d/VGG.java new file mode 100644 index 00000000..7c3ffd8a --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xfeatures2d/VGG.java @@ -0,0 +1,276 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xfeatures2d; + +import org.opencv.features2d.Feature2D; +import org.opencv.xfeatures2d.VGG; + +// C++: class VGG +//javadoc: VGG + +public class VGG extends Feature2D { + + protected VGG(long addr) { super(addr); } + + // internal usage only + public static VGG __fromPtr__(long addr) { return new VGG(addr); } + + // + // C++: static Ptr_VGG cv::xfeatures2d::VGG::create(int desc = VGG::VGG_120, float isigma = 1.4f, bool img_normalize = true, bool use_scale_orientation = true, float scale_factor = 6.25f, bool dsc_normalize = false) + // + + //javadoc: VGG::create(desc, isigma, img_normalize, use_scale_orientation, scale_factor, dsc_normalize) + public static VGG create(int desc, float isigma, boolean img_normalize, boolean use_scale_orientation, float scale_factor, boolean dsc_normalize) + { + + VGG retVal = VGG.__fromPtr__(create_0(desc, isigma, img_normalize, use_scale_orientation, scale_factor, dsc_normalize)); + + return retVal; + } + + //javadoc: VGG::create(desc, isigma, img_normalize, use_scale_orientation, scale_factor) + public static VGG create(int desc, float isigma, boolean img_normalize, boolean use_scale_orientation, float scale_factor) + { + + VGG retVal = VGG.__fromPtr__(create_1(desc, isigma, img_normalize, use_scale_orientation, scale_factor)); + + return retVal; + } + + //javadoc: VGG::create(desc, isigma, img_normalize, use_scale_orientation) + public static VGG create(int desc, float isigma, boolean img_normalize, boolean use_scale_orientation) + { + + VGG retVal = VGG.__fromPtr__(create_2(desc, isigma, img_normalize, use_scale_orientation)); + + return retVal; + } + + //javadoc: VGG::create(desc, isigma, img_normalize) + public static VGG create(int desc, float isigma, boolean img_normalize) + { + + VGG retVal = VGG.__fromPtr__(create_3(desc, isigma, img_normalize)); + + return retVal; + } + + //javadoc: VGG::create(desc, isigma) + public static VGG create(int desc, float isigma) + { + + VGG retVal = VGG.__fromPtr__(create_4(desc, isigma)); + + return retVal; + } + + //javadoc: VGG::create(desc) + public static VGG create(int desc) + { + + VGG retVal = VGG.__fromPtr__(create_5(desc)); + + return retVal; + } + + //javadoc: VGG::create() + public static VGG create() + { + + VGG retVal = VGG.__fromPtr__(create_6()); + + return retVal; + } + + + // + // C++: bool cv::xfeatures2d::VGG::getUseNormalizeDescriptor() + // + + //javadoc: VGG::getUseNormalizeDescriptor() + public boolean getUseNormalizeDescriptor() + { + + boolean retVal = getUseNormalizeDescriptor_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::xfeatures2d::VGG::getUseNormalizeImage() + // + + //javadoc: VGG::getUseNormalizeImage() + public boolean getUseNormalizeImage() + { + + boolean retVal = getUseNormalizeImage_0(nativeObj); + + return retVal; + } + + + // + // C++: bool cv::xfeatures2d::VGG::getUseScaleOrientation() + // + + //javadoc: VGG::getUseScaleOrientation() + public boolean getUseScaleOrientation() + { + + boolean retVal = getUseScaleOrientation_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::xfeatures2d::VGG::getScaleFactor() + // + + //javadoc: VGG::getScaleFactor() + public float getScaleFactor() + { + + float retVal = getScaleFactor_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::xfeatures2d::VGG::getSigma() + // + + //javadoc: VGG::getSigma() + public float getSigma() + { + + float retVal = getSigma_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::xfeatures2d::VGG::setScaleFactor(float scale_factor) + // + + //javadoc: VGG::setScaleFactor(scale_factor) + public void setScaleFactor(float scale_factor) + { + + setScaleFactor_0(nativeObj, scale_factor); + + return; + } + + + // + // C++: void cv::xfeatures2d::VGG::setSigma(float isigma) + // + + //javadoc: VGG::setSigma(isigma) + public void setSigma(float isigma) + { + + setSigma_0(nativeObj, isigma); + + return; + } + + + // + // C++: void cv::xfeatures2d::VGG::setUseNormalizeDescriptor(bool dsc_normalize) + // + + //javadoc: VGG::setUseNormalizeDescriptor(dsc_normalize) + public void setUseNormalizeDescriptor(boolean dsc_normalize) + { + + setUseNormalizeDescriptor_0(nativeObj, dsc_normalize); + + return; + } + + + // + // C++: void cv::xfeatures2d::VGG::setUseNormalizeImage(bool img_normalize) + // + + //javadoc: VGG::setUseNormalizeImage(img_normalize) + public void setUseNormalizeImage(boolean img_normalize) + { + + setUseNormalizeImage_0(nativeObj, img_normalize); + + return; + } + + + // + // C++: void cv::xfeatures2d::VGG::setUseScaleOrientation(bool use_scale_orientation) + // + + //javadoc: VGG::setUseScaleOrientation(use_scale_orientation) + public void setUseScaleOrientation(boolean use_scale_orientation) + { + + setUseScaleOrientation_0(nativeObj, use_scale_orientation); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_VGG cv::xfeatures2d::VGG::create(int desc = VGG::VGG_120, float isigma = 1.4f, bool img_normalize = true, bool use_scale_orientation = true, float scale_factor = 6.25f, bool dsc_normalize = false) + private static native long create_0(int desc, float isigma, boolean img_normalize, boolean use_scale_orientation, float scale_factor, boolean dsc_normalize); + private static native long create_1(int desc, float isigma, boolean img_normalize, boolean use_scale_orientation, float scale_factor); + private static native long create_2(int desc, float isigma, boolean img_normalize, boolean use_scale_orientation); + private static native long create_3(int desc, float isigma, boolean img_normalize); + private static native long create_4(int desc, float isigma); + private static native long create_5(int desc); + private static native long create_6(); + + // C++: bool cv::xfeatures2d::VGG::getUseNormalizeDescriptor() + private static native boolean getUseNormalizeDescriptor_0(long nativeObj); + + // C++: bool cv::xfeatures2d::VGG::getUseNormalizeImage() + private static native boolean getUseNormalizeImage_0(long nativeObj); + + // C++: bool cv::xfeatures2d::VGG::getUseScaleOrientation() + private static native boolean getUseScaleOrientation_0(long nativeObj); + + // C++: float cv::xfeatures2d::VGG::getScaleFactor() + private static native float getScaleFactor_0(long nativeObj); + + // C++: float cv::xfeatures2d::VGG::getSigma() + private static native float getSigma_0(long nativeObj); + + // C++: void cv::xfeatures2d::VGG::setScaleFactor(float scale_factor) + private static native void setScaleFactor_0(long nativeObj, float scale_factor); + + // C++: void cv::xfeatures2d::VGG::setSigma(float isigma) + private static native void setSigma_0(long nativeObj, float isigma); + + // C++: void cv::xfeatures2d::VGG::setUseNormalizeDescriptor(bool dsc_normalize) + private static native void setUseNormalizeDescriptor_0(long nativeObj, boolean dsc_normalize); + + // C++: void cv::xfeatures2d::VGG::setUseNormalizeImage(bool img_normalize) + private static native void setUseNormalizeImage_0(long nativeObj, boolean img_normalize); + + // C++: void cv::xfeatures2d::VGG::setUseScaleOrientation(bool use_scale_orientation) + private static native void setUseScaleOrientation_0(long nativeObj, boolean use_scale_orientation); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/xfeatures2d/Xfeatures2d.java b/OpenCV/src/main/java/org/opencv/xfeatures2d/Xfeatures2d.java new file mode 100644 index 00000000..30bb87c7 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xfeatures2d/Xfeatures2d.java @@ -0,0 +1,92 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xfeatures2d; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Mat; +import org.opencv.core.MatOfDMatch; +import org.opencv.core.MatOfKeyPoint; +import org.opencv.core.Size; +import org.opencv.utils.Converters; + +// C++: class Xfeatures2d +//javadoc: Xfeatures2d + +public class Xfeatures2d { + + // C++: enum KeypointLayout + public static final int + SURF_CUDA_X_ROW = 0, + SURF_CUDA_Y_ROW = 0+1, + SURF_CUDA_LAPLACIAN_ROW = 0+2, + SURF_CUDA_OCTAVE_ROW = 0+3, + SURF_CUDA_SIZE_ROW = 0+4, + SURF_CUDA_ANGLE_ROW = 0+5, + SURF_CUDA_HESSIAN_ROW = 0+6, + SURF_CUDA_ROWS_COUNT = 0+7; + + + // + // C++: void cv::xfeatures2d::matchGMS(Size size1, Size size2, vector_KeyPoint keypoints1, vector_KeyPoint keypoints2, vector_DMatch matches1to2, vector_DMatch& matchesGMS, bool withRotation = false, bool withScale = false, double thresholdFactor = 6.0) + // + + //javadoc: matchGMS(size1, size2, keypoints1, keypoints2, matches1to2, matchesGMS, withRotation, withScale, thresholdFactor) + public static void matchGMS(Size size1, Size size2, MatOfKeyPoint keypoints1, MatOfKeyPoint keypoints2, MatOfDMatch matches1to2, MatOfDMatch matchesGMS, boolean withRotation, boolean withScale, double thresholdFactor) + { + Mat keypoints1_mat = keypoints1; + Mat keypoints2_mat = keypoints2; + Mat matches1to2_mat = matches1to2; + Mat matchesGMS_mat = matchesGMS; + matchGMS_0(size1.width, size1.height, size2.width, size2.height, keypoints1_mat.nativeObj, keypoints2_mat.nativeObj, matches1to2_mat.nativeObj, matchesGMS_mat.nativeObj, withRotation, withScale, thresholdFactor); + + return; + } + + //javadoc: matchGMS(size1, size2, keypoints1, keypoints2, matches1to2, matchesGMS, withRotation, withScale) + public static void matchGMS(Size size1, Size size2, MatOfKeyPoint keypoints1, MatOfKeyPoint keypoints2, MatOfDMatch matches1to2, MatOfDMatch matchesGMS, boolean withRotation, boolean withScale) + { + Mat keypoints1_mat = keypoints1; + Mat keypoints2_mat = keypoints2; + Mat matches1to2_mat = matches1to2; + Mat matchesGMS_mat = matchesGMS; + matchGMS_1(size1.width, size1.height, size2.width, size2.height, keypoints1_mat.nativeObj, keypoints2_mat.nativeObj, matches1to2_mat.nativeObj, matchesGMS_mat.nativeObj, withRotation, withScale); + + return; + } + + //javadoc: matchGMS(size1, size2, keypoints1, keypoints2, matches1to2, matchesGMS, withRotation) + public static void matchGMS(Size size1, Size size2, MatOfKeyPoint keypoints1, MatOfKeyPoint keypoints2, MatOfDMatch matches1to2, MatOfDMatch matchesGMS, boolean withRotation) + { + Mat keypoints1_mat = keypoints1; + Mat keypoints2_mat = keypoints2; + Mat matches1to2_mat = matches1to2; + Mat matchesGMS_mat = matchesGMS; + matchGMS_2(size1.width, size1.height, size2.width, size2.height, keypoints1_mat.nativeObj, keypoints2_mat.nativeObj, matches1to2_mat.nativeObj, matchesGMS_mat.nativeObj, withRotation); + + return; + } + + //javadoc: matchGMS(size1, size2, keypoints1, keypoints2, matches1to2, matchesGMS) + public static void matchGMS(Size size1, Size size2, MatOfKeyPoint keypoints1, MatOfKeyPoint keypoints2, MatOfDMatch matches1to2, MatOfDMatch matchesGMS) + { + Mat keypoints1_mat = keypoints1; + Mat keypoints2_mat = keypoints2; + Mat matches1to2_mat = matches1to2; + Mat matchesGMS_mat = matchesGMS; + matchGMS_3(size1.width, size1.height, size2.width, size2.height, keypoints1_mat.nativeObj, keypoints2_mat.nativeObj, matches1to2_mat.nativeObj, matchesGMS_mat.nativeObj); + + return; + } + + + + + // C++: void cv::xfeatures2d::matchGMS(Size size1, Size size2, vector_KeyPoint keypoints1, vector_KeyPoint keypoints2, vector_DMatch matches1to2, vector_DMatch& matchesGMS, bool withRotation = false, bool withScale = false, double thresholdFactor = 6.0) + private static native void matchGMS_0(double size1_width, double size1_height, double size2_width, double size2_height, long keypoints1_mat_nativeObj, long keypoints2_mat_nativeObj, long matches1to2_mat_nativeObj, long matchesGMS_mat_nativeObj, boolean withRotation, boolean withScale, double thresholdFactor); + private static native void matchGMS_1(double size1_width, double size1_height, double size2_width, double size2_height, long keypoints1_mat_nativeObj, long keypoints2_mat_nativeObj, long matches1to2_mat_nativeObj, long matchesGMS_mat_nativeObj, boolean withRotation, boolean withScale); + private static native void matchGMS_2(double size1_width, double size1_height, double size2_width, double size2_height, long keypoints1_mat_nativeObj, long keypoints2_mat_nativeObj, long matches1to2_mat_nativeObj, long matchesGMS_mat_nativeObj, boolean withRotation); + private static native void matchGMS_3(double size1_width, double size1_height, double size2_width, double size2_height, long keypoints1_mat_nativeObj, long keypoints2_mat_nativeObj, long matches1to2_mat_nativeObj, long matchesGMS_mat_nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/AdaptiveManifoldFilter.java b/OpenCV/src/main/java/org/opencv/ximgproc/AdaptiveManifoldFilter.java new file mode 100644 index 00000000..666c99fe --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/AdaptiveManifoldFilter.java @@ -0,0 +1,91 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.ximgproc.AdaptiveManifoldFilter; + +// C++: class AdaptiveManifoldFilter +//javadoc: AdaptiveManifoldFilter + +public class AdaptiveManifoldFilter extends Algorithm { + + protected AdaptiveManifoldFilter(long addr) { super(addr); } + + // internal usage only + public static AdaptiveManifoldFilter __fromPtr__(long addr) { return new AdaptiveManifoldFilter(addr); } + + // + // C++: static Ptr_AdaptiveManifoldFilter cv::ximgproc::AdaptiveManifoldFilter::create() + // + + //javadoc: AdaptiveManifoldFilter::create() + public static AdaptiveManifoldFilter create() + { + + AdaptiveManifoldFilter retVal = AdaptiveManifoldFilter.__fromPtr__(create_0()); + + return retVal; + } + + + // + // C++: void cv::ximgproc::AdaptiveManifoldFilter::collectGarbage() + // + + //javadoc: AdaptiveManifoldFilter::collectGarbage() + public void collectGarbage() + { + + collectGarbage_0(nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::AdaptiveManifoldFilter::filter(Mat src, Mat& dst, Mat joint = Mat()) + // + + //javadoc: AdaptiveManifoldFilter::filter(src, dst, joint) + public void filter(Mat src, Mat dst, Mat joint) + { + + filter_0(nativeObj, src.nativeObj, dst.nativeObj, joint.nativeObj); + + return; + } + + //javadoc: AdaptiveManifoldFilter::filter(src, dst) + public void filter(Mat src, Mat dst) + { + + filter_1(nativeObj, src.nativeObj, dst.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_AdaptiveManifoldFilter cv::ximgproc::AdaptiveManifoldFilter::create() + private static native long create_0(); + + // C++: void cv::ximgproc::AdaptiveManifoldFilter::collectGarbage() + private static native void collectGarbage_0(long nativeObj); + + // C++: void cv::ximgproc::AdaptiveManifoldFilter::filter(Mat src, Mat& dst, Mat joint = Mat()) + private static native void filter_0(long nativeObj, long src_nativeObj, long dst_nativeObj, long joint_nativeObj); + private static native void filter_1(long nativeObj, long src_nativeObj, long dst_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/ContourFitting.java b/OpenCV/src/main/java/org/opencv/ximgproc/ContourFitting.java new file mode 100644 index 00000000..0343a489 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/ContourFitting.java @@ -0,0 +1,124 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class ContourFitting +//javadoc: ContourFitting + +public class ContourFitting extends Algorithm { + + protected ContourFitting(long addr) { super(addr); } + + // internal usage only + public static ContourFitting __fromPtr__(long addr) { return new ContourFitting(addr); } + + // + // C++: int cv::ximgproc::ContourFitting::getCtrSize() + // + + //javadoc: ContourFitting::getCtrSize() + public int getCtrSize() + { + + int retVal = getCtrSize_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ximgproc::ContourFitting::getFDSize() + // + + //javadoc: ContourFitting::getFDSize() + public int getFDSize() + { + + int retVal = getFDSize_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::ximgproc::ContourFitting::estimateTransformation(Mat src, Mat dst, Mat& alphaPhiST, double& dist, bool fdContour = false) + // + + //javadoc: ContourFitting::estimateTransformation(src, dst, alphaPhiST, dist, fdContour) + public void estimateTransformation(Mat src, Mat dst, Mat alphaPhiST, double[] dist, boolean fdContour) + { + double[] dist_out = new double[1]; + estimateTransformation_0(nativeObj, src.nativeObj, dst.nativeObj, alphaPhiST.nativeObj, dist_out, fdContour); + if(dist!=null) dist[0] = (double)dist_out[0]; + return; + } + + //javadoc: ContourFitting::estimateTransformation(src, dst, alphaPhiST, dist) + public void estimateTransformation(Mat src, Mat dst, Mat alphaPhiST, double[] dist) + { + double[] dist_out = new double[1]; + estimateTransformation_1(nativeObj, src.nativeObj, dst.nativeObj, alphaPhiST.nativeObj, dist_out); + if(dist!=null) dist[0] = (double)dist_out[0]; + return; + } + + + // + // C++: void cv::ximgproc::ContourFitting::setCtrSize(int n) + // + + //javadoc: ContourFitting::setCtrSize(n) + public void setCtrSize(int n) + { + + setCtrSize_0(nativeObj, n); + + return; + } + + + // + // C++: void cv::ximgproc::ContourFitting::setFDSize(int n) + // + + //javadoc: ContourFitting::setFDSize(n) + public void setFDSize(int n) + { + + setFDSize_0(nativeObj, n); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: int cv::ximgproc::ContourFitting::getCtrSize() + private static native int getCtrSize_0(long nativeObj); + + // C++: int cv::ximgproc::ContourFitting::getFDSize() + private static native int getFDSize_0(long nativeObj); + + // C++: void cv::ximgproc::ContourFitting::estimateTransformation(Mat src, Mat dst, Mat& alphaPhiST, double& dist, bool fdContour = false) + private static native void estimateTransformation_0(long nativeObj, long src_nativeObj, long dst_nativeObj, long alphaPhiST_nativeObj, double[] dist_out, boolean fdContour); + private static native void estimateTransformation_1(long nativeObj, long src_nativeObj, long dst_nativeObj, long alphaPhiST_nativeObj, double[] dist_out); + + // C++: void cv::ximgproc::ContourFitting::setCtrSize(int n) + private static native void setCtrSize_0(long nativeObj, int n); + + // C++: void cv::ximgproc::ContourFitting::setFDSize(int n) + private static native void setFDSize_0(long nativeObj, int n); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/DTFilter.java b/OpenCV/src/main/java/org/opencv/ximgproc/DTFilter.java new file mode 100644 index 00000000..8d65f890 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/DTFilter.java @@ -0,0 +1,56 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class DTFilter +//javadoc: DTFilter + +public class DTFilter extends Algorithm { + + protected DTFilter(long addr) { super(addr); } + + // internal usage only + public static DTFilter __fromPtr__(long addr) { return new DTFilter(addr); } + + // + // C++: void cv::ximgproc::DTFilter::filter(Mat src, Mat& dst, int dDepth = -1) + // + + //javadoc: DTFilter::filter(src, dst, dDepth) + public void filter(Mat src, Mat dst, int dDepth) + { + + filter_0(nativeObj, src.nativeObj, dst.nativeObj, dDepth); + + return; + } + + //javadoc: DTFilter::filter(src, dst) + public void filter(Mat src, Mat dst) + { + + filter_1(nativeObj, src.nativeObj, dst.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::ximgproc::DTFilter::filter(Mat src, Mat& dst, int dDepth = -1) + private static native void filter_0(long nativeObj, long src_nativeObj, long dst_nativeObj, int dDepth); + private static native void filter_1(long nativeObj, long src_nativeObj, long dst_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/DisparityFilter.java b/OpenCV/src/main/java/org/opencv/ximgproc/DisparityFilter.java new file mode 100644 index 00000000..d5cff5ec --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/DisparityFilter.java @@ -0,0 +1,77 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.core.Rect; + +// C++: class DisparityFilter +//javadoc: DisparityFilter + +public class DisparityFilter extends Algorithm { + + protected DisparityFilter(long addr) { super(addr); } + + // internal usage only + public static DisparityFilter __fromPtr__(long addr) { return new DisparityFilter(addr); } + + // + // C++: void cv::ximgproc::DisparityFilter::filter(Mat disparity_map_left, Mat left_view, Mat& filtered_disparity_map, Mat disparity_map_right = Mat(), Rect ROI = Rect(), Mat right_view = Mat()) + // + + //javadoc: DisparityFilter::filter(disparity_map_left, left_view, filtered_disparity_map, disparity_map_right, ROI, right_view) + public void filter(Mat disparity_map_left, Mat left_view, Mat filtered_disparity_map, Mat disparity_map_right, Rect ROI, Mat right_view) + { + + filter_0(nativeObj, disparity_map_left.nativeObj, left_view.nativeObj, filtered_disparity_map.nativeObj, disparity_map_right.nativeObj, ROI.x, ROI.y, ROI.width, ROI.height, right_view.nativeObj); + + return; + } + + //javadoc: DisparityFilter::filter(disparity_map_left, left_view, filtered_disparity_map, disparity_map_right, ROI) + public void filter(Mat disparity_map_left, Mat left_view, Mat filtered_disparity_map, Mat disparity_map_right, Rect ROI) + { + + filter_1(nativeObj, disparity_map_left.nativeObj, left_view.nativeObj, filtered_disparity_map.nativeObj, disparity_map_right.nativeObj, ROI.x, ROI.y, ROI.width, ROI.height); + + return; + } + + //javadoc: DisparityFilter::filter(disparity_map_left, left_view, filtered_disparity_map, disparity_map_right) + public void filter(Mat disparity_map_left, Mat left_view, Mat filtered_disparity_map, Mat disparity_map_right) + { + + filter_2(nativeObj, disparity_map_left.nativeObj, left_view.nativeObj, filtered_disparity_map.nativeObj, disparity_map_right.nativeObj); + + return; + } + + //javadoc: DisparityFilter::filter(disparity_map_left, left_view, filtered_disparity_map) + public void filter(Mat disparity_map_left, Mat left_view, Mat filtered_disparity_map) + { + + filter_3(nativeObj, disparity_map_left.nativeObj, left_view.nativeObj, filtered_disparity_map.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::ximgproc::DisparityFilter::filter(Mat disparity_map_left, Mat left_view, Mat& filtered_disparity_map, Mat disparity_map_right = Mat(), Rect ROI = Rect(), Mat right_view = Mat()) + private static native void filter_0(long nativeObj, long disparity_map_left_nativeObj, long left_view_nativeObj, long filtered_disparity_map_nativeObj, long disparity_map_right_nativeObj, int ROI_x, int ROI_y, int ROI_width, int ROI_height, long right_view_nativeObj); + private static native void filter_1(long nativeObj, long disparity_map_left_nativeObj, long left_view_nativeObj, long filtered_disparity_map_nativeObj, long disparity_map_right_nativeObj, int ROI_x, int ROI_y, int ROI_width, int ROI_height); + private static native void filter_2(long nativeObj, long disparity_map_left_nativeObj, long left_view_nativeObj, long filtered_disparity_map_nativeObj, long disparity_map_right_nativeObj); + private static native void filter_3(long nativeObj, long disparity_map_left_nativeObj, long left_view_nativeObj, long filtered_disparity_map_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/DisparityWLSFilter.java b/OpenCV/src/main/java/org/opencv/ximgproc/DisparityWLSFilter.java new file mode 100644 index 00000000..abc79878 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/DisparityWLSFilter.java @@ -0,0 +1,200 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.core.Mat; +import org.opencv.core.Rect; +import org.opencv.ximgproc.DisparityFilter; + +// C++: class DisparityWLSFilter +//javadoc: DisparityWLSFilter + +public class DisparityWLSFilter extends DisparityFilter { + + protected DisparityWLSFilter(long addr) { super(addr); } + + // internal usage only + public static DisparityWLSFilter __fromPtr__(long addr) { return new DisparityWLSFilter(addr); } + + // + // C++: Mat cv::ximgproc::DisparityWLSFilter::getConfidenceMap() + // + + //javadoc: DisparityWLSFilter::getConfidenceMap() + public Mat getConfidenceMap() + { + + Mat retVal = new Mat(getConfidenceMap_0(nativeObj)); + + return retVal; + } + + + // + // C++: Rect cv::ximgproc::DisparityWLSFilter::getROI() + // + + //javadoc: DisparityWLSFilter::getROI() + public Rect getROI() + { + + Rect retVal = new Rect(getROI_0(nativeObj)); + + return retVal; + } + + + // + // C++: double cv::ximgproc::DisparityWLSFilter::getLambda() + // + + //javadoc: DisparityWLSFilter::getLambda() + public double getLambda() + { + + double retVal = getLambda_0(nativeObj); + + return retVal; + } + + + // + // C++: double cv::ximgproc::DisparityWLSFilter::getSigmaColor() + // + + //javadoc: DisparityWLSFilter::getSigmaColor() + public double getSigmaColor() + { + + double retVal = getSigmaColor_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ximgproc::DisparityWLSFilter::getDepthDiscontinuityRadius() + // + + //javadoc: DisparityWLSFilter::getDepthDiscontinuityRadius() + public int getDepthDiscontinuityRadius() + { + + int retVal = getDepthDiscontinuityRadius_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ximgproc::DisparityWLSFilter::getLRCthresh() + // + + //javadoc: DisparityWLSFilter::getLRCthresh() + public int getLRCthresh() + { + + int retVal = getLRCthresh_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::ximgproc::DisparityWLSFilter::setDepthDiscontinuityRadius(int _disc_radius) + // + + //javadoc: DisparityWLSFilter::setDepthDiscontinuityRadius(_disc_radius) + public void setDepthDiscontinuityRadius(int _disc_radius) + { + + setDepthDiscontinuityRadius_0(nativeObj, _disc_radius); + + return; + } + + + // + // C++: void cv::ximgproc::DisparityWLSFilter::setLRCthresh(int _LRC_thresh) + // + + //javadoc: DisparityWLSFilter::setLRCthresh(_LRC_thresh) + public void setLRCthresh(int _LRC_thresh) + { + + setLRCthresh_0(nativeObj, _LRC_thresh); + + return; + } + + + // + // C++: void cv::ximgproc::DisparityWLSFilter::setLambda(double _lambda) + // + + //javadoc: DisparityWLSFilter::setLambda(_lambda) + public void setLambda(double _lambda) + { + + setLambda_0(nativeObj, _lambda); + + return; + } + + + // + // C++: void cv::ximgproc::DisparityWLSFilter::setSigmaColor(double _sigma_color) + // + + //javadoc: DisparityWLSFilter::setSigmaColor(_sigma_color) + public void setSigmaColor(double _sigma_color) + { + + setSigmaColor_0(nativeObj, _sigma_color); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: Mat cv::ximgproc::DisparityWLSFilter::getConfidenceMap() + private static native long getConfidenceMap_0(long nativeObj); + + // C++: Rect cv::ximgproc::DisparityWLSFilter::getROI() + private static native double[] getROI_0(long nativeObj); + + // C++: double cv::ximgproc::DisparityWLSFilter::getLambda() + private static native double getLambda_0(long nativeObj); + + // C++: double cv::ximgproc::DisparityWLSFilter::getSigmaColor() + private static native double getSigmaColor_0(long nativeObj); + + // C++: int cv::ximgproc::DisparityWLSFilter::getDepthDiscontinuityRadius() + private static native int getDepthDiscontinuityRadius_0(long nativeObj); + + // C++: int cv::ximgproc::DisparityWLSFilter::getLRCthresh() + private static native int getLRCthresh_0(long nativeObj); + + // C++: void cv::ximgproc::DisparityWLSFilter::setDepthDiscontinuityRadius(int _disc_radius) + private static native void setDepthDiscontinuityRadius_0(long nativeObj, int _disc_radius); + + // C++: void cv::ximgproc::DisparityWLSFilter::setLRCthresh(int _LRC_thresh) + private static native void setLRCthresh_0(long nativeObj, int _LRC_thresh); + + // C++: void cv::ximgproc::DisparityWLSFilter::setLambda(double _lambda) + private static native void setLambda_0(long nativeObj, double _lambda); + + // C++: void cv::ximgproc::DisparityWLSFilter::setSigmaColor(double _sigma_color) + private static native void setSigmaColor_0(long nativeObj, double _sigma_color); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/EdgeAwareInterpolator.java b/OpenCV/src/main/java/org/opencv/ximgproc/EdgeAwareInterpolator.java new file mode 100644 index 00000000..55131192 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/EdgeAwareInterpolator.java @@ -0,0 +1,232 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.ximgproc.SparseMatchInterpolator; + +// C++: class EdgeAwareInterpolator +//javadoc: EdgeAwareInterpolator + +public class EdgeAwareInterpolator extends SparseMatchInterpolator { + + protected EdgeAwareInterpolator(long addr) { super(addr); } + + // internal usage only + public static EdgeAwareInterpolator __fromPtr__(long addr) { return new EdgeAwareInterpolator(addr); } + + // + // C++: bool cv::ximgproc::EdgeAwareInterpolator::getUsePostProcessing() + // + + //javadoc: EdgeAwareInterpolator::getUsePostProcessing() + public boolean getUsePostProcessing() + { + + boolean retVal = getUsePostProcessing_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ximgproc::EdgeAwareInterpolator::getFGSLambda() + // + + //javadoc: EdgeAwareInterpolator::getFGSLambda() + public float getFGSLambda() + { + + float retVal = getFGSLambda_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ximgproc::EdgeAwareInterpolator::getFGSSigma() + // + + //javadoc: EdgeAwareInterpolator::getFGSSigma() + public float getFGSSigma() + { + + float retVal = getFGSSigma_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ximgproc::EdgeAwareInterpolator::getLambda() + // + + //javadoc: EdgeAwareInterpolator::getLambda() + public float getLambda() + { + + float retVal = getLambda_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ximgproc::EdgeAwareInterpolator::getSigma() + // + + //javadoc: EdgeAwareInterpolator::getSigma() + public float getSigma() + { + + float retVal = getSigma_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ximgproc::EdgeAwareInterpolator::getK() + // + + //javadoc: EdgeAwareInterpolator::getK() + public int getK() + { + + int retVal = getK_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::ximgproc::EdgeAwareInterpolator::setFGSLambda(float _lambda) + // + + //javadoc: EdgeAwareInterpolator::setFGSLambda(_lambda) + public void setFGSLambda(float _lambda) + { + + setFGSLambda_0(nativeObj, _lambda); + + return; + } + + + // + // C++: void cv::ximgproc::EdgeAwareInterpolator::setFGSSigma(float _sigma) + // + + //javadoc: EdgeAwareInterpolator::setFGSSigma(_sigma) + public void setFGSSigma(float _sigma) + { + + setFGSSigma_0(nativeObj, _sigma); + + return; + } + + + // + // C++: void cv::ximgproc::EdgeAwareInterpolator::setK(int _k) + // + + //javadoc: EdgeAwareInterpolator::setK(_k) + public void setK(int _k) + { + + setK_0(nativeObj, _k); + + return; + } + + + // + // C++: void cv::ximgproc::EdgeAwareInterpolator::setLambda(float _lambda) + // + + //javadoc: EdgeAwareInterpolator::setLambda(_lambda) + public void setLambda(float _lambda) + { + + setLambda_0(nativeObj, _lambda); + + return; + } + + + // + // C++: void cv::ximgproc::EdgeAwareInterpolator::setSigma(float _sigma) + // + + //javadoc: EdgeAwareInterpolator::setSigma(_sigma) + public void setSigma(float _sigma) + { + + setSigma_0(nativeObj, _sigma); + + return; + } + + + // + // C++: void cv::ximgproc::EdgeAwareInterpolator::setUsePostProcessing(bool _use_post_proc) + // + + //javadoc: EdgeAwareInterpolator::setUsePostProcessing(_use_post_proc) + public void setUsePostProcessing(boolean _use_post_proc) + { + + setUsePostProcessing_0(nativeObj, _use_post_proc); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: bool cv::ximgproc::EdgeAwareInterpolator::getUsePostProcessing() + private static native boolean getUsePostProcessing_0(long nativeObj); + + // C++: float cv::ximgproc::EdgeAwareInterpolator::getFGSLambda() + private static native float getFGSLambda_0(long nativeObj); + + // C++: float cv::ximgproc::EdgeAwareInterpolator::getFGSSigma() + private static native float getFGSSigma_0(long nativeObj); + + // C++: float cv::ximgproc::EdgeAwareInterpolator::getLambda() + private static native float getLambda_0(long nativeObj); + + // C++: float cv::ximgproc::EdgeAwareInterpolator::getSigma() + private static native float getSigma_0(long nativeObj); + + // C++: int cv::ximgproc::EdgeAwareInterpolator::getK() + private static native int getK_0(long nativeObj); + + // C++: void cv::ximgproc::EdgeAwareInterpolator::setFGSLambda(float _lambda) + private static native void setFGSLambda_0(long nativeObj, float _lambda); + + // C++: void cv::ximgproc::EdgeAwareInterpolator::setFGSSigma(float _sigma) + private static native void setFGSSigma_0(long nativeObj, float _sigma); + + // C++: void cv::ximgproc::EdgeAwareInterpolator::setK(int _k) + private static native void setK_0(long nativeObj, int _k); + + // C++: void cv::ximgproc::EdgeAwareInterpolator::setLambda(float _lambda) + private static native void setLambda_0(long nativeObj, float _lambda); + + // C++: void cv::ximgproc::EdgeAwareInterpolator::setSigma(float _sigma) + private static native void setSigma_0(long nativeObj, float _sigma); + + // C++: void cv::ximgproc::EdgeAwareInterpolator::setUsePostProcessing(bool _use_post_proc) + private static native void setUsePostProcessing_0(long nativeObj, boolean _use_post_proc); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/EdgeBoxes.java b/OpenCV/src/main/java/org/opencv/ximgproc/EdgeBoxes.java new file mode 100644 index 00000000..ce7f9ffe --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/EdgeBoxes.java @@ -0,0 +1,458 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.core.MatOfRect; +import org.opencv.utils.Converters; + +// C++: class EdgeBoxes +//javadoc: EdgeBoxes + +public class EdgeBoxes extends Algorithm { + + protected EdgeBoxes(long addr) { super(addr); } + + // internal usage only + public static EdgeBoxes __fromPtr__(long addr) { return new EdgeBoxes(addr); } + + // + // C++: float cv::ximgproc::EdgeBoxes::getAlpha() + // + + //javadoc: EdgeBoxes::getAlpha() + public float getAlpha() + { + + float retVal = getAlpha_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ximgproc::EdgeBoxes::getBeta() + // + + //javadoc: EdgeBoxes::getBeta() + public float getBeta() + { + + float retVal = getBeta_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ximgproc::EdgeBoxes::getClusterMinMag() + // + + //javadoc: EdgeBoxes::getClusterMinMag() + public float getClusterMinMag() + { + + float retVal = getClusterMinMag_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ximgproc::EdgeBoxes::getEdgeMergeThr() + // + + //javadoc: EdgeBoxes::getEdgeMergeThr() + public float getEdgeMergeThr() + { + + float retVal = getEdgeMergeThr_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ximgproc::EdgeBoxes::getEdgeMinMag() + // + + //javadoc: EdgeBoxes::getEdgeMinMag() + public float getEdgeMinMag() + { + + float retVal = getEdgeMinMag_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ximgproc::EdgeBoxes::getEta() + // + + //javadoc: EdgeBoxes::getEta() + public float getEta() + { + + float retVal = getEta_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ximgproc::EdgeBoxes::getGamma() + // + + //javadoc: EdgeBoxes::getGamma() + public float getGamma() + { + + float retVal = getGamma_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ximgproc::EdgeBoxes::getKappa() + // + + //javadoc: EdgeBoxes::getKappa() + public float getKappa() + { + + float retVal = getKappa_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ximgproc::EdgeBoxes::getMaxAspectRatio() + // + + //javadoc: EdgeBoxes::getMaxAspectRatio() + public float getMaxAspectRatio() + { + + float retVal = getMaxAspectRatio_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ximgproc::EdgeBoxes::getMinBoxArea() + // + + //javadoc: EdgeBoxes::getMinBoxArea() + public float getMinBoxArea() + { + + float retVal = getMinBoxArea_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ximgproc::EdgeBoxes::getMinScore() + // + + //javadoc: EdgeBoxes::getMinScore() + public float getMinScore() + { + + float retVal = getMinScore_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ximgproc::EdgeBoxes::getMaxBoxes() + // + + //javadoc: EdgeBoxes::getMaxBoxes() + public int getMaxBoxes() + { + + int retVal = getMaxBoxes_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::ximgproc::EdgeBoxes::getBoundingBoxes(Mat edge_map, Mat orientation_map, vector_Rect& boxes) + // + + //javadoc: EdgeBoxes::getBoundingBoxes(edge_map, orientation_map, boxes) + public void getBoundingBoxes(Mat edge_map, Mat orientation_map, MatOfRect boxes) + { + Mat boxes_mat = boxes; + getBoundingBoxes_0(nativeObj, edge_map.nativeObj, orientation_map.nativeObj, boxes_mat.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::EdgeBoxes::setAlpha(float value) + // + + //javadoc: EdgeBoxes::setAlpha(value) + public void setAlpha(float value) + { + + setAlpha_0(nativeObj, value); + + return; + } + + + // + // C++: void cv::ximgproc::EdgeBoxes::setBeta(float value) + // + + //javadoc: EdgeBoxes::setBeta(value) + public void setBeta(float value) + { + + setBeta_0(nativeObj, value); + + return; + } + + + // + // C++: void cv::ximgproc::EdgeBoxes::setClusterMinMag(float value) + // + + //javadoc: EdgeBoxes::setClusterMinMag(value) + public void setClusterMinMag(float value) + { + + setClusterMinMag_0(nativeObj, value); + + return; + } + + + // + // C++: void cv::ximgproc::EdgeBoxes::setEdgeMergeThr(float value) + // + + //javadoc: EdgeBoxes::setEdgeMergeThr(value) + public void setEdgeMergeThr(float value) + { + + setEdgeMergeThr_0(nativeObj, value); + + return; + } + + + // + // C++: void cv::ximgproc::EdgeBoxes::setEdgeMinMag(float value) + // + + //javadoc: EdgeBoxes::setEdgeMinMag(value) + public void setEdgeMinMag(float value) + { + + setEdgeMinMag_0(nativeObj, value); + + return; + } + + + // + // C++: void cv::ximgproc::EdgeBoxes::setEta(float value) + // + + //javadoc: EdgeBoxes::setEta(value) + public void setEta(float value) + { + + setEta_0(nativeObj, value); + + return; + } + + + // + // C++: void cv::ximgproc::EdgeBoxes::setGamma(float value) + // + + //javadoc: EdgeBoxes::setGamma(value) + public void setGamma(float value) + { + + setGamma_0(nativeObj, value); + + return; + } + + + // + // C++: void cv::ximgproc::EdgeBoxes::setKappa(float value) + // + + //javadoc: EdgeBoxes::setKappa(value) + public void setKappa(float value) + { + + setKappa_0(nativeObj, value); + + return; + } + + + // + // C++: void cv::ximgproc::EdgeBoxes::setMaxAspectRatio(float value) + // + + //javadoc: EdgeBoxes::setMaxAspectRatio(value) + public void setMaxAspectRatio(float value) + { + + setMaxAspectRatio_0(nativeObj, value); + + return; + } + + + // + // C++: void cv::ximgproc::EdgeBoxes::setMaxBoxes(int value) + // + + //javadoc: EdgeBoxes::setMaxBoxes(value) + public void setMaxBoxes(int value) + { + + setMaxBoxes_0(nativeObj, value); + + return; + } + + + // + // C++: void cv::ximgproc::EdgeBoxes::setMinBoxArea(float value) + // + + //javadoc: EdgeBoxes::setMinBoxArea(value) + public void setMinBoxArea(float value) + { + + setMinBoxArea_0(nativeObj, value); + + return; + } + + + // + // C++: void cv::ximgproc::EdgeBoxes::setMinScore(float value) + // + + //javadoc: EdgeBoxes::setMinScore(value) + public void setMinScore(float value) + { + + setMinScore_0(nativeObj, value); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: float cv::ximgproc::EdgeBoxes::getAlpha() + private static native float getAlpha_0(long nativeObj); + + // C++: float cv::ximgproc::EdgeBoxes::getBeta() + private static native float getBeta_0(long nativeObj); + + // C++: float cv::ximgproc::EdgeBoxes::getClusterMinMag() + private static native float getClusterMinMag_0(long nativeObj); + + // C++: float cv::ximgproc::EdgeBoxes::getEdgeMergeThr() + private static native float getEdgeMergeThr_0(long nativeObj); + + // C++: float cv::ximgproc::EdgeBoxes::getEdgeMinMag() + private static native float getEdgeMinMag_0(long nativeObj); + + // C++: float cv::ximgproc::EdgeBoxes::getEta() + private static native float getEta_0(long nativeObj); + + // C++: float cv::ximgproc::EdgeBoxes::getGamma() + private static native float getGamma_0(long nativeObj); + + // C++: float cv::ximgproc::EdgeBoxes::getKappa() + private static native float getKappa_0(long nativeObj); + + // C++: float cv::ximgproc::EdgeBoxes::getMaxAspectRatio() + private static native float getMaxAspectRatio_0(long nativeObj); + + // C++: float cv::ximgproc::EdgeBoxes::getMinBoxArea() + private static native float getMinBoxArea_0(long nativeObj); + + // C++: float cv::ximgproc::EdgeBoxes::getMinScore() + private static native float getMinScore_0(long nativeObj); + + // C++: int cv::ximgproc::EdgeBoxes::getMaxBoxes() + private static native int getMaxBoxes_0(long nativeObj); + + // C++: void cv::ximgproc::EdgeBoxes::getBoundingBoxes(Mat edge_map, Mat orientation_map, vector_Rect& boxes) + private static native void getBoundingBoxes_0(long nativeObj, long edge_map_nativeObj, long orientation_map_nativeObj, long boxes_mat_nativeObj); + + // C++: void cv::ximgproc::EdgeBoxes::setAlpha(float value) + private static native void setAlpha_0(long nativeObj, float value); + + // C++: void cv::ximgproc::EdgeBoxes::setBeta(float value) + private static native void setBeta_0(long nativeObj, float value); + + // C++: void cv::ximgproc::EdgeBoxes::setClusterMinMag(float value) + private static native void setClusterMinMag_0(long nativeObj, float value); + + // C++: void cv::ximgproc::EdgeBoxes::setEdgeMergeThr(float value) + private static native void setEdgeMergeThr_0(long nativeObj, float value); + + // C++: void cv::ximgproc::EdgeBoxes::setEdgeMinMag(float value) + private static native void setEdgeMinMag_0(long nativeObj, float value); + + // C++: void cv::ximgproc::EdgeBoxes::setEta(float value) + private static native void setEta_0(long nativeObj, float value); + + // C++: void cv::ximgproc::EdgeBoxes::setGamma(float value) + private static native void setGamma_0(long nativeObj, float value); + + // C++: void cv::ximgproc::EdgeBoxes::setKappa(float value) + private static native void setKappa_0(long nativeObj, float value); + + // C++: void cv::ximgproc::EdgeBoxes::setMaxAspectRatio(float value) + private static native void setMaxAspectRatio_0(long nativeObj, float value); + + // C++: void cv::ximgproc::EdgeBoxes::setMaxBoxes(int value) + private static native void setMaxBoxes_0(long nativeObj, int value); + + // C++: void cv::ximgproc::EdgeBoxes::setMinBoxArea(float value) + private static native void setMinBoxArea_0(long nativeObj, float value); + + // C++: void cv::ximgproc::EdgeBoxes::setMinScore(float value) + private static native void setMinScore_0(long nativeObj, float value); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/FastBilateralSolverFilter.java b/OpenCV/src/main/java/org/opencv/ximgproc/FastBilateralSolverFilter.java new file mode 100644 index 00000000..e1deb29e --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/FastBilateralSolverFilter.java @@ -0,0 +1,46 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class FastBilateralSolverFilter +//javadoc: FastBilateralSolverFilter + +public class FastBilateralSolverFilter extends Algorithm { + + protected FastBilateralSolverFilter(long addr) { super(addr); } + + // internal usage only + public static FastBilateralSolverFilter __fromPtr__(long addr) { return new FastBilateralSolverFilter(addr); } + + // + // C++: void cv::ximgproc::FastBilateralSolverFilter::filter(Mat src, Mat confidence, Mat& dst) + // + + //javadoc: FastBilateralSolverFilter::filter(src, confidence, dst) + public void filter(Mat src, Mat confidence, Mat dst) + { + + filter_0(nativeObj, src.nativeObj, confidence.nativeObj, dst.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::ximgproc::FastBilateralSolverFilter::filter(Mat src, Mat confidence, Mat& dst) + private static native void filter_0(long nativeObj, long src_nativeObj, long confidence_nativeObj, long dst_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/FastGlobalSmootherFilter.java b/OpenCV/src/main/java/org/opencv/ximgproc/FastGlobalSmootherFilter.java new file mode 100644 index 00000000..c987c613 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/FastGlobalSmootherFilter.java @@ -0,0 +1,46 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class FastGlobalSmootherFilter +//javadoc: FastGlobalSmootherFilter + +public class FastGlobalSmootherFilter extends Algorithm { + + protected FastGlobalSmootherFilter(long addr) { super(addr); } + + // internal usage only + public static FastGlobalSmootherFilter __fromPtr__(long addr) { return new FastGlobalSmootherFilter(addr); } + + // + // C++: void cv::ximgproc::FastGlobalSmootherFilter::filter(Mat src, Mat& dst) + // + + //javadoc: FastGlobalSmootherFilter::filter(src, dst) + public void filter(Mat src, Mat dst) + { + + filter_0(nativeObj, src.nativeObj, dst.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::ximgproc::FastGlobalSmootherFilter::filter(Mat src, Mat& dst) + private static native void filter_0(long nativeObj, long src_nativeObj, long dst_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/FastLineDetector.java b/OpenCV/src/main/java/org/opencv/ximgproc/FastLineDetector.java new file mode 100644 index 00000000..dbd41075 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/FastLineDetector.java @@ -0,0 +1,73 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class FastLineDetector +//javadoc: FastLineDetector + +public class FastLineDetector extends Algorithm { + + protected FastLineDetector(long addr) { super(addr); } + + // internal usage only + public static FastLineDetector __fromPtr__(long addr) { return new FastLineDetector(addr); } + + // + // C++: void cv::ximgproc::FastLineDetector::detect(Mat _image, Mat& _lines) + // + + //javadoc: FastLineDetector::detect(_image, _lines) + public void detect(Mat _image, Mat _lines) + { + + detect_0(nativeObj, _image.nativeObj, _lines.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::FastLineDetector::drawSegments(Mat& _image, Mat lines, bool draw_arrow = false) + // + + //javadoc: FastLineDetector::drawSegments(_image, lines, draw_arrow) + public void drawSegments(Mat _image, Mat lines, boolean draw_arrow) + { + + drawSegments_0(nativeObj, _image.nativeObj, lines.nativeObj, draw_arrow); + + return; + } + + //javadoc: FastLineDetector::drawSegments(_image, lines) + public void drawSegments(Mat _image, Mat lines) + { + + drawSegments_1(nativeObj, _image.nativeObj, lines.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::ximgproc::FastLineDetector::detect(Mat _image, Mat& _lines) + private static native void detect_0(long nativeObj, long _image_nativeObj, long _lines_nativeObj); + + // C++: void cv::ximgproc::FastLineDetector::drawSegments(Mat& _image, Mat lines, bool draw_arrow = false) + private static native void drawSegments_0(long nativeObj, long _image_nativeObj, long lines_nativeObj, boolean draw_arrow); + private static native void drawSegments_1(long nativeObj, long _image_nativeObj, long lines_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/GraphSegmentation.java b/OpenCV/src/main/java/org/opencv/ximgproc/GraphSegmentation.java new file mode 100644 index 00000000..16b53990 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/GraphSegmentation.java @@ -0,0 +1,148 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class GraphSegmentation +//javadoc: GraphSegmentation + +public class GraphSegmentation extends Algorithm { + + protected GraphSegmentation(long addr) { super(addr); } + + // internal usage only + public static GraphSegmentation __fromPtr__(long addr) { return new GraphSegmentation(addr); } + + // + // C++: double cv::ximgproc::segmentation::GraphSegmentation::getSigma() + // + + //javadoc: GraphSegmentation::getSigma() + public double getSigma() + { + + double retVal = getSigma_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::ximgproc::segmentation::GraphSegmentation::getK() + // + + //javadoc: GraphSegmentation::getK() + public float getK() + { + + float retVal = getK_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::ximgproc::segmentation::GraphSegmentation::getMinSize() + // + + //javadoc: GraphSegmentation::getMinSize() + public int getMinSize() + { + + int retVal = getMinSize_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::ximgproc::segmentation::GraphSegmentation::processImage(Mat src, Mat& dst) + // + + //javadoc: GraphSegmentation::processImage(src, dst) + public void processImage(Mat src, Mat dst) + { + + processImage_0(nativeObj, src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::segmentation::GraphSegmentation::setK(float k) + // + + //javadoc: GraphSegmentation::setK(k) + public void setK(float k) + { + + setK_0(nativeObj, k); + + return; + } + + + // + // C++: void cv::ximgproc::segmentation::GraphSegmentation::setMinSize(int min_size) + // + + //javadoc: GraphSegmentation::setMinSize(min_size) + public void setMinSize(int min_size) + { + + setMinSize_0(nativeObj, min_size); + + return; + } + + + // + // C++: void cv::ximgproc::segmentation::GraphSegmentation::setSigma(double sigma) + // + + //javadoc: GraphSegmentation::setSigma(sigma) + public void setSigma(double sigma) + { + + setSigma_0(nativeObj, sigma); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: double cv::ximgproc::segmentation::GraphSegmentation::getSigma() + private static native double getSigma_0(long nativeObj); + + // C++: float cv::ximgproc::segmentation::GraphSegmentation::getK() + private static native float getK_0(long nativeObj); + + // C++: int cv::ximgproc::segmentation::GraphSegmentation::getMinSize() + private static native int getMinSize_0(long nativeObj); + + // C++: void cv::ximgproc::segmentation::GraphSegmentation::processImage(Mat src, Mat& dst) + private static native void processImage_0(long nativeObj, long src_nativeObj, long dst_nativeObj); + + // C++: void cv::ximgproc::segmentation::GraphSegmentation::setK(float k) + private static native void setK_0(long nativeObj, float k); + + // C++: void cv::ximgproc::segmentation::GraphSegmentation::setMinSize(int min_size) + private static native void setMinSize_0(long nativeObj, int min_size); + + // C++: void cv::ximgproc::segmentation::GraphSegmentation::setSigma(double sigma) + private static native void setSigma_0(long nativeObj, double sigma); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/GuidedFilter.java b/OpenCV/src/main/java/org/opencv/ximgproc/GuidedFilter.java new file mode 100644 index 00000000..ae587fa8 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/GuidedFilter.java @@ -0,0 +1,56 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class GuidedFilter +//javadoc: GuidedFilter + +public class GuidedFilter extends Algorithm { + + protected GuidedFilter(long addr) { super(addr); } + + // internal usage only + public static GuidedFilter __fromPtr__(long addr) { return new GuidedFilter(addr); } + + // + // C++: void cv::ximgproc::GuidedFilter::filter(Mat src, Mat& dst, int dDepth = -1) + // + + //javadoc: GuidedFilter::filter(src, dst, dDepth) + public void filter(Mat src, Mat dst, int dDepth) + { + + filter_0(nativeObj, src.nativeObj, dst.nativeObj, dDepth); + + return; + } + + //javadoc: GuidedFilter::filter(src, dst) + public void filter(Mat src, Mat dst) + { + + filter_1(nativeObj, src.nativeObj, dst.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::ximgproc::GuidedFilter::filter(Mat src, Mat& dst, int dDepth = -1) + private static native void filter_0(long nativeObj, long src_nativeObj, long dst_nativeObj, int dDepth); + private static native void filter_1(long nativeObj, long src_nativeObj, long dst_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/RFFeatureGetter.java b/OpenCV/src/main/java/org/opencv/ximgproc/RFFeatureGetter.java new file mode 100644 index 00000000..cdcd4356 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/RFFeatureGetter.java @@ -0,0 +1,46 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class RFFeatureGetter +//javadoc: RFFeatureGetter + +public class RFFeatureGetter extends Algorithm { + + protected RFFeatureGetter(long addr) { super(addr); } + + // internal usage only + public static RFFeatureGetter __fromPtr__(long addr) { return new RFFeatureGetter(addr); } + + // + // C++: void cv::ximgproc::RFFeatureGetter::getFeatures(Mat src, Mat features, int gnrmRad, int gsmthRad, int shrink, int outNum, int gradNum) + // + + //javadoc: RFFeatureGetter::getFeatures(src, features, gnrmRad, gsmthRad, shrink, outNum, gradNum) + public void getFeatures(Mat src, Mat features, int gnrmRad, int gsmthRad, int shrink, int outNum, int gradNum) + { + + getFeatures_0(nativeObj, src.nativeObj, features.nativeObj, gnrmRad, gsmthRad, shrink, outNum, gradNum); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::ximgproc::RFFeatureGetter::getFeatures(Mat src, Mat features, int gnrmRad, int gsmthRad, int shrink, int outNum, int gradNum) + private static native void getFeatures_0(long nativeObj, long src_nativeObj, long features_nativeObj, int gnrmRad, int gsmthRad, int shrink, int outNum, int gradNum); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/RidgeDetectionFilter.java b/OpenCV/src/main/java/org/opencv/ximgproc/RidgeDetectionFilter.java new file mode 100644 index 00000000..c9c925c4 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/RidgeDetectionFilter.java @@ -0,0 +1,144 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.ximgproc.RidgeDetectionFilter; + +// C++: class RidgeDetectionFilter +//javadoc: RidgeDetectionFilter + +public class RidgeDetectionFilter extends Algorithm { + + protected RidgeDetectionFilter(long addr) { super(addr); } + + // internal usage only + public static RidgeDetectionFilter __fromPtr__(long addr) { return new RidgeDetectionFilter(addr); } + + // + // C++: static Ptr_RidgeDetectionFilter cv::ximgproc::RidgeDetectionFilter::create(int ddepth = CV_32FC1, int dx = 1, int dy = 1, int ksize = 3, int out_dtype = CV_8UC1, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT) + // + + //javadoc: RidgeDetectionFilter::create(ddepth, dx, dy, ksize, out_dtype, scale, delta, borderType) + public static RidgeDetectionFilter create(int ddepth, int dx, int dy, int ksize, int out_dtype, double scale, double delta, int borderType) + { + + RidgeDetectionFilter retVal = RidgeDetectionFilter.__fromPtr__(create_0(ddepth, dx, dy, ksize, out_dtype, scale, delta, borderType)); + + return retVal; + } + + //javadoc: RidgeDetectionFilter::create(ddepth, dx, dy, ksize, out_dtype, scale, delta) + public static RidgeDetectionFilter create(int ddepth, int dx, int dy, int ksize, int out_dtype, double scale, double delta) + { + + RidgeDetectionFilter retVal = RidgeDetectionFilter.__fromPtr__(create_1(ddepth, dx, dy, ksize, out_dtype, scale, delta)); + + return retVal; + } + + //javadoc: RidgeDetectionFilter::create(ddepth, dx, dy, ksize, out_dtype, scale) + public static RidgeDetectionFilter create(int ddepth, int dx, int dy, int ksize, int out_dtype, double scale) + { + + RidgeDetectionFilter retVal = RidgeDetectionFilter.__fromPtr__(create_2(ddepth, dx, dy, ksize, out_dtype, scale)); + + return retVal; + } + + //javadoc: RidgeDetectionFilter::create(ddepth, dx, dy, ksize, out_dtype) + public static RidgeDetectionFilter create(int ddepth, int dx, int dy, int ksize, int out_dtype) + { + + RidgeDetectionFilter retVal = RidgeDetectionFilter.__fromPtr__(create_3(ddepth, dx, dy, ksize, out_dtype)); + + return retVal; + } + + //javadoc: RidgeDetectionFilter::create(ddepth, dx, dy, ksize) + public static RidgeDetectionFilter create(int ddepth, int dx, int dy, int ksize) + { + + RidgeDetectionFilter retVal = RidgeDetectionFilter.__fromPtr__(create_4(ddepth, dx, dy, ksize)); + + return retVal; + } + + //javadoc: RidgeDetectionFilter::create(ddepth, dx, dy) + public static RidgeDetectionFilter create(int ddepth, int dx, int dy) + { + + RidgeDetectionFilter retVal = RidgeDetectionFilter.__fromPtr__(create_5(ddepth, dx, dy)); + + return retVal; + } + + //javadoc: RidgeDetectionFilter::create(ddepth, dx) + public static RidgeDetectionFilter create(int ddepth, int dx) + { + + RidgeDetectionFilter retVal = RidgeDetectionFilter.__fromPtr__(create_6(ddepth, dx)); + + return retVal; + } + + //javadoc: RidgeDetectionFilter::create(ddepth) + public static RidgeDetectionFilter create(int ddepth) + { + + RidgeDetectionFilter retVal = RidgeDetectionFilter.__fromPtr__(create_7(ddepth)); + + return retVal; + } + + //javadoc: RidgeDetectionFilter::create() + public static RidgeDetectionFilter create() + { + + RidgeDetectionFilter retVal = RidgeDetectionFilter.__fromPtr__(create_8()); + + return retVal; + } + + + // + // C++: void cv::ximgproc::RidgeDetectionFilter::getRidgeFilteredImage(Mat _img, Mat& out) + // + + //javadoc: RidgeDetectionFilter::getRidgeFilteredImage(_img, out) + public void getRidgeFilteredImage(Mat _img, Mat out) + { + + getRidgeFilteredImage_0(nativeObj, _img.nativeObj, out.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: static Ptr_RidgeDetectionFilter cv::ximgproc::RidgeDetectionFilter::create(int ddepth = CV_32FC1, int dx = 1, int dy = 1, int ksize = 3, int out_dtype = CV_8UC1, double scale = 1, double delta = 0, int borderType = BORDER_DEFAULT) + private static native long create_0(int ddepth, int dx, int dy, int ksize, int out_dtype, double scale, double delta, int borderType); + private static native long create_1(int ddepth, int dx, int dy, int ksize, int out_dtype, double scale, double delta); + private static native long create_2(int ddepth, int dx, int dy, int ksize, int out_dtype, double scale); + private static native long create_3(int ddepth, int dx, int dy, int ksize, int out_dtype); + private static native long create_4(int ddepth, int dx, int dy, int ksize); + private static native long create_5(int ddepth, int dx, int dy); + private static native long create_6(int ddepth, int dx); + private static native long create_7(int ddepth); + private static native long create_8(); + + // C++: void cv::ximgproc::RidgeDetectionFilter::getRidgeFilteredImage(Mat _img, Mat& out) + private static native void getRidgeFilteredImage_0(long nativeObj, long _img_nativeObj, long out_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentation.java b/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentation.java new file mode 100644 index 00000000..10a92df5 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentation.java @@ -0,0 +1,302 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import java.util.ArrayList; +import java.util.List; +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; +import org.opencv.core.MatOfRect; +import org.opencv.utils.Converters; +import org.opencv.ximgproc.GraphSegmentation; +import org.opencv.ximgproc.SelectiveSearchSegmentationStrategy; + +// C++: class SelectiveSearchSegmentation +//javadoc: SelectiveSearchSegmentation + +public class SelectiveSearchSegmentation extends Algorithm { + + protected SelectiveSearchSegmentation(long addr) { super(addr); } + + // internal usage only + public static SelectiveSearchSegmentation __fromPtr__(long addr) { return new SelectiveSearchSegmentation(addr); } + + // + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::addGraphSegmentation(Ptr_GraphSegmentation g) + // + + //javadoc: SelectiveSearchSegmentation::addGraphSegmentation(g) + public void addGraphSegmentation(GraphSegmentation g) + { + + addGraphSegmentation_0(nativeObj, g.getNativeObjAddr()); + + return; + } + + + // + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::addImage(Mat img) + // + + //javadoc: SelectiveSearchSegmentation::addImage(img) + public void addImage(Mat img) + { + + addImage_0(nativeObj, img.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::addStrategy(Ptr_SelectiveSearchSegmentationStrategy s) + // + + //javadoc: SelectiveSearchSegmentation::addStrategy(s) + public void addStrategy(SelectiveSearchSegmentationStrategy s) + { + + addStrategy_0(nativeObj, s.getNativeObjAddr()); + + return; + } + + + // + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::clearGraphSegmentations() + // + + //javadoc: SelectiveSearchSegmentation::clearGraphSegmentations() + public void clearGraphSegmentations() + { + + clearGraphSegmentations_0(nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::clearImages() + // + + //javadoc: SelectiveSearchSegmentation::clearImages() + public void clearImages() + { + + clearImages_0(nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::clearStrategies() + // + + //javadoc: SelectiveSearchSegmentation::clearStrategies() + public void clearStrategies() + { + + clearStrategies_0(nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::process(vector_Rect& rects) + // + + //javadoc: SelectiveSearchSegmentation::process(rects) + public void process(MatOfRect rects) + { + Mat rects_mat = rects; + process_0(nativeObj, rects_mat.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::setBaseImage(Mat img) + // + + //javadoc: SelectiveSearchSegmentation::setBaseImage(img) + public void setBaseImage(Mat img) + { + + setBaseImage_0(nativeObj, img.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::switchToSelectiveSearchFast(int base_k = 150, int inc_k = 150, float sigma = 0.8f) + // + + //javadoc: SelectiveSearchSegmentation::switchToSelectiveSearchFast(base_k, inc_k, sigma) + public void switchToSelectiveSearchFast(int base_k, int inc_k, float sigma) + { + + switchToSelectiveSearchFast_0(nativeObj, base_k, inc_k, sigma); + + return; + } + + //javadoc: SelectiveSearchSegmentation::switchToSelectiveSearchFast(base_k, inc_k) + public void switchToSelectiveSearchFast(int base_k, int inc_k) + { + + switchToSelectiveSearchFast_1(nativeObj, base_k, inc_k); + + return; + } + + //javadoc: SelectiveSearchSegmentation::switchToSelectiveSearchFast(base_k) + public void switchToSelectiveSearchFast(int base_k) + { + + switchToSelectiveSearchFast_2(nativeObj, base_k); + + return; + } + + //javadoc: SelectiveSearchSegmentation::switchToSelectiveSearchFast() + public void switchToSelectiveSearchFast() + { + + switchToSelectiveSearchFast_3(nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::switchToSelectiveSearchQuality(int base_k = 150, int inc_k = 150, float sigma = 0.8f) + // + + //javadoc: SelectiveSearchSegmentation::switchToSelectiveSearchQuality(base_k, inc_k, sigma) + public void switchToSelectiveSearchQuality(int base_k, int inc_k, float sigma) + { + + switchToSelectiveSearchQuality_0(nativeObj, base_k, inc_k, sigma); + + return; + } + + //javadoc: SelectiveSearchSegmentation::switchToSelectiveSearchQuality(base_k, inc_k) + public void switchToSelectiveSearchQuality(int base_k, int inc_k) + { + + switchToSelectiveSearchQuality_1(nativeObj, base_k, inc_k); + + return; + } + + //javadoc: SelectiveSearchSegmentation::switchToSelectiveSearchQuality(base_k) + public void switchToSelectiveSearchQuality(int base_k) + { + + switchToSelectiveSearchQuality_2(nativeObj, base_k); + + return; + } + + //javadoc: SelectiveSearchSegmentation::switchToSelectiveSearchQuality() + public void switchToSelectiveSearchQuality() + { + + switchToSelectiveSearchQuality_3(nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::switchToSingleStrategy(int k = 200, float sigma = 0.8f) + // + + //javadoc: SelectiveSearchSegmentation::switchToSingleStrategy(k, sigma) + public void switchToSingleStrategy(int k, float sigma) + { + + switchToSingleStrategy_0(nativeObj, k, sigma); + + return; + } + + //javadoc: SelectiveSearchSegmentation::switchToSingleStrategy(k) + public void switchToSingleStrategy(int k) + { + + switchToSingleStrategy_1(nativeObj, k); + + return; + } + + //javadoc: SelectiveSearchSegmentation::switchToSingleStrategy() + public void switchToSingleStrategy() + { + + switchToSingleStrategy_2(nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::addGraphSegmentation(Ptr_GraphSegmentation g) + private static native void addGraphSegmentation_0(long nativeObj, long g_nativeObj); + + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::addImage(Mat img) + private static native void addImage_0(long nativeObj, long img_nativeObj); + + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::addStrategy(Ptr_SelectiveSearchSegmentationStrategy s) + private static native void addStrategy_0(long nativeObj, long s_nativeObj); + + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::clearGraphSegmentations() + private static native void clearGraphSegmentations_0(long nativeObj); + + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::clearImages() + private static native void clearImages_0(long nativeObj); + + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::clearStrategies() + private static native void clearStrategies_0(long nativeObj); + + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::process(vector_Rect& rects) + private static native void process_0(long nativeObj, long rects_mat_nativeObj); + + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::setBaseImage(Mat img) + private static native void setBaseImage_0(long nativeObj, long img_nativeObj); + + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::switchToSelectiveSearchFast(int base_k = 150, int inc_k = 150, float sigma = 0.8f) + private static native void switchToSelectiveSearchFast_0(long nativeObj, int base_k, int inc_k, float sigma); + private static native void switchToSelectiveSearchFast_1(long nativeObj, int base_k, int inc_k); + private static native void switchToSelectiveSearchFast_2(long nativeObj, int base_k); + private static native void switchToSelectiveSearchFast_3(long nativeObj); + + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::switchToSelectiveSearchQuality(int base_k = 150, int inc_k = 150, float sigma = 0.8f) + private static native void switchToSelectiveSearchQuality_0(long nativeObj, int base_k, int inc_k, float sigma); + private static native void switchToSelectiveSearchQuality_1(long nativeObj, int base_k, int inc_k); + private static native void switchToSelectiveSearchQuality_2(long nativeObj, int base_k); + private static native void switchToSelectiveSearchQuality_3(long nativeObj); + + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentation::switchToSingleStrategy(int k = 200, float sigma = 0.8f) + private static native void switchToSingleStrategy_0(long nativeObj, int k, float sigma); + private static native void switchToSingleStrategy_1(long nativeObj, int k); + private static native void switchToSingleStrategy_2(long nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentationStrategy.java b/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentationStrategy.java new file mode 100644 index 00000000..0af2f638 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentationStrategy.java @@ -0,0 +1,90 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class SelectiveSearchSegmentationStrategy +//javadoc: SelectiveSearchSegmentationStrategy + +public class SelectiveSearchSegmentationStrategy extends Algorithm { + + protected SelectiveSearchSegmentationStrategy(long addr) { super(addr); } + + // internal usage only + public static SelectiveSearchSegmentationStrategy __fromPtr__(long addr) { return new SelectiveSearchSegmentationStrategy(addr); } + + // + // C++: float cv::ximgproc::segmentation::SelectiveSearchSegmentationStrategy::get(int r1, int r2) + // + + //javadoc: SelectiveSearchSegmentationStrategy::get(r1, r2) + public float get(int r1, int r2) + { + + float retVal = get_0(nativeObj, r1, r2); + + return retVal; + } + + + // + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentationStrategy::merge(int r1, int r2) + // + + //javadoc: SelectiveSearchSegmentationStrategy::merge(r1, r2) + public void merge(int r1, int r2) + { + + merge_0(nativeObj, r1, r2); + + return; + } + + + // + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentationStrategy::setImage(Mat img, Mat regions, Mat sizes, int image_id = -1) + // + + //javadoc: SelectiveSearchSegmentationStrategy::setImage(img, regions, sizes, image_id) + public void setImage(Mat img, Mat regions, Mat sizes, int image_id) + { + + setImage_0(nativeObj, img.nativeObj, regions.nativeObj, sizes.nativeObj, image_id); + + return; + } + + //javadoc: SelectiveSearchSegmentationStrategy::setImage(img, regions, sizes) + public void setImage(Mat img, Mat regions, Mat sizes) + { + + setImage_1(nativeObj, img.nativeObj, regions.nativeObj, sizes.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: float cv::ximgproc::segmentation::SelectiveSearchSegmentationStrategy::get(int r1, int r2) + private static native float get_0(long nativeObj, int r1, int r2); + + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentationStrategy::merge(int r1, int r2) + private static native void merge_0(long nativeObj, int r1, int r2); + + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentationStrategy::setImage(Mat img, Mat regions, Mat sizes, int image_id = -1) + private static native void setImage_0(long nativeObj, long img_nativeObj, long regions_nativeObj, long sizes_nativeObj, int image_id); + private static native void setImage_1(long nativeObj, long img_nativeObj, long regions_nativeObj, long sizes_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentationStrategyColor.java b/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentationStrategyColor.java new file mode 100644 index 00000000..567845c3 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentationStrategyColor.java @@ -0,0 +1,28 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.ximgproc.SelectiveSearchSegmentationStrategy; + +// C++: class SelectiveSearchSegmentationStrategyColor +//javadoc: SelectiveSearchSegmentationStrategyColor + +public class SelectiveSearchSegmentationStrategyColor extends SelectiveSearchSegmentationStrategy { + + protected SelectiveSearchSegmentationStrategyColor(long addr) { super(addr); } + + // internal usage only + public static SelectiveSearchSegmentationStrategyColor __fromPtr__(long addr) { return new SelectiveSearchSegmentationStrategyColor(addr); } + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentationStrategyFill.java b/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentationStrategyFill.java new file mode 100644 index 00000000..a7106556 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentationStrategyFill.java @@ -0,0 +1,28 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.ximgproc.SelectiveSearchSegmentationStrategy; + +// C++: class SelectiveSearchSegmentationStrategyFill +//javadoc: SelectiveSearchSegmentationStrategyFill + +public class SelectiveSearchSegmentationStrategyFill extends SelectiveSearchSegmentationStrategy { + + protected SelectiveSearchSegmentationStrategyFill(long addr) { super(addr); } + + // internal usage only + public static SelectiveSearchSegmentationStrategyFill __fromPtr__(long addr) { return new SelectiveSearchSegmentationStrategyFill(addr); } + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentationStrategyMultiple.java b/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentationStrategyMultiple.java new file mode 100644 index 00000000..6ea5c5ed --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentationStrategyMultiple.java @@ -0,0 +1,62 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.ximgproc.SelectiveSearchSegmentationStrategy; + +// C++: class SelectiveSearchSegmentationStrategyMultiple +//javadoc: SelectiveSearchSegmentationStrategyMultiple + +public class SelectiveSearchSegmentationStrategyMultiple extends SelectiveSearchSegmentationStrategy { + + protected SelectiveSearchSegmentationStrategyMultiple(long addr) { super(addr); } + + // internal usage only + public static SelectiveSearchSegmentationStrategyMultiple __fromPtr__(long addr) { return new SelectiveSearchSegmentationStrategyMultiple(addr); } + + // + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentationStrategyMultiple::addStrategy(Ptr_SelectiveSearchSegmentationStrategy g, float weight) + // + + //javadoc: SelectiveSearchSegmentationStrategyMultiple::addStrategy(g, weight) + public void addStrategy(SelectiveSearchSegmentationStrategy g, float weight) + { + + addStrategy_0(nativeObj, g.getNativeObjAddr(), weight); + + return; + } + + + // + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentationStrategyMultiple::clearStrategies() + // + + //javadoc: SelectiveSearchSegmentationStrategyMultiple::clearStrategies() + public void clearStrategies() + { + + clearStrategies_0(nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentationStrategyMultiple::addStrategy(Ptr_SelectiveSearchSegmentationStrategy g, float weight) + private static native void addStrategy_0(long nativeObj, long g_nativeObj, float weight); + + // C++: void cv::ximgproc::segmentation::SelectiveSearchSegmentationStrategyMultiple::clearStrategies() + private static native void clearStrategies_0(long nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentationStrategySize.java b/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentationStrategySize.java new file mode 100644 index 00000000..0aa8e9ec --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentationStrategySize.java @@ -0,0 +1,28 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.ximgproc.SelectiveSearchSegmentationStrategy; + +// C++: class SelectiveSearchSegmentationStrategySize +//javadoc: SelectiveSearchSegmentationStrategySize + +public class SelectiveSearchSegmentationStrategySize extends SelectiveSearchSegmentationStrategy { + + protected SelectiveSearchSegmentationStrategySize(long addr) { super(addr); } + + // internal usage only + public static SelectiveSearchSegmentationStrategySize __fromPtr__(long addr) { return new SelectiveSearchSegmentationStrategySize(addr); } + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentationStrategyTexture.java b/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentationStrategyTexture.java new file mode 100644 index 00000000..41a41aaa --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/SelectiveSearchSegmentationStrategyTexture.java @@ -0,0 +1,28 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.ximgproc.SelectiveSearchSegmentationStrategy; + +// C++: class SelectiveSearchSegmentationStrategyTexture +//javadoc: SelectiveSearchSegmentationStrategyTexture + +public class SelectiveSearchSegmentationStrategyTexture extends SelectiveSearchSegmentationStrategy { + + protected SelectiveSearchSegmentationStrategyTexture(long addr) { super(addr); } + + // internal usage only + public static SelectiveSearchSegmentationStrategyTexture __fromPtr__(long addr) { return new SelectiveSearchSegmentationStrategyTexture(addr); } + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/SparseMatchInterpolator.java b/OpenCV/src/main/java/org/opencv/ximgproc/SparseMatchInterpolator.java new file mode 100644 index 00000000..7d6a4874 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/SparseMatchInterpolator.java @@ -0,0 +1,46 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class SparseMatchInterpolator +//javadoc: SparseMatchInterpolator + +public class SparseMatchInterpolator extends Algorithm { + + protected SparseMatchInterpolator(long addr) { super(addr); } + + // internal usage only + public static SparseMatchInterpolator __fromPtr__(long addr) { return new SparseMatchInterpolator(addr); } + + // + // C++: void cv::ximgproc::SparseMatchInterpolator::interpolate(Mat from_image, Mat from_points, Mat to_image, Mat to_points, Mat& dense_flow) + // + + //javadoc: SparseMatchInterpolator::interpolate(from_image, from_points, to_image, to_points, dense_flow) + public void interpolate(Mat from_image, Mat from_points, Mat to_image, Mat to_points, Mat dense_flow) + { + + interpolate_0(nativeObj, from_image.nativeObj, from_points.nativeObj, to_image.nativeObj, to_points.nativeObj, dense_flow.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::ximgproc::SparseMatchInterpolator::interpolate(Mat from_image, Mat from_points, Mat to_image, Mat to_points, Mat& dense_flow) + private static native void interpolate_0(long nativeObj, long from_image_nativeObj, long from_points_nativeObj, long to_image_nativeObj, long to_points_nativeObj, long dense_flow_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/StructuredEdgeDetection.java b/OpenCV/src/main/java/org/opencv/ximgproc/StructuredEdgeDetection.java new file mode 100644 index 00000000..c88f9ada --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/StructuredEdgeDetection.java @@ -0,0 +1,120 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class StructuredEdgeDetection +//javadoc: StructuredEdgeDetection + +public class StructuredEdgeDetection extends Algorithm { + + protected StructuredEdgeDetection(long addr) { super(addr); } + + // internal usage only + public static StructuredEdgeDetection __fromPtr__(long addr) { return new StructuredEdgeDetection(addr); } + + // + // C++: void cv::ximgproc::StructuredEdgeDetection::computeOrientation(Mat _src, Mat& _dst) + // + + //javadoc: StructuredEdgeDetection::computeOrientation(_src, _dst) + public void computeOrientation(Mat _src, Mat _dst) + { + + computeOrientation_0(nativeObj, _src.nativeObj, _dst.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::StructuredEdgeDetection::detectEdges(Mat _src, Mat& _dst) + // + + //javadoc: StructuredEdgeDetection::detectEdges(_src, _dst) + public void detectEdges(Mat _src, Mat _dst) + { + + detectEdges_0(nativeObj, _src.nativeObj, _dst.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::StructuredEdgeDetection::edgesNms(Mat edge_image, Mat orientation_image, Mat& _dst, int r = 2, int s = 0, float m = 1, bool isParallel = true) + // + + //javadoc: StructuredEdgeDetection::edgesNms(edge_image, orientation_image, _dst, r, s, m, isParallel) + public void edgesNms(Mat edge_image, Mat orientation_image, Mat _dst, int r, int s, float m, boolean isParallel) + { + + edgesNms_0(nativeObj, edge_image.nativeObj, orientation_image.nativeObj, _dst.nativeObj, r, s, m, isParallel); + + return; + } + + //javadoc: StructuredEdgeDetection::edgesNms(edge_image, orientation_image, _dst, r, s, m) + public void edgesNms(Mat edge_image, Mat orientation_image, Mat _dst, int r, int s, float m) + { + + edgesNms_1(nativeObj, edge_image.nativeObj, orientation_image.nativeObj, _dst.nativeObj, r, s, m); + + return; + } + + //javadoc: StructuredEdgeDetection::edgesNms(edge_image, orientation_image, _dst, r, s) + public void edgesNms(Mat edge_image, Mat orientation_image, Mat _dst, int r, int s) + { + + edgesNms_2(nativeObj, edge_image.nativeObj, orientation_image.nativeObj, _dst.nativeObj, r, s); + + return; + } + + //javadoc: StructuredEdgeDetection::edgesNms(edge_image, orientation_image, _dst, r) + public void edgesNms(Mat edge_image, Mat orientation_image, Mat _dst, int r) + { + + edgesNms_3(nativeObj, edge_image.nativeObj, orientation_image.nativeObj, _dst.nativeObj, r); + + return; + } + + //javadoc: StructuredEdgeDetection::edgesNms(edge_image, orientation_image, _dst) + public void edgesNms(Mat edge_image, Mat orientation_image, Mat _dst) + { + + edgesNms_4(nativeObj, edge_image.nativeObj, orientation_image.nativeObj, _dst.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::ximgproc::StructuredEdgeDetection::computeOrientation(Mat _src, Mat& _dst) + private static native void computeOrientation_0(long nativeObj, long _src_nativeObj, long _dst_nativeObj); + + // C++: void cv::ximgproc::StructuredEdgeDetection::detectEdges(Mat _src, Mat& _dst) + private static native void detectEdges_0(long nativeObj, long _src_nativeObj, long _dst_nativeObj); + + // C++: void cv::ximgproc::StructuredEdgeDetection::edgesNms(Mat edge_image, Mat orientation_image, Mat& _dst, int r = 2, int s = 0, float m = 1, bool isParallel = true) + private static native void edgesNms_0(long nativeObj, long edge_image_nativeObj, long orientation_image_nativeObj, long _dst_nativeObj, int r, int s, float m, boolean isParallel); + private static native void edgesNms_1(long nativeObj, long edge_image_nativeObj, long orientation_image_nativeObj, long _dst_nativeObj, int r, int s, float m); + private static native void edgesNms_2(long nativeObj, long edge_image_nativeObj, long orientation_image_nativeObj, long _dst_nativeObj, int r, int s); + private static native void edgesNms_3(long nativeObj, long edge_image_nativeObj, long orientation_image_nativeObj, long _dst_nativeObj, int r); + private static native void edgesNms_4(long nativeObj, long edge_image_nativeObj, long orientation_image_nativeObj, long _dst_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/SuperpixelLSC.java b/OpenCV/src/main/java/org/opencv/ximgproc/SuperpixelLSC.java new file mode 100644 index 00000000..b4296182 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/SuperpixelLSC.java @@ -0,0 +1,144 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class SuperpixelLSC +//javadoc: SuperpixelLSC + +public class SuperpixelLSC extends Algorithm { + + protected SuperpixelLSC(long addr) { super(addr); } + + // internal usage only + public static SuperpixelLSC __fromPtr__(long addr) { return new SuperpixelLSC(addr); } + + // + // C++: int cv::ximgproc::SuperpixelLSC::getNumberOfSuperpixels() + // + + //javadoc: SuperpixelLSC::getNumberOfSuperpixels() + public int getNumberOfSuperpixels() + { + + int retVal = getNumberOfSuperpixels_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::ximgproc::SuperpixelLSC::enforceLabelConnectivity(int min_element_size = 20) + // + + //javadoc: SuperpixelLSC::enforceLabelConnectivity(min_element_size) + public void enforceLabelConnectivity(int min_element_size) + { + + enforceLabelConnectivity_0(nativeObj, min_element_size); + + return; + } + + //javadoc: SuperpixelLSC::enforceLabelConnectivity() + public void enforceLabelConnectivity() + { + + enforceLabelConnectivity_1(nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::SuperpixelLSC::getLabelContourMask(Mat& image, bool thick_line = true) + // + + //javadoc: SuperpixelLSC::getLabelContourMask(image, thick_line) + public void getLabelContourMask(Mat image, boolean thick_line) + { + + getLabelContourMask_0(nativeObj, image.nativeObj, thick_line); + + return; + } + + //javadoc: SuperpixelLSC::getLabelContourMask(image) + public void getLabelContourMask(Mat image) + { + + getLabelContourMask_1(nativeObj, image.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::SuperpixelLSC::getLabels(Mat& labels_out) + // + + //javadoc: SuperpixelLSC::getLabels(labels_out) + public void getLabels(Mat labels_out) + { + + getLabels_0(nativeObj, labels_out.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::SuperpixelLSC::iterate(int num_iterations = 10) + // + + //javadoc: SuperpixelLSC::iterate(num_iterations) + public void iterate(int num_iterations) + { + + iterate_0(nativeObj, num_iterations); + + return; + } + + //javadoc: SuperpixelLSC::iterate() + public void iterate() + { + + iterate_1(nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: int cv::ximgproc::SuperpixelLSC::getNumberOfSuperpixels() + private static native int getNumberOfSuperpixels_0(long nativeObj); + + // C++: void cv::ximgproc::SuperpixelLSC::enforceLabelConnectivity(int min_element_size = 20) + private static native void enforceLabelConnectivity_0(long nativeObj, int min_element_size); + private static native void enforceLabelConnectivity_1(long nativeObj); + + // C++: void cv::ximgproc::SuperpixelLSC::getLabelContourMask(Mat& image, bool thick_line = true) + private static native void getLabelContourMask_0(long nativeObj, long image_nativeObj, boolean thick_line); + private static native void getLabelContourMask_1(long nativeObj, long image_nativeObj); + + // C++: void cv::ximgproc::SuperpixelLSC::getLabels(Mat& labels_out) + private static native void getLabels_0(long nativeObj, long labels_out_nativeObj); + + // C++: void cv::ximgproc::SuperpixelLSC::iterate(int num_iterations = 10) + private static native void iterate_0(long nativeObj, int num_iterations); + private static native void iterate_1(long nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/SuperpixelSEEDS.java b/OpenCV/src/main/java/org/opencv/ximgproc/SuperpixelSEEDS.java new file mode 100644 index 00000000..9616b0c7 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/SuperpixelSEEDS.java @@ -0,0 +1,117 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class SuperpixelSEEDS +//javadoc: SuperpixelSEEDS + +public class SuperpixelSEEDS extends Algorithm { + + protected SuperpixelSEEDS(long addr) { super(addr); } + + // internal usage only + public static SuperpixelSEEDS __fromPtr__(long addr) { return new SuperpixelSEEDS(addr); } + + // + // C++: int cv::ximgproc::SuperpixelSEEDS::getNumberOfSuperpixels() + // + + //javadoc: SuperpixelSEEDS::getNumberOfSuperpixels() + public int getNumberOfSuperpixels() + { + + int retVal = getNumberOfSuperpixels_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::ximgproc::SuperpixelSEEDS::getLabelContourMask(Mat& image, bool thick_line = false) + // + + //javadoc: SuperpixelSEEDS::getLabelContourMask(image, thick_line) + public void getLabelContourMask(Mat image, boolean thick_line) + { + + getLabelContourMask_0(nativeObj, image.nativeObj, thick_line); + + return; + } + + //javadoc: SuperpixelSEEDS::getLabelContourMask(image) + public void getLabelContourMask(Mat image) + { + + getLabelContourMask_1(nativeObj, image.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::SuperpixelSEEDS::getLabels(Mat& labels_out) + // + + //javadoc: SuperpixelSEEDS::getLabels(labels_out) + public void getLabels(Mat labels_out) + { + + getLabels_0(nativeObj, labels_out.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::SuperpixelSEEDS::iterate(Mat img, int num_iterations = 4) + // + + //javadoc: SuperpixelSEEDS::iterate(img, num_iterations) + public void iterate(Mat img, int num_iterations) + { + + iterate_0(nativeObj, img.nativeObj, num_iterations); + + return; + } + + //javadoc: SuperpixelSEEDS::iterate(img) + public void iterate(Mat img) + { + + iterate_1(nativeObj, img.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: int cv::ximgproc::SuperpixelSEEDS::getNumberOfSuperpixels() + private static native int getNumberOfSuperpixels_0(long nativeObj); + + // C++: void cv::ximgproc::SuperpixelSEEDS::getLabelContourMask(Mat& image, bool thick_line = false) + private static native void getLabelContourMask_0(long nativeObj, long image_nativeObj, boolean thick_line); + private static native void getLabelContourMask_1(long nativeObj, long image_nativeObj); + + // C++: void cv::ximgproc::SuperpixelSEEDS::getLabels(Mat& labels_out) + private static native void getLabels_0(long nativeObj, long labels_out_nativeObj); + + // C++: void cv::ximgproc::SuperpixelSEEDS::iterate(Mat img, int num_iterations = 4) + private static native void iterate_0(long nativeObj, long img_nativeObj, int num_iterations); + private static native void iterate_1(long nativeObj, long img_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/SuperpixelSLIC.java b/OpenCV/src/main/java/org/opencv/ximgproc/SuperpixelSLIC.java new file mode 100644 index 00000000..c7e8c8d9 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/SuperpixelSLIC.java @@ -0,0 +1,144 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class SuperpixelSLIC +//javadoc: SuperpixelSLIC + +public class SuperpixelSLIC extends Algorithm { + + protected SuperpixelSLIC(long addr) { super(addr); } + + // internal usage only + public static SuperpixelSLIC __fromPtr__(long addr) { return new SuperpixelSLIC(addr); } + + // + // C++: int cv::ximgproc::SuperpixelSLIC::getNumberOfSuperpixels() + // + + //javadoc: SuperpixelSLIC::getNumberOfSuperpixels() + public int getNumberOfSuperpixels() + { + + int retVal = getNumberOfSuperpixels_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::ximgproc::SuperpixelSLIC::enforceLabelConnectivity(int min_element_size = 25) + // + + //javadoc: SuperpixelSLIC::enforceLabelConnectivity(min_element_size) + public void enforceLabelConnectivity(int min_element_size) + { + + enforceLabelConnectivity_0(nativeObj, min_element_size); + + return; + } + + //javadoc: SuperpixelSLIC::enforceLabelConnectivity() + public void enforceLabelConnectivity() + { + + enforceLabelConnectivity_1(nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::SuperpixelSLIC::getLabelContourMask(Mat& image, bool thick_line = true) + // + + //javadoc: SuperpixelSLIC::getLabelContourMask(image, thick_line) + public void getLabelContourMask(Mat image, boolean thick_line) + { + + getLabelContourMask_0(nativeObj, image.nativeObj, thick_line); + + return; + } + + //javadoc: SuperpixelSLIC::getLabelContourMask(image) + public void getLabelContourMask(Mat image) + { + + getLabelContourMask_1(nativeObj, image.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::SuperpixelSLIC::getLabels(Mat& labels_out) + // + + //javadoc: SuperpixelSLIC::getLabels(labels_out) + public void getLabels(Mat labels_out) + { + + getLabels_0(nativeObj, labels_out.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::SuperpixelSLIC::iterate(int num_iterations = 10) + // + + //javadoc: SuperpixelSLIC::iterate(num_iterations) + public void iterate(int num_iterations) + { + + iterate_0(nativeObj, num_iterations); + + return; + } + + //javadoc: SuperpixelSLIC::iterate() + public void iterate() + { + + iterate_1(nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: int cv::ximgproc::SuperpixelSLIC::getNumberOfSuperpixels() + private static native int getNumberOfSuperpixels_0(long nativeObj); + + // C++: void cv::ximgproc::SuperpixelSLIC::enforceLabelConnectivity(int min_element_size = 25) + private static native void enforceLabelConnectivity_0(long nativeObj, int min_element_size); + private static native void enforceLabelConnectivity_1(long nativeObj); + + // C++: void cv::ximgproc::SuperpixelSLIC::getLabelContourMask(Mat& image, bool thick_line = true) + private static native void getLabelContourMask_0(long nativeObj, long image_nativeObj, boolean thick_line); + private static native void getLabelContourMask_1(long nativeObj, long image_nativeObj); + + // C++: void cv::ximgproc::SuperpixelSLIC::getLabels(Mat& labels_out) + private static native void getLabels_0(long nativeObj, long labels_out_nativeObj); + + // C++: void cv::ximgproc::SuperpixelSLIC::iterate(int num_iterations = 10) + private static native void iterate_0(long nativeObj, int num_iterations); + private static native void iterate_1(long nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/ximgproc/Ximgproc.java b/OpenCV/src/main/java/org/opencv/ximgproc/Ximgproc.java new file mode 100644 index 00000000..14c928ee --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/ximgproc/Ximgproc.java @@ -0,0 +1,1816 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.ximgproc; + +import java.lang.String; +import org.opencv.calib3d.StereoMatcher; +import org.opencv.core.Mat; +import org.opencv.ximgproc.AdaptiveManifoldFilter; +import org.opencv.ximgproc.ContourFitting; +import org.opencv.ximgproc.DTFilter; +import org.opencv.ximgproc.DisparityWLSFilter; +import org.opencv.ximgproc.EdgeAwareInterpolator; +import org.opencv.ximgproc.EdgeBoxes; +import org.opencv.ximgproc.FastBilateralSolverFilter; +import org.opencv.ximgproc.FastGlobalSmootherFilter; +import org.opencv.ximgproc.FastLineDetector; +import org.opencv.ximgproc.GraphSegmentation; +import org.opencv.ximgproc.GuidedFilter; +import org.opencv.ximgproc.RFFeatureGetter; +import org.opencv.ximgproc.SelectiveSearchSegmentation; +import org.opencv.ximgproc.SelectiveSearchSegmentationStrategy; +import org.opencv.ximgproc.SelectiveSearchSegmentationStrategyColor; +import org.opencv.ximgproc.SelectiveSearchSegmentationStrategyFill; +import org.opencv.ximgproc.SelectiveSearchSegmentationStrategyMultiple; +import org.opencv.ximgproc.SelectiveSearchSegmentationStrategySize; +import org.opencv.ximgproc.SelectiveSearchSegmentationStrategyTexture; +import org.opencv.ximgproc.StructuredEdgeDetection; +import org.opencv.ximgproc.SuperpixelLSC; +import org.opencv.ximgproc.SuperpixelSEEDS; +import org.opencv.ximgproc.SuperpixelSLIC; + +// C++: class Ximgproc +//javadoc: Ximgproc + +public class Ximgproc { + + // C++: enum LocalBinarizationMethods + public static final int + BINARIZATION_NIBLACK = 0, + BINARIZATION_SAUVOLA = 1, + BINARIZATION_WOLF = 2, + BINARIZATION_NICK = 3; + + + // C++: enum HoughDeskewOption + public static final int + HDO_RAW = 0, + HDO_DESKEW = 1; + + + // C++: enum WMFWeightType + public static final int + WMF_EXP = 1, + WMF_IV1 = 1 << 1, + WMF_IV2 = 1 << 2, + WMF_COS = 1 << 3, + WMF_JAC = 1 << 4, + WMF_OFF = 1 << 5; + + + // C++: enum EdgeAwareFiltersList + public static final int + DTF_NC = 0, + DTF_IC = 1, + DTF_RF = 2, + GUIDED_FILTER = 3, + AM_FILTER = 4; + + + // C++: enum ThinningTypes + public static final int + THINNING_ZHANGSUEN = 0, + THINNING_GUOHALL = 1; + + + // C++: enum HoughOp + public static final int + FHT_MIN = 0, + FHT_MAX = 1, + FHT_ADD = 2, + FHT_AVE = 3; + + + // C++: enum SLICType + public static final int + SLIC = 100, + SLICO = 101, + MSLIC = 102; + + + // C++: enum AngleRangeOption + public static final int + ARO_0_45 = 0, + ARO_45_90 = 1, + ARO_90_135 = 2, + ARO_315_0 = 3, + ARO_315_45 = 4, + ARO_45_135 = 5, + ARO_315_135 = 6, + ARO_CTR_HOR = 7, + ARO_CTR_VER = 8; + + + // + // C++: Ptr_AdaptiveManifoldFilter cv::ximgproc::createAMFilter(double sigma_s, double sigma_r, bool adjust_outliers = false) + // + + //javadoc: createAMFilter(sigma_s, sigma_r, adjust_outliers) + public static AdaptiveManifoldFilter createAMFilter(double sigma_s, double sigma_r, boolean adjust_outliers) + { + + AdaptiveManifoldFilter retVal = AdaptiveManifoldFilter.__fromPtr__(createAMFilter_0(sigma_s, sigma_r, adjust_outliers)); + + return retVal; + } + + //javadoc: createAMFilter(sigma_s, sigma_r) + public static AdaptiveManifoldFilter createAMFilter(double sigma_s, double sigma_r) + { + + AdaptiveManifoldFilter retVal = AdaptiveManifoldFilter.__fromPtr__(createAMFilter_1(sigma_s, sigma_r)); + + return retVal; + } + + + // + // C++: Ptr_ContourFitting cv::ximgproc::createContourFitting(int ctr = 1024, int fd = 16) + // + + //javadoc: createContourFitting(ctr, fd) + public static ContourFitting createContourFitting(int ctr, int fd) + { + + ContourFitting retVal = ContourFitting.__fromPtr__(createContourFitting_0(ctr, fd)); + + return retVal; + } + + //javadoc: createContourFitting(ctr) + public static ContourFitting createContourFitting(int ctr) + { + + ContourFitting retVal = ContourFitting.__fromPtr__(createContourFitting_1(ctr)); + + return retVal; + } + + //javadoc: createContourFitting() + public static ContourFitting createContourFitting() + { + + ContourFitting retVal = ContourFitting.__fromPtr__(createContourFitting_2()); + + return retVal; + } + + + // + // C++: Ptr_DTFilter cv::ximgproc::createDTFilter(Mat guide, double sigmaSpatial, double sigmaColor, int mode = DTF_NC, int numIters = 3) + // + + //javadoc: createDTFilter(guide, sigmaSpatial, sigmaColor, mode, numIters) + public static DTFilter createDTFilter(Mat guide, double sigmaSpatial, double sigmaColor, int mode, int numIters) + { + + DTFilter retVal = DTFilter.__fromPtr__(createDTFilter_0(guide.nativeObj, sigmaSpatial, sigmaColor, mode, numIters)); + + return retVal; + } + + //javadoc: createDTFilter(guide, sigmaSpatial, sigmaColor, mode) + public static DTFilter createDTFilter(Mat guide, double sigmaSpatial, double sigmaColor, int mode) + { + + DTFilter retVal = DTFilter.__fromPtr__(createDTFilter_1(guide.nativeObj, sigmaSpatial, sigmaColor, mode)); + + return retVal; + } + + //javadoc: createDTFilter(guide, sigmaSpatial, sigmaColor) + public static DTFilter createDTFilter(Mat guide, double sigmaSpatial, double sigmaColor) + { + + DTFilter retVal = DTFilter.__fromPtr__(createDTFilter_2(guide.nativeObj, sigmaSpatial, sigmaColor)); + + return retVal; + } + + + // + // C++: Ptr_DisparityWLSFilter cv::ximgproc::createDisparityWLSFilter(Ptr_StereoMatcher matcher_left) + // + + //javadoc: createDisparityWLSFilter(matcher_left) + public static DisparityWLSFilter createDisparityWLSFilter(StereoMatcher matcher_left) + { + + DisparityWLSFilter retVal = DisparityWLSFilter.__fromPtr__(createDisparityWLSFilter_0(matcher_left.getNativeObjAddr())); + + return retVal; + } + + + // + // C++: Ptr_DisparityWLSFilter cv::ximgproc::createDisparityWLSFilterGeneric(bool use_confidence) + // + + //javadoc: createDisparityWLSFilterGeneric(use_confidence) + public static DisparityWLSFilter createDisparityWLSFilterGeneric(boolean use_confidence) + { + + DisparityWLSFilter retVal = DisparityWLSFilter.__fromPtr__(createDisparityWLSFilterGeneric_0(use_confidence)); + + return retVal; + } + + + // + // C++: Ptr_EdgeAwareInterpolator cv::ximgproc::createEdgeAwareInterpolator() + // + + //javadoc: createEdgeAwareInterpolator() + public static EdgeAwareInterpolator createEdgeAwareInterpolator() + { + + EdgeAwareInterpolator retVal = EdgeAwareInterpolator.__fromPtr__(createEdgeAwareInterpolator_0()); + + return retVal; + } + + + // + // C++: Ptr_EdgeBoxes cv::ximgproc::createEdgeBoxes(float alpha = 0.65f, float beta = 0.75f, float eta = 1, float minScore = 0.01f, int maxBoxes = 10000, float edgeMinMag = 0.1f, float edgeMergeThr = 0.5f, float clusterMinMag = 0.5f, float maxAspectRatio = 3, float minBoxArea = 1000, float gamma = 2, float kappa = 1.5f) + // + + //javadoc: createEdgeBoxes(alpha, beta, eta, minScore, maxBoxes, edgeMinMag, edgeMergeThr, clusterMinMag, maxAspectRatio, minBoxArea, gamma, kappa) + public static EdgeBoxes createEdgeBoxes(float alpha, float beta, float eta, float minScore, int maxBoxes, float edgeMinMag, float edgeMergeThr, float clusterMinMag, float maxAspectRatio, float minBoxArea, float gamma, float kappa) + { + + EdgeBoxes retVal = EdgeBoxes.__fromPtr__(createEdgeBoxes_0(alpha, beta, eta, minScore, maxBoxes, edgeMinMag, edgeMergeThr, clusterMinMag, maxAspectRatio, minBoxArea, gamma, kappa)); + + return retVal; + } + + //javadoc: createEdgeBoxes(alpha, beta, eta, minScore, maxBoxes, edgeMinMag, edgeMergeThr, clusterMinMag, maxAspectRatio, minBoxArea, gamma) + public static EdgeBoxes createEdgeBoxes(float alpha, float beta, float eta, float minScore, int maxBoxes, float edgeMinMag, float edgeMergeThr, float clusterMinMag, float maxAspectRatio, float minBoxArea, float gamma) + { + + EdgeBoxes retVal = EdgeBoxes.__fromPtr__(createEdgeBoxes_1(alpha, beta, eta, minScore, maxBoxes, edgeMinMag, edgeMergeThr, clusterMinMag, maxAspectRatio, minBoxArea, gamma)); + + return retVal; + } + + //javadoc: createEdgeBoxes(alpha, beta, eta, minScore, maxBoxes, edgeMinMag, edgeMergeThr, clusterMinMag, maxAspectRatio, minBoxArea) + public static EdgeBoxes createEdgeBoxes(float alpha, float beta, float eta, float minScore, int maxBoxes, float edgeMinMag, float edgeMergeThr, float clusterMinMag, float maxAspectRatio, float minBoxArea) + { + + EdgeBoxes retVal = EdgeBoxes.__fromPtr__(createEdgeBoxes_2(alpha, beta, eta, minScore, maxBoxes, edgeMinMag, edgeMergeThr, clusterMinMag, maxAspectRatio, minBoxArea)); + + return retVal; + } + + //javadoc: createEdgeBoxes(alpha, beta, eta, minScore, maxBoxes, edgeMinMag, edgeMergeThr, clusterMinMag, maxAspectRatio) + public static EdgeBoxes createEdgeBoxes(float alpha, float beta, float eta, float minScore, int maxBoxes, float edgeMinMag, float edgeMergeThr, float clusterMinMag, float maxAspectRatio) + { + + EdgeBoxes retVal = EdgeBoxes.__fromPtr__(createEdgeBoxes_3(alpha, beta, eta, minScore, maxBoxes, edgeMinMag, edgeMergeThr, clusterMinMag, maxAspectRatio)); + + return retVal; + } + + //javadoc: createEdgeBoxes(alpha, beta, eta, minScore, maxBoxes, edgeMinMag, edgeMergeThr, clusterMinMag) + public static EdgeBoxes createEdgeBoxes(float alpha, float beta, float eta, float minScore, int maxBoxes, float edgeMinMag, float edgeMergeThr, float clusterMinMag) + { + + EdgeBoxes retVal = EdgeBoxes.__fromPtr__(createEdgeBoxes_4(alpha, beta, eta, minScore, maxBoxes, edgeMinMag, edgeMergeThr, clusterMinMag)); + + return retVal; + } + + //javadoc: createEdgeBoxes(alpha, beta, eta, minScore, maxBoxes, edgeMinMag, edgeMergeThr) + public static EdgeBoxes createEdgeBoxes(float alpha, float beta, float eta, float minScore, int maxBoxes, float edgeMinMag, float edgeMergeThr) + { + + EdgeBoxes retVal = EdgeBoxes.__fromPtr__(createEdgeBoxes_5(alpha, beta, eta, minScore, maxBoxes, edgeMinMag, edgeMergeThr)); + + return retVal; + } + + //javadoc: createEdgeBoxes(alpha, beta, eta, minScore, maxBoxes, edgeMinMag) + public static EdgeBoxes createEdgeBoxes(float alpha, float beta, float eta, float minScore, int maxBoxes, float edgeMinMag) + { + + EdgeBoxes retVal = EdgeBoxes.__fromPtr__(createEdgeBoxes_6(alpha, beta, eta, minScore, maxBoxes, edgeMinMag)); + + return retVal; + } + + //javadoc: createEdgeBoxes(alpha, beta, eta, minScore, maxBoxes) + public static EdgeBoxes createEdgeBoxes(float alpha, float beta, float eta, float minScore, int maxBoxes) + { + + EdgeBoxes retVal = EdgeBoxes.__fromPtr__(createEdgeBoxes_7(alpha, beta, eta, minScore, maxBoxes)); + + return retVal; + } + + //javadoc: createEdgeBoxes(alpha, beta, eta, minScore) + public static EdgeBoxes createEdgeBoxes(float alpha, float beta, float eta, float minScore) + { + + EdgeBoxes retVal = EdgeBoxes.__fromPtr__(createEdgeBoxes_8(alpha, beta, eta, minScore)); + + return retVal; + } + + //javadoc: createEdgeBoxes(alpha, beta, eta) + public static EdgeBoxes createEdgeBoxes(float alpha, float beta, float eta) + { + + EdgeBoxes retVal = EdgeBoxes.__fromPtr__(createEdgeBoxes_9(alpha, beta, eta)); + + return retVal; + } + + //javadoc: createEdgeBoxes(alpha, beta) + public static EdgeBoxes createEdgeBoxes(float alpha, float beta) + { + + EdgeBoxes retVal = EdgeBoxes.__fromPtr__(createEdgeBoxes_10(alpha, beta)); + + return retVal; + } + + //javadoc: createEdgeBoxes(alpha) + public static EdgeBoxes createEdgeBoxes(float alpha) + { + + EdgeBoxes retVal = EdgeBoxes.__fromPtr__(createEdgeBoxes_11(alpha)); + + return retVal; + } + + //javadoc: createEdgeBoxes() + public static EdgeBoxes createEdgeBoxes() + { + + EdgeBoxes retVal = EdgeBoxes.__fromPtr__(createEdgeBoxes_12()); + + return retVal; + } + + + // + // C++: Ptr_FastBilateralSolverFilter cv::ximgproc::createFastBilateralSolverFilter(Mat guide, double sigma_spatial, double sigma_luma, double sigma_chroma, double lambda = 128.0, int num_iter = 25, double max_tol = 1e-5) + // + + //javadoc: createFastBilateralSolverFilter(guide, sigma_spatial, sigma_luma, sigma_chroma, lambda, num_iter, max_tol) + public static FastBilateralSolverFilter createFastBilateralSolverFilter(Mat guide, double sigma_spatial, double sigma_luma, double sigma_chroma, double lambda, int num_iter, double max_tol) + { + + FastBilateralSolverFilter retVal = FastBilateralSolverFilter.__fromPtr__(createFastBilateralSolverFilter_0(guide.nativeObj, sigma_spatial, sigma_luma, sigma_chroma, lambda, num_iter, max_tol)); + + return retVal; + } + + //javadoc: createFastBilateralSolverFilter(guide, sigma_spatial, sigma_luma, sigma_chroma, lambda, num_iter) + public static FastBilateralSolverFilter createFastBilateralSolverFilter(Mat guide, double sigma_spatial, double sigma_luma, double sigma_chroma, double lambda, int num_iter) + { + + FastBilateralSolverFilter retVal = FastBilateralSolverFilter.__fromPtr__(createFastBilateralSolverFilter_1(guide.nativeObj, sigma_spatial, sigma_luma, sigma_chroma, lambda, num_iter)); + + return retVal; + } + + //javadoc: createFastBilateralSolverFilter(guide, sigma_spatial, sigma_luma, sigma_chroma, lambda) + public static FastBilateralSolverFilter createFastBilateralSolverFilter(Mat guide, double sigma_spatial, double sigma_luma, double sigma_chroma, double lambda) + { + + FastBilateralSolverFilter retVal = FastBilateralSolverFilter.__fromPtr__(createFastBilateralSolverFilter_2(guide.nativeObj, sigma_spatial, sigma_luma, sigma_chroma, lambda)); + + return retVal; + } + + //javadoc: createFastBilateralSolverFilter(guide, sigma_spatial, sigma_luma, sigma_chroma) + public static FastBilateralSolverFilter createFastBilateralSolverFilter(Mat guide, double sigma_spatial, double sigma_luma, double sigma_chroma) + { + + FastBilateralSolverFilter retVal = FastBilateralSolverFilter.__fromPtr__(createFastBilateralSolverFilter_3(guide.nativeObj, sigma_spatial, sigma_luma, sigma_chroma)); + + return retVal; + } + + + // + // C++: Ptr_FastGlobalSmootherFilter cv::ximgproc::createFastGlobalSmootherFilter(Mat guide, double lambda, double sigma_color, double lambda_attenuation = 0.25, int num_iter = 3) + // + + //javadoc: createFastGlobalSmootherFilter(guide, lambda, sigma_color, lambda_attenuation, num_iter) + public static FastGlobalSmootherFilter createFastGlobalSmootherFilter(Mat guide, double lambda, double sigma_color, double lambda_attenuation, int num_iter) + { + + FastGlobalSmootherFilter retVal = FastGlobalSmootherFilter.__fromPtr__(createFastGlobalSmootherFilter_0(guide.nativeObj, lambda, sigma_color, lambda_attenuation, num_iter)); + + return retVal; + } + + //javadoc: createFastGlobalSmootherFilter(guide, lambda, sigma_color, lambda_attenuation) + public static FastGlobalSmootherFilter createFastGlobalSmootherFilter(Mat guide, double lambda, double sigma_color, double lambda_attenuation) + { + + FastGlobalSmootherFilter retVal = FastGlobalSmootherFilter.__fromPtr__(createFastGlobalSmootherFilter_1(guide.nativeObj, lambda, sigma_color, lambda_attenuation)); + + return retVal; + } + + //javadoc: createFastGlobalSmootherFilter(guide, lambda, sigma_color) + public static FastGlobalSmootherFilter createFastGlobalSmootherFilter(Mat guide, double lambda, double sigma_color) + { + + FastGlobalSmootherFilter retVal = FastGlobalSmootherFilter.__fromPtr__(createFastGlobalSmootherFilter_2(guide.nativeObj, lambda, sigma_color)); + + return retVal; + } + + + // + // C++: Ptr_FastLineDetector cv::ximgproc::createFastLineDetector(int _length_threshold = 10, float _distance_threshold = 1.414213562f, double _canny_th1 = 50.0, double _canny_th2 = 50.0, int _canny_aperture_size = 3, bool _do_merge = false) + // + + //javadoc: createFastLineDetector(_length_threshold, _distance_threshold, _canny_th1, _canny_th2, _canny_aperture_size, _do_merge) + public static FastLineDetector createFastLineDetector(int _length_threshold, float _distance_threshold, double _canny_th1, double _canny_th2, int _canny_aperture_size, boolean _do_merge) + { + + FastLineDetector retVal = FastLineDetector.__fromPtr__(createFastLineDetector_0(_length_threshold, _distance_threshold, _canny_th1, _canny_th2, _canny_aperture_size, _do_merge)); + + return retVal; + } + + //javadoc: createFastLineDetector(_length_threshold, _distance_threshold, _canny_th1, _canny_th2, _canny_aperture_size) + public static FastLineDetector createFastLineDetector(int _length_threshold, float _distance_threshold, double _canny_th1, double _canny_th2, int _canny_aperture_size) + { + + FastLineDetector retVal = FastLineDetector.__fromPtr__(createFastLineDetector_1(_length_threshold, _distance_threshold, _canny_th1, _canny_th2, _canny_aperture_size)); + + return retVal; + } + + //javadoc: createFastLineDetector(_length_threshold, _distance_threshold, _canny_th1, _canny_th2) + public static FastLineDetector createFastLineDetector(int _length_threshold, float _distance_threshold, double _canny_th1, double _canny_th2) + { + + FastLineDetector retVal = FastLineDetector.__fromPtr__(createFastLineDetector_2(_length_threshold, _distance_threshold, _canny_th1, _canny_th2)); + + return retVal; + } + + //javadoc: createFastLineDetector(_length_threshold, _distance_threshold, _canny_th1) + public static FastLineDetector createFastLineDetector(int _length_threshold, float _distance_threshold, double _canny_th1) + { + + FastLineDetector retVal = FastLineDetector.__fromPtr__(createFastLineDetector_3(_length_threshold, _distance_threshold, _canny_th1)); + + return retVal; + } + + //javadoc: createFastLineDetector(_length_threshold, _distance_threshold) + public static FastLineDetector createFastLineDetector(int _length_threshold, float _distance_threshold) + { + + FastLineDetector retVal = FastLineDetector.__fromPtr__(createFastLineDetector_4(_length_threshold, _distance_threshold)); + + return retVal; + } + + //javadoc: createFastLineDetector(_length_threshold) + public static FastLineDetector createFastLineDetector(int _length_threshold) + { + + FastLineDetector retVal = FastLineDetector.__fromPtr__(createFastLineDetector_5(_length_threshold)); + + return retVal; + } + + //javadoc: createFastLineDetector() + public static FastLineDetector createFastLineDetector() + { + + FastLineDetector retVal = FastLineDetector.__fromPtr__(createFastLineDetector_6()); + + return retVal; + } + + + // + // C++: Ptr_GraphSegmentation cv::ximgproc::segmentation::createGraphSegmentation(double sigma = 0.5, float k = 300, int min_size = 100) + // + + //javadoc: createGraphSegmentation(sigma, k, min_size) + public static GraphSegmentation createGraphSegmentation(double sigma, float k, int min_size) + { + + GraphSegmentation retVal = GraphSegmentation.__fromPtr__(createGraphSegmentation_0(sigma, k, min_size)); + + return retVal; + } + + //javadoc: createGraphSegmentation(sigma, k) + public static GraphSegmentation createGraphSegmentation(double sigma, float k) + { + + GraphSegmentation retVal = GraphSegmentation.__fromPtr__(createGraphSegmentation_1(sigma, k)); + + return retVal; + } + + //javadoc: createGraphSegmentation(sigma) + public static GraphSegmentation createGraphSegmentation(double sigma) + { + + GraphSegmentation retVal = GraphSegmentation.__fromPtr__(createGraphSegmentation_2(sigma)); + + return retVal; + } + + //javadoc: createGraphSegmentation() + public static GraphSegmentation createGraphSegmentation() + { + + GraphSegmentation retVal = GraphSegmentation.__fromPtr__(createGraphSegmentation_3()); + + return retVal; + } + + + // + // C++: Ptr_GuidedFilter cv::ximgproc::createGuidedFilter(Mat guide, int radius, double eps) + // + + //javadoc: createGuidedFilter(guide, radius, eps) + public static GuidedFilter createGuidedFilter(Mat guide, int radius, double eps) + { + + GuidedFilter retVal = GuidedFilter.__fromPtr__(createGuidedFilter_0(guide.nativeObj, radius, eps)); + + return retVal; + } + + + // + // C++: Ptr_RFFeatureGetter cv::ximgproc::createRFFeatureGetter() + // + + //javadoc: createRFFeatureGetter() + public static RFFeatureGetter createRFFeatureGetter() + { + + RFFeatureGetter retVal = RFFeatureGetter.__fromPtr__(createRFFeatureGetter_0()); + + return retVal; + } + + + // + // C++: Ptr_SelectiveSearchSegmentation cv::ximgproc::segmentation::createSelectiveSearchSegmentation() + // + + //javadoc: createSelectiveSearchSegmentation() + public static SelectiveSearchSegmentation createSelectiveSearchSegmentation() + { + + SelectiveSearchSegmentation retVal = SelectiveSearchSegmentation.__fromPtr__(createSelectiveSearchSegmentation_0()); + + return retVal; + } + + + // + // C++: Ptr_SelectiveSearchSegmentationStrategyColor cv::ximgproc::segmentation::createSelectiveSearchSegmentationStrategyColor() + // + + //javadoc: createSelectiveSearchSegmentationStrategyColor() + public static SelectiveSearchSegmentationStrategyColor createSelectiveSearchSegmentationStrategyColor() + { + + SelectiveSearchSegmentationStrategyColor retVal = SelectiveSearchSegmentationStrategyColor.__fromPtr__(createSelectiveSearchSegmentationStrategyColor_0()); + + return retVal; + } + + + // + // C++: Ptr_SelectiveSearchSegmentationStrategyFill cv::ximgproc::segmentation::createSelectiveSearchSegmentationStrategyFill() + // + + //javadoc: createSelectiveSearchSegmentationStrategyFill() + public static SelectiveSearchSegmentationStrategyFill createSelectiveSearchSegmentationStrategyFill() + { + + SelectiveSearchSegmentationStrategyFill retVal = SelectiveSearchSegmentationStrategyFill.__fromPtr__(createSelectiveSearchSegmentationStrategyFill_0()); + + return retVal; + } + + + // + // C++: Ptr_SelectiveSearchSegmentationStrategyMultiple cv::ximgproc::segmentation::createSelectiveSearchSegmentationStrategyMultiple(Ptr_SelectiveSearchSegmentationStrategy s1, Ptr_SelectiveSearchSegmentationStrategy s2, Ptr_SelectiveSearchSegmentationStrategy s3, Ptr_SelectiveSearchSegmentationStrategy s4) + // + + //javadoc: createSelectiveSearchSegmentationStrategyMultiple(s1, s2, s3, s4) + public static SelectiveSearchSegmentationStrategyMultiple createSelectiveSearchSegmentationStrategyMultiple(SelectiveSearchSegmentationStrategy s1, SelectiveSearchSegmentationStrategy s2, SelectiveSearchSegmentationStrategy s3, SelectiveSearchSegmentationStrategy s4) + { + + SelectiveSearchSegmentationStrategyMultiple retVal = SelectiveSearchSegmentationStrategyMultiple.__fromPtr__(createSelectiveSearchSegmentationStrategyMultiple_0(s1.getNativeObjAddr(), s2.getNativeObjAddr(), s3.getNativeObjAddr(), s4.getNativeObjAddr())); + + return retVal; + } + + + // + // C++: Ptr_SelectiveSearchSegmentationStrategyMultiple cv::ximgproc::segmentation::createSelectiveSearchSegmentationStrategyMultiple(Ptr_SelectiveSearchSegmentationStrategy s1, Ptr_SelectiveSearchSegmentationStrategy s2, Ptr_SelectiveSearchSegmentationStrategy s3) + // + + //javadoc: createSelectiveSearchSegmentationStrategyMultiple(s1, s2, s3) + public static SelectiveSearchSegmentationStrategyMultiple createSelectiveSearchSegmentationStrategyMultiple(SelectiveSearchSegmentationStrategy s1, SelectiveSearchSegmentationStrategy s2, SelectiveSearchSegmentationStrategy s3) + { + + SelectiveSearchSegmentationStrategyMultiple retVal = SelectiveSearchSegmentationStrategyMultiple.__fromPtr__(createSelectiveSearchSegmentationStrategyMultiple_1(s1.getNativeObjAddr(), s2.getNativeObjAddr(), s3.getNativeObjAddr())); + + return retVal; + } + + + // + // C++: Ptr_SelectiveSearchSegmentationStrategyMultiple cv::ximgproc::segmentation::createSelectiveSearchSegmentationStrategyMultiple(Ptr_SelectiveSearchSegmentationStrategy s1, Ptr_SelectiveSearchSegmentationStrategy s2) + // + + //javadoc: createSelectiveSearchSegmentationStrategyMultiple(s1, s2) + public static SelectiveSearchSegmentationStrategyMultiple createSelectiveSearchSegmentationStrategyMultiple(SelectiveSearchSegmentationStrategy s1, SelectiveSearchSegmentationStrategy s2) + { + + SelectiveSearchSegmentationStrategyMultiple retVal = SelectiveSearchSegmentationStrategyMultiple.__fromPtr__(createSelectiveSearchSegmentationStrategyMultiple_2(s1.getNativeObjAddr(), s2.getNativeObjAddr())); + + return retVal; + } + + + // + // C++: Ptr_SelectiveSearchSegmentationStrategyMultiple cv::ximgproc::segmentation::createSelectiveSearchSegmentationStrategyMultiple(Ptr_SelectiveSearchSegmentationStrategy s1) + // + + //javadoc: createSelectiveSearchSegmentationStrategyMultiple(s1) + public static SelectiveSearchSegmentationStrategyMultiple createSelectiveSearchSegmentationStrategyMultiple(SelectiveSearchSegmentationStrategy s1) + { + + SelectiveSearchSegmentationStrategyMultiple retVal = SelectiveSearchSegmentationStrategyMultiple.__fromPtr__(createSelectiveSearchSegmentationStrategyMultiple_3(s1.getNativeObjAddr())); + + return retVal; + } + + + // + // C++: Ptr_SelectiveSearchSegmentationStrategyMultiple cv::ximgproc::segmentation::createSelectiveSearchSegmentationStrategyMultiple() + // + + //javadoc: createSelectiveSearchSegmentationStrategyMultiple() + public static SelectiveSearchSegmentationStrategyMultiple createSelectiveSearchSegmentationStrategyMultiple() + { + + SelectiveSearchSegmentationStrategyMultiple retVal = SelectiveSearchSegmentationStrategyMultiple.__fromPtr__(createSelectiveSearchSegmentationStrategyMultiple_4()); + + return retVal; + } + + + // + // C++: Ptr_SelectiveSearchSegmentationStrategySize cv::ximgproc::segmentation::createSelectiveSearchSegmentationStrategySize() + // + + //javadoc: createSelectiveSearchSegmentationStrategySize() + public static SelectiveSearchSegmentationStrategySize createSelectiveSearchSegmentationStrategySize() + { + + SelectiveSearchSegmentationStrategySize retVal = SelectiveSearchSegmentationStrategySize.__fromPtr__(createSelectiveSearchSegmentationStrategySize_0()); + + return retVal; + } + + + // + // C++: Ptr_SelectiveSearchSegmentationStrategyTexture cv::ximgproc::segmentation::createSelectiveSearchSegmentationStrategyTexture() + // + + //javadoc: createSelectiveSearchSegmentationStrategyTexture() + public static SelectiveSearchSegmentationStrategyTexture createSelectiveSearchSegmentationStrategyTexture() + { + + SelectiveSearchSegmentationStrategyTexture retVal = SelectiveSearchSegmentationStrategyTexture.__fromPtr__(createSelectiveSearchSegmentationStrategyTexture_0()); + + return retVal; + } + + + // + // C++: Ptr_StereoMatcher cv::ximgproc::createRightMatcher(Ptr_StereoMatcher matcher_left) + // + + //javadoc: createRightMatcher(matcher_left) + public static StereoMatcher createRightMatcher(StereoMatcher matcher_left) + { + + StereoMatcher retVal = StereoMatcher.__fromPtr__(createRightMatcher_0(matcher_left.getNativeObjAddr())); + + return retVal; + } + + + // + // C++: Ptr_StructuredEdgeDetection cv::ximgproc::createStructuredEdgeDetection(String model, Ptr_RFFeatureGetter howToGetFeatures = Ptr()) + // + + //javadoc: createStructuredEdgeDetection(model, howToGetFeatures) + public static StructuredEdgeDetection createStructuredEdgeDetection(String model, RFFeatureGetter howToGetFeatures) + { + + StructuredEdgeDetection retVal = StructuredEdgeDetection.__fromPtr__(createStructuredEdgeDetection_0(model, howToGetFeatures.getNativeObjAddr())); + + return retVal; + } + + //javadoc: createStructuredEdgeDetection(model) + public static StructuredEdgeDetection createStructuredEdgeDetection(String model) + { + + StructuredEdgeDetection retVal = StructuredEdgeDetection.__fromPtr__(createStructuredEdgeDetection_1(model)); + + return retVal; + } + + + // + // C++: Ptr_SuperpixelLSC cv::ximgproc::createSuperpixelLSC(Mat image, int region_size = 10, float ratio = 0.075f) + // + + //javadoc: createSuperpixelLSC(image, region_size, ratio) + public static SuperpixelLSC createSuperpixelLSC(Mat image, int region_size, float ratio) + { + + SuperpixelLSC retVal = SuperpixelLSC.__fromPtr__(createSuperpixelLSC_0(image.nativeObj, region_size, ratio)); + + return retVal; + } + + //javadoc: createSuperpixelLSC(image, region_size) + public static SuperpixelLSC createSuperpixelLSC(Mat image, int region_size) + { + + SuperpixelLSC retVal = SuperpixelLSC.__fromPtr__(createSuperpixelLSC_1(image.nativeObj, region_size)); + + return retVal; + } + + //javadoc: createSuperpixelLSC(image) + public static SuperpixelLSC createSuperpixelLSC(Mat image) + { + + SuperpixelLSC retVal = SuperpixelLSC.__fromPtr__(createSuperpixelLSC_2(image.nativeObj)); + + return retVal; + } + + + // + // C++: Ptr_SuperpixelSEEDS cv::ximgproc::createSuperpixelSEEDS(int image_width, int image_height, int image_channels, int num_superpixels, int num_levels, int prior = 2, int histogram_bins = 5, bool double_step = false) + // + + //javadoc: createSuperpixelSEEDS(image_width, image_height, image_channels, num_superpixels, num_levels, prior, histogram_bins, double_step) + public static SuperpixelSEEDS createSuperpixelSEEDS(int image_width, int image_height, int image_channels, int num_superpixels, int num_levels, int prior, int histogram_bins, boolean double_step) + { + + SuperpixelSEEDS retVal = SuperpixelSEEDS.__fromPtr__(createSuperpixelSEEDS_0(image_width, image_height, image_channels, num_superpixels, num_levels, prior, histogram_bins, double_step)); + + return retVal; + } + + //javadoc: createSuperpixelSEEDS(image_width, image_height, image_channels, num_superpixels, num_levels, prior, histogram_bins) + public static SuperpixelSEEDS createSuperpixelSEEDS(int image_width, int image_height, int image_channels, int num_superpixels, int num_levels, int prior, int histogram_bins) + { + + SuperpixelSEEDS retVal = SuperpixelSEEDS.__fromPtr__(createSuperpixelSEEDS_1(image_width, image_height, image_channels, num_superpixels, num_levels, prior, histogram_bins)); + + return retVal; + } + + //javadoc: createSuperpixelSEEDS(image_width, image_height, image_channels, num_superpixels, num_levels, prior) + public static SuperpixelSEEDS createSuperpixelSEEDS(int image_width, int image_height, int image_channels, int num_superpixels, int num_levels, int prior) + { + + SuperpixelSEEDS retVal = SuperpixelSEEDS.__fromPtr__(createSuperpixelSEEDS_2(image_width, image_height, image_channels, num_superpixels, num_levels, prior)); + + return retVal; + } + + //javadoc: createSuperpixelSEEDS(image_width, image_height, image_channels, num_superpixels, num_levels) + public static SuperpixelSEEDS createSuperpixelSEEDS(int image_width, int image_height, int image_channels, int num_superpixels, int num_levels) + { + + SuperpixelSEEDS retVal = SuperpixelSEEDS.__fromPtr__(createSuperpixelSEEDS_3(image_width, image_height, image_channels, num_superpixels, num_levels)); + + return retVal; + } + + + // + // C++: Ptr_SuperpixelSLIC cv::ximgproc::createSuperpixelSLIC(Mat image, int algorithm = SLICO, int region_size = 10, float ruler = 10.0f) + // + + //javadoc: createSuperpixelSLIC(image, algorithm, region_size, ruler) + public static SuperpixelSLIC createSuperpixelSLIC(Mat image, int algorithm, int region_size, float ruler) + { + + SuperpixelSLIC retVal = SuperpixelSLIC.__fromPtr__(createSuperpixelSLIC_0(image.nativeObj, algorithm, region_size, ruler)); + + return retVal; + } + + //javadoc: createSuperpixelSLIC(image, algorithm, region_size) + public static SuperpixelSLIC createSuperpixelSLIC(Mat image, int algorithm, int region_size) + { + + SuperpixelSLIC retVal = SuperpixelSLIC.__fromPtr__(createSuperpixelSLIC_1(image.nativeObj, algorithm, region_size)); + + return retVal; + } + + //javadoc: createSuperpixelSLIC(image, algorithm) + public static SuperpixelSLIC createSuperpixelSLIC(Mat image, int algorithm) + { + + SuperpixelSLIC retVal = SuperpixelSLIC.__fromPtr__(createSuperpixelSLIC_2(image.nativeObj, algorithm)); + + return retVal; + } + + //javadoc: createSuperpixelSLIC(image) + public static SuperpixelSLIC createSuperpixelSLIC(Mat image) + { + + SuperpixelSLIC retVal = SuperpixelSLIC.__fromPtr__(createSuperpixelSLIC_3(image.nativeObj)); + + return retVal; + } + + + // + // C++: Vec4i cv::ximgproc::HoughPoint2Line(Point houghPoint, Mat srcImgInfo, int angleRange = ARO_315_135, int makeSkew = HDO_DESKEW, int rules = RO_IGNORE_BORDERS) + // + + // Return type 'Vec4i' is not supported, skipping the function + + + // + // C++: void cv::ximgproc::FastHoughTransform(Mat src, Mat& dst, int dstMatDepth, int angleRange = ARO_315_135, int op = FHT_ADD, int makeSkew = HDO_DESKEW) + // + + //javadoc: FastHoughTransform(src, dst, dstMatDepth, angleRange, op, makeSkew) + public static void FastHoughTransform(Mat src, Mat dst, int dstMatDepth, int angleRange, int op, int makeSkew) + { + + FastHoughTransform_0(src.nativeObj, dst.nativeObj, dstMatDepth, angleRange, op, makeSkew); + + return; + } + + //javadoc: FastHoughTransform(src, dst, dstMatDepth, angleRange, op) + public static void FastHoughTransform(Mat src, Mat dst, int dstMatDepth, int angleRange, int op) + { + + FastHoughTransform_1(src.nativeObj, dst.nativeObj, dstMatDepth, angleRange, op); + + return; + } + + //javadoc: FastHoughTransform(src, dst, dstMatDepth, angleRange) + public static void FastHoughTransform(Mat src, Mat dst, int dstMatDepth, int angleRange) + { + + FastHoughTransform_2(src.nativeObj, dst.nativeObj, dstMatDepth, angleRange); + + return; + } + + //javadoc: FastHoughTransform(src, dst, dstMatDepth) + public static void FastHoughTransform(Mat src, Mat dst, int dstMatDepth) + { + + FastHoughTransform_3(src.nativeObj, dst.nativeObj, dstMatDepth); + + return; + } + + + // + // C++: void cv::ximgproc::GradientDericheX(Mat op, Mat& dst, double alpha, double omega) + // + + //javadoc: GradientDericheX(op, dst, alpha, omega) + public static void GradientDericheX(Mat op, Mat dst, double alpha, double omega) + { + + GradientDericheX_0(op.nativeObj, dst.nativeObj, alpha, omega); + + return; + } + + + // + // C++: void cv::ximgproc::GradientDericheY(Mat op, Mat& dst, double alpha, double omega) + // + + //javadoc: GradientDericheY(op, dst, alpha, omega) + public static void GradientDericheY(Mat op, Mat dst, double alpha, double omega) + { + + GradientDericheY_0(op.nativeObj, dst.nativeObj, alpha, omega); + + return; + } + + + // + // C++: void cv::ximgproc::PeiLinNormalization(Mat I, Mat& T) + // + + //javadoc: PeiLinNormalization(I, T) + public static void PeiLinNormalization(Mat I, Mat T) + { + + PeiLinNormalization_0(I.nativeObj, T.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::amFilter(Mat joint, Mat src, Mat& dst, double sigma_s, double sigma_r, bool adjust_outliers = false) + // + + //javadoc: amFilter(joint, src, dst, sigma_s, sigma_r, adjust_outliers) + public static void amFilter(Mat joint, Mat src, Mat dst, double sigma_s, double sigma_r, boolean adjust_outliers) + { + + amFilter_0(joint.nativeObj, src.nativeObj, dst.nativeObj, sigma_s, sigma_r, adjust_outliers); + + return; + } + + //javadoc: amFilter(joint, src, dst, sigma_s, sigma_r) + public static void amFilter(Mat joint, Mat src, Mat dst, double sigma_s, double sigma_r) + { + + amFilter_1(joint.nativeObj, src.nativeObj, dst.nativeObj, sigma_s, sigma_r); + + return; + } + + + // + // C++: void cv::ximgproc::anisotropicDiffusion(Mat src, Mat& dst, float alpha, float K, int niters) + // + + //javadoc: anisotropicDiffusion(src, dst, alpha, K, niters) + public static void anisotropicDiffusion(Mat src, Mat dst, float alpha, float K, int niters) + { + + anisotropicDiffusion_0(src.nativeObj, dst.nativeObj, alpha, K, niters); + + return; + } + + + // + // C++: void cv::ximgproc::bilateralTextureFilter(Mat src, Mat& dst, int fr = 3, int numIter = 1, double sigmaAlpha = -1., double sigmaAvg = -1.) + // + + //javadoc: bilateralTextureFilter(src, dst, fr, numIter, sigmaAlpha, sigmaAvg) + public static void bilateralTextureFilter(Mat src, Mat dst, int fr, int numIter, double sigmaAlpha, double sigmaAvg) + { + + bilateralTextureFilter_0(src.nativeObj, dst.nativeObj, fr, numIter, sigmaAlpha, sigmaAvg); + + return; + } + + //javadoc: bilateralTextureFilter(src, dst, fr, numIter, sigmaAlpha) + public static void bilateralTextureFilter(Mat src, Mat dst, int fr, int numIter, double sigmaAlpha) + { + + bilateralTextureFilter_1(src.nativeObj, dst.nativeObj, fr, numIter, sigmaAlpha); + + return; + } + + //javadoc: bilateralTextureFilter(src, dst, fr, numIter) + public static void bilateralTextureFilter(Mat src, Mat dst, int fr, int numIter) + { + + bilateralTextureFilter_2(src.nativeObj, dst.nativeObj, fr, numIter); + + return; + } + + //javadoc: bilateralTextureFilter(src, dst, fr) + public static void bilateralTextureFilter(Mat src, Mat dst, int fr) + { + + bilateralTextureFilter_3(src.nativeObj, dst.nativeObj, fr); + + return; + } + + //javadoc: bilateralTextureFilter(src, dst) + public static void bilateralTextureFilter(Mat src, Mat dst) + { + + bilateralTextureFilter_4(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::colorMatchTemplate(Mat img, Mat templ, Mat& result) + // + + //javadoc: colorMatchTemplate(img, templ, result) + public static void colorMatchTemplate(Mat img, Mat templ, Mat result) + { + + colorMatchTemplate_0(img.nativeObj, templ.nativeObj, result.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::contourSampling(Mat src, Mat& out, int nbElt) + // + + //javadoc: contourSampling(src, out, nbElt) + public static void contourSampling(Mat src, Mat out, int nbElt) + { + + contourSampling_0(src.nativeObj, out.nativeObj, nbElt); + + return; + } + + + // + // C++: void cv::ximgproc::covarianceEstimation(Mat src, Mat& dst, int windowRows, int windowCols) + // + + //javadoc: covarianceEstimation(src, dst, windowRows, windowCols) + public static void covarianceEstimation(Mat src, Mat dst, int windowRows, int windowCols) + { + + covarianceEstimation_0(src.nativeObj, dst.nativeObj, windowRows, windowCols); + + return; + } + + + // + // C++: void cv::ximgproc::createQuaternionImage(Mat img, Mat& qimg) + // + + //javadoc: createQuaternionImage(img, qimg) + public static void createQuaternionImage(Mat img, Mat qimg) + { + + createQuaternionImage_0(img.nativeObj, qimg.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::dtFilter(Mat guide, Mat src, Mat& dst, double sigmaSpatial, double sigmaColor, int mode = DTF_NC, int numIters = 3) + // + + //javadoc: dtFilter(guide, src, dst, sigmaSpatial, sigmaColor, mode, numIters) + public static void dtFilter(Mat guide, Mat src, Mat dst, double sigmaSpatial, double sigmaColor, int mode, int numIters) + { + + dtFilter_0(guide.nativeObj, src.nativeObj, dst.nativeObj, sigmaSpatial, sigmaColor, mode, numIters); + + return; + } + + //javadoc: dtFilter(guide, src, dst, sigmaSpatial, sigmaColor, mode) + public static void dtFilter(Mat guide, Mat src, Mat dst, double sigmaSpatial, double sigmaColor, int mode) + { + + dtFilter_1(guide.nativeObj, src.nativeObj, dst.nativeObj, sigmaSpatial, sigmaColor, mode); + + return; + } + + //javadoc: dtFilter(guide, src, dst, sigmaSpatial, sigmaColor) + public static void dtFilter(Mat guide, Mat src, Mat dst, double sigmaSpatial, double sigmaColor) + { + + dtFilter_2(guide.nativeObj, src.nativeObj, dst.nativeObj, sigmaSpatial, sigmaColor); + + return; + } + + + // + // C++: void cv::ximgproc::edgePreservingFilter(Mat src, Mat& dst, int d, double threshold) + // + + //javadoc: edgePreservingFilter(src, dst, d, threshold) + public static void edgePreservingFilter(Mat src, Mat dst, int d, double threshold) + { + + edgePreservingFilter_0(src.nativeObj, dst.nativeObj, d, threshold); + + return; + } + + + // + // C++: void cv::ximgproc::fastBilateralSolverFilter(Mat guide, Mat src, Mat confidence, Mat& dst, double sigma_spatial = 8, double sigma_luma = 8, double sigma_chroma = 8, double lambda = 128.0, int num_iter = 25, double max_tol = 1e-5) + // + + //javadoc: fastBilateralSolverFilter(guide, src, confidence, dst, sigma_spatial, sigma_luma, sigma_chroma, lambda, num_iter, max_tol) + public static void fastBilateralSolverFilter(Mat guide, Mat src, Mat confidence, Mat dst, double sigma_spatial, double sigma_luma, double sigma_chroma, double lambda, int num_iter, double max_tol) + { + + fastBilateralSolverFilter_0(guide.nativeObj, src.nativeObj, confidence.nativeObj, dst.nativeObj, sigma_spatial, sigma_luma, sigma_chroma, lambda, num_iter, max_tol); + + return; + } + + //javadoc: fastBilateralSolverFilter(guide, src, confidence, dst, sigma_spatial, sigma_luma, sigma_chroma, lambda, num_iter) + public static void fastBilateralSolverFilter(Mat guide, Mat src, Mat confidence, Mat dst, double sigma_spatial, double sigma_luma, double sigma_chroma, double lambda, int num_iter) + { + + fastBilateralSolverFilter_1(guide.nativeObj, src.nativeObj, confidence.nativeObj, dst.nativeObj, sigma_spatial, sigma_luma, sigma_chroma, lambda, num_iter); + + return; + } + + //javadoc: fastBilateralSolverFilter(guide, src, confidence, dst, sigma_spatial, sigma_luma, sigma_chroma, lambda) + public static void fastBilateralSolverFilter(Mat guide, Mat src, Mat confidence, Mat dst, double sigma_spatial, double sigma_luma, double sigma_chroma, double lambda) + { + + fastBilateralSolverFilter_2(guide.nativeObj, src.nativeObj, confidence.nativeObj, dst.nativeObj, sigma_spatial, sigma_luma, sigma_chroma, lambda); + + return; + } + + //javadoc: fastBilateralSolverFilter(guide, src, confidence, dst, sigma_spatial, sigma_luma, sigma_chroma) + public static void fastBilateralSolverFilter(Mat guide, Mat src, Mat confidence, Mat dst, double sigma_spatial, double sigma_luma, double sigma_chroma) + { + + fastBilateralSolverFilter_3(guide.nativeObj, src.nativeObj, confidence.nativeObj, dst.nativeObj, sigma_spatial, sigma_luma, sigma_chroma); + + return; + } + + //javadoc: fastBilateralSolverFilter(guide, src, confidence, dst, sigma_spatial, sigma_luma) + public static void fastBilateralSolverFilter(Mat guide, Mat src, Mat confidence, Mat dst, double sigma_spatial, double sigma_luma) + { + + fastBilateralSolverFilter_4(guide.nativeObj, src.nativeObj, confidence.nativeObj, dst.nativeObj, sigma_spatial, sigma_luma); + + return; + } + + //javadoc: fastBilateralSolverFilter(guide, src, confidence, dst, sigma_spatial) + public static void fastBilateralSolverFilter(Mat guide, Mat src, Mat confidence, Mat dst, double sigma_spatial) + { + + fastBilateralSolverFilter_5(guide.nativeObj, src.nativeObj, confidence.nativeObj, dst.nativeObj, sigma_spatial); + + return; + } + + //javadoc: fastBilateralSolverFilter(guide, src, confidence, dst) + public static void fastBilateralSolverFilter(Mat guide, Mat src, Mat confidence, Mat dst) + { + + fastBilateralSolverFilter_6(guide.nativeObj, src.nativeObj, confidence.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::fastGlobalSmootherFilter(Mat guide, Mat src, Mat& dst, double lambda, double sigma_color, double lambda_attenuation = 0.25, int num_iter = 3) + // + + //javadoc: fastGlobalSmootherFilter(guide, src, dst, lambda, sigma_color, lambda_attenuation, num_iter) + public static void fastGlobalSmootherFilter(Mat guide, Mat src, Mat dst, double lambda, double sigma_color, double lambda_attenuation, int num_iter) + { + + fastGlobalSmootherFilter_0(guide.nativeObj, src.nativeObj, dst.nativeObj, lambda, sigma_color, lambda_attenuation, num_iter); + + return; + } + + //javadoc: fastGlobalSmootherFilter(guide, src, dst, lambda, sigma_color, lambda_attenuation) + public static void fastGlobalSmootherFilter(Mat guide, Mat src, Mat dst, double lambda, double sigma_color, double lambda_attenuation) + { + + fastGlobalSmootherFilter_1(guide.nativeObj, src.nativeObj, dst.nativeObj, lambda, sigma_color, lambda_attenuation); + + return; + } + + //javadoc: fastGlobalSmootherFilter(guide, src, dst, lambda, sigma_color) + public static void fastGlobalSmootherFilter(Mat guide, Mat src, Mat dst, double lambda, double sigma_color) + { + + fastGlobalSmootherFilter_2(guide.nativeObj, src.nativeObj, dst.nativeObj, lambda, sigma_color); + + return; + } + + + // + // C++: void cv::ximgproc::fourierDescriptor(Mat src, Mat& dst, int nbElt = -1, int nbFD = -1) + // + + //javadoc: fourierDescriptor(src, dst, nbElt, nbFD) + public static void fourierDescriptor(Mat src, Mat dst, int nbElt, int nbFD) + { + + fourierDescriptor_0(src.nativeObj, dst.nativeObj, nbElt, nbFD); + + return; + } + + //javadoc: fourierDescriptor(src, dst, nbElt) + public static void fourierDescriptor(Mat src, Mat dst, int nbElt) + { + + fourierDescriptor_1(src.nativeObj, dst.nativeObj, nbElt); + + return; + } + + //javadoc: fourierDescriptor(src, dst) + public static void fourierDescriptor(Mat src, Mat dst) + { + + fourierDescriptor_2(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::guidedFilter(Mat guide, Mat src, Mat& dst, int radius, double eps, int dDepth = -1) + // + + //javadoc: guidedFilter(guide, src, dst, radius, eps, dDepth) + public static void guidedFilter(Mat guide, Mat src, Mat dst, int radius, double eps, int dDepth) + { + + guidedFilter_0(guide.nativeObj, src.nativeObj, dst.nativeObj, radius, eps, dDepth); + + return; + } + + //javadoc: guidedFilter(guide, src, dst, radius, eps) + public static void guidedFilter(Mat guide, Mat src, Mat dst, int radius, double eps) + { + + guidedFilter_1(guide.nativeObj, src.nativeObj, dst.nativeObj, radius, eps); + + return; + } + + + // + // C++: void cv::ximgproc::jointBilateralFilter(Mat joint, Mat src, Mat& dst, int d, double sigmaColor, double sigmaSpace, int borderType = BORDER_DEFAULT) + // + + //javadoc: jointBilateralFilter(joint, src, dst, d, sigmaColor, sigmaSpace, borderType) + public static void jointBilateralFilter(Mat joint, Mat src, Mat dst, int d, double sigmaColor, double sigmaSpace, int borderType) + { + + jointBilateralFilter_0(joint.nativeObj, src.nativeObj, dst.nativeObj, d, sigmaColor, sigmaSpace, borderType); + + return; + } + + //javadoc: jointBilateralFilter(joint, src, dst, d, sigmaColor, sigmaSpace) + public static void jointBilateralFilter(Mat joint, Mat src, Mat dst, int d, double sigmaColor, double sigmaSpace) + { + + jointBilateralFilter_1(joint.nativeObj, src.nativeObj, dst.nativeObj, d, sigmaColor, sigmaSpace); + + return; + } + + + // + // C++: void cv::ximgproc::l0Smooth(Mat src, Mat& dst, double lambda = 0.02, double kappa = 2.0) + // + + //javadoc: l0Smooth(src, dst, lambda, kappa) + public static void l0Smooth(Mat src, Mat dst, double lambda, double kappa) + { + + l0Smooth_0(src.nativeObj, dst.nativeObj, lambda, kappa); + + return; + } + + //javadoc: l0Smooth(src, dst, lambda) + public static void l0Smooth(Mat src, Mat dst, double lambda) + { + + l0Smooth_1(src.nativeObj, dst.nativeObj, lambda); + + return; + } + + //javadoc: l0Smooth(src, dst) + public static void l0Smooth(Mat src, Mat dst) + { + + l0Smooth_2(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::niBlackThreshold(Mat _src, Mat& _dst, double maxValue, int type, int blockSize, double k, int binarizationMethod = BINARIZATION_NIBLACK) + // + + //javadoc: niBlackThreshold(_src, _dst, maxValue, type, blockSize, k, binarizationMethod) + public static void niBlackThreshold(Mat _src, Mat _dst, double maxValue, int type, int blockSize, double k, int binarizationMethod) + { + + niBlackThreshold_0(_src.nativeObj, _dst.nativeObj, maxValue, type, blockSize, k, binarizationMethod); + + return; + } + + //javadoc: niBlackThreshold(_src, _dst, maxValue, type, blockSize, k) + public static void niBlackThreshold(Mat _src, Mat _dst, double maxValue, int type, int blockSize, double k) + { + + niBlackThreshold_1(_src.nativeObj, _dst.nativeObj, maxValue, type, blockSize, k); + + return; + } + + + // + // C++: void cv::ximgproc::qconj(Mat qimg, Mat& qcimg) + // + + //javadoc: qconj(qimg, qcimg) + public static void qconj(Mat qimg, Mat qcimg) + { + + qconj_0(qimg.nativeObj, qcimg.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::qdft(Mat img, Mat& qimg, int flags, bool sideLeft) + // + + //javadoc: qdft(img, qimg, flags, sideLeft) + public static void qdft(Mat img, Mat qimg, int flags, boolean sideLeft) + { + + qdft_0(img.nativeObj, qimg.nativeObj, flags, sideLeft); + + return; + } + + + // + // C++: void cv::ximgproc::qmultiply(Mat src1, Mat src2, Mat& dst) + // + + //javadoc: qmultiply(src1, src2, dst) + public static void qmultiply(Mat src1, Mat src2, Mat dst) + { + + qmultiply_0(src1.nativeObj, src2.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::qunitary(Mat qimg, Mat& qnimg) + // + + //javadoc: qunitary(qimg, qnimg) + public static void qunitary(Mat qimg, Mat qnimg) + { + + qunitary_0(qimg.nativeObj, qnimg.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::rollingGuidanceFilter(Mat src, Mat& dst, int d = -1, double sigmaColor = 25, double sigmaSpace = 3, int numOfIter = 4, int borderType = BORDER_DEFAULT) + // + + //javadoc: rollingGuidanceFilter(src, dst, d, sigmaColor, sigmaSpace, numOfIter, borderType) + public static void rollingGuidanceFilter(Mat src, Mat dst, int d, double sigmaColor, double sigmaSpace, int numOfIter, int borderType) + { + + rollingGuidanceFilter_0(src.nativeObj, dst.nativeObj, d, sigmaColor, sigmaSpace, numOfIter, borderType); + + return; + } + + //javadoc: rollingGuidanceFilter(src, dst, d, sigmaColor, sigmaSpace, numOfIter) + public static void rollingGuidanceFilter(Mat src, Mat dst, int d, double sigmaColor, double sigmaSpace, int numOfIter) + { + + rollingGuidanceFilter_1(src.nativeObj, dst.nativeObj, d, sigmaColor, sigmaSpace, numOfIter); + + return; + } + + //javadoc: rollingGuidanceFilter(src, dst, d, sigmaColor, sigmaSpace) + public static void rollingGuidanceFilter(Mat src, Mat dst, int d, double sigmaColor, double sigmaSpace) + { + + rollingGuidanceFilter_2(src.nativeObj, dst.nativeObj, d, sigmaColor, sigmaSpace); + + return; + } + + //javadoc: rollingGuidanceFilter(src, dst, d, sigmaColor) + public static void rollingGuidanceFilter(Mat src, Mat dst, int d, double sigmaColor) + { + + rollingGuidanceFilter_3(src.nativeObj, dst.nativeObj, d, sigmaColor); + + return; + } + + //javadoc: rollingGuidanceFilter(src, dst, d) + public static void rollingGuidanceFilter(Mat src, Mat dst, int d) + { + + rollingGuidanceFilter_4(src.nativeObj, dst.nativeObj, d); + + return; + } + + //javadoc: rollingGuidanceFilter(src, dst) + public static void rollingGuidanceFilter(Mat src, Mat dst) + { + + rollingGuidanceFilter_5(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::thinning(Mat src, Mat& dst, int thinningType = THINNING_ZHANGSUEN) + // + + //javadoc: thinning(src, dst, thinningType) + public static void thinning(Mat src, Mat dst, int thinningType) + { + + thinning_0(src.nativeObj, dst.nativeObj, thinningType); + + return; + } + + //javadoc: thinning(src, dst) + public static void thinning(Mat src, Mat dst) + { + + thinning_1(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::transformFD(Mat src, Mat t, Mat& dst, bool fdContour = true) + // + + //javadoc: transformFD(src, t, dst, fdContour) + public static void transformFD(Mat src, Mat t, Mat dst, boolean fdContour) + { + + transformFD_0(src.nativeObj, t.nativeObj, dst.nativeObj, fdContour); + + return; + } + + //javadoc: transformFD(src, t, dst) + public static void transformFD(Mat src, Mat t, Mat dst) + { + + transformFD_1(src.nativeObj, t.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::ximgproc::weightedMedianFilter(Mat joint, Mat src, Mat& dst, int r, double sigma = 25.5, int weightType = WMF_EXP, Mat mask = Mat()) + // + + //javadoc: weightedMedianFilter(joint, src, dst, r, sigma, weightType, mask) + public static void weightedMedianFilter(Mat joint, Mat src, Mat dst, int r, double sigma, int weightType, Mat mask) + { + + weightedMedianFilter_0(joint.nativeObj, src.nativeObj, dst.nativeObj, r, sigma, weightType, mask.nativeObj); + + return; + } + + //javadoc: weightedMedianFilter(joint, src, dst, r, sigma, weightType) + public static void weightedMedianFilter(Mat joint, Mat src, Mat dst, int r, double sigma, int weightType) + { + + weightedMedianFilter_1(joint.nativeObj, src.nativeObj, dst.nativeObj, r, sigma, weightType); + + return; + } + + //javadoc: weightedMedianFilter(joint, src, dst, r, sigma) + public static void weightedMedianFilter(Mat joint, Mat src, Mat dst, int r, double sigma) + { + + weightedMedianFilter_2(joint.nativeObj, src.nativeObj, dst.nativeObj, r, sigma); + + return; + } + + //javadoc: weightedMedianFilter(joint, src, dst, r) + public static void weightedMedianFilter(Mat joint, Mat src, Mat dst, int r) + { + + weightedMedianFilter_3(joint.nativeObj, src.nativeObj, dst.nativeObj, r); + + return; + } + + + + + // C++: Ptr_AdaptiveManifoldFilter cv::ximgproc::createAMFilter(double sigma_s, double sigma_r, bool adjust_outliers = false) + private static native long createAMFilter_0(double sigma_s, double sigma_r, boolean adjust_outliers); + private static native long createAMFilter_1(double sigma_s, double sigma_r); + + // C++: Ptr_ContourFitting cv::ximgproc::createContourFitting(int ctr = 1024, int fd = 16) + private static native long createContourFitting_0(int ctr, int fd); + private static native long createContourFitting_1(int ctr); + private static native long createContourFitting_2(); + + // C++: Ptr_DTFilter cv::ximgproc::createDTFilter(Mat guide, double sigmaSpatial, double sigmaColor, int mode = DTF_NC, int numIters = 3) + private static native long createDTFilter_0(long guide_nativeObj, double sigmaSpatial, double sigmaColor, int mode, int numIters); + private static native long createDTFilter_1(long guide_nativeObj, double sigmaSpatial, double sigmaColor, int mode); + private static native long createDTFilter_2(long guide_nativeObj, double sigmaSpatial, double sigmaColor); + + // C++: Ptr_DisparityWLSFilter cv::ximgproc::createDisparityWLSFilter(Ptr_StereoMatcher matcher_left) + private static native long createDisparityWLSFilter_0(long matcher_left_nativeObj); + + // C++: Ptr_DisparityWLSFilter cv::ximgproc::createDisparityWLSFilterGeneric(bool use_confidence) + private static native long createDisparityWLSFilterGeneric_0(boolean use_confidence); + + // C++: Ptr_EdgeAwareInterpolator cv::ximgproc::createEdgeAwareInterpolator() + private static native long createEdgeAwareInterpolator_0(); + + // C++: Ptr_EdgeBoxes cv::ximgproc::createEdgeBoxes(float alpha = 0.65f, float beta = 0.75f, float eta = 1, float minScore = 0.01f, int maxBoxes = 10000, float edgeMinMag = 0.1f, float edgeMergeThr = 0.5f, float clusterMinMag = 0.5f, float maxAspectRatio = 3, float minBoxArea = 1000, float gamma = 2, float kappa = 1.5f) + private static native long createEdgeBoxes_0(float alpha, float beta, float eta, float minScore, int maxBoxes, float edgeMinMag, float edgeMergeThr, float clusterMinMag, float maxAspectRatio, float minBoxArea, float gamma, float kappa); + private static native long createEdgeBoxes_1(float alpha, float beta, float eta, float minScore, int maxBoxes, float edgeMinMag, float edgeMergeThr, float clusterMinMag, float maxAspectRatio, float minBoxArea, float gamma); + private static native long createEdgeBoxes_2(float alpha, float beta, float eta, float minScore, int maxBoxes, float edgeMinMag, float edgeMergeThr, float clusterMinMag, float maxAspectRatio, float minBoxArea); + private static native long createEdgeBoxes_3(float alpha, float beta, float eta, float minScore, int maxBoxes, float edgeMinMag, float edgeMergeThr, float clusterMinMag, float maxAspectRatio); + private static native long createEdgeBoxes_4(float alpha, float beta, float eta, float minScore, int maxBoxes, float edgeMinMag, float edgeMergeThr, float clusterMinMag); + private static native long createEdgeBoxes_5(float alpha, float beta, float eta, float minScore, int maxBoxes, float edgeMinMag, float edgeMergeThr); + private static native long createEdgeBoxes_6(float alpha, float beta, float eta, float minScore, int maxBoxes, float edgeMinMag); + private static native long createEdgeBoxes_7(float alpha, float beta, float eta, float minScore, int maxBoxes); + private static native long createEdgeBoxes_8(float alpha, float beta, float eta, float minScore); + private static native long createEdgeBoxes_9(float alpha, float beta, float eta); + private static native long createEdgeBoxes_10(float alpha, float beta); + private static native long createEdgeBoxes_11(float alpha); + private static native long createEdgeBoxes_12(); + + // C++: Ptr_FastBilateralSolverFilter cv::ximgproc::createFastBilateralSolverFilter(Mat guide, double sigma_spatial, double sigma_luma, double sigma_chroma, double lambda = 128.0, int num_iter = 25, double max_tol = 1e-5) + private static native long createFastBilateralSolverFilter_0(long guide_nativeObj, double sigma_spatial, double sigma_luma, double sigma_chroma, double lambda, int num_iter, double max_tol); + private static native long createFastBilateralSolverFilter_1(long guide_nativeObj, double sigma_spatial, double sigma_luma, double sigma_chroma, double lambda, int num_iter); + private static native long createFastBilateralSolverFilter_2(long guide_nativeObj, double sigma_spatial, double sigma_luma, double sigma_chroma, double lambda); + private static native long createFastBilateralSolverFilter_3(long guide_nativeObj, double sigma_spatial, double sigma_luma, double sigma_chroma); + + // C++: Ptr_FastGlobalSmootherFilter cv::ximgproc::createFastGlobalSmootherFilter(Mat guide, double lambda, double sigma_color, double lambda_attenuation = 0.25, int num_iter = 3) + private static native long createFastGlobalSmootherFilter_0(long guide_nativeObj, double lambda, double sigma_color, double lambda_attenuation, int num_iter); + private static native long createFastGlobalSmootherFilter_1(long guide_nativeObj, double lambda, double sigma_color, double lambda_attenuation); + private static native long createFastGlobalSmootherFilter_2(long guide_nativeObj, double lambda, double sigma_color); + + // C++: Ptr_FastLineDetector cv::ximgproc::createFastLineDetector(int _length_threshold = 10, float _distance_threshold = 1.414213562f, double _canny_th1 = 50.0, double _canny_th2 = 50.0, int _canny_aperture_size = 3, bool _do_merge = false) + private static native long createFastLineDetector_0(int _length_threshold, float _distance_threshold, double _canny_th1, double _canny_th2, int _canny_aperture_size, boolean _do_merge); + private static native long createFastLineDetector_1(int _length_threshold, float _distance_threshold, double _canny_th1, double _canny_th2, int _canny_aperture_size); + private static native long createFastLineDetector_2(int _length_threshold, float _distance_threshold, double _canny_th1, double _canny_th2); + private static native long createFastLineDetector_3(int _length_threshold, float _distance_threshold, double _canny_th1); + private static native long createFastLineDetector_4(int _length_threshold, float _distance_threshold); + private static native long createFastLineDetector_5(int _length_threshold); + private static native long createFastLineDetector_6(); + + // C++: Ptr_GraphSegmentation cv::ximgproc::segmentation::createGraphSegmentation(double sigma = 0.5, float k = 300, int min_size = 100) + private static native long createGraphSegmentation_0(double sigma, float k, int min_size); + private static native long createGraphSegmentation_1(double sigma, float k); + private static native long createGraphSegmentation_2(double sigma); + private static native long createGraphSegmentation_3(); + + // C++: Ptr_GuidedFilter cv::ximgproc::createGuidedFilter(Mat guide, int radius, double eps) + private static native long createGuidedFilter_0(long guide_nativeObj, int radius, double eps); + + // C++: Ptr_RFFeatureGetter cv::ximgproc::createRFFeatureGetter() + private static native long createRFFeatureGetter_0(); + + // C++: Ptr_SelectiveSearchSegmentation cv::ximgproc::segmentation::createSelectiveSearchSegmentation() + private static native long createSelectiveSearchSegmentation_0(); + + // C++: Ptr_SelectiveSearchSegmentationStrategyColor cv::ximgproc::segmentation::createSelectiveSearchSegmentationStrategyColor() + private static native long createSelectiveSearchSegmentationStrategyColor_0(); + + // C++: Ptr_SelectiveSearchSegmentationStrategyFill cv::ximgproc::segmentation::createSelectiveSearchSegmentationStrategyFill() + private static native long createSelectiveSearchSegmentationStrategyFill_0(); + + // C++: Ptr_SelectiveSearchSegmentationStrategyMultiple cv::ximgproc::segmentation::createSelectiveSearchSegmentationStrategyMultiple(Ptr_SelectiveSearchSegmentationStrategy s1, Ptr_SelectiveSearchSegmentationStrategy s2, Ptr_SelectiveSearchSegmentationStrategy s3, Ptr_SelectiveSearchSegmentationStrategy s4) + private static native long createSelectiveSearchSegmentationStrategyMultiple_0(long s1_nativeObj, long s2_nativeObj, long s3_nativeObj, long s4_nativeObj); + + // C++: Ptr_SelectiveSearchSegmentationStrategyMultiple cv::ximgproc::segmentation::createSelectiveSearchSegmentationStrategyMultiple(Ptr_SelectiveSearchSegmentationStrategy s1, Ptr_SelectiveSearchSegmentationStrategy s2, Ptr_SelectiveSearchSegmentationStrategy s3) + private static native long createSelectiveSearchSegmentationStrategyMultiple_1(long s1_nativeObj, long s2_nativeObj, long s3_nativeObj); + + // C++: Ptr_SelectiveSearchSegmentationStrategyMultiple cv::ximgproc::segmentation::createSelectiveSearchSegmentationStrategyMultiple(Ptr_SelectiveSearchSegmentationStrategy s1, Ptr_SelectiveSearchSegmentationStrategy s2) + private static native long createSelectiveSearchSegmentationStrategyMultiple_2(long s1_nativeObj, long s2_nativeObj); + + // C++: Ptr_SelectiveSearchSegmentationStrategyMultiple cv::ximgproc::segmentation::createSelectiveSearchSegmentationStrategyMultiple(Ptr_SelectiveSearchSegmentationStrategy s1) + private static native long createSelectiveSearchSegmentationStrategyMultiple_3(long s1_nativeObj); + + // C++: Ptr_SelectiveSearchSegmentationStrategyMultiple cv::ximgproc::segmentation::createSelectiveSearchSegmentationStrategyMultiple() + private static native long createSelectiveSearchSegmentationStrategyMultiple_4(); + + // C++: Ptr_SelectiveSearchSegmentationStrategySize cv::ximgproc::segmentation::createSelectiveSearchSegmentationStrategySize() + private static native long createSelectiveSearchSegmentationStrategySize_0(); + + // C++: Ptr_SelectiveSearchSegmentationStrategyTexture cv::ximgproc::segmentation::createSelectiveSearchSegmentationStrategyTexture() + private static native long createSelectiveSearchSegmentationStrategyTexture_0(); + + // C++: Ptr_StereoMatcher cv::ximgproc::createRightMatcher(Ptr_StereoMatcher matcher_left) + private static native long createRightMatcher_0(long matcher_left_nativeObj); + + // C++: Ptr_StructuredEdgeDetection cv::ximgproc::createStructuredEdgeDetection(String model, Ptr_RFFeatureGetter howToGetFeatures = Ptr()) + private static native long createStructuredEdgeDetection_0(String model, long howToGetFeatures_nativeObj); + private static native long createStructuredEdgeDetection_1(String model); + + // C++: Ptr_SuperpixelLSC cv::ximgproc::createSuperpixelLSC(Mat image, int region_size = 10, float ratio = 0.075f) + private static native long createSuperpixelLSC_0(long image_nativeObj, int region_size, float ratio); + private static native long createSuperpixelLSC_1(long image_nativeObj, int region_size); + private static native long createSuperpixelLSC_2(long image_nativeObj); + + // C++: Ptr_SuperpixelSEEDS cv::ximgproc::createSuperpixelSEEDS(int image_width, int image_height, int image_channels, int num_superpixels, int num_levels, int prior = 2, int histogram_bins = 5, bool double_step = false) + private static native long createSuperpixelSEEDS_0(int image_width, int image_height, int image_channels, int num_superpixels, int num_levels, int prior, int histogram_bins, boolean double_step); + private static native long createSuperpixelSEEDS_1(int image_width, int image_height, int image_channels, int num_superpixels, int num_levels, int prior, int histogram_bins); + private static native long createSuperpixelSEEDS_2(int image_width, int image_height, int image_channels, int num_superpixels, int num_levels, int prior); + private static native long createSuperpixelSEEDS_3(int image_width, int image_height, int image_channels, int num_superpixels, int num_levels); + + // C++: Ptr_SuperpixelSLIC cv::ximgproc::createSuperpixelSLIC(Mat image, int algorithm = SLICO, int region_size = 10, float ruler = 10.0f) + private static native long createSuperpixelSLIC_0(long image_nativeObj, int algorithm, int region_size, float ruler); + private static native long createSuperpixelSLIC_1(long image_nativeObj, int algorithm, int region_size); + private static native long createSuperpixelSLIC_2(long image_nativeObj, int algorithm); + private static native long createSuperpixelSLIC_3(long image_nativeObj); + + // C++: void cv::ximgproc::FastHoughTransform(Mat src, Mat& dst, int dstMatDepth, int angleRange = ARO_315_135, int op = FHT_ADD, int makeSkew = HDO_DESKEW) + private static native void FastHoughTransform_0(long src_nativeObj, long dst_nativeObj, int dstMatDepth, int angleRange, int op, int makeSkew); + private static native void FastHoughTransform_1(long src_nativeObj, long dst_nativeObj, int dstMatDepth, int angleRange, int op); + private static native void FastHoughTransform_2(long src_nativeObj, long dst_nativeObj, int dstMatDepth, int angleRange); + private static native void FastHoughTransform_3(long src_nativeObj, long dst_nativeObj, int dstMatDepth); + + // C++: void cv::ximgproc::GradientDericheX(Mat op, Mat& dst, double alpha, double omega) + private static native void GradientDericheX_0(long op_nativeObj, long dst_nativeObj, double alpha, double omega); + + // C++: void cv::ximgproc::GradientDericheY(Mat op, Mat& dst, double alpha, double omega) + private static native void GradientDericheY_0(long op_nativeObj, long dst_nativeObj, double alpha, double omega); + + // C++: void cv::ximgproc::PeiLinNormalization(Mat I, Mat& T) + private static native void PeiLinNormalization_0(long I_nativeObj, long T_nativeObj); + + // C++: void cv::ximgproc::amFilter(Mat joint, Mat src, Mat& dst, double sigma_s, double sigma_r, bool adjust_outliers = false) + private static native void amFilter_0(long joint_nativeObj, long src_nativeObj, long dst_nativeObj, double sigma_s, double sigma_r, boolean adjust_outliers); + private static native void amFilter_1(long joint_nativeObj, long src_nativeObj, long dst_nativeObj, double sigma_s, double sigma_r); + + // C++: void cv::ximgproc::anisotropicDiffusion(Mat src, Mat& dst, float alpha, float K, int niters) + private static native void anisotropicDiffusion_0(long src_nativeObj, long dst_nativeObj, float alpha, float K, int niters); + + // C++: void cv::ximgproc::bilateralTextureFilter(Mat src, Mat& dst, int fr = 3, int numIter = 1, double sigmaAlpha = -1., double sigmaAvg = -1.) + private static native void bilateralTextureFilter_0(long src_nativeObj, long dst_nativeObj, int fr, int numIter, double sigmaAlpha, double sigmaAvg); + private static native void bilateralTextureFilter_1(long src_nativeObj, long dst_nativeObj, int fr, int numIter, double sigmaAlpha); + private static native void bilateralTextureFilter_2(long src_nativeObj, long dst_nativeObj, int fr, int numIter); + private static native void bilateralTextureFilter_3(long src_nativeObj, long dst_nativeObj, int fr); + private static native void bilateralTextureFilter_4(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::ximgproc::colorMatchTemplate(Mat img, Mat templ, Mat& result) + private static native void colorMatchTemplate_0(long img_nativeObj, long templ_nativeObj, long result_nativeObj); + + // C++: void cv::ximgproc::contourSampling(Mat src, Mat& out, int nbElt) + private static native void contourSampling_0(long src_nativeObj, long out_nativeObj, int nbElt); + + // C++: void cv::ximgproc::covarianceEstimation(Mat src, Mat& dst, int windowRows, int windowCols) + private static native void covarianceEstimation_0(long src_nativeObj, long dst_nativeObj, int windowRows, int windowCols); + + // C++: void cv::ximgproc::createQuaternionImage(Mat img, Mat& qimg) + private static native void createQuaternionImage_0(long img_nativeObj, long qimg_nativeObj); + + // C++: void cv::ximgproc::dtFilter(Mat guide, Mat src, Mat& dst, double sigmaSpatial, double sigmaColor, int mode = DTF_NC, int numIters = 3) + private static native void dtFilter_0(long guide_nativeObj, long src_nativeObj, long dst_nativeObj, double sigmaSpatial, double sigmaColor, int mode, int numIters); + private static native void dtFilter_1(long guide_nativeObj, long src_nativeObj, long dst_nativeObj, double sigmaSpatial, double sigmaColor, int mode); + private static native void dtFilter_2(long guide_nativeObj, long src_nativeObj, long dst_nativeObj, double sigmaSpatial, double sigmaColor); + + // C++: void cv::ximgproc::edgePreservingFilter(Mat src, Mat& dst, int d, double threshold) + private static native void edgePreservingFilter_0(long src_nativeObj, long dst_nativeObj, int d, double threshold); + + // C++: void cv::ximgproc::fastBilateralSolverFilter(Mat guide, Mat src, Mat confidence, Mat& dst, double sigma_spatial = 8, double sigma_luma = 8, double sigma_chroma = 8, double lambda = 128.0, int num_iter = 25, double max_tol = 1e-5) + private static native void fastBilateralSolverFilter_0(long guide_nativeObj, long src_nativeObj, long confidence_nativeObj, long dst_nativeObj, double sigma_spatial, double sigma_luma, double sigma_chroma, double lambda, int num_iter, double max_tol); + private static native void fastBilateralSolverFilter_1(long guide_nativeObj, long src_nativeObj, long confidence_nativeObj, long dst_nativeObj, double sigma_spatial, double sigma_luma, double sigma_chroma, double lambda, int num_iter); + private static native void fastBilateralSolverFilter_2(long guide_nativeObj, long src_nativeObj, long confidence_nativeObj, long dst_nativeObj, double sigma_spatial, double sigma_luma, double sigma_chroma, double lambda); + private static native void fastBilateralSolverFilter_3(long guide_nativeObj, long src_nativeObj, long confidence_nativeObj, long dst_nativeObj, double sigma_spatial, double sigma_luma, double sigma_chroma); + private static native void fastBilateralSolverFilter_4(long guide_nativeObj, long src_nativeObj, long confidence_nativeObj, long dst_nativeObj, double sigma_spatial, double sigma_luma); + private static native void fastBilateralSolverFilter_5(long guide_nativeObj, long src_nativeObj, long confidence_nativeObj, long dst_nativeObj, double sigma_spatial); + private static native void fastBilateralSolverFilter_6(long guide_nativeObj, long src_nativeObj, long confidence_nativeObj, long dst_nativeObj); + + // C++: void cv::ximgproc::fastGlobalSmootherFilter(Mat guide, Mat src, Mat& dst, double lambda, double sigma_color, double lambda_attenuation = 0.25, int num_iter = 3) + private static native void fastGlobalSmootherFilter_0(long guide_nativeObj, long src_nativeObj, long dst_nativeObj, double lambda, double sigma_color, double lambda_attenuation, int num_iter); + private static native void fastGlobalSmootherFilter_1(long guide_nativeObj, long src_nativeObj, long dst_nativeObj, double lambda, double sigma_color, double lambda_attenuation); + private static native void fastGlobalSmootherFilter_2(long guide_nativeObj, long src_nativeObj, long dst_nativeObj, double lambda, double sigma_color); + + // C++: void cv::ximgproc::fourierDescriptor(Mat src, Mat& dst, int nbElt = -1, int nbFD = -1) + private static native void fourierDescriptor_0(long src_nativeObj, long dst_nativeObj, int nbElt, int nbFD); + private static native void fourierDescriptor_1(long src_nativeObj, long dst_nativeObj, int nbElt); + private static native void fourierDescriptor_2(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::ximgproc::guidedFilter(Mat guide, Mat src, Mat& dst, int radius, double eps, int dDepth = -1) + private static native void guidedFilter_0(long guide_nativeObj, long src_nativeObj, long dst_nativeObj, int radius, double eps, int dDepth); + private static native void guidedFilter_1(long guide_nativeObj, long src_nativeObj, long dst_nativeObj, int radius, double eps); + + // C++: void cv::ximgproc::jointBilateralFilter(Mat joint, Mat src, Mat& dst, int d, double sigmaColor, double sigmaSpace, int borderType = BORDER_DEFAULT) + private static native void jointBilateralFilter_0(long joint_nativeObj, long src_nativeObj, long dst_nativeObj, int d, double sigmaColor, double sigmaSpace, int borderType); + private static native void jointBilateralFilter_1(long joint_nativeObj, long src_nativeObj, long dst_nativeObj, int d, double sigmaColor, double sigmaSpace); + + // C++: void cv::ximgproc::l0Smooth(Mat src, Mat& dst, double lambda = 0.02, double kappa = 2.0) + private static native void l0Smooth_0(long src_nativeObj, long dst_nativeObj, double lambda, double kappa); + private static native void l0Smooth_1(long src_nativeObj, long dst_nativeObj, double lambda); + private static native void l0Smooth_2(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::ximgproc::niBlackThreshold(Mat _src, Mat& _dst, double maxValue, int type, int blockSize, double k, int binarizationMethod = BINARIZATION_NIBLACK) + private static native void niBlackThreshold_0(long _src_nativeObj, long _dst_nativeObj, double maxValue, int type, int blockSize, double k, int binarizationMethod); + private static native void niBlackThreshold_1(long _src_nativeObj, long _dst_nativeObj, double maxValue, int type, int blockSize, double k); + + // C++: void cv::ximgproc::qconj(Mat qimg, Mat& qcimg) + private static native void qconj_0(long qimg_nativeObj, long qcimg_nativeObj); + + // C++: void cv::ximgproc::qdft(Mat img, Mat& qimg, int flags, bool sideLeft) + private static native void qdft_0(long img_nativeObj, long qimg_nativeObj, int flags, boolean sideLeft); + + // C++: void cv::ximgproc::qmultiply(Mat src1, Mat src2, Mat& dst) + private static native void qmultiply_0(long src1_nativeObj, long src2_nativeObj, long dst_nativeObj); + + // C++: void cv::ximgproc::qunitary(Mat qimg, Mat& qnimg) + private static native void qunitary_0(long qimg_nativeObj, long qnimg_nativeObj); + + // C++: void cv::ximgproc::rollingGuidanceFilter(Mat src, Mat& dst, int d = -1, double sigmaColor = 25, double sigmaSpace = 3, int numOfIter = 4, int borderType = BORDER_DEFAULT) + private static native void rollingGuidanceFilter_0(long src_nativeObj, long dst_nativeObj, int d, double sigmaColor, double sigmaSpace, int numOfIter, int borderType); + private static native void rollingGuidanceFilter_1(long src_nativeObj, long dst_nativeObj, int d, double sigmaColor, double sigmaSpace, int numOfIter); + private static native void rollingGuidanceFilter_2(long src_nativeObj, long dst_nativeObj, int d, double sigmaColor, double sigmaSpace); + private static native void rollingGuidanceFilter_3(long src_nativeObj, long dst_nativeObj, int d, double sigmaColor); + private static native void rollingGuidanceFilter_4(long src_nativeObj, long dst_nativeObj, int d); + private static native void rollingGuidanceFilter_5(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::ximgproc::thinning(Mat src, Mat& dst, int thinningType = THINNING_ZHANGSUEN) + private static native void thinning_0(long src_nativeObj, long dst_nativeObj, int thinningType); + private static native void thinning_1(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::ximgproc::transformFD(Mat src, Mat t, Mat& dst, bool fdContour = true) + private static native void transformFD_0(long src_nativeObj, long t_nativeObj, long dst_nativeObj, boolean fdContour); + private static native void transformFD_1(long src_nativeObj, long t_nativeObj, long dst_nativeObj); + + // C++: void cv::ximgproc::weightedMedianFilter(Mat joint, Mat src, Mat& dst, int r, double sigma = 25.5, int weightType = WMF_EXP, Mat mask = Mat()) + private static native void weightedMedianFilter_0(long joint_nativeObj, long src_nativeObj, long dst_nativeObj, int r, double sigma, int weightType, long mask_nativeObj); + private static native void weightedMedianFilter_1(long joint_nativeObj, long src_nativeObj, long dst_nativeObj, int r, double sigma, int weightType); + private static native void weightedMedianFilter_2(long joint_nativeObj, long src_nativeObj, long dst_nativeObj, int r, double sigma); + private static native void weightedMedianFilter_3(long joint_nativeObj, long src_nativeObj, long dst_nativeObj, int r); + +} diff --git a/OpenCV/src/main/java/org/opencv/xphoto/GrayworldWB.java b/OpenCV/src/main/java/org/opencv/xphoto/GrayworldWB.java new file mode 100644 index 00000000..3c38740f --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xphoto/GrayworldWB.java @@ -0,0 +1,62 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xphoto; + +import org.opencv.xphoto.WhiteBalancer; + +// C++: class GrayworldWB +//javadoc: GrayworldWB + +public class GrayworldWB extends WhiteBalancer { + + protected GrayworldWB(long addr) { super(addr); } + + // internal usage only + public static GrayworldWB __fromPtr__(long addr) { return new GrayworldWB(addr); } + + // + // C++: float cv::xphoto::GrayworldWB::getSaturationThreshold() + // + + //javadoc: GrayworldWB::getSaturationThreshold() + public float getSaturationThreshold() + { + + float retVal = getSaturationThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::xphoto::GrayworldWB::setSaturationThreshold(float val) + // + + //javadoc: GrayworldWB::setSaturationThreshold(val) + public void setSaturationThreshold(float val) + { + + setSaturationThreshold_0(nativeObj, val); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: float cv::xphoto::GrayworldWB::getSaturationThreshold() + private static native float getSaturationThreshold_0(long nativeObj); + + // C++: void cv::xphoto::GrayworldWB::setSaturationThreshold(float val) + private static native void setSaturationThreshold_0(long nativeObj, float val); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/xphoto/LearningBasedWB.java b/OpenCV/src/main/java/org/opencv/xphoto/LearningBasedWB.java new file mode 100644 index 00000000..89720888 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xphoto/LearningBasedWB.java @@ -0,0 +1,148 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xphoto; + +import org.opencv.core.Mat; +import org.opencv.xphoto.WhiteBalancer; + +// C++: class LearningBasedWB +//javadoc: LearningBasedWB + +public class LearningBasedWB extends WhiteBalancer { + + protected LearningBasedWB(long addr) { super(addr); } + + // internal usage only + public static LearningBasedWB __fromPtr__(long addr) { return new LearningBasedWB(addr); } + + // + // C++: float cv::xphoto::LearningBasedWB::getSaturationThreshold() + // + + //javadoc: LearningBasedWB::getSaturationThreshold() + public float getSaturationThreshold() + { + + float retVal = getSaturationThreshold_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::xphoto::LearningBasedWB::getHistBinNum() + // + + //javadoc: LearningBasedWB::getHistBinNum() + public int getHistBinNum() + { + + int retVal = getHistBinNum_0(nativeObj); + + return retVal; + } + + + // + // C++: int cv::xphoto::LearningBasedWB::getRangeMaxVal() + // + + //javadoc: LearningBasedWB::getRangeMaxVal() + public int getRangeMaxVal() + { + + int retVal = getRangeMaxVal_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::xphoto::LearningBasedWB::extractSimpleFeatures(Mat src, Mat& dst) + // + + //javadoc: LearningBasedWB::extractSimpleFeatures(src, dst) + public void extractSimpleFeatures(Mat src, Mat dst) + { + + extractSimpleFeatures_0(nativeObj, src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::xphoto::LearningBasedWB::setHistBinNum(int val) + // + + //javadoc: LearningBasedWB::setHistBinNum(val) + public void setHistBinNum(int val) + { + + setHistBinNum_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::xphoto::LearningBasedWB::setRangeMaxVal(int val) + // + + //javadoc: LearningBasedWB::setRangeMaxVal(val) + public void setRangeMaxVal(int val) + { + + setRangeMaxVal_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::xphoto::LearningBasedWB::setSaturationThreshold(float val) + // + + //javadoc: LearningBasedWB::setSaturationThreshold(val) + public void setSaturationThreshold(float val) + { + + setSaturationThreshold_0(nativeObj, val); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: float cv::xphoto::LearningBasedWB::getSaturationThreshold() + private static native float getSaturationThreshold_0(long nativeObj); + + // C++: int cv::xphoto::LearningBasedWB::getHistBinNum() + private static native int getHistBinNum_0(long nativeObj); + + // C++: int cv::xphoto::LearningBasedWB::getRangeMaxVal() + private static native int getRangeMaxVal_0(long nativeObj); + + // C++: void cv::xphoto::LearningBasedWB::extractSimpleFeatures(Mat src, Mat& dst) + private static native void extractSimpleFeatures_0(long nativeObj, long src_nativeObj, long dst_nativeObj); + + // C++: void cv::xphoto::LearningBasedWB::setHistBinNum(int val) + private static native void setHistBinNum_0(long nativeObj, int val); + + // C++: void cv::xphoto::LearningBasedWB::setRangeMaxVal(int val) + private static native void setRangeMaxVal_0(long nativeObj, int val); + + // C++: void cv::xphoto::LearningBasedWB::setSaturationThreshold(float val) + private static native void setSaturationThreshold_0(long nativeObj, float val); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/xphoto/SimpleWB.java b/OpenCV/src/main/java/org/opencv/xphoto/SimpleWB.java new file mode 100644 index 00000000..072438f1 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xphoto/SimpleWB.java @@ -0,0 +1,198 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xphoto; + +import org.opencv.xphoto.WhiteBalancer; + +// C++: class SimpleWB +//javadoc: SimpleWB + +public class SimpleWB extends WhiteBalancer { + + protected SimpleWB(long addr) { super(addr); } + + // internal usage only + public static SimpleWB __fromPtr__(long addr) { return new SimpleWB(addr); } + + // + // C++: float cv::xphoto::SimpleWB::getInputMax() + // + + //javadoc: SimpleWB::getInputMax() + public float getInputMax() + { + + float retVal = getInputMax_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::xphoto::SimpleWB::getInputMin() + // + + //javadoc: SimpleWB::getInputMin() + public float getInputMin() + { + + float retVal = getInputMin_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::xphoto::SimpleWB::getOutputMax() + // + + //javadoc: SimpleWB::getOutputMax() + public float getOutputMax() + { + + float retVal = getOutputMax_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::xphoto::SimpleWB::getOutputMin() + // + + //javadoc: SimpleWB::getOutputMin() + public float getOutputMin() + { + + float retVal = getOutputMin_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::xphoto::SimpleWB::getP() + // + + //javadoc: SimpleWB::getP() + public float getP() + { + + float retVal = getP_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::xphoto::SimpleWB::setInputMax(float val) + // + + //javadoc: SimpleWB::setInputMax(val) + public void setInputMax(float val) + { + + setInputMax_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::xphoto::SimpleWB::setInputMin(float val) + // + + //javadoc: SimpleWB::setInputMin(val) + public void setInputMin(float val) + { + + setInputMin_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::xphoto::SimpleWB::setOutputMax(float val) + // + + //javadoc: SimpleWB::setOutputMax(val) + public void setOutputMax(float val) + { + + setOutputMax_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::xphoto::SimpleWB::setOutputMin(float val) + // + + //javadoc: SimpleWB::setOutputMin(val) + public void setOutputMin(float val) + { + + setOutputMin_0(nativeObj, val); + + return; + } + + + // + // C++: void cv::xphoto::SimpleWB::setP(float val) + // + + //javadoc: SimpleWB::setP(val) + public void setP(float val) + { + + setP_0(nativeObj, val); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: float cv::xphoto::SimpleWB::getInputMax() + private static native float getInputMax_0(long nativeObj); + + // C++: float cv::xphoto::SimpleWB::getInputMin() + private static native float getInputMin_0(long nativeObj); + + // C++: float cv::xphoto::SimpleWB::getOutputMax() + private static native float getOutputMax_0(long nativeObj); + + // C++: float cv::xphoto::SimpleWB::getOutputMin() + private static native float getOutputMin_0(long nativeObj); + + // C++: float cv::xphoto::SimpleWB::getP() + private static native float getP_0(long nativeObj); + + // C++: void cv::xphoto::SimpleWB::setInputMax(float val) + private static native void setInputMax_0(long nativeObj, float val); + + // C++: void cv::xphoto::SimpleWB::setInputMin(float val) + private static native void setInputMin_0(long nativeObj, float val); + + // C++: void cv::xphoto::SimpleWB::setOutputMax(float val) + private static native void setOutputMax_0(long nativeObj, float val); + + // C++: void cv::xphoto::SimpleWB::setOutputMin(float val) + private static native void setOutputMin_0(long nativeObj, float val); + + // C++: void cv::xphoto::SimpleWB::setP(float val) + private static native void setP_0(long nativeObj, float val); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/xphoto/TonemapDurand.java b/OpenCV/src/main/java/org/opencv/xphoto/TonemapDurand.java new file mode 100644 index 00000000..8ba5df85 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xphoto/TonemapDurand.java @@ -0,0 +1,164 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xphoto; + +import org.opencv.photo.Tonemap; + +// C++: class TonemapDurand +//javadoc: TonemapDurand + +public class TonemapDurand extends Tonemap { + + protected TonemapDurand(long addr) { super(addr); } + + // internal usage only + public static TonemapDurand __fromPtr__(long addr) { return new TonemapDurand(addr); } + + // + // C++: float cv::xphoto::TonemapDurand::getContrast() + // + + //javadoc: TonemapDurand::getContrast() + public float getContrast() + { + + float retVal = getContrast_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::xphoto::TonemapDurand::getSaturation() + // + + //javadoc: TonemapDurand::getSaturation() + public float getSaturation() + { + + float retVal = getSaturation_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::xphoto::TonemapDurand::getSigmaColor() + // + + //javadoc: TonemapDurand::getSigmaColor() + public float getSigmaColor() + { + + float retVal = getSigmaColor_0(nativeObj); + + return retVal; + } + + + // + // C++: float cv::xphoto::TonemapDurand::getSigmaSpace() + // + + //javadoc: TonemapDurand::getSigmaSpace() + public float getSigmaSpace() + { + + float retVal = getSigmaSpace_0(nativeObj); + + return retVal; + } + + + // + // C++: void cv::xphoto::TonemapDurand::setContrast(float contrast) + // + + //javadoc: TonemapDurand::setContrast(contrast) + public void setContrast(float contrast) + { + + setContrast_0(nativeObj, contrast); + + return; + } + + + // + // C++: void cv::xphoto::TonemapDurand::setSaturation(float saturation) + // + + //javadoc: TonemapDurand::setSaturation(saturation) + public void setSaturation(float saturation) + { + + setSaturation_0(nativeObj, saturation); + + return; + } + + + // + // C++: void cv::xphoto::TonemapDurand::setSigmaColor(float sigma_color) + // + + //javadoc: TonemapDurand::setSigmaColor(sigma_color) + public void setSigmaColor(float sigma_color) + { + + setSigmaColor_0(nativeObj, sigma_color); + + return; + } + + + // + // C++: void cv::xphoto::TonemapDurand::setSigmaSpace(float sigma_space) + // + + //javadoc: TonemapDurand::setSigmaSpace(sigma_space) + public void setSigmaSpace(float sigma_space) + { + + setSigmaSpace_0(nativeObj, sigma_space); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: float cv::xphoto::TonemapDurand::getContrast() + private static native float getContrast_0(long nativeObj); + + // C++: float cv::xphoto::TonemapDurand::getSaturation() + private static native float getSaturation_0(long nativeObj); + + // C++: float cv::xphoto::TonemapDurand::getSigmaColor() + private static native float getSigmaColor_0(long nativeObj); + + // C++: float cv::xphoto::TonemapDurand::getSigmaSpace() + private static native float getSigmaSpace_0(long nativeObj); + + // C++: void cv::xphoto::TonemapDurand::setContrast(float contrast) + private static native void setContrast_0(long nativeObj, float contrast); + + // C++: void cv::xphoto::TonemapDurand::setSaturation(float saturation) + private static native void setSaturation_0(long nativeObj, float saturation); + + // C++: void cv::xphoto::TonemapDurand::setSigmaColor(float sigma_color) + private static native void setSigmaColor_0(long nativeObj, float sigma_color); + + // C++: void cv::xphoto::TonemapDurand::setSigmaSpace(float sigma_space) + private static native void setSigmaSpace_0(long nativeObj, float sigma_space); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/xphoto/WhiteBalancer.java b/OpenCV/src/main/java/org/opencv/xphoto/WhiteBalancer.java new file mode 100644 index 00000000..3afa496a --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xphoto/WhiteBalancer.java @@ -0,0 +1,46 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xphoto; + +import org.opencv.core.Algorithm; +import org.opencv.core.Mat; + +// C++: class WhiteBalancer +//javadoc: WhiteBalancer + +public class WhiteBalancer extends Algorithm { + + protected WhiteBalancer(long addr) { super(addr); } + + // internal usage only + public static WhiteBalancer __fromPtr__(long addr) { return new WhiteBalancer(addr); } + + // + // C++: void cv::xphoto::WhiteBalancer::balanceWhite(Mat src, Mat& dst) + // + + //javadoc: WhiteBalancer::balanceWhite(src, dst) + public void balanceWhite(Mat src, Mat dst) + { + + balanceWhite_0(nativeObj, src.nativeObj, dst.nativeObj); + + return; + } + + + @Override + protected void finalize() throws Throwable { + delete(nativeObj); + } + + + + // C++: void cv::xphoto::WhiteBalancer::balanceWhite(Mat src, Mat& dst) + private static native void balanceWhite_0(long nativeObj, long src_nativeObj, long dst_nativeObj); + + // native support for java finalize() + private static native void delete(long nativeObj); + +} diff --git a/OpenCV/src/main/java/org/opencv/xphoto/Xphoto.java b/OpenCV/src/main/java/org/opencv/xphoto/Xphoto.java new file mode 100644 index 00000000..986867a9 --- /dev/null +++ b/OpenCV/src/main/java/org/opencv/xphoto/Xphoto.java @@ -0,0 +1,514 @@ +// +// This file is auto-generated. Please don't modify it! +// +package org.opencv.xphoto; + +import java.lang.String; +import org.opencv.core.Mat; +import org.opencv.xphoto.GrayworldWB; +import org.opencv.xphoto.LearningBasedWB; +import org.opencv.xphoto.SimpleWB; +import org.opencv.xphoto.TonemapDurand; + +// C++: class Xphoto +//javadoc: Xphoto + +public class Xphoto { + + // C++: enum Bm3dSteps + public static final int + BM3D_STEPALL = 0, + BM3D_STEP1 = 1, + BM3D_STEP2 = 2; + + + // C++: enum InpaintTypes + public static final int + INPAINT_SHIFTMAP = 0; + + + // C++: enum TransformTypes + public static final int + HAAR = 0; + + + // + // C++: Ptr_GrayworldWB cv::xphoto::createGrayworldWB() + // + + //javadoc: createGrayworldWB() + public static GrayworldWB createGrayworldWB() + { + + GrayworldWB retVal = GrayworldWB.__fromPtr__(createGrayworldWB_0()); + + return retVal; + } + + + // + // C++: Ptr_LearningBasedWB cv::xphoto::createLearningBasedWB(String path_to_model = String()) + // + + //javadoc: createLearningBasedWB(path_to_model) + public static LearningBasedWB createLearningBasedWB(String path_to_model) + { + + LearningBasedWB retVal = LearningBasedWB.__fromPtr__(createLearningBasedWB_0(path_to_model)); + + return retVal; + } + + //javadoc: createLearningBasedWB() + public static LearningBasedWB createLearningBasedWB() + { + + LearningBasedWB retVal = LearningBasedWB.__fromPtr__(createLearningBasedWB_1()); + + return retVal; + } + + + // + // C++: Ptr_SimpleWB cv::xphoto::createSimpleWB() + // + + //javadoc: createSimpleWB() + public static SimpleWB createSimpleWB() + { + + SimpleWB retVal = SimpleWB.__fromPtr__(createSimpleWB_0()); + + return retVal; + } + + + // + // C++: Ptr_TonemapDurand cv::xphoto::createTonemapDurand(float gamma = 1.0f, float contrast = 4.0f, float saturation = 1.0f, float sigma_space = 2.0f, float sigma_color = 2.0f) + // + + //javadoc: createTonemapDurand(gamma, contrast, saturation, sigma_space, sigma_color) + public static TonemapDurand createTonemapDurand(float gamma, float contrast, float saturation, float sigma_space, float sigma_color) + { + + TonemapDurand retVal = TonemapDurand.__fromPtr__(createTonemapDurand_0(gamma, contrast, saturation, sigma_space, sigma_color)); + + return retVal; + } + + //javadoc: createTonemapDurand(gamma, contrast, saturation, sigma_space) + public static TonemapDurand createTonemapDurand(float gamma, float contrast, float saturation, float sigma_space) + { + + TonemapDurand retVal = TonemapDurand.__fromPtr__(createTonemapDurand_1(gamma, contrast, saturation, sigma_space)); + + return retVal; + } + + //javadoc: createTonemapDurand(gamma, contrast, saturation) + public static TonemapDurand createTonemapDurand(float gamma, float contrast, float saturation) + { + + TonemapDurand retVal = TonemapDurand.__fromPtr__(createTonemapDurand_2(gamma, contrast, saturation)); + + return retVal; + } + + //javadoc: createTonemapDurand(gamma, contrast) + public static TonemapDurand createTonemapDurand(float gamma, float contrast) + { + + TonemapDurand retVal = TonemapDurand.__fromPtr__(createTonemapDurand_3(gamma, contrast)); + + return retVal; + } + + //javadoc: createTonemapDurand(gamma) + public static TonemapDurand createTonemapDurand(float gamma) + { + + TonemapDurand retVal = TonemapDurand.__fromPtr__(createTonemapDurand_4(gamma)); + + return retVal; + } + + //javadoc: createTonemapDurand() + public static TonemapDurand createTonemapDurand() + { + + TonemapDurand retVal = TonemapDurand.__fromPtr__(createTonemapDurand_5()); + + return retVal; + } + + + // + // C++: void cv::xphoto::applyChannelGains(Mat src, Mat& dst, float gainB, float gainG, float gainR) + // + + //javadoc: applyChannelGains(src, dst, gainB, gainG, gainR) + public static void applyChannelGains(Mat src, Mat dst, float gainB, float gainG, float gainR) + { + + applyChannelGains_0(src.nativeObj, dst.nativeObj, gainB, gainG, gainR); + + return; + } + + + // + // C++: void cv::xphoto::bm3dDenoising(Mat src, Mat& dst, float h = 1, int templateWindowSize = 4, int searchWindowSize = 16, int blockMatchingStep1 = 2500, int blockMatchingStep2 = 400, int groupSize = 8, int slidingStep = 1, float beta = 2.0f, int normType = cv::NORM_L2, int step = cv::xphoto::BM3D_STEPALL, int transformType = cv::xphoto::HAAR) + // + + //javadoc: bm3dDenoising(src, dst, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep, beta, normType, step, transformType) + public static void bm3dDenoising(Mat src, Mat dst, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep, float beta, int normType, int step, int transformType) + { + + bm3dDenoising_0(src.nativeObj, dst.nativeObj, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep, beta, normType, step, transformType); + + return; + } + + //javadoc: bm3dDenoising(src, dst, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep, beta, normType, step) + public static void bm3dDenoising(Mat src, Mat dst, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep, float beta, int normType, int step) + { + + bm3dDenoising_1(src.nativeObj, dst.nativeObj, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep, beta, normType, step); + + return; + } + + //javadoc: bm3dDenoising(src, dst, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep, beta, normType) + public static void bm3dDenoising(Mat src, Mat dst, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep, float beta, int normType) + { + + bm3dDenoising_2(src.nativeObj, dst.nativeObj, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep, beta, normType); + + return; + } + + //javadoc: bm3dDenoising(src, dst, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep, beta) + public static void bm3dDenoising(Mat src, Mat dst, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep, float beta) + { + + bm3dDenoising_3(src.nativeObj, dst.nativeObj, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep, beta); + + return; + } + + //javadoc: bm3dDenoising(src, dst, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep) + public static void bm3dDenoising(Mat src, Mat dst, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep) + { + + bm3dDenoising_4(src.nativeObj, dst.nativeObj, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep); + + return; + } + + //javadoc: bm3dDenoising(src, dst, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize) + public static void bm3dDenoising(Mat src, Mat dst, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize) + { + + bm3dDenoising_5(src.nativeObj, dst.nativeObj, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize); + + return; + } + + //javadoc: bm3dDenoising(src, dst, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2) + public static void bm3dDenoising(Mat src, Mat dst, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2) + { + + bm3dDenoising_6(src.nativeObj, dst.nativeObj, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2); + + return; + } + + //javadoc: bm3dDenoising(src, dst, h, templateWindowSize, searchWindowSize, blockMatchingStep1) + public static void bm3dDenoising(Mat src, Mat dst, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1) + { + + bm3dDenoising_7(src.nativeObj, dst.nativeObj, h, templateWindowSize, searchWindowSize, blockMatchingStep1); + + return; + } + + //javadoc: bm3dDenoising(src, dst, h, templateWindowSize, searchWindowSize) + public static void bm3dDenoising(Mat src, Mat dst, float h, int templateWindowSize, int searchWindowSize) + { + + bm3dDenoising_8(src.nativeObj, dst.nativeObj, h, templateWindowSize, searchWindowSize); + + return; + } + + //javadoc: bm3dDenoising(src, dst, h, templateWindowSize) + public static void bm3dDenoising(Mat src, Mat dst, float h, int templateWindowSize) + { + + bm3dDenoising_9(src.nativeObj, dst.nativeObj, h, templateWindowSize); + + return; + } + + //javadoc: bm3dDenoising(src, dst, h) + public static void bm3dDenoising(Mat src, Mat dst, float h) + { + + bm3dDenoising_10(src.nativeObj, dst.nativeObj, h); + + return; + } + + //javadoc: bm3dDenoising(src, dst) + public static void bm3dDenoising(Mat src, Mat dst) + { + + bm3dDenoising_11(src.nativeObj, dst.nativeObj); + + return; + } + + + // + // C++: void cv::xphoto::bm3dDenoising(Mat src, Mat& dstStep1, Mat& dstStep2, float h = 1, int templateWindowSize = 4, int searchWindowSize = 16, int blockMatchingStep1 = 2500, int blockMatchingStep2 = 400, int groupSize = 8, int slidingStep = 1, float beta = 2.0f, int normType = cv::NORM_L2, int step = cv::xphoto::BM3D_STEPALL, int transformType = cv::xphoto::HAAR) + // + + //javadoc: bm3dDenoising(src, dstStep1, dstStep2, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep, beta, normType, step, transformType) + public static void bm3dDenoising(Mat src, Mat dstStep1, Mat dstStep2, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep, float beta, int normType, int step, int transformType) + { + + bm3dDenoising_12(src.nativeObj, dstStep1.nativeObj, dstStep2.nativeObj, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep, beta, normType, step, transformType); + + return; + } + + //javadoc: bm3dDenoising(src, dstStep1, dstStep2, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep, beta, normType, step) + public static void bm3dDenoising(Mat src, Mat dstStep1, Mat dstStep2, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep, float beta, int normType, int step) + { + + bm3dDenoising_13(src.nativeObj, dstStep1.nativeObj, dstStep2.nativeObj, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep, beta, normType, step); + + return; + } + + //javadoc: bm3dDenoising(src, dstStep1, dstStep2, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep, beta, normType) + public static void bm3dDenoising(Mat src, Mat dstStep1, Mat dstStep2, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep, float beta, int normType) + { + + bm3dDenoising_14(src.nativeObj, dstStep1.nativeObj, dstStep2.nativeObj, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep, beta, normType); + + return; + } + + //javadoc: bm3dDenoising(src, dstStep1, dstStep2, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep, beta) + public static void bm3dDenoising(Mat src, Mat dstStep1, Mat dstStep2, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep, float beta) + { + + bm3dDenoising_15(src.nativeObj, dstStep1.nativeObj, dstStep2.nativeObj, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep, beta); + + return; + } + + //javadoc: bm3dDenoising(src, dstStep1, dstStep2, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep) + public static void bm3dDenoising(Mat src, Mat dstStep1, Mat dstStep2, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep) + { + + bm3dDenoising_16(src.nativeObj, dstStep1.nativeObj, dstStep2.nativeObj, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize, slidingStep); + + return; + } + + //javadoc: bm3dDenoising(src, dstStep1, dstStep2, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize) + public static void bm3dDenoising(Mat src, Mat dstStep1, Mat dstStep2, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize) + { + + bm3dDenoising_17(src.nativeObj, dstStep1.nativeObj, dstStep2.nativeObj, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2, groupSize); + + return; + } + + //javadoc: bm3dDenoising(src, dstStep1, dstStep2, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2) + public static void bm3dDenoising(Mat src, Mat dstStep1, Mat dstStep2, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2) + { + + bm3dDenoising_18(src.nativeObj, dstStep1.nativeObj, dstStep2.nativeObj, h, templateWindowSize, searchWindowSize, blockMatchingStep1, blockMatchingStep2); + + return; + } + + //javadoc: bm3dDenoising(src, dstStep1, dstStep2, h, templateWindowSize, searchWindowSize, blockMatchingStep1) + public static void bm3dDenoising(Mat src, Mat dstStep1, Mat dstStep2, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1) + { + + bm3dDenoising_19(src.nativeObj, dstStep1.nativeObj, dstStep2.nativeObj, h, templateWindowSize, searchWindowSize, blockMatchingStep1); + + return; + } + + //javadoc: bm3dDenoising(src, dstStep1, dstStep2, h, templateWindowSize, searchWindowSize) + public static void bm3dDenoising(Mat src, Mat dstStep1, Mat dstStep2, float h, int templateWindowSize, int searchWindowSize) + { + + bm3dDenoising_20(src.nativeObj, dstStep1.nativeObj, dstStep2.nativeObj, h, templateWindowSize, searchWindowSize); + + return; + } + + //javadoc: bm3dDenoising(src, dstStep1, dstStep2, h, templateWindowSize) + public static void bm3dDenoising(Mat src, Mat dstStep1, Mat dstStep2, float h, int templateWindowSize) + { + + bm3dDenoising_21(src.nativeObj, dstStep1.nativeObj, dstStep2.nativeObj, h, templateWindowSize); + + return; + } + + //javadoc: bm3dDenoising(src, dstStep1, dstStep2, h) + public static void bm3dDenoising(Mat src, Mat dstStep1, Mat dstStep2, float h) + { + + bm3dDenoising_22(src.nativeObj, dstStep1.nativeObj, dstStep2.nativeObj, h); + + return; + } + + //javadoc: bm3dDenoising(src, dstStep1, dstStep2) + public static void bm3dDenoising(Mat src, Mat dstStep1, Mat dstStep2) + { + + bm3dDenoising_23(src.nativeObj, dstStep1.nativeObj, dstStep2.nativeObj); + + return; + } + + + // + // C++: void cv::xphoto::dctDenoising(Mat src, Mat dst, double sigma, int psize = 16) + // + + //javadoc: dctDenoising(src, dst, sigma, psize) + public static void dctDenoising(Mat src, Mat dst, double sigma, int psize) + { + + dctDenoising_0(src.nativeObj, dst.nativeObj, sigma, psize); + + return; + } + + //javadoc: dctDenoising(src, dst, sigma) + public static void dctDenoising(Mat src, Mat dst, double sigma) + { + + dctDenoising_1(src.nativeObj, dst.nativeObj, sigma); + + return; + } + + + // + // C++: void cv::xphoto::inpaint(Mat src, Mat mask, Mat dst, int algorithmType) + // + + //javadoc: inpaint(src, mask, dst, algorithmType) + public static void inpaint(Mat src, Mat mask, Mat dst, int algorithmType) + { + + inpaint_0(src.nativeObj, mask.nativeObj, dst.nativeObj, algorithmType); + + return; + } + + + // + // C++: void cv::xphoto::oilPainting(Mat src, Mat& dst, int size, int dynRatio, int code) + // + + //javadoc: oilPainting(src, dst, size, dynRatio, code) + public static void oilPainting(Mat src, Mat dst, int size, int dynRatio, int code) + { + + oilPainting_0(src.nativeObj, dst.nativeObj, size, dynRatio, code); + + return; + } + + + // + // C++: void cv::xphoto::oilPainting(Mat src, Mat& dst, int size, int dynRatio) + // + + //javadoc: oilPainting(src, dst, size, dynRatio) + public static void oilPainting(Mat src, Mat dst, int size, int dynRatio) + { + + oilPainting_1(src.nativeObj, dst.nativeObj, size, dynRatio); + + return; + } + + + + + // C++: Ptr_GrayworldWB cv::xphoto::createGrayworldWB() + private static native long createGrayworldWB_0(); + + // C++: Ptr_LearningBasedWB cv::xphoto::createLearningBasedWB(String path_to_model = String()) + private static native long createLearningBasedWB_0(String path_to_model); + private static native long createLearningBasedWB_1(); + + // C++: Ptr_SimpleWB cv::xphoto::createSimpleWB() + private static native long createSimpleWB_0(); + + // C++: Ptr_TonemapDurand cv::xphoto::createTonemapDurand(float gamma = 1.0f, float contrast = 4.0f, float saturation = 1.0f, float sigma_space = 2.0f, float sigma_color = 2.0f) + private static native long createTonemapDurand_0(float gamma, float contrast, float saturation, float sigma_space, float sigma_color); + private static native long createTonemapDurand_1(float gamma, float contrast, float saturation, float sigma_space); + private static native long createTonemapDurand_2(float gamma, float contrast, float saturation); + private static native long createTonemapDurand_3(float gamma, float contrast); + private static native long createTonemapDurand_4(float gamma); + private static native long createTonemapDurand_5(); + + // C++: void cv::xphoto::applyChannelGains(Mat src, Mat& dst, float gainB, float gainG, float gainR) + private static native void applyChannelGains_0(long src_nativeObj, long dst_nativeObj, float gainB, float gainG, float gainR); + + // C++: void cv::xphoto::bm3dDenoising(Mat src, Mat& dst, float h = 1, int templateWindowSize = 4, int searchWindowSize = 16, int blockMatchingStep1 = 2500, int blockMatchingStep2 = 400, int groupSize = 8, int slidingStep = 1, float beta = 2.0f, int normType = cv::NORM_L2, int step = cv::xphoto::BM3D_STEPALL, int transformType = cv::xphoto::HAAR) + private static native void bm3dDenoising_0(long src_nativeObj, long dst_nativeObj, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep, float beta, int normType, int step, int transformType); + private static native void bm3dDenoising_1(long src_nativeObj, long dst_nativeObj, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep, float beta, int normType, int step); + private static native void bm3dDenoising_2(long src_nativeObj, long dst_nativeObj, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep, float beta, int normType); + private static native void bm3dDenoising_3(long src_nativeObj, long dst_nativeObj, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep, float beta); + private static native void bm3dDenoising_4(long src_nativeObj, long dst_nativeObj, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep); + private static native void bm3dDenoising_5(long src_nativeObj, long dst_nativeObj, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize); + private static native void bm3dDenoising_6(long src_nativeObj, long dst_nativeObj, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2); + private static native void bm3dDenoising_7(long src_nativeObj, long dst_nativeObj, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1); + private static native void bm3dDenoising_8(long src_nativeObj, long dst_nativeObj, float h, int templateWindowSize, int searchWindowSize); + private static native void bm3dDenoising_9(long src_nativeObj, long dst_nativeObj, float h, int templateWindowSize); + private static native void bm3dDenoising_10(long src_nativeObj, long dst_nativeObj, float h); + private static native void bm3dDenoising_11(long src_nativeObj, long dst_nativeObj); + + // C++: void cv::xphoto::bm3dDenoising(Mat src, Mat& dstStep1, Mat& dstStep2, float h = 1, int templateWindowSize = 4, int searchWindowSize = 16, int blockMatchingStep1 = 2500, int blockMatchingStep2 = 400, int groupSize = 8, int slidingStep = 1, float beta = 2.0f, int normType = cv::NORM_L2, int step = cv::xphoto::BM3D_STEPALL, int transformType = cv::xphoto::HAAR) + private static native void bm3dDenoising_12(long src_nativeObj, long dstStep1_nativeObj, long dstStep2_nativeObj, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep, float beta, int normType, int step, int transformType); + private static native void bm3dDenoising_13(long src_nativeObj, long dstStep1_nativeObj, long dstStep2_nativeObj, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep, float beta, int normType, int step); + private static native void bm3dDenoising_14(long src_nativeObj, long dstStep1_nativeObj, long dstStep2_nativeObj, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep, float beta, int normType); + private static native void bm3dDenoising_15(long src_nativeObj, long dstStep1_nativeObj, long dstStep2_nativeObj, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep, float beta); + private static native void bm3dDenoising_16(long src_nativeObj, long dstStep1_nativeObj, long dstStep2_nativeObj, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize, int slidingStep); + private static native void bm3dDenoising_17(long src_nativeObj, long dstStep1_nativeObj, long dstStep2_nativeObj, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2, int groupSize); + private static native void bm3dDenoising_18(long src_nativeObj, long dstStep1_nativeObj, long dstStep2_nativeObj, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1, int blockMatchingStep2); + private static native void bm3dDenoising_19(long src_nativeObj, long dstStep1_nativeObj, long dstStep2_nativeObj, float h, int templateWindowSize, int searchWindowSize, int blockMatchingStep1); + private static native void bm3dDenoising_20(long src_nativeObj, long dstStep1_nativeObj, long dstStep2_nativeObj, float h, int templateWindowSize, int searchWindowSize); + private static native void bm3dDenoising_21(long src_nativeObj, long dstStep1_nativeObj, long dstStep2_nativeObj, float h, int templateWindowSize); + private static native void bm3dDenoising_22(long src_nativeObj, long dstStep1_nativeObj, long dstStep2_nativeObj, float h); + private static native void bm3dDenoising_23(long src_nativeObj, long dstStep1_nativeObj, long dstStep2_nativeObj); + + // C++: void cv::xphoto::dctDenoising(Mat src, Mat dst, double sigma, int psize = 16) + private static native void dctDenoising_0(long src_nativeObj, long dst_nativeObj, double sigma, int psize); + private static native void dctDenoising_1(long src_nativeObj, long dst_nativeObj, double sigma); + + // C++: void cv::xphoto::inpaint(Mat src, Mat mask, Mat dst, int algorithmType) + private static native void inpaint_0(long src_nativeObj, long mask_nativeObj, long dst_nativeObj, int algorithmType); + + // C++: void cv::xphoto::oilPainting(Mat src, Mat& dst, int size, int dynRatio, int code) + private static native void oilPainting_0(long src_nativeObj, long dst_nativeObj, int size, int dynRatio, int code); + + // C++: void cv::xphoto::oilPainting(Mat src, Mat& dst, int size, int dynRatio) + private static native void oilPainting_1(long src_nativeObj, long dst_nativeObj, int size, int dynRatio); + +} diff --git a/OpenCV/src/main/res/values/attrs.xml b/OpenCV/src/main/res/values/attrs.xml new file mode 100644 index 00000000..6902621f --- /dev/null +++ b/OpenCV/src/main/res/values/attrs.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_aruco.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_aruco.a new file mode 100644 index 00000000..9767cd1c Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_aruco.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_bgsegm.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_bgsegm.a new file mode 100644 index 00000000..e202079d Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_bgsegm.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_bioinspired.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_bioinspired.a new file mode 100644 index 00000000..bd4031ef Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_bioinspired.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_calib3d.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_calib3d.a new file mode 100644 index 00000000..4b754aa8 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_calib3d.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_ccalib.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_ccalib.a new file mode 100644 index 00000000..609d645f Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_ccalib.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_core.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_core.a new file mode 100644 index 00000000..86bb9d84 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_core.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_datasets.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_datasets.a new file mode 100644 index 00000000..f8070e6d Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_datasets.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_dnn.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_dnn.a new file mode 100644 index 00000000..622963d9 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_dnn.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_dnn_objdetect.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_dnn_objdetect.a new file mode 100644 index 00000000..a24f5368 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_dnn_objdetect.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_dpm.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_dpm.a new file mode 100644 index 00000000..3996f2ef Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_dpm.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_face.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_face.a new file mode 100644 index 00000000..b0dd4c33 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_face.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_features2d.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_features2d.a new file mode 100644 index 00000000..04650040 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_features2d.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_flann.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_flann.a new file mode 100644 index 00000000..2eee6708 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_flann.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_fuzzy.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_fuzzy.a new file mode 100644 index 00000000..8b2da5f5 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_fuzzy.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_hfs.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_hfs.a new file mode 100644 index 00000000..0994245a Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_hfs.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_highgui.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_highgui.a new file mode 100644 index 00000000..56c2fcfa Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_highgui.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_img_hash.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_img_hash.a new file mode 100644 index 00000000..74ec2cc3 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_img_hash.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_imgcodecs.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_imgcodecs.a new file mode 100644 index 00000000..a0562c03 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_imgcodecs.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_imgproc.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_imgproc.a new file mode 100644 index 00000000..68d178ce Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_imgproc.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_line_descriptor.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_line_descriptor.a new file mode 100644 index 00000000..9dff8e5e Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_line_descriptor.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_ml.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_ml.a new file mode 100644 index 00000000..2852818b Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_ml.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_objdetect.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_objdetect.a new file mode 100644 index 00000000..f3aec9ba Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_objdetect.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_optflow.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_optflow.a new file mode 100644 index 00000000..64553f6b Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_optflow.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_phase_unwrapping.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_phase_unwrapping.a new file mode 100644 index 00000000..13a69fb1 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_phase_unwrapping.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_photo.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_photo.a new file mode 100644 index 00000000..b1440e7e Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_photo.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_plot.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_plot.a new file mode 100644 index 00000000..4b360321 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_plot.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_quality.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_quality.a new file mode 100644 index 00000000..565a70bd Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_quality.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_reg.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_reg.a new file mode 100644 index 00000000..ce9f7a65 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_reg.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_rgbd.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_rgbd.a new file mode 100644 index 00000000..c10ebbef Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_rgbd.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_saliency.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_saliency.a new file mode 100644 index 00000000..683848d2 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_saliency.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_shape.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_shape.a new file mode 100644 index 00000000..db53dbca Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_shape.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_stereo.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_stereo.a new file mode 100644 index 00000000..5a5d1f98 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_stereo.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_stitching.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_stitching.a new file mode 100644 index 00000000..404fb10a Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_stitching.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_structured_light.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_structured_light.a new file mode 100644 index 00000000..ffab5981 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_structured_light.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_superres.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_superres.a new file mode 100644 index 00000000..eec46fa5 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_superres.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_surface_matching.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_surface_matching.a new file mode 100644 index 00000000..35cb0a96 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_surface_matching.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_text.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_text.a new file mode 100644 index 00000000..60a4017c Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_text.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_tracking.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_tracking.a new file mode 100644 index 00000000..615ea80c Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_tracking.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_video.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_video.a new file mode 100644 index 00000000..2ebc0147 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_video.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_videoio.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_videoio.a new file mode 100644 index 00000000..2417713e Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_videoio.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_videostab.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_videostab.a new file mode 100644 index 00000000..7e3d5e9e Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_videostab.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_xfeatures2d.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_xfeatures2d.a new file mode 100644 index 00000000..a7bb747f Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_xfeatures2d.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_ximgproc.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_ximgproc.a new file mode 100644 index 00000000..42008846 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_ximgproc.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_xobjdetect.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_xobjdetect.a new file mode 100644 index 00000000..0b034bc5 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_xobjdetect.a differ diff --git a/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_xphoto.a b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_xphoto.a new file mode 100644 index 00000000..d86c7d60 Binary files /dev/null and b/OpenCV/src/main/staticlibs/arm64-v8a/libopencv_xphoto.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_aruco.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_aruco.a new file mode 100644 index 00000000..50ecb2d4 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_aruco.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_bgsegm.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_bgsegm.a new file mode 100644 index 00000000..a469a862 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_bgsegm.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_bioinspired.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_bioinspired.a new file mode 100644 index 00000000..dbf6a9e1 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_bioinspired.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_calib3d.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_calib3d.a new file mode 100644 index 00000000..015a0110 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_calib3d.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_ccalib.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_ccalib.a new file mode 100644 index 00000000..7aea9ea3 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_ccalib.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_core.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_core.a new file mode 100644 index 00000000..cba51336 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_core.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_datasets.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_datasets.a new file mode 100644 index 00000000..0e6ced35 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_datasets.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_dnn.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_dnn.a new file mode 100644 index 00000000..80217da4 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_dnn.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_dnn_objdetect.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_dnn_objdetect.a new file mode 100644 index 00000000..3fc15621 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_dnn_objdetect.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_dpm.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_dpm.a new file mode 100644 index 00000000..131accfa Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_dpm.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_face.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_face.a new file mode 100644 index 00000000..9a5e1c7e Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_face.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_features2d.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_features2d.a new file mode 100644 index 00000000..1051f778 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_features2d.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_flann.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_flann.a new file mode 100644 index 00000000..a70de042 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_flann.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_fuzzy.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_fuzzy.a new file mode 100644 index 00000000..11a99453 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_fuzzy.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_hfs.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_hfs.a new file mode 100644 index 00000000..ff1bb7f7 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_hfs.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_highgui.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_highgui.a new file mode 100644 index 00000000..7f6c676c Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_highgui.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_img_hash.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_img_hash.a new file mode 100644 index 00000000..2d5993a6 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_img_hash.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_imgcodecs.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_imgcodecs.a new file mode 100644 index 00000000..4883792d Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_imgcodecs.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_imgproc.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_imgproc.a new file mode 100644 index 00000000..05881bad Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_imgproc.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_line_descriptor.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_line_descriptor.a new file mode 100644 index 00000000..ca7ab4de Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_line_descriptor.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_ml.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_ml.a new file mode 100644 index 00000000..5abef18d Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_ml.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_objdetect.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_objdetect.a new file mode 100644 index 00000000..0bacc92b Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_objdetect.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_optflow.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_optflow.a new file mode 100644 index 00000000..4f9ba608 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_optflow.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_phase_unwrapping.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_phase_unwrapping.a new file mode 100644 index 00000000..da51060c Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_phase_unwrapping.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_photo.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_photo.a new file mode 100644 index 00000000..e0302fe2 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_photo.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_plot.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_plot.a new file mode 100644 index 00000000..e6896866 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_plot.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_quality.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_quality.a new file mode 100644 index 00000000..922440c9 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_quality.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_reg.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_reg.a new file mode 100644 index 00000000..c0d8a1f3 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_reg.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_rgbd.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_rgbd.a new file mode 100644 index 00000000..7ce3e62a Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_rgbd.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_saliency.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_saliency.a new file mode 100644 index 00000000..74521aa0 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_saliency.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_shape.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_shape.a new file mode 100644 index 00000000..15e4da60 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_shape.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_stereo.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_stereo.a new file mode 100644 index 00000000..df8f5838 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_stereo.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_stitching.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_stitching.a new file mode 100644 index 00000000..a726da37 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_stitching.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_structured_light.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_structured_light.a new file mode 100644 index 00000000..68e10c76 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_structured_light.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_superres.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_superres.a new file mode 100644 index 00000000..40b155b0 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_superres.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_surface_matching.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_surface_matching.a new file mode 100644 index 00000000..daaaaf54 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_surface_matching.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_text.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_text.a new file mode 100644 index 00000000..611e84d3 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_text.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_tracking.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_tracking.a new file mode 100644 index 00000000..01b78757 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_tracking.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_video.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_video.a new file mode 100644 index 00000000..2fb4db88 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_video.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_videoio.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_videoio.a new file mode 100644 index 00000000..f9426ff2 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_videoio.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_videostab.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_videostab.a new file mode 100644 index 00000000..b1b8c387 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_videostab.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_xfeatures2d.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_xfeatures2d.a new file mode 100644 index 00000000..77fed5fb Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_xfeatures2d.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_ximgproc.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_ximgproc.a new file mode 100644 index 00000000..eb913672 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_ximgproc.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_xobjdetect.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_xobjdetect.a new file mode 100644 index 00000000..77249562 Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_xobjdetect.a differ diff --git a/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_xphoto.a b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_xphoto.a new file mode 100644 index 00000000..8cd8f7da Binary files /dev/null and b/OpenCV/src/main/staticlibs/armeabi-v7a/libopencv_xphoto.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_aruco.a b/OpenCV/src/main/staticlibs/x86/libopencv_aruco.a new file mode 100644 index 00000000..f47711f5 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_aruco.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_bgsegm.a b/OpenCV/src/main/staticlibs/x86/libopencv_bgsegm.a new file mode 100644 index 00000000..5f696dfa Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_bgsegm.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_bioinspired.a b/OpenCV/src/main/staticlibs/x86/libopencv_bioinspired.a new file mode 100644 index 00000000..27256e20 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_bioinspired.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_calib3d.a b/OpenCV/src/main/staticlibs/x86/libopencv_calib3d.a new file mode 100644 index 00000000..a17bf116 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_calib3d.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_ccalib.a b/OpenCV/src/main/staticlibs/x86/libopencv_ccalib.a new file mode 100644 index 00000000..4e560331 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_ccalib.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_core.a b/OpenCV/src/main/staticlibs/x86/libopencv_core.a new file mode 100644 index 00000000..5adbcec1 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_core.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_datasets.a b/OpenCV/src/main/staticlibs/x86/libopencv_datasets.a new file mode 100644 index 00000000..10ffa2f5 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_datasets.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_dnn.a b/OpenCV/src/main/staticlibs/x86/libopencv_dnn.a new file mode 100644 index 00000000..d8b1a66b Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_dnn.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_dnn_objdetect.a b/OpenCV/src/main/staticlibs/x86/libopencv_dnn_objdetect.a new file mode 100644 index 00000000..3f3994ab Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_dnn_objdetect.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_dpm.a b/OpenCV/src/main/staticlibs/x86/libopencv_dpm.a new file mode 100644 index 00000000..28be1728 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_dpm.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_face.a b/OpenCV/src/main/staticlibs/x86/libopencv_face.a new file mode 100644 index 00000000..0f8fef62 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_face.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_features2d.a b/OpenCV/src/main/staticlibs/x86/libopencv_features2d.a new file mode 100644 index 00000000..c4971c76 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_features2d.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_flann.a b/OpenCV/src/main/staticlibs/x86/libopencv_flann.a new file mode 100644 index 00000000..924d7f82 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_flann.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_fuzzy.a b/OpenCV/src/main/staticlibs/x86/libopencv_fuzzy.a new file mode 100644 index 00000000..1b40f1ff Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_fuzzy.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_hfs.a b/OpenCV/src/main/staticlibs/x86/libopencv_hfs.a new file mode 100644 index 00000000..764b5661 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_hfs.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_highgui.a b/OpenCV/src/main/staticlibs/x86/libopencv_highgui.a new file mode 100644 index 00000000..5ef90d39 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_highgui.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_img_hash.a b/OpenCV/src/main/staticlibs/x86/libopencv_img_hash.a new file mode 100644 index 00000000..92112d3d Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_img_hash.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_imgcodecs.a b/OpenCV/src/main/staticlibs/x86/libopencv_imgcodecs.a new file mode 100644 index 00000000..8a7260b7 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_imgcodecs.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_imgproc.a b/OpenCV/src/main/staticlibs/x86/libopencv_imgproc.a new file mode 100644 index 00000000..6ccc3318 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_imgproc.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_line_descriptor.a b/OpenCV/src/main/staticlibs/x86/libopencv_line_descriptor.a new file mode 100644 index 00000000..c969d54b Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_line_descriptor.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_ml.a b/OpenCV/src/main/staticlibs/x86/libopencv_ml.a new file mode 100644 index 00000000..411a20c6 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_ml.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_objdetect.a b/OpenCV/src/main/staticlibs/x86/libopencv_objdetect.a new file mode 100644 index 00000000..0a16e1da Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_objdetect.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_optflow.a b/OpenCV/src/main/staticlibs/x86/libopencv_optflow.a new file mode 100644 index 00000000..cff248cf Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_optflow.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_phase_unwrapping.a b/OpenCV/src/main/staticlibs/x86/libopencv_phase_unwrapping.a new file mode 100644 index 00000000..80491fed Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_phase_unwrapping.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_photo.a b/OpenCV/src/main/staticlibs/x86/libopencv_photo.a new file mode 100644 index 00000000..cc662290 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_photo.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_plot.a b/OpenCV/src/main/staticlibs/x86/libopencv_plot.a new file mode 100644 index 00000000..c109964a Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_plot.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_quality.a b/OpenCV/src/main/staticlibs/x86/libopencv_quality.a new file mode 100644 index 00000000..ec39079a Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_quality.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_reg.a b/OpenCV/src/main/staticlibs/x86/libopencv_reg.a new file mode 100644 index 00000000..f317512a Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_reg.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_rgbd.a b/OpenCV/src/main/staticlibs/x86/libopencv_rgbd.a new file mode 100644 index 00000000..7f077987 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_rgbd.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_saliency.a b/OpenCV/src/main/staticlibs/x86/libopencv_saliency.a new file mode 100644 index 00000000..b0f512a2 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_saliency.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_shape.a b/OpenCV/src/main/staticlibs/x86/libopencv_shape.a new file mode 100644 index 00000000..0bd91294 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_shape.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_stereo.a b/OpenCV/src/main/staticlibs/x86/libopencv_stereo.a new file mode 100644 index 00000000..21234c57 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_stereo.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_stitching.a b/OpenCV/src/main/staticlibs/x86/libopencv_stitching.a new file mode 100644 index 00000000..db88e455 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_stitching.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_structured_light.a b/OpenCV/src/main/staticlibs/x86/libopencv_structured_light.a new file mode 100644 index 00000000..3e2e13c8 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_structured_light.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_superres.a b/OpenCV/src/main/staticlibs/x86/libopencv_superres.a new file mode 100644 index 00000000..0302e640 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_superres.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_surface_matching.a b/OpenCV/src/main/staticlibs/x86/libopencv_surface_matching.a new file mode 100644 index 00000000..107f4e6e Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_surface_matching.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_text.a b/OpenCV/src/main/staticlibs/x86/libopencv_text.a new file mode 100644 index 00000000..eb1c1bb3 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_text.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_tracking.a b/OpenCV/src/main/staticlibs/x86/libopencv_tracking.a new file mode 100644 index 00000000..141cd140 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_tracking.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_video.a b/OpenCV/src/main/staticlibs/x86/libopencv_video.a new file mode 100644 index 00000000..afee0127 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_video.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_videoio.a b/OpenCV/src/main/staticlibs/x86/libopencv_videoio.a new file mode 100644 index 00000000..ba6e2e02 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_videoio.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_videostab.a b/OpenCV/src/main/staticlibs/x86/libopencv_videostab.a new file mode 100644 index 00000000..606224a5 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_videostab.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_xfeatures2d.a b/OpenCV/src/main/staticlibs/x86/libopencv_xfeatures2d.a new file mode 100644 index 00000000..a9d21137 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_xfeatures2d.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_ximgproc.a b/OpenCV/src/main/staticlibs/x86/libopencv_ximgproc.a new file mode 100644 index 00000000..7e7b5397 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_ximgproc.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_xobjdetect.a b/OpenCV/src/main/staticlibs/x86/libopencv_xobjdetect.a new file mode 100644 index 00000000..591338ac Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_xobjdetect.a differ diff --git a/OpenCV/src/main/staticlibs/x86/libopencv_xphoto.a b/OpenCV/src/main/staticlibs/x86/libopencv_xphoto.a new file mode 100644 index 00000000..7c4c7638 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86/libopencv_xphoto.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_aruco.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_aruco.a new file mode 100644 index 00000000..9cfccfa4 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_aruco.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_bgsegm.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_bgsegm.a new file mode 100644 index 00000000..aae6a89c Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_bgsegm.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_bioinspired.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_bioinspired.a new file mode 100644 index 00000000..9cb8d6e9 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_bioinspired.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_calib3d.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_calib3d.a new file mode 100644 index 00000000..a33e3480 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_calib3d.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_ccalib.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_ccalib.a new file mode 100644 index 00000000..65959d0e Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_ccalib.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_core.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_core.a new file mode 100644 index 00000000..a1a9de4f Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_core.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_datasets.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_datasets.a new file mode 100644 index 00000000..176d837f Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_datasets.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_dnn.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_dnn.a new file mode 100644 index 00000000..dce4fcc0 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_dnn.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_dnn_objdetect.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_dnn_objdetect.a new file mode 100644 index 00000000..d35b5d14 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_dnn_objdetect.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_dpm.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_dpm.a new file mode 100644 index 00000000..437de7f3 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_dpm.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_face.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_face.a new file mode 100644 index 00000000..10211e9c Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_face.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_features2d.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_features2d.a new file mode 100644 index 00000000..7b40aabd Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_features2d.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_flann.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_flann.a new file mode 100644 index 00000000..a819c73b Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_flann.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_fuzzy.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_fuzzy.a new file mode 100644 index 00000000..7795353c Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_fuzzy.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_hfs.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_hfs.a new file mode 100644 index 00000000..4596d14e Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_hfs.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_highgui.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_highgui.a new file mode 100644 index 00000000..1d86ebc1 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_highgui.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_img_hash.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_img_hash.a new file mode 100644 index 00000000..8e8c311e Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_img_hash.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_imgcodecs.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_imgcodecs.a new file mode 100644 index 00000000..4cdf8dc6 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_imgcodecs.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_imgproc.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_imgproc.a new file mode 100644 index 00000000..b07b2a72 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_imgproc.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_line_descriptor.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_line_descriptor.a new file mode 100644 index 00000000..0ce72cb9 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_line_descriptor.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_ml.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_ml.a new file mode 100644 index 00000000..8030d0af Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_ml.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_objdetect.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_objdetect.a new file mode 100644 index 00000000..ede56eeb Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_objdetect.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_optflow.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_optflow.a new file mode 100644 index 00000000..936ce36e Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_optflow.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_phase_unwrapping.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_phase_unwrapping.a new file mode 100644 index 00000000..25e05aa7 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_phase_unwrapping.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_photo.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_photo.a new file mode 100644 index 00000000..c16e19ac Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_photo.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_plot.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_plot.a new file mode 100644 index 00000000..1f21b561 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_plot.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_quality.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_quality.a new file mode 100644 index 00000000..84c0ea6e Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_quality.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_reg.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_reg.a new file mode 100644 index 00000000..1fb6d5eb Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_reg.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_rgbd.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_rgbd.a new file mode 100644 index 00000000..70a8477e Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_rgbd.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_saliency.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_saliency.a new file mode 100644 index 00000000..9b62f7d4 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_saliency.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_shape.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_shape.a new file mode 100644 index 00000000..1618f476 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_shape.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_stereo.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_stereo.a new file mode 100644 index 00000000..7234d3d5 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_stereo.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_stitching.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_stitching.a new file mode 100644 index 00000000..2a2d3d63 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_stitching.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_structured_light.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_structured_light.a new file mode 100644 index 00000000..2e1d1c8d Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_structured_light.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_superres.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_superres.a new file mode 100644 index 00000000..a6b630a8 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_superres.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_surface_matching.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_surface_matching.a new file mode 100644 index 00000000..21411627 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_surface_matching.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_text.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_text.a new file mode 100644 index 00000000..f96c3019 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_text.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_tracking.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_tracking.a new file mode 100644 index 00000000..da81926c Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_tracking.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_video.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_video.a new file mode 100644 index 00000000..6463d316 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_video.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_videoio.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_videoio.a new file mode 100644 index 00000000..ae7ae7fc Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_videoio.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_videostab.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_videostab.a new file mode 100644 index 00000000..177aef4c Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_videostab.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_xfeatures2d.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_xfeatures2d.a new file mode 100644 index 00000000..0af35037 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_xfeatures2d.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_ximgproc.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_ximgproc.a new file mode 100644 index 00000000..9dd61624 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_ximgproc.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_xobjdetect.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_xobjdetect.a new file mode 100644 index 00000000..76f5d7d4 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_xobjdetect.a differ diff --git a/OpenCV/src/main/staticlibs/x86_64/libopencv_xphoto.a b/OpenCV/src/main/staticlibs/x86_64/libopencv_xphoto.a new file mode 100644 index 00000000..e619fdb5 Binary files /dev/null and b/OpenCV/src/main/staticlibs/x86_64/libopencv_xphoto.a differ diff --git a/android-sdk-v5-uxsdk/build.gradle b/android-sdk-v5-uxsdk/build.gradle new file mode 100644 index 00000000..00ff7dbf --- /dev/null +++ b/android-sdk-v5-uxsdk/build.gradle @@ -0,0 +1,72 @@ +apply plugin: 'com.android.library' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' +apply plugin: 'kotlin-kapt' + +android { + compileSdkVersion 32 + + resourcePrefix "uxsdk_" + defaultConfig { + minSdkVersion 24 + targetSdkVersion 32 + versionCode 1 + versionName "1.0" + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_1_8 + targetCompatibility JavaVersion.VERSION_1_8 + } + + kotlinOptions{ + jvmTarget = JavaVersion.VERSION_1_8 + freeCompilerArgs += ["-Xjvm-default=all"] + } + buildFeatures { + viewBinding true + } +} + +dependencies { + implementation 'androidx.annotation:annotation:1.1.0' + implementation 'androidx.appcompat:appcompat:1.3.1' + implementation 'androidx.multidex:multidex:2.0.1' + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'androidx.recyclerview:recyclerview:1.1.0' + implementation 'com.squareup.okio:okio:1.17.2' + implementation 'com.squareup.wire:wire-runtime:2.2.0' + implementation 'androidx.constraintlayout:constraintlayout:2.1.4' + implementation 'androidx.lifecycle:lifecycle-common-java8:2.3.1' + implementation 'androidx.lifecycle:lifecycle-runtime:2.3.1' + implementation 'androidx.lifecycle:lifecycle-process:2.3.1' + implementation 'androidx.media:media:1.0.0' +// implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$KOTLIN_VERSION" + implementation "androidx.core:core-ktx:1.3.2" + implementation 'io.reactivex.rxjava3:rxandroid:3.0.0' + implementation 'io.reactivex.rxjava3:rxkotlin:3.0.0' + + implementation 'com.dji:wpmzsdk:1.0.1.7' + implementation 'io.reactivex.rxjava2:rxjava:2.2.4' + implementation 'com.airbnb.android:lottie:3.3.1'//RTK扫描页中使用,用于实现动画效果 + implementation 'androidx.cardview:cardview:1.0.0'//PopoverView中使用 + implementation "com.mikepenz:community-material-typeface:3.5.95.1-kotlin@aar" + implementation 'com.mikepenz:google-material-typeface:3.0.1.4.original-kotlin@aar' + implementation 'com.mikepenz:iconics-views:4.0.2@aar' + implementation 'com.mikepenz:iconics-core:4.0.2@aar' + implementation 'com.mikepenz:ionicons-typeface:2.0.1.5-kotlin@aar' + implementation 'com.google.android.material:material:1.0.0'//AvoidanceShortcutWidget使用 + + api 'org.maplibre.gl:android-sdk-turf:5.9.1' + api 'org.maplibre.gl:android-sdk:10.3.1' + + + api 'com.google.android.gms:play-services-places:16.0.0' + api 'com.google.android.gms:play-services-maps:16.0.0' + api 'com.google.android.gms:play-services-location:16.0.0' + api 'com.google.android.gms:play-services-base:16.0.0' + + compileOnly "com.dji:dji-sdk-v5-aircraft-provided:5.15.0" + compileOnly "com.dji:dji-sdk-v5-aircraft:5.15.0" + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/AndroidManifest.xml b/android-sdk-v5-uxsdk/src/main/AndroidManifest.xml new file mode 100644 index 00000000..e29fdebe --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/AndroidManifest.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/assets/htmls/air_sense_terms_of_use.html b/android-sdk-v5-uxsdk/src/main/assets/htmls/air_sense_terms_of_use.html new file mode 100644 index 00000000..92fcf4c7 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/assets/htmls/air_sense_terms_of_use.html @@ -0,0 +1,95 @@ + + + + + + + DJI AirSense Warnings + + + + + + + + + + +

DJI AirSense Warnings

+
+ + +
    + +
  • + DJI AirSense can detect nearby civil aircrafts and send out warnings only under certain circumstances;it will NOT control DJI aircraft to avoid other aircraft automatically. Make sure to fly with your aircraft within visual line of sight at all times, and always fly with caution. After receiving warnings, lower your aircraft to safe height. In addition, DJI AirSense has the following limitations: + +
  • + +
+
    +
  1. +
    +
    + DJI AirSense can only receive messages sent from civil aircraft equipped with an ADS-B out device under 1090ES (RTCA DO-260) or UAT (RTCA Do-282) standards. For civil aircraft without ADS-B outs or with malfunctioning ADS-B outs, DJI AirSense cannot receive related broadcasted messages or send out warnings. +
    +
    +
  2. +
  3. +
    +
    + When there are obstacles in between a civil aircraft and DJI aircraft, DJI AirSense will fail to receive ADS-B messages sent from civil aircraft or to send out warnings. +
    +
    +
  4. +
  5. +
    +
    + DJI AirSense may fail to receive ADS-B messages sent from civil aircraft or send out warnings due to ever changing circumstances and interference. It is highly recommended to fly with caution and stay aware of your surroundings during flight. +
    +
    +
  6. +
  7. +
    +
    + DJI AirSense cannot send out warnings when the DJI aircraft cannot accurately determine its location. +
    +
    +
  8. +
  9. +
    +
    + DJI AirSense cannot receive ADS-B messages sent from civil aircraft or send out warnings when it is disabled or misconfigured. +
    +
    +
  10. + +
+ + +
+ + + \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_0.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_0.png new file mode 100644 index 00000000..a79ee064 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_0.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_1.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_1.png new file mode 100644 index 00000000..53fd7eb5 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_1.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_10.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_10.png new file mode 100644 index 00000000..edda19dc Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_10.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_2.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_2.png new file mode 100644 index 00000000..7b0e27a0 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_2.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_3.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_3.png new file mode 100644 index 00000000..608bab93 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_3.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_4.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_4.png new file mode 100644 index 00000000..df8acc08 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_4.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_5.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_5.png new file mode 100644 index 00000000..ee645cfe Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_5.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_6.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_6.png new file mode 100644 index 00000000..22a923a2 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_6.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_7.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_7.png new file mode 100644 index 00000000..9f0395d7 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_7.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_8.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_8.png new file mode 100644 index 00000000..260b43cb Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_8.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_9.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_9.png new file mode 100644 index 00000000..9de0cce0 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_reset_images/img_9.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_0.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_0.png new file mode 100644 index 00000000..53fd7eb5 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_0.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_1.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_1.png new file mode 100644 index 00000000..7b0e27a0 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_1.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_2.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_2.png new file mode 100644 index 00000000..608bab93 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_2.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_3.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_3.png new file mode 100644 index 00000000..ee645cfe Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_3.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_4.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_4.png new file mode 100644 index 00000000..22a923a2 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_4.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_5.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_5.png new file mode 100644 index 00000000..e2f95d55 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_5.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_6.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_6.png new file mode 100644 index 00000000..9de0cce0 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_6.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_7.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_7.png new file mode 100644 index 00000000..260b43cb Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_7.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_8.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_8.png new file mode 100644 index 00000000..9f0395d7 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_8.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_9.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_9.png new file mode 100644 index 00000000..edda19dc Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step1_images/img_9.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/RTK.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/RTK.png new file mode 100644 index 00000000..46f3b716 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/RTK.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/circle-max.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/circle-max.png new file mode 100644 index 00000000..797f8835 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/circle-max.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/circle-mini.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/circle-mini.png new file mode 100644 index 00000000..ea78f6f5 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/circle-mini.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/drawing_board.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/drawing_board.png new file mode 100644 index 00000000..764f7bfc Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/drawing_board.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/ic-m.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/ic-m.png new file mode 100644 index 00000000..06facde2 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/ic-m.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/ic-pair frequency.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/ic-pair frequency.png new file mode 100644 index 00000000..b9d4d85c Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/ic-pair frequency.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/ic-power.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/ic-power.png new file mode 100644 index 00000000..aaad110a Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/ic-power.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/lightg.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/lightg.png new file mode 100644 index 00000000..bb6294f8 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/lightg.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/lighty.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/lighty.png new file mode 100644 index 00000000..968158c0 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/lighty.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/number-1.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/number-1.png new file mode 100644 index 00000000..f7f3d0e4 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/number-1.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/number-2.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/number-2.png new file mode 100644 index 00000000..e0eb556d Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/number-2.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/righthand.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/righthand.png new file mode 100644 index 00000000..b0bd9dae Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step2_images/righthand.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_0.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_0.png new file mode 100644 index 00000000..a34b4b6a Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_0.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_1.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_1.png new file mode 100644 index 00000000..d2906d95 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_1.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_2.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_2.png new file mode 100644 index 00000000..9bb1b135 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_2.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_3.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_3.png new file mode 100644 index 00000000..546b1755 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_3.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_4.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_4.png new file mode 100644 index 00000000..373d8195 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_4.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_5.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_5.png new file mode 100644 index 00000000..ee645cfe Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_5.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_6.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_6.png new file mode 100644 index 00000000..32ce62dc Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_6.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_7.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_7.png new file mode 100644 index 00000000..8e7db560 Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_7.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_8.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_8.png new file mode 100644 index 00000000..2da1829d Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_8.png differ diff --git a/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_9.png b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_9.png new file mode 100644 index 00000000..6acd4a8e Binary files /dev/null and b/android-sdk-v5-uxsdk/src/main/assets/rtk_guidance_step3_images/img_9.png differ diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/DescSpinnerCell.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/DescSpinnerCell.kt new file mode 100644 index 00000000..97888358 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/DescSpinnerCell.kt @@ -0,0 +1,200 @@ +package dji.v5.ux.accessory + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.* +import androidx.core.content.ContextCompat +import dji.v5.utils.common.LogUtils +import dji.v5.ux.R +import dji.v5.ux.core.extension.hide +import dji.v5.ux.core.extension.show +import java.util.ArrayList + +/** + * Description :RTK坐标系和RTK服务类型选择器 + * + * @author: Byte.Cai + * date : 2022/7/25 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ +private const val TAG = "DescSpinnerCell" + +open class DescSpinnerCell @kotlin.jvm.JvmOverloads constructor( + context: Context, + val attrs: AttributeSet? = null, + val defStyleAttr: Int = 0, +) : LinearLayout(context, attrs, defStyleAttr) { + private var mSpinner: Spinner? = null + private var mSummary: TextView? = null + private var mDesc: TextView? = null + private var mAdapter: ArrayAdapter? = null + + private var mSelectedPosition = 0 + private var mSelectedListener: OnItemSelectedListener? = null + + + init { + initView() + initListener() + initAttrs() + } + + private fun initView() { + LayoutInflater.from(context).inflate(R.layout.uxsdk_spinner_desc_layout, this, true) + mSpinner = findViewById(R.id.spinner) + mSummary = findViewById(R.id.summary) + mDesc = findViewById(R.id.desc) + + mAdapter = object : ArrayAdapter(context, R.layout.uxsdk_spinner_item_bord) { + override fun getDropDownView(position: Int, convertView: View?, parent: ViewGroup): View? { + var rootView = super.getDropDownView(position, convertView, parent) + rootView?.let { + val view = rootView as TextView + // 右边的下拉图标 + if (position != 0 && checkRightCompoundDrawable(view)) { + val rightDrawable = view.compoundDrawables[2].mutate() + rightDrawable.alpha = 0 + view.setCompoundDrawables(null, null, rightDrawable, null) + + } + if (mSelectedPosition == position) { + view.setTextColor(ContextCompat.getColor(context, R.color.uxsdk_white)) + } else { + view.setTextColor(ContextCompat.getColor(context, R.color.uxsdk_white_75_percent)) + } + } + return rootView + + + } + + + private fun checkRightCompoundDrawable(view: TextView?): Boolean { + return view?.compoundDrawables != null && view.compoundDrawables.size == 4 && view.compoundDrawables[2] != null + } + } + + mAdapter?.setDropDownViewResource(R.layout.uxsdk_spinner_item_drop) + + + } + + + private fun initListener() { + // 这里需要设置不保存状态。否则在view被销毁重新加载并恢复时,由于spinnerID相同,导致value被复用 + mSpinner?.isSaveEnabled = false + mSpinner?.adapter = mAdapter + mSpinner?.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + LogUtils.i(TAG, "onItemSelected , mSelectedPosition=$mSelectedPosition,position=$position") + + if (mSelectedPosition != position) { + mSpinner?.setSelection(position, true) + mSelectedListener?.onItemSelected(position) + mSelectedPosition = position + } + + } + + + override fun onNothingSelected(parent: AdapterView<*>?) { + LogUtils.e(TAG, "onNothingSelected") + //不需要实现 + } + + } + + } + + fun initAttrs() { + val ta = context.theme.obtainStyledAttributes(attrs, R.styleable.DescSpinnerCell, defStyleAttr, 0) + if (ta.hasValue(R.styleable.DescSpinnerCell_uxsdk_summary)) { + mSummary?.show() + mSummary?.text = ta.getString(R.styleable.DescSpinnerCell_uxsdk_summary) + } else { + mSummary?.hide() + } + + if (ta.hasValue(R.styleable.DescSpinnerCell_uxsdk_desc)) { + mDesc?.show() + mDesc?.text = ta.getString(R.styleable.DescSpinnerCell_uxsdk_desc) + } else { + mDesc?.hide() + } + + if (ta.hasValue(R.styleable.DescSpinnerCell_uxsdk_entries)) { + var entries = ta.getTextArray(R.styleable.DescSpinnerCell_uxsdk_entries) + if (entries != null && entries.isNotEmpty()) { + val list: MutableList = ArrayList(entries.size) + for (s in entries) { + list.add(s.toString()) + } + setEntries(list) + } + } + } + + + interface OnItemSelectedListener { + fun onItemSelected(position: Int) + } + + fun addOnItemSelectedListener(listener: OnItemSelectedListener?) { + mSelectedListener = listener + } + + + open fun setSummaryText(summaryText: String) { + if (mSummary?.text?.equals(summaryText) != true) { + mSummary?.show() + mSummary?.text = summaryText + } + } + + open fun setSummaryText(summaryTextId: Int) { + mSummary?.show() + mSummary?.setText(summaryTextId) + + } + + open fun setSDescText(descText: String) { + if (mDesc?.text?.equals(descText) != true) { + mDesc?.show() + mDesc?.text = descText + } + + } + + open fun getDescText():TextView?{ + return mDesc + } + + open fun getSelectPosition() :Int{ + return mSelectedPosition; + } + + open fun setEntries(entries: List) { + mAdapter?.clear() + mAdapter?.addAll(entries) + + } + + fun select(position: Int) { + if (position >= 0 && position < mAdapter?.count ?: -1) { + mSpinner?.setSelection(position, true) + mSelectedPosition = position + } + invalidate() + } + + + override fun setEnabled(enable: Boolean) { + super.setEnabled(enable) + mSpinner?.isEnabled = enable + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKEnabledWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKEnabledWidget.kt new file mode 100644 index 00000000..5ae08609 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKEnabledWidget.kt @@ -0,0 +1,369 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.accessory + +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.drawable.Drawable +import android.os.Build +import android.util.AttributeSet +import android.widget.CompoundButton +import android.widget.Switch +import android.widget.TextView +import androidx.annotation.* +import androidx.core.content.res.use +import dji.v5.utils.common.DisplayUtil +import dji.v5.utils.common.LogUtils +import dji.v5.ux.R +import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.disposables.Disposable +import io.reactivex.rxjava3.processors.PublishProcessor +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.util.UxErrorHandle + +private const val TAG = "RTKEnabledWidget" + +/** + * This widget displays a switch that will enable or disable RTK. + */ +open class RTKEnabledWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ConstraintLayoutWidget(context, attrs, defStyleAttr), CompoundButton.OnCheckedChangeListener { + + //region Fields + private val rtkTitleTextView: TextView = findViewById(R.id.textview_rtk_title) + private val rtkEnabledSwitch: Switch = findViewById(R.id.switch_rtk_enabled) + private val rtkEnabledDescriptionTextView: TextView = findViewById(R.id.textview_rtk_enabled_description) + private val uiUpdateStateProcessor: PublishProcessor = PublishProcessor.create() + + private val widgetModel by lazy { + RTKEnabledWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()) + } + + /** + * Background of the title text + */ + var titleTextBackground: Drawable? + get() = rtkTitleTextView.background + set(value) { + rtkTitleTextView.background = value + } + + /** + * Size of the title text + */ + var titleTextSize: Float + @Dimension + get() = rtkTitleTextView.textSize + set(@Dimension textSize) { + rtkTitleTextView.textSize = textSize + } + + /** + * Color of the title text + */ + var titleTextColor: Int + @ColorInt + get() = rtkTitleTextView.textColor + set(@ColorInt textColor) { + rtkTitleTextView.textColor = textColor + } + + /** + * The drawable resource for the RTK enabled switch's thumb + */ + var rtkEnabledSwitchThumbIcon: Drawable + @JvmName("getRTKEnabledSwitchThumbIcon") + get() = rtkEnabledSwitch.thumbDrawable + @JvmName("setRTKEnabledSwitchThumbIcon") + set(value) { + rtkEnabledSwitch.thumbDrawable = value + } + + /** + * The drawable resource for the RTK enabled switch's track + */ + var rtkEnabledSwitchTrackIcon: Drawable + @JvmName("getRTKEnabledSwitchTrackIcon") + get() = rtkEnabledSwitch.trackDrawable + @JvmName("setRTKEnabledSwitchTrackIcon") + set(value) { + rtkEnabledSwitch.trackDrawable = value + } + + /** + * The text color state list for the RTK enabled switch's track + */ + var rtkEnabledSwitchTrackColor: ColorStateList? + @RequiresApi(Build.VERSION_CODES.M) + @JvmName("getRTKEnabledSwitchTrackColor") + get() = rtkEnabledSwitch.trackTintList + @RequiresApi(Build.VERSION_CODES.M) + @JvmName("setRTKEnabledSwitchTrackColor") + set(value) { + rtkEnabledSwitch.trackTintList = value + } + + /** + * Background of the description text + */ + var descriptionTextBackground: Drawable? + get() = rtkEnabledDescriptionTextView.background + set(value) { + rtkEnabledDescriptionTextView.background = value + } + + /** + * Size of the description text + */ + var descriptionTextSize: Float + @Dimension + get() = rtkEnabledDescriptionTextView.textSize + set(@Dimension textSize) { + rtkEnabledDescriptionTextView.textSize = textSize + } + + /** + * Color of the description text + */ + var descriptionTextColor: Int + @ColorInt + get() = rtkEnabledDescriptionTextView.textColor + set(@ColorInt textColor) { + rtkEnabledDescriptionTextView.textColor = textColor + } + //endregion + + //region Constructor + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + inflate(context, R.layout.uxsdk_widget_rtk_enabled, this) + } + + init { + rtkEnabledSwitch.setOnCheckedChangeListener(this) + attrs?.let { initAttributes(context, it) } + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) { + addDisposable(widgetModel.canEnableRTK.firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe({ canEnableRTK: Boolean -> + if (!canEnableRTK) { + setRTKSwitch(!isChecked) + showLongToast(R.string.uxsdk_rtk_enabled_motors_running) + } else { + setRTKEnabled(isChecked) + } + }, UxErrorHandle.logErrorConsumer(TAG, "canEnableRTK: "))) + uiUpdateStateProcessor.onNext(UIState.SwitchChanged(isChecked)) + } + + override fun reactToModelChanges() { + addReaction(widgetModel.rtkEnabled + .observeOn(SchedulerProvider.ui()) + .subscribe { updateUIForRTKEnabled(it) }) + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ModelState.ProductConnected(it)) }) + } + //endregion + + //region Reaction helpers + private fun updateUIForRTKEnabled(rtkEnabled: Boolean) { + setRTKSwitch(rtkEnabled) + widgetStateDataProcessor.onNext(ModelState.RTKEnabledUpdated(rtkEnabled)) + } + + private fun setRTKEnabled(enabled: Boolean) { + addDisposable(widgetModel.rtkEnabled + .firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe({ rtkEnabled: Boolean -> + if (rtkEnabled != enabled) { + addDisposable(toggleRTK(enabled)) + } + }, UxErrorHandle.logErrorConsumer(TAG, "rtkEnabled: "))) + } + + private fun toggleRTK(enabled: Boolean): Disposable { + return widgetModel.setRTKEnabled(enabled) + .observeOn(SchedulerProvider.ui()) + .subscribe({}) { throwable: Throwable -> + setRTKSwitch(!enabled) + LogUtils.e(TAG, "setRTKEnabled: " + throwable.localizedMessage) + } + } + + private fun setRTKSwitch(isChecked: Boolean) { + rtkEnabledSwitch.setOnCheckedChangeListener(null) + rtkEnabledSwitch.isChecked = isChecked + rtkEnabledSwitch.setOnCheckedChangeListener(this) + } + //endregion + + //region Customization + override fun getIdealDimensionRatioString(): String { + return getString(R.string.uxsdk_widget_rtk_enabled_ratio) + } + + /** + * Set text appearance of the title text + * + * @param textAppearanceResId Style resource for text appearance + */ + fun setTitleTextAppearance(@StyleRes textAppearanceResId: Int) { + rtkTitleTextView.setTextAppearance(context, textAppearanceResId) + } + + /** + * Set the resource ID for the RTK enabled switch's thumb + * + * @param resourceId Integer ID of the drawable resource + */ + fun setRTKEnabledSwitchThumbIcon(@DrawableRes resourceId: Int) { + rtkEnabledSwitchThumbIcon = getDrawable(resourceId) + } + + /** + * Set the resource ID for the RTK enabled switch's track + * + * @param resourceId Integer ID of the drawable resource + */ + fun setRTKEnabledSwitchTrackIcon(@DrawableRes resourceId: Int) { + rtkEnabledSwitchTrackIcon = getDrawable(resourceId) + } + + /** + * Set text appearance of the description text + * + * @param textAppearanceResId Style resource for text appearance + */ + fun setDescriptionTextAppearance(@StyleRes textAppearanceResId: Int) { + rtkEnabledDescriptionTextView.setTextAppearance(context, textAppearanceResId) + } + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.RTKEnabledWidget).use { typedArray -> + typedArray.getResourceIdAndUse(R.styleable.RTKEnabledWidget_uxsdk_titleTextAppearance) { + setTitleTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.RTKEnabledWidget_uxsdk_titleTextSize) { + titleTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.RTKEnabledWidget_uxsdk_titleTextColor) { + titleTextColor = it + } + typedArray.getDrawableAndUse(R.styleable.RTKEnabledWidget_uxsdk_titleTextBackground) { + titleTextBackground = it + } + typedArray.getDrawableAndUse(R.styleable.RTKEnabledWidget_uxsdk_rtkEnabledSwitchThumbIcon) { + rtkEnabledSwitchThumbIcon = it + } + typedArray.getDrawableAndUse(R.styleable.RTKEnabledWidget_uxsdk_rtkEnabledSwitchTrackIcon) { + rtkEnabledSwitchTrackIcon = it + } + typedArray.getResourceIdAndUse(R.styleable.RTKEnabledWidget_uxsdk_descriptionTextAppearance) { + setDescriptionTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.RTKEnabledWidget_uxsdk_descriptionTextSize) { + descriptionTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.RTKEnabledWidget_uxsdk_descriptionTextColor) { + descriptionTextColor = it + } + typedArray.getDrawableAndUse(R.styleable.RTKEnabledWidget_uxsdk_descriptionTextBackground) { + descriptionTextBackground = it + } + } + } + //endregion + + //region Hooks + /** + * Get the [UIState] updates + */ + fun getUIStateUpdates(): Flowable { + return uiUpdateStateProcessor.onBackpressureBuffer() + } + + /** + * Widget UI update State + */ + sealed class UIState { + /** + * RTK enabled switch check changed update + */ + data class SwitchChanged(val isChecked: Boolean) : UIState() + } + + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines the widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * RTK enabled update + */ + data class RTKEnabledUpdated(val isRTKEnabled: Boolean) : ModelState() + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKEnabledWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKEnabledWidgetModel.kt new file mode 100644 index 00000000..6c0ef73e --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKEnabledWidgetModel.kt @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.accessory + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.key.DJIKey +import dji.sdk.keyvalue.key.RtkMobileStationKey +import dji.sdk.keyvalue.value.rtkmobilestation.RTKHomePointDataSource +import dji.sdk.keyvalue.value.rtkmobilestation.RTKHomePointInfo +import dji.sdk.keyvalue.value.rtkmobilestation.RTKTakeoffAltitudeInfo +import dji.sdk.keyvalue.key.KeyTools +import dji.v5.manager.KeyManager +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Completable +import io.reactivex.rxjava3.core.Flowable + +/** + * Widget Model for the [RTKEnabledWidget] used to define + * the underlying logic and communication + */ +private const val TAG = "RTKEnabledWidgetModel" + +class RTKEnabledWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + + //region Fields + private val isRTKEnabledKey: DJIKey = KeyTools.createKey( + RtkMobileStationKey.KeyRTKEnable) + private val isRTKEnabledProcessor: DataProcessor = DataProcessor.create(false) + private val isMotorOnProcessor: DataProcessor = DataProcessor.create(false) + private val homePointDataSourceProcessor: DataProcessor = DataProcessor.create(RTKHomePointInfo()) + private val isRTKTakeoffHeightSetProcessor: DataProcessor = DataProcessor.create(RTKTakeoffAltitudeInfo()) + private val canEnableRTKProcessor: DataProcessor = DataProcessor.create(true) + //endregion + + //region Data + /** + * Get whether RTK is enabled. + */ + val rtkEnabled: Flowable + @JvmName("getRTKEnabled") + get() = isRTKEnabledProcessor.toFlowable() + + /** + * Get whether RTK can be enabled. + */ + val canEnableRTK: Flowable + get() = canEnableRTKProcessor.toFlowable() + + //endregion + + //region Lifecycle + override fun inSetup() { + bindDataProcessor(isRTKEnabledKey, isRTKEnabledProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAreMotorsOn), isMotorOnProcessor) + bindDataProcessor( + KeyTools.createKey( + RtkMobileStationKey.KeyRTKHomePointInfo), homePointDataSourceProcessor) + bindDataProcessor( + KeyTools.createKey( + RtkMobileStationKey.KeyRTKTakeoffAltitudeInfo), isRTKTakeoffHeightSetProcessor) + } + + override fun inCleanup() { + KeyManager.getInstance().cancelListen(this) + } + + /** + * RTK能否开启,这里捆绑了几个逻辑: + * 1、只有在电机关闭时才可以设置RTK开启/关闭状态; + * 2、如果电机已开启,则需要飞行高度已设置+返航点的类型设置为RTK,这时才可以开启/关闭RTK + */ + override fun updateStates() { + canEnableRTKProcessor.onNext( + !isMotorOnProcessor.value || (isRTKTakeoffHeightSetProcessor.value.valid + && homePointDataSourceProcessor.value.homePointDataSource == RTKHomePointDataSource.RTK) + ) + } + //endregion + + //region User interaction + fun setRTKEnabled(enabled: Boolean): Completable { + return djiSdkModel.setValue(isRTKEnabledKey, enabled) + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKKeepStatusWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKKeepStatusWidget.kt new file mode 100644 index 00000000..5353fff8 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKKeepStatusWidget.kt @@ -0,0 +1,106 @@ +package dji.v5.ux.accessory + +import android.content.Context +import android.util.AttributeSet +import android.widget.CompoundButton +import android.widget.Switch +import dji.v5.manager.aircraft.rtk.RTKCenter +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.util.UxErrorHandle +import io.reactivex.rxjava3.core.CompletableObserver +import io.reactivex.rxjava3.disposables.Disposable + +/** + * Description : This widget displays a switch that will enable or disable RTK Keep Status. + + * + * @author: Byte.Cai + * date : 2022/7/11 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ +private const val TAG = "RTKKeepStatusWidget" + +class RTKKeepStatusWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, +) : ConstraintLayoutWidget(context, attrs, defStyleAttr), CompoundButton.OnCheckedChangeListener { + + + private val rtkKeepStatusSwitch: Switch = findViewById(R.id.rtk_keep_status_switch) + + private val widgetModel by lazy { + RTKKeepStatusWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + RTKCenter.getInstance() + ) + } + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + inflate(context, R.layout.uxsdk_widget_keep_status_enable_layout, this) + } + + init { + rtkKeepStatusSwitch.setOnCheckedChangeListener(this) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.rtkKeepStatusEnable + .observeOn(SchedulerProvider.ui()) + .subscribe { + setRTKSwitch(it) + } + ) + } + + private fun setRTKSwitch(isChecked: Boolean) { + rtkKeepStatusSwitch.setOnCheckedChangeListener(null) + rtkKeepStatusSwitch.isChecked = isChecked + rtkKeepStatusSwitch.setOnCheckedChangeListener(this) + } + + override fun getIdealDimensionRatioString(): String { + return getString(R.string.uxsdk_widget_rtk_keep_status_ratio) + } + + override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) { + widgetModel.setRTKKeepStatusEnable(isChecked) + .observeOn(SchedulerProvider.ui()) + .subscribe(object : CompletableObserver { + override fun onSubscribe(d: Disposable) { + //Do nothing + } + + override fun onComplete() { + //Do nothing + } + + override fun onError(e: Throwable) { + setRTKSwitch(!isChecked) + UxErrorHandle.logErrorConsumer(TAG, "canEnableRTK: ") + } + }) + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKKeepStatusWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKKeepStatusWidgetModel.kt new file mode 100644 index 00000000..836b42cd --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKKeepStatusWidgetModel.kt @@ -0,0 +1,67 @@ +package dji.v5.ux.accessory + +import dji.v5.common.callback.CommonCallbacks +import dji.v5.common.error.IDJIError +import dji.v5.common.error.RxError +import dji.v5.manager.aircraft.rtk.RTKSystemState +import dji.v5.manager.aircraft.rtk.RTKSystemStateListener +import dji.v5.manager.interfaces.IRTKCenter +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Completable +import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.schedulers.Schedulers + +/** + * Description :Widget Model for the [RTKKeepStatusWidget] used to define + * the underlying logic and communication + * + * @author: Byte.Cai + * date : 2022/7/11 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ +class RTKKeepStatusWidgetModel( + djiSdkModel: DJISDKModel, + uxKeyManager: ObservableInMemoryKeyedStore, + private val rtkCenter: IRTKCenter, +) : WidgetModel(djiSdkModel, uxKeyManager), RTKSystemStateListener { + private val isRTKKeepStatusEnabledProcessor: DataProcessor = DataProcessor.create(false) + + override fun inSetup() { + rtkCenter.addRTKSystemStateListener(this) + + } + + override fun inCleanup() { + rtkCenter.removeRTKSystemStateListener(this) + } + + val rtkKeepStatusEnable: Flowable + get() = isRTKKeepStatusEnabledProcessor.toFlowable() + + fun setRTKKeepStatusEnable(enabled: Boolean): Completable { + return Completable.create { + rtkCenter.setRTKMaintainAccuracyEnabled(enabled, object : CommonCallbacks.CompletionCallback { + override fun onSuccess() { + it.onComplete() + } + + override fun onFailure(error: IDJIError) { + it.onError(RxError(error)) + } + }) + + }.subscribeOn(Schedulers.computation()) + } + + override fun onUpdate(rtkSystemState: RTKSystemState?) { + rtkSystemState?.let { + isRTKKeepStatusEnabledProcessor.onNext(it.rtkMaintainAccuracyEnabled) + } + + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKSatelliteStatusWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKSatelliteStatusWidget.kt new file mode 100644 index 00000000..4ca502b0 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKSatelliteStatusWidget.kt @@ -0,0 +1,1061 @@ +package dji.v5.ux.accessory + +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.View +import android.widget.ImageView +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.annotation.Dimension +import androidx.annotation.StyleRes +import androidx.core.content.res.use +import dji.sdk.keyvalue.utils.ProductUtil +import dji.sdk.keyvalue.value.rtkbasestation.RTKReferenceStationSource +import dji.sdk.keyvalue.value.rtkbasestation.RTKServiceState +import dji.sdk.keyvalue.value.rtkmobilestation.GNSSType +import dji.sdk.keyvalue.value.rtkmobilestation.RTKPositioningSolution +import dji.v5.manager.aircraft.rtk.RTKCenter +import dji.v5.manager.aircraft.rtk.RTKLocationInfo +import dji.v5.manager.aircraft.rtk.RTKSystemState +import dji.v5.utils.common.DisplayUtil +import dji.v5.utils.common.LogUtils +import dji.v5.ux.R + +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.GlobalPreferencesManager +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.util.UnitConversionUtil +import java.util.* + +/** + * Description :This widget shows all the information related to RTK. This includes coordinates and altitude + * of the aircraft and base station, course angle, GLONASS, Beidou, Galileo, and GPS satellite + * counts for both antennas and the base station, and overall state of the RTK system. + * + * @author: Byte.Cai + * date : 2022/5/23 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ +private const val TAG = "RTKSatelliteStatusWidget" + +open class RTKSatelliteStatusWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, +) : ConstraintLayoutWidget(context, attrs, defStyleAttr) { + //region Fields + private val rtkStatusTitleTextView: TextView = findViewById(R.id.textview_rtk_status_title) + private val rtkStatusTextView: TextView = findViewById(R.id.textview_rtk_status) + private val baseStationConnectImageView: ImageView = findViewById(R.id.imageview_connect_arrow) + private val tableBackgroundImageView: ImageView = findViewById(R.id.imageview_table_background) + private val antenna1TitleTextView: TextView = findViewById(R.id.textview_ant1_title) + private val antenna2TitleTextView: TextView = findViewById(R.id.textview_ant2_title) + private val gpsTitleTextView: TextView = findViewById(R.id.textview_gps_title) + private val gpsAntenna1TextView: TextView = findViewById(R.id.textview_gps_antenna_1) + private val gpsAntenna2TextView: TextView = findViewById(R.id.textview_gps_antenna_2) + private val gpsBaseStationTextView: TextView = findViewById(R.id.textview_gps_base_station) + private val beiDouTitleTextView: TextView = findViewById(R.id.textview_beidou_title) + private val beiDouAntenna1TextView: TextView = findViewById(R.id.textview_beidou_antenna_1) + private val beiDouAntenna2TextView: TextView = findViewById(R.id.textview_beidou_antenna_2) + private val beiDouBaseStationTextView: TextView = findViewById(R.id.textview_beidou_base_station) + private val glonassTitleTextView: TextView = findViewById(R.id.textview_glonass_title) + private val glonassAntenna1TextView: TextView = findViewById(R.id.textview_glonass_antenna_1) + private val glonassAntenna2TextView: TextView = findViewById(R.id.textview_glonass_antenna_2) + private val glonassBaseStationTextView: TextView = findViewById(R.id.textview_glonass_base_station) + private val galileoTitleTextView: TextView = findViewById(R.id.textview_galileo_title) + private val galileoAntenna1TextView: TextView = findViewById(R.id.textview_galileo_antenna_1) + private val galileoAntenna2TextView: TextView = findViewById(R.id.textview_galileo_antenna_2) + private val galileoBaseStationTextView: TextView = findViewById(R.id.textview_galileo_base_station) + private val latitudeTitleTextView: TextView = findViewById(R.id.textview_latitude_title) + private val longitudeTitleTextView: TextView = findViewById(R.id.textview_longitude_title) + private val altitudeTitleTextView: TextView = findViewById(R.id.textview_altitude_title) + private val aircraftCoordinatesTitleTextView: TextView = findViewById(R.id.textview_aircraft_coordinates_title) + private val aircraftLatitudeTextView: TextView = findViewById(R.id.textview_aircraft_latitude) + private val aircraftLongitudeTextView: TextView = findViewById(R.id.textview_aircraft_longitude) + private val aircraftAltitudeTextView: TextView = findViewById(R.id.textview_aircraft_altitude) + private val baseStationCoordinatesTitleTextView: TextView = + findViewById(R.id.textview_base_station_coordinates_title) + private val baseStationLatitudeTextView: TextView = findViewById(R.id.textview_base_station_latitude) + private val baseStationLongitudeTextView: TextView = findViewById(R.id.textview_base_station_longitude) + private val baseStationAltitudeTextView: TextView = findViewById(R.id.textview_base_station_altitude) + private val courseAngleTitleTextView: TextView = findViewById(R.id.textview_course_angle_title) + private val courseAngleTextView: TextView = findViewById(R.id.textview_course_angle_value) + private val orientationTitleTextView: TextView = findViewById(R.id.textview_orientation_title) + private val orientationTextView: TextView = findViewById(R.id.textview_orientation) + private val positioningTitleTextView: TextView = findViewById(R.id.textview_positioning_title) + private val positioningTextView: TextView = findViewById(R.id.textview_positioning) + private val standardDeviationTitleTextView: TextView = findViewById(R.id.textview_standard_deviation_title) + private val standardDeviationTextView: TextView = findViewById(R.id.textview_standard_deviation) + private val rtkAircraftSeparator: View = findViewById(R.id.rtk_aircraft_separator) + private val rtkBaseStationSeparator: View = findViewById(R.id.rtk_base_station_separator) + private val rtkOrientationPositioningSeparator: View = findViewById(R.id.rtk_orientation_positioning_separator) + private val rtkLocationSeparator: View = findViewById(R.id.rtk_location_separator) + private val rtkSatelliteCountSeparator: View = findViewById(R.id.rtk_satellite_count_separator) + private var positioningSolution :RTKPositioningSolution ?= null + private val connectionStateTextColorMap: MutableMap = + mutableMapOf( + RTKSatelliteStatusWidgetModel.RTKBaseStationState.CONNECTED_IN_USE to getColor(R.color.uxsdk_rtk_status_connected_in_use), + RTKSatelliteStatusWidgetModel.RTKBaseStationState.CONNECTED_NOT_IN_USE to getColor(R.color.uxsdk_rtk_status_connected_not_in_use), + RTKSatelliteStatusWidgetModel.RTKBaseStationState.DISCONNECTED to getColor(R.color.uxsdk_rtk_status_disconnected) + ) + + private val widgetModel by lazy { + RTKSatelliteStatusWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + GlobalPreferencesManager.getInstance(), + RTKCenter.getInstance() + ) + } + + + /** + * The text size of the RTK connection state title. + */ + var rtkConnectionStatusTitleTextSize: Float + @JvmName("getRTKConnectionStatusTitleTextSize") + @Dimension + get() = rtkStatusTitleTextView.textSize + @JvmName("setRTKConnectionStatusTitleTextSize") + set(@Dimension textSize) { + rtkStatusTitleTextView.textSize = textSize + } + + /** + * The text color of the RTK connection state title. + */ + var rtkConnectionStatusTitleTextColor: Int + @JvmName("getRTKConnectionStatusTitleTextColor") + @ColorInt + get() = rtkStatusTitleTextView.currentTextColor + @JvmName("setRTKConnectionStatusTitleTextColor") + set(@ColorInt color) { + rtkStatusTitleTextView.textColor = color + } + + /** + * The background of the RTK connection state title. + */ + var rtkConnectionStatusTitleTextBackground: Drawable? + @JvmName("getRTKConnectionStatusTitleTextBackground") + get() = rtkStatusTitleTextView.background + @JvmName("setRTKConnectionStatusTitleTextBackground") + set(drawable) { + rtkStatusTitleTextView.background = drawable + } + + /** + * The text size of the RTK connection state. + */ + var rtkConnectionStatusTextSize: Float + @JvmName("getRTKConnectionStatusTextSize") + @Dimension + get() = rtkStatusTextView.textSize + @JvmName("setRTKConnectionStatusTextSize") + set(@Dimension textSize) { + rtkStatusTextView.textSize = textSize + } + + /** + * The background of the RTK connection state. + */ + var rtkConnectionStatusTextBackground: Drawable? + @JvmName("getRTKConnectionStatusTextBackground") + get() = rtkStatusTextView.background + @JvmName("setRTKConnectionStatusTextBackground") + set(drawable) { + rtkStatusTextView.background = drawable + } + + /** + * The text color state list of the RTK labels text views + */ + var rtkLabelsTextColors: ColorStateList? + @JvmName("getRTKLabelsTextColors") + get() = antenna1TitleTextView.textColors + @JvmName("setRTKLabelsTextColors") + set(colorStateList) { + antenna1TitleTextView.setTextColor(colorStateList) + antenna2TitleTextView.setTextColor(colorStateList) + gpsTitleTextView.setTextColor(colorStateList) + beiDouTitleTextView.setTextColor(colorStateList) + glonassTitleTextView.setTextColor(colorStateList) + galileoTitleTextView.setTextColor(colorStateList) + latitudeTitleTextView.setTextColor(colorStateList) + longitudeTitleTextView.setTextColor(colorStateList) + altitudeTitleTextView.setTextColor(colorStateList) + aircraftCoordinatesTitleTextView.setTextColor(colorStateList) + baseStationCoordinatesTitleTextView.setTextColor(colorStateList) + courseAngleTitleTextView.setTextColor(colorStateList) + orientationTitleTextView.setTextColor(colorStateList) + positioningTitleTextView.setTextColor(colorStateList) + standardDeviationTitleTextView.setTextColor(colorStateList) + } + + /** + * The text color of the RTK labels text views + */ + var rtkLabelsTextColor: Int + @JvmName("getRTKLabelsTextColor") + @ColorInt + get() = antenna1TitleTextView.currentTextColor + @JvmName("setRTKLabelsTextColor") + set(@ColorInt color) { + antenna1TitleTextView.textColor = color + antenna2TitleTextView.textColor = color + gpsTitleTextView.textColor = color + beiDouTitleTextView.textColor = color + glonassTitleTextView.textColor = color + galileoTitleTextView.textColor = color + latitudeTitleTextView.textColor = color + longitudeTitleTextView.textColor = color + altitudeTitleTextView.textColor = color + aircraftCoordinatesTitleTextView.textColor = color + baseStationCoordinatesTitleTextView.textColor = color + courseAngleTitleTextView.textColor = color + orientationTitleTextView.textColor = color + positioningTitleTextView.textColor = color + standardDeviationTitleTextView.textColor = color + } + + /** + * The text size of the RTK labels text views + */ + var rtkLabelsTextSize: Float + @JvmName("getRTKLabelsTextSize") + @Dimension + get() = antenna1TitleTextView.textSize + @JvmName("setRTKLabelsTextSize") + set(@Dimension textSize) { + antenna1TitleTextView.textSize = textSize + antenna2TitleTextView.textSize = textSize + gpsTitleTextView.textSize = textSize + beiDouTitleTextView.textSize = textSize + glonassTitleTextView.textSize = textSize + galileoTitleTextView.textSize = textSize + latitudeTitleTextView.textSize = textSize + longitudeTitleTextView.textSize = textSize + altitudeTitleTextView.textSize = textSize + aircraftCoordinatesTitleTextView.textSize = textSize + baseStationCoordinatesTitleTextView.textSize = textSize + courseAngleTitleTextView.textSize = textSize + orientationTitleTextView.textSize = textSize + positioningTitleTextView.textSize = textSize + standardDeviationTitleTextView.textSize = textSize + } + + /** + * The background for the RTK labels text views + */ + var rtkLabelsTextBackground: Drawable? + @JvmName("getRTKLabelsTextBackground") + get() = antenna1TitleTextView.background + @JvmName("setRTKLabelsTextBackground") + set(drawable) { + antenna1TitleTextView.background = drawable + antenna2TitleTextView.background = drawable + gpsTitleTextView.background = drawable + beiDouTitleTextView.background = drawable + glonassTitleTextView.background = drawable + galileoTitleTextView.background = drawable + latitudeTitleTextView.background = drawable + longitudeTitleTextView.background = drawable + altitudeTitleTextView.background = drawable + aircraftCoordinatesTitleTextView.background = drawable + baseStationCoordinatesTitleTextView.background = drawable + courseAngleTitleTextView.background = drawable + orientationTitleTextView.background = drawable + positioningTitleTextView.background = drawable + standardDeviationTitleTextView.background = drawable + + } + + /** + * The text color state list of the RTK values text views + */ + var rtkValuesTextColors: ColorStateList? + @JvmName("getRTKValuesTextColors") + get() = gpsAntenna1TextView.textColors + @JvmName("setRTKValuesTextColors") + set(colorStateList) { + gpsAntenna1TextView.setTextColor(colorStateList) + gpsAntenna2TextView.setTextColor(colorStateList) + gpsBaseStationTextView.setTextColor(colorStateList) + beiDouAntenna1TextView.setTextColor(colorStateList) + beiDouAntenna2TextView.setTextColor(colorStateList) + beiDouBaseStationTextView.setTextColor(colorStateList) + glonassAntenna1TextView.setTextColor(colorStateList) + glonassAntenna2TextView.setTextColor(colorStateList) + glonassBaseStationTextView.setTextColor(colorStateList) + galileoAntenna1TextView.setTextColor(colorStateList) + galileoAntenna2TextView.setTextColor(colorStateList) + galileoBaseStationTextView.setTextColor(colorStateList) + aircraftLatitudeTextView.setTextColor(colorStateList) + aircraftLongitudeTextView.setTextColor(colorStateList) + aircraftAltitudeTextView.setTextColor(colorStateList) + baseStationLatitudeTextView.setTextColor(colorStateList) + baseStationLongitudeTextView.setTextColor(colorStateList) + baseStationAltitudeTextView.setTextColor(colorStateList) + courseAngleTextView.setTextColor(colorStateList) + orientationTextView.setTextColor(colorStateList) + positioningTextView.setTextColor(colorStateList) + standardDeviationTextView.setTextColor(colorStateList) + } + + /** + * The text color of the RTK values text views + */ + var rtkValuesTextColor: Int + @JvmName("getRTKValuesTextColor") + @ColorInt + get() = gpsAntenna1TextView.currentTextColor + @JvmName("setRTKValuesTextColor") + set(@ColorInt color) { + gpsAntenna1TextView.textColor = color + gpsAntenna2TextView.textColor = color + gpsBaseStationTextView.textColor = color + beiDouAntenna1TextView.textColor = color + beiDouAntenna2TextView.textColor = color + beiDouBaseStationTextView.textColor = color + glonassAntenna1TextView.textColor = color + glonassAntenna2TextView.textColor = color + glonassBaseStationTextView.textColor = color + galileoAntenna1TextView.textColor = color + galileoAntenna2TextView.textColor = color + galileoBaseStationTextView.textColor = color + aircraftLatitudeTextView.textColor = color + aircraftLongitudeTextView.textColor = color + aircraftAltitudeTextView.textColor = color + baseStationLatitudeTextView.textColor = color + baseStationLongitudeTextView.textColor = color + baseStationAltitudeTextView.textColor = color + courseAngleTextView.textColor = color + orientationTextView.textColor = color + positioningTextView.textColor = color + standardDeviationTextView.textColor = color + } + + /** + * The text size of the RTK values text views + */ + var rtkValuesTextSize: Float + @JvmName("getRTKValuesTextSize") + @Dimension + get() = gpsAntenna1TextView.textSize + @JvmName("setRTKValuesTextSize") + set(@Dimension textSize) { + gpsAntenna1TextView.textSize = textSize + gpsAntenna2TextView.textSize = textSize + gpsBaseStationTextView.textSize = textSize + beiDouAntenna1TextView.textSize = textSize + beiDouAntenna2TextView.textSize = textSize + beiDouBaseStationTextView.textSize = textSize + glonassAntenna1TextView.textSize = textSize + glonassAntenna2TextView.textSize = textSize + glonassBaseStationTextView.textSize = textSize + galileoAntenna1TextView.textSize = textSize + galileoAntenna2TextView.textSize = textSize + galileoBaseStationTextView.textSize = textSize + aircraftLatitudeTextView.textSize = textSize + aircraftLongitudeTextView.textSize = textSize + aircraftAltitudeTextView.textSize = textSize + baseStationLatitudeTextView.textSize = textSize + baseStationLongitudeTextView.textSize = textSize + baseStationAltitudeTextView.textSize = textSize + courseAngleTextView.textSize = textSize + orientationTextView.textSize = textSize + positioningTextView.textSize = textSize + standardDeviationTextView.textSize = textSize + } + + /** + * The background for the RTK values text views + */ + var rtkValuesTextBackground: Drawable? + @JvmName("getRTKValuesTextBackground") + get() = gpsAntenna1TextView.background + @JvmName("setRTKValuesTextBackground") + set(drawable) { + gpsAntenna1TextView.background = drawable + gpsAntenna2TextView.background = drawable + gpsBaseStationTextView.background = drawable + beiDouAntenna1TextView.background = drawable + beiDouAntenna2TextView.background = drawable + beiDouBaseStationTextView.background = drawable + glonassAntenna1TextView.background = drawable + glonassAntenna2TextView.background = drawable + glonassBaseStationTextView.background = drawable + galileoAntenna1TextView.background = drawable + galileoAntenna2TextView.background = drawable + galileoBaseStationTextView.background = drawable + aircraftLatitudeTextView.background = drawable + aircraftLongitudeTextView.background = drawable + aircraftAltitudeTextView.background = drawable + baseStationLatitudeTextView.background = drawable + baseStationLongitudeTextView.background = drawable + baseStationAltitudeTextView.background = drawable + courseAngleTextView.background = drawable + orientationTextView.background = drawable + positioningTextView.background = drawable + standardDeviationTextView.background = drawable + } + + + /** + * The color for the separator line views + */ + var rtkSeparatorsColor: Int + @JvmName("getRTKSeparatorsColor") + @ColorInt + get() = rtkAircraftSeparator.solidColor + @JvmName("setRTKSeparatorsColor") + set(@ColorInt color) { + rtkAircraftSeparator.setBackgroundColor(color) + rtkBaseStationSeparator.setBackgroundColor(color) + rtkOrientationPositioningSeparator.setBackgroundColor(color) + rtkLocationSeparator.setBackgroundColor(color) + rtkSatelliteCountSeparator.setBackgroundColor(color) + } + + /** + * Shows or hides the BeiDou satellite information. + */ + var isBeiDouSatelliteInfoVisible = true + set(isVisible) { + field = isVisible + if (isVisible) { + beiDouTitleTextView.visibility = View.VISIBLE + beiDouAntenna1TextView.visibility = View.VISIBLE + beiDouBaseStationTextView.visibility = View.VISIBLE + } else { + beiDouTitleTextView.visibility = View.GONE + beiDouAntenna1TextView.visibility = View.GONE + beiDouBaseStationTextView.visibility = View.GONE + } + } + + /** + * Shows or hides the GLONASS satellite information. + */ + var isGLONASSSatelliteInfoVisible = true + set(isVisible) { + field = isVisible + if (isVisible) { + glonassTitleTextView.visibility = View.VISIBLE + glonassAntenna1TextView.visibility = View.VISIBLE + glonassBaseStationTextView.visibility = View.VISIBLE + } else { + glonassTitleTextView.visibility = View.GONE + glonassAntenna1TextView.visibility = View.GONE + glonassBaseStationTextView.visibility = View.GONE + } + } + + /** + * Shows or hides the Galileo satellite information. + */ + var isGalileoSatelliteInfoVisible = true + set(isVisible) { + field = isVisible + if (isVisible) { + galileoTitleTextView.visibility = View.VISIBLE + galileoAntenna1TextView.visibility = View.VISIBLE + galileoBaseStationTextView.visibility = View.VISIBLE + } else { + galileoTitleTextView.visibility = View.GONE + galileoAntenna1TextView.visibility = View.GONE + galileoBaseStationTextView.visibility = View.GONE + } + } + + /** + * The image displayed behind the satellite state table. + */ + var tableBackground: Drawable? + get() = tableBackgroundImageView.imageDrawable + set(value) { + tableBackgroundImageView.imageDrawable = value + } + //end region + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + inflate(context, R.layout.uxsdk_widget_rtk_satellite_status, this) + } + + init { + initItemValues() + initListener() + updateLabelView() + attrs?.let { initAttributes(context, it) } + } + + private fun updateLabelView() { + if (ProductUtil.isM3EProduct() || ProductUtil.isM4EProduct() || ProductUtil.isM4DProduct()) { + //orientation + orientationTextView.visibility = GONE + orientationTitleTextView.visibility = GONE + //Antenna2 + beiDouAntenna2TextView.visibility = GONE + galileoAntenna2TextView.visibility = GONE + glonassAntenna2TextView.visibility = GONE + gpsAntenna2TextView.visibility = GONE + antenna2TitleTextView.visibility = GONE + antenna1TitleTextView.visibility = GONE + //courseAngle + courseAngleTitleTextView.visibility = GONE + courseAngleTextView.visibility = GONE + + + } else { + //orientation + orientationTextView.visibility = VISIBLE + orientationTitleTextView.visibility = VISIBLE + //Antenna2 + beiDouAntenna2TextView.visibility = VISIBLE + galileoAntenna2TextView.visibility = VISIBLE + glonassAntenna2TextView.visibility = VISIBLE + gpsAntenna2TextView.visibility = VISIBLE + antenna2TitleTextView.visibility = VISIBLE + antenna1TitleTextView.visibility = VISIBLE + //courseAngle + courseAngleTitleTextView.visibility = VISIBLE + courseAngleTextView.visibility = VISIBLE + } + } + + private fun initListener() { + baseStationConnectImageView.setOnClickListener { + rtkStationListener?.showConnectView() + } + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.productConnection.observeOn(SchedulerProvider.ui()).subscribe { updateUIForIsRTKConnected(it) }) + addReaction(widgetModel.rtkLocationInfo.observeOn(SchedulerProvider.ui()).subscribe(this::updateRTKLocationInfo)) + + addReaction(widgetModel.rtkSystemState.observeOn(SchedulerProvider.ui()).subscribe(this::updateRTKSystemState)) + addReaction(widgetModel.standardDeviation.observeOn(SchedulerProvider.ui()).subscribe { updateStandardDeviation(it) }) + addReaction(widgetModel.rtkBaseStationState.observeOn(SchedulerProvider.ui()).subscribe { updateBaseStationStatus(it) }) + addReaction(widgetModel.rtkNetworkServiceState.observeOn(SchedulerProvider.ui()).subscribe { updateNetworkServiceStatus(it) }) + + } + + + //region Helper methods + private fun initItemValues() { + gpsAntenna1TextView.setText(R.string.uxsdk_string_default_value) + gpsAntenna2TextView.setText(R.string.uxsdk_string_default_value) + gpsBaseStationTextView.setText(R.string.uxsdk_string_default_value) + beiDouAntenna1TextView.setText(R.string.uxsdk_string_default_value) + beiDouAntenna2TextView.setText(R.string.uxsdk_string_default_value) + beiDouBaseStationTextView.setText(R.string.uxsdk_string_default_value) + glonassAntenna1TextView.setText(R.string.uxsdk_string_default_value) + glonassAntenna2TextView.setText(R.string.uxsdk_string_default_value) + glonassBaseStationTextView.setText(R.string.uxsdk_string_default_value) + galileoAntenna1TextView.setText(R.string.uxsdk_string_default_value) + galileoAntenna2TextView.setText(R.string.uxsdk_string_default_value) + galileoBaseStationTextView.setText(R.string.uxsdk_string_default_value) + aircraftLatitudeTextView.setText(R.string.uxsdk_string_default_value) + aircraftLongitudeTextView.setText(R.string.uxsdk_string_default_value) + aircraftAltitudeTextView.setText(R.string.uxsdk_string_default_value) + baseStationLatitudeTextView.setText(R.string.uxsdk_string_default_value) + baseStationLongitudeTextView.setText(R.string.uxsdk_string_default_value) + baseStationAltitudeTextView.setText(R.string.uxsdk_string_default_value) + courseAngleTextView.setText(R.string.uxsdk_string_default_value) + orientationTextView.setText(R.string.uxsdk_string_default_value) + positioningTextView.setText(R.string.uxsdk_string_default_value) + } + + //endregion + + + //region Customization + override fun getIdealDimensionRatioString(): String { + return getString(R.string.uxsdk_widget_rtk_satellite_status_ratio) + } + + /** + * Set the text appearance of the RTK connection state title. + * + * @param textAppearance Style resource for text appearance + */ + fun setRTKConnectionStatusTitleTextAppearance(@StyleRes textAppearance: Int) { + rtkStatusTitleTextView.setTextAppearance(context, textAppearance) + } + + /** + * Set the text appearance of the RTK connection state. + * + * @param textAppearance Style resource for text appearance + */ + fun setRTKConnectionStatusTextAppearance(@StyleRes textAppearance: Int) { + rtkStatusTextView.setTextAppearance(context, textAppearance) + } + + /** + * Set the text color of the RTK connection state when the RTKBaseStationState is the given + * value. + * + * @param state The state for which to set the text color. + * @param color The color of the text + */ + fun setRTKConnectionStatusLabelTextColor( + state: RTKSatelliteStatusWidgetModel.RTKBaseStationState, @ColorInt color: Int, + ) { + connectionStateTextColorMap[state] = color + widgetModel.updateRTKConnectionState() + } + + /** + * Get the text color of the RTK connection state when the RTKBaseStationState is the given + * value. + * + * @param state The state for which to get the text color. + * @return The color of the text + */ + @ColorInt + fun getRTKConnectionStatusLabelTextColor(state: RTKSatelliteStatusWidgetModel.RTKBaseStationState): Int { + return (connectionStateTextColorMap[state]?.let { it } + ?: getColor(R.color.uxsdk_rtk_status_disconnected)) + } + + /** + * Set text appearance of the RTK labels text views + * + * @param textAppearance Style resource for text appearance + */ + fun setRTKLabelsTextAppearance(@StyleRes textAppearance: Int) { + antenna1TitleTextView.setTextAppearance(context, textAppearance) + antenna2TitleTextView.setTextAppearance(context, textAppearance) + gpsTitleTextView.setTextAppearance(context, textAppearance) + beiDouTitleTextView.setTextAppearance(context, textAppearance) + glonassTitleTextView.setTextAppearance(context, textAppearance) + galileoTitleTextView.setTextAppearance(context, textAppearance) + latitudeTitleTextView.setTextAppearance(context, textAppearance) + longitudeTitleTextView.setTextAppearance(context, textAppearance) + altitudeTitleTextView.setTextAppearance(context, textAppearance) + aircraftCoordinatesTitleTextView.setTextAppearance(context, textAppearance) + baseStationCoordinatesTitleTextView.setTextAppearance(context, textAppearance) + courseAngleTitleTextView.setTextAppearance(context, textAppearance) + orientationTitleTextView.setTextAppearance(context, textAppearance) + positioningTitleTextView.setTextAppearance(context, textAppearance) + standardDeviationTitleTextView.setTextAppearance(context, textAppearance) + } + + + /** + * Set text appearance of the RTK values text views + * + * @param textAppearance Style resource for text appearance + */ + fun setRTKValuesTextAppearance(@StyleRes textAppearance: Int) { + gpsAntenna1TextView.setTextAppearance(context, textAppearance) + gpsAntenna2TextView.setTextAppearance(context, textAppearance) + gpsBaseStationTextView.setTextAppearance(context, textAppearance) + beiDouAntenna1TextView.setTextAppearance(context, textAppearance) + beiDouAntenna2TextView.setTextAppearance(context, textAppearance) + beiDouBaseStationTextView.setTextAppearance(context, textAppearance) + glonassAntenna1TextView.setTextAppearance(context, textAppearance) + glonassAntenna2TextView.setTextAppearance(context, textAppearance) + glonassBaseStationTextView.setTextAppearance(context, textAppearance) + galileoAntenna1TextView.setTextAppearance(context, textAppearance) + galileoAntenna2TextView.setTextAppearance(context, textAppearance) + galileoBaseStationTextView.setTextAppearance(context, textAppearance) + aircraftLatitudeTextView.setTextAppearance(context, textAppearance) + aircraftLongitudeTextView.setTextAppearance(context, textAppearance) + aircraftAltitudeTextView.setTextAppearance(context, textAppearance) + baseStationLatitudeTextView.setTextAppearance(context, textAppearance) + baseStationLongitudeTextView.setTextAppearance(context, textAppearance) + baseStationAltitudeTextView.setTextAppearance(context, textAppearance) + courseAngleTextView.setTextAppearance(context, textAppearance) + orientationTextView.setTextAppearance(context, textAppearance) + positioningTextView.setTextAppearance(context, textAppearance) + standardDeviationTextView.setTextAppearance(context, textAppearance) + } + + //Initialize all customizable attributes + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.RTKSatelliteStatusWidget).use { typedArray -> + typedArray.getResourceIdAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_rtkConnectionStatusTitleTextAppearance) { + setRTKConnectionStatusTitleTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_rtkConnectionStatusTitleTextSize) { + rtkConnectionStatusTitleTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_rtkConnectionStatusTitleTextColor) { + rtkConnectionStatusTitleTextColor = it + } + typedArray.getDrawableAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_rtkConnectionStatusTitleBackgroundDrawable) { + rtkConnectionStatusTitleTextBackground = it + } + typedArray.getResourceIdAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_rtkConnectionStatusTextAppearance) { + setRTKConnectionStatusTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_rtkConnectionStatusTextSize) { + rtkConnectionStatusTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_rtkConnectionStatusConnectedInUseTextColor) { + setRTKConnectionStatusLabelTextColor( + RTKSatelliteStatusWidgetModel.RTKBaseStationState.CONNECTED_IN_USE, + it + ) + } + typedArray.getColorAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_rtkConnectionStatusConnectedNotInUseTextColor) { + setRTKConnectionStatusLabelTextColor( + RTKSatelliteStatusWidgetModel.RTKBaseStationState.CONNECTED_NOT_IN_USE, + it + ) + } + typedArray.getColorAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_rtkConnectionStatusDisconnectedTextColor) { + setRTKConnectionStatusLabelTextColor(RTKSatelliteStatusWidgetModel.RTKBaseStationState.DISCONNECTED, it) + } + typedArray.getDrawableAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_rtkConnectionStatusBackgroundDrawable) { + rtkConnectionStatusTextBackground = it + } + typedArray.getResourceIdAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_rtkLabelsTextAppearance) { + setRTKLabelsTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_rtkLabelsTextSize) { + rtkLabelsTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_rtkLabelsTextColor) { + rtkLabelsTextColor = it + } + typedArray.getDrawableAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_rtkLabelsBackgroundDrawable) { + rtkLabelsTextBackground = it + } + typedArray.getResourceIdAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_rtkValuesTextAppearance) { + setRTKValuesTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_rtkValuesTextSize) { + rtkValuesTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_rtkValuesTextColor) { + rtkValuesTextColor = it + } + typedArray.getDrawableAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_rtkValuesBackgroundDrawable) { + rtkValuesTextBackground = it + } + + typedArray.getColorAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_rtkSeparatorsColor) { + rtkSeparatorsColor = it + } + typedArray.getDrawableAndUse(R.styleable.RTKSatelliteStatusWidget_uxsdk_tableBackground) { + tableBackground = it + } + isBeiDouSatelliteInfoVisible = + typedArray.getBoolean(R.styleable.RTKSatelliteStatusWidget_uxsdk_beiDouSatellitesVisibility, true) + isGLONASSSatelliteInfoVisible = + typedArray.getBoolean(R.styleable.RTKSatelliteStatusWidget_uxsdk_glonassSatellitesVisibility, true) + isGalileoSatelliteInfoVisible = + typedArray.getBoolean(R.styleable.RTKSatelliteStatusWidget_uxsdk_galileoSatellitesVisibility, true) + } + } + + + private fun updateBaseStationStatus(connectionState: RTKSatelliteStatusWidgetModel.RTKBaseStationState) { + when (connectionState) { + RTKSatelliteStatusWidgetModel.RTKBaseStationState.CONNECTED_IN_USE -> { + rtkStatusTextView.setText(R.string.uxsdk_rtk_state_connect) + rtkStatusTextView.setTextColor(getRTKConnectionStatusLabelTextColor(RTKSatelliteStatusWidgetModel.RTKBaseStationState.CONNECTED_IN_USE)) + } + RTKSatelliteStatusWidgetModel.RTKBaseStationState.CONNECTED_NOT_IN_USE -> { + rtkStatusTextView.setText(R.string.uxsdk_rtk_state_connect_not_healthy) + rtkStatusTextView.setTextColor(getRTKConnectionStatusLabelTextColor(RTKSatelliteStatusWidgetModel.RTKBaseStationState.CONNECTED_NOT_IN_USE)) + } + RTKSatelliteStatusWidgetModel.RTKBaseStationState.DISCONNECTED -> { + rtkStatusTextView.setText(R.string.uxsdk_rtk_state_disconnect) + rtkStatusTextView.textColor = + getRTKConnectionStatusLabelTextColor(RTKSatelliteStatusWidgetModel.RTKBaseStationState.DISCONNECTED) + } + } + + } + + private fun updateNetworkServiceStatus(networkServiceState: RTKSatelliteStatusWidgetModel.RTKNetworkServiceState) { + //去除RTKNetworkServiceState默认值带来的的影响 + LogUtils.i(TAG, "updateNetworkServiceStatus:$networkServiceState") + if (networkServiceState.isNetworkServiceOpen == false) { + return + } + val rtkStatusStr: String + var rtkStatusColor: Int = + getRTKConnectionStatusLabelTextColor(RTKSatelliteStatusWidgetModel.RTKBaseStationState.DISCONNECTED) + + when (networkServiceState.state) { + RTKServiceState.RTCM_CONNECTED, + RTKServiceState.RTCM_NORMAL, + RTKServiceState.RTCM_USER_HAS_ACTIVATE, + RTKServiceState.RTCM_USER_ACCOUNT_EXPIRES_SOON, + RTKServiceState.RTCM_USE_DEFAULT_MOUNT_POINT, + RTKServiceState.TRANSMITTING, + -> + if (networkServiceState.isRTKBeingUsed == true) { + rtkStatusColor = + getRTKConnectionStatusLabelTextColor(RTKSatelliteStatusWidgetModel.RTKBaseStationState.CONNECTED_IN_USE) + rtkStatusStr = getString(R.string.uxsdk_rtk_state_connect) + } else { + rtkStatusColor = + getRTKConnectionStatusLabelTextColor(RTKSatelliteStatusWidgetModel.RTKBaseStationState.CONNECTED_NOT_IN_USE) + rtkStatusStr = getString(R.string.uxsdk_rtk_state_connect_not_healthy) + } + + RTKServiceState.RTCM_AUTH_FAILED -> rtkStatusStr = getString(R.string.uxsdk_rtk_state_auth_failed) + RTKServiceState.RTCM_USER_NOT_BOUNDED -> rtkStatusStr = getString(R.string.uxsdk_rtk_state_not_bind) + RTKServiceState.SERVICE_SUSPENSION -> rtkStatusStr = getString(R.string.uxsdk_rtk_state_pause) + RTKServiceState.RTCM_USER_NOT_ACTIVATED -> rtkStatusStr = getString(R.string.uxsdk_rtk_state_not_active) + RTKServiceState.RTCM_ILLEGAL_UTC_TIME, + RTKServiceState.ACCOUNT_EXPIRED, + -> rtkStatusStr = getString(R.string.uxsdk_rtk_state_account_expire) + RTKServiceState.NETWORK_NOT_REACHABLE -> rtkStatusStr = getString(R.string.uxsdk_rtk_state_network_err) + RTKServiceState.LOGIN_FAILURE -> rtkStatusStr = getString(R.string.uxsdk_rtk_state_auth_failed) + RTKServiceState.RTCM_SET_COORDINATE_FAILURE -> rtkStatusStr = + getString(R.string.uxsdk_rtk_state_coordinate_fialed) + RTKServiceState.RTCM_CONNECTING, + RTKServiceState.READY, + RTKServiceState.RTK_START_PROCESSING, + -> rtkStatusStr = getString(R.string.uxsdk_rtk_state_connecting) + RTKServiceState.ACCOUNT_ERROR -> rtkStatusStr = getString(R.string.uxsdk_rtk_nrtk_account_error) + RTKServiceState.CONNECTING -> rtkStatusStr = getString(R.string.uxsdk_rtk_nrtk_connecting) + RTKServiceState.INVALID_REQUEST -> rtkStatusStr = getString(R.string.uxsdk_rtk_nrtk_invalid_request) + RTKServiceState.SERVER_NOT_REACHABLE -> rtkStatusStr = + getString(R.string.uxsdk_rtk_nrtk_server_not_reachable) + else -> rtkStatusStr = getString(R.string.uxsdk_rtk_state_disconnect) + } + rtkStatusTextView.text = rtkStatusStr + rtkStatusTextView.setTextColor(rtkStatusColor) + } + + private fun updateUIForIsRTKConnected(isRTKConnected: Boolean) { + if (!isRTKConnected) { + initItemValues() + } + } + + private fun updateRTKLocationInfo(rtkLocationInfo: RTKLocationInfo?) { + //更新飞行器位置信息 + val aircraftLocation = rtkLocationInfo?.rtkLocation?.mobileStationLocation + aircraftLocation?.run { + aircraftLatitudeTextView.text = resources.getString( + R.string.uxsdk_rtk_panel_coordinate_value, + latitude + ) + aircraftLongitudeTextView.text = resources.getString( + R.string.uxsdk_rtk_panel_coordinate_value, + longitude + ) + aircraftAltitudeTextView.text = resources.getString( + R.string.uxsdk_rtk_panel_altitude_value, + altitude + ) + } + + + //更新基站位置信息 + val baseStationLocation = rtkLocationInfo?.rtkLocation?.baseStationLocation + baseStationLocation?.run { + baseStationLatitudeTextView.text = resources.getString( + R.string.uxsdk_rtk_panel_coordinate_value, + latitude + ) + baseStationLongitudeTextView.text = resources.getString( + R.string.uxsdk_rtk_panel_coordinate_value, + longitude + ) + baseStationAltitudeTextView.text = resources.getString( + R.string.uxsdk_rtk_panel_altitude_value, + altitude + ) + } + + + //更新航向角 + val rtkHeading = rtkLocationInfo?.rtkHeading + var heading: Double? = rtkHeading?.heading + heading?.let { + heading += 90.0 + if (heading >= 360) { + heading -= 360.0 + } + courseAngleTextView.text = String.format(Locale.US, "%.1f", heading) + } + + //更新定向信息 + if (rtkHeading?.directEnable == true) { + orientationTextView.text = getString(R.string.uxsdk_rtk_solution_fixed) + } else { + orientationTextView.setText(R.string.uxsdk_string_default_value) + } + + //更新定位信息 + positioningSolution = rtkLocationInfo?.rtkLocation?.positioningSolution + if (positioningSolution == RTKPositioningSolution.NONE || positioningSolution == RTKPositioningSolution.UNKNOWN) { + positioningTextView.setText(R.string.uxsdk_string_default_value) + } else { + positioningTextView.text = RTKUtil.getRTKStatusName(this, positioningSolution) + } + + if (positioningSolution == RTKPositioningSolution.FIXED_POINT ) { + rtkStatusTextView.setText(R.string.uxsdk_rtk_state_connect) + rtkStatusTextView.setTextColor(getRTKConnectionStatusLabelTextColor(RTKSatelliteStatusWidgetModel.RTKBaseStationState.CONNECTED_IN_USE)) + } + + } + + //更新标准差 + private fun updateStandardDeviation(standardDeviation: RTKSatelliteStatusWidgetModel.StandardDeviation) { + val resourceString = if (standardDeviation.unitType == UnitConversionUtil.UnitType.IMPERIAL) { + R.string.uxsdk_value_feet + } else { + R.string.uxsdk_value_meters + } + val standardDeviationStr = + (resources.getString(resourceString, String.format(Locale.US, "%s", standardDeviation.latitude)) + "\n" + + resources.getString( + resourceString, + String.format(Locale.US, "%s", standardDeviation.longitude) + ) + "\n" + + resources.getString(resourceString, String.format(Locale.US, "%s", standardDeviation.altitude))) + standardDeviationTextView.text = standardDeviationStr + } + + private fun updateRTKSystemState(rtkSystemState: RTKSystemState?) { + LogUtils.i(TAG, "rtkSystemState=$rtkSystemState") + //更新天线1的卫星数 + val mobileStationReceiver1Info = rtkSystemState?.satelliteInfo?.mobileStationReceiver1Info + mobileStationReceiver1Info?.let { + for (receiverInfo in mobileStationReceiver1Info) { + val type = receiverInfo.type + val count = receiverInfo.count.toString() + when (type) { + GNSSType.BEIDOU -> { + beiDouAntenna1TextView.text = count + } + GNSSType.GALILEO -> { + galileoAntenna1TextView.text = count + } + GNSSType.GLONASS -> { + glonassAntenna1TextView.text = count + } + GNSSType.GPS -> { + gpsAntenna1TextView.text = count + } + else -> { + //do something + } + } + } + } + + //更新天线2的卫星数 + val mobileStationReceiver2Info = rtkSystemState?.satelliteInfo?.mobileStationReceiver2Info + mobileStationReceiver2Info?.let { + for (receiverInfo in mobileStationReceiver2Info) { + val type = receiverInfo.type + val count = receiverInfo.count.toString() + when (type) { + GNSSType.BEIDOU -> { + beiDouAntenna2TextView.text = count + } + GNSSType.GALILEO -> { + galileoAntenna2TextView.text = count + } + GNSSType.GLONASS -> { + glonassAntenna2TextView.text = count + } + GNSSType.GPS -> { + gpsAntenna2TextView.text = count + } + else -> { + //do something + } + } + } + } + + //更新基站的卫星数 + val baseStationReceiverInfo = rtkSystemState?.satelliteInfo?.baseStationReceiverInfo + baseStationReceiverInfo?.let { + for (receiverInfo in baseStationReceiverInfo) { + val type = receiverInfo.type + val count = receiverInfo.count.toString() + when (type) { + GNSSType.BEIDOU -> { + beiDouBaseStationTextView.text = count + } + GNSSType.GALILEO -> { + galileoBaseStationTextView.text = count + } + GNSSType.GLONASS -> { + glonassBaseStationTextView.text = count + } + GNSSType.GPS -> { + gpsBaseStationTextView.text = count + } + else -> { + //do something + } + } + } + } + + updateBaseStationUI(rtkSystemState?.rtkReferenceStationSource) + } + + private fun updateBaseStationUI(stationSource: RTKReferenceStationSource?) { + stationSource?.let { + val name = RTKUtil.getRTKTypeName(this, stationSource) + baseStationCoordinatesTitleTextView.text = name + rtkStatusTitleTextView.text = resources.getString(R.string.uxsdk_rtk_status_desc, name) + } + if (stationSource == RTKReferenceStationSource.BASE_STATION) { + baseStationConnectImageView.show() + } else { + baseStationConnectImageView.hide() + } + } + + + /** + * Class defines the widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + } + + interface RTKStationListener { + fun showConnectView() + } + + private var rtkStationListener: RTKStationListener? = null + fun setRTKConnectListener(rtkStationListener: RTKStationListener) { + this.rtkStationListener = rtkStationListener + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKSatelliteStatusWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKSatelliteStatusWidgetModel.kt new file mode 100644 index 00000000..0407a168 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKSatelliteStatusWidgetModel.kt @@ -0,0 +1,331 @@ +package dji.v5.ux.accessory + + +import dji.sdk.keyvalue.value.rtkbasestation.RTKReferenceStationSource +import dji.sdk.keyvalue.value.rtkbasestation.RTKServiceState +import dji.sdk.keyvalue.value.rtkbasestation.RTKStationConnetState +import dji.sdk.keyvalue.value.rtkmobilestation.RTKLocation +import dji.v5.common.error.IDJIError +import dji.v5.manager.aircraft.rtk.* +import dji.v5.manager.aircraft.rtk.network.INetworkServiceInfoListener +import dji.v5.manager.aircraft.rtk.station.RTKStationConnectStatusListener +import dji.v5.manager.interfaces.IRTKCenter +import dji.v5.utils.common.LogUtils +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.GlobalPreferenceKeys +import dji.v5.ux.core.communication.GlobalPreferencesInterface +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.communication.UXKeys +import dji.v5.ux.core.util.DataProcessor +import dji.v5.ux.core.util.UnitConversionUtil +import io.reactivex.rxjava3.core.Flowable + +/** + * Description :Widget Model for the [RTKSatelliteStatusWidget] used to define + * the underlying logic and communication + * + * @author: Byte.Cai + * date : 2022/5/23 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ + +class RTKSatelliteStatusWidgetModel( + djiSdkModel: DJISDKModel, + uxKeyManager: ObservableInMemoryKeyedStore, + private val preferencesManager: GlobalPreferencesInterface?, + private val rtkCenter: IRTKCenter, +) : + WidgetModel(djiSdkModel, uxKeyManager) { + + private val TAG = LogUtils.getTag(this) + private val rtkLocationInfoProcessor: DataProcessor = DataProcessor.create(RTKLocationInfo()) + private val rtkSystemStateProcessor: DataProcessor = DataProcessor.create(RTKSystemState()) + private val rtkStationConnectStateProcessor: DataProcessor = + DataProcessor.create(RTKStationConnetState.UNKNOWN) + private val rtkNetworkServiceInfoProcessor: DataProcessor = + DataProcessor.create(RTKServiceState.UNKNOWN) + + private val unitTypeProcessor: DataProcessor = + DataProcessor.create(UnitConversionUtil.UnitType.METRIC) + + //rtk连接数据的封装Processor,用于widget显示rtk是否连接和数据是否正在使用 + private val rtkBaseStationStateProcessor: DataProcessor = + DataProcessor.create(RTKBaseStationState.DISCONNECTED) + private val rtkNetworkServiceStateProcessor: DataProcessor = DataProcessor.create( + RTKNetworkServiceState( + RTKServiceState.UNKNOWN, + isRTKBeingUsed = false, + isNetworkServiceOpen = false, + rtkSignal = RTKReferenceStationSource.UNKNOWN + ) + ) + + //标准差 + private val standardDeviationProcessor: DataProcessor = DataProcessor.create( + StandardDeviation( + 0f, + 0f, + 0f, + UnitConversionUtil.UnitType.METRIC + ) + ) + + private val rtkLocationInfoListener = RTKLocationInfoListener { + rtkLocationInfoProcessor.onNext(it) + updateStandardDeviation(it.rtkLocation) + + } + private val rtkSystemStateListener = RTKSystemStateListener { + rtkSystemStateProcessor.onNext(it) + //RTKSystemState涉及RTK服务类型的改变,所以有关于RTK服务类型的都需要更新 + updateRTKConnectionState() + updateRTKListener(it.rtkReferenceStationSource) + + } + private val stationConnectStatusListener = RTKStationConnectStatusListener { + LogUtils.i(TAG, it) + rtkStationConnectStateProcessor.onNext(it) + updateRTKConnectionState() + } + + private var mRTKServiceState = RTKServiceState.UNKNOWN + + private val networkServiceInfoListener: INetworkServiceInfoListener = object : + INetworkServiceInfoListener { + override fun onServiceStateUpdate(state: RTKServiceState?) { + state?.let { + if (mRTKServiceState != state) { + LogUtils.i(TAG, "onServiceStateUpdate RTKServiceState=$state") + mRTKServiceState = state + rtkNetworkServiceInfoProcessor.onNext(it) + updateRTKConnectionState() + } + } + } + + override fun onErrorCodeUpdate(error: IDJIError?) { + error?.let { + LogUtils.e(TAG, error.toString()) + } + } + } + + + @get:JvmName("getRTKLocationInfo") + val rtkLocationInfo: Flowable + get() = rtkLocationInfoProcessor.toFlowable() + + + @get:JvmName("getRTKSystemState") + val rtkSystemState: Flowable + get() = rtkSystemStateProcessor.toFlowable() + + + /** + * Get the standard deviation of the location accuracy. + */ + val standardDeviation: Flowable + get() = standardDeviationProcessor.toFlowable() + + /** + * Get the state of the RTK base station. + */ + @get:JvmName("getRTKBaseStationState") + val rtkBaseStationState: Flowable + get() = rtkBaseStationStateProcessor.toFlowable() + + /** + * Get the state of the network service. + */ + @get:JvmName("getRTKNetworkServiceState") + val rtkNetworkServiceState: Flowable + get() = rtkNetworkServiceStateProcessor.toFlowable() + + + //region Constructor + init { + if (preferencesManager != null) { + unitTypeProcessor.onNext(preferencesManager.unitType) + } + } + //endregion + + + override fun inSetup() { + rtkCenter.addRTKLocationInfoListener(rtkLocationInfoListener) + rtkCenter.addRTKSystemStateListener(rtkSystemStateListener) + rtkCenter.qxrtkManager.addNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.customRTKManager.addNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.cmccrtkManager.addNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.rtkStationManager.addRTKStationConnectStatusListener(stationConnectStatusListener) + //测试发现productConnection有时候返回true比较慢,所以在其值返回也是要刷新依赖其者的状态 + productConnection.observeOn(SchedulerProvider.ui()).subscribe { + updateRTKConnectionState() + } + + val unitKey = UXKeys.create(GlobalPreferenceKeys.UNIT_TYPE) + bindDataProcessor(unitKey, unitTypeProcessor) + updateRTKConnectionState() + } + + override fun inCleanup() { + rtkCenter.removeRTKLocationInfoListener(rtkLocationInfoListener) + rtkCenter.removeRTKSystemStateListener(rtkSystemStateListener) + rtkCenter.rtkStationManager.removeRTKStationConnectStatusListener(stationConnectStatusListener) + rtkCenter.qxrtkManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.customRTKManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.cmccrtkManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + } + + private fun updateRTKListener(rtkSource: RTKReferenceStationSource) { + when (rtkSource) { + RTKReferenceStationSource.QX_NETWORK_SERVICE -> { + rtkCenter.customRTKManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.cmccrtkManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.rtkStationManager.removeRTKStationConnectStatusListener(stationConnectStatusListener) + rtkCenter.qxrtkManager.addNetworkRTKServiceInfoListener(networkServiceInfoListener) + } + RTKReferenceStationSource.CUSTOM_NETWORK_SERVICE -> { + rtkCenter.qxrtkManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.cmccrtkManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.rtkStationManager.removeRTKStationConnectStatusListener(stationConnectStatusListener) + rtkCenter.customRTKManager.addNetworkRTKServiceInfoListener(networkServiceInfoListener) + + } + RTKReferenceStationSource.NTRIP_NETWORK_SERVICE -> { + rtkCenter.qxrtkManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.customRTKManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.rtkStationManager.removeRTKStationConnectStatusListener(stationConnectStatusListener) + rtkCenter.cmccrtkManager.addNetworkRTKServiceInfoListener(networkServiceInfoListener) + + } + RTKReferenceStationSource.BASE_STATION -> { + rtkCenter.qxrtkManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.customRTKManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.cmccrtkManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.rtkStationManager.addRTKStationConnectStatusListener(stationConnectStatusListener) + + } + else -> { + //do nothing + } + } + + } + + + private fun updateStandardDeviation(rtkLocation: RTKLocation?) { + var stdLatitude = 0f + var stdLongitude = 0f + var stdAltitude = 0f + rtkLocation?.let { + if (unitTypeProcessor.value == UnitConversionUtil.UnitType.IMPERIAL) { + stdLatitude = UnitConversionUtil.convertMetersToFeet(it.stdLatitude.toFloat()) + stdLongitude = UnitConversionUtil.convertMetersToFeet(it.stdLongitude.toFloat()) + stdAltitude = UnitConversionUtil.convertMetersToFeet(it.stdAltitude.toFloat()) + } else { + stdLatitude = it.stdLatitude.toFloat() + stdLongitude = it.stdLongitude.toFloat() + stdAltitude = it.stdAltitude.toFloat() + } + } + standardDeviationProcessor.onNext( + StandardDeviation( + stdLatitude, + stdLongitude, + stdAltitude, + unitTypeProcessor.value + ) + ) + } + + /** + * Sends the latest network service state or base station state to the corresponding flowable. + */ + fun updateRTKConnectionState() { + rtkSystemStateProcessor.value.rtkReferenceStationSource?.let { + if (isNetworkServiceOpen(it)) { + updateNetworkServiceState() + } else { + updateBaseStationState() + } + } + + } + + + /** + * The state of the network service. + */ + data class RTKNetworkServiceState( + val state: RTKServiceState?, + val isRTKBeingUsed: Boolean?, + val isNetworkServiceOpen: Boolean?, + @get:JvmName("getRTKSignal") + val rtkSignal: RTKReferenceStationSource?, + ) + + /** + * The state of the RTK base station + */ + enum class RTKBaseStationState { + /** + * The RTK base station is connected and in use. + */ + CONNECTED_IN_USE, + + /** + * The RTK base station is connected and not in use. + */ + CONNECTED_NOT_IN_USE, + + /** + * The RTK base station is disconnected. + */ + DISCONNECTED + } + + /** + * The standard deviation of the location accuracy. + */ + data class StandardDeviation( + val latitude: Float, + val longitude: Float, + val altitude: Float, + val unitType: UnitConversionUtil.UnitType, + ) + + //region Helper methods + private fun updateNetworkServiceState() { + rtkNetworkServiceStateProcessor.onNext( + RTKNetworkServiceState( + rtkNetworkServiceInfoProcessor.value, + rtkSystemStateProcessor.value.rtkHealthy, + isNetworkServiceOpen(rtkSystemStateProcessor.value.rtkReferenceStationSource), + rtkSystemStateProcessor.value.rtkReferenceStationSource + ) + ) + } + + private fun updateBaseStationState() { + if (rtkStationConnectStateProcessor.value == RTKStationConnetState.CONNECTED && productConnectionProcessor.value) { + if (rtkSystemStateProcessor.value.rtkHealthy) { + rtkBaseStationStateProcessor.onNext(RTKBaseStationState.CONNECTED_IN_USE) + } else { + rtkBaseStationStateProcessor.onNext(RTKBaseStationState.CONNECTED_NOT_IN_USE) + } + } else { + rtkBaseStationStateProcessor.onNext(RTKBaseStationState.DISCONNECTED) + } + } + + + private fun isNetworkServiceOpen(rtkSignal: RTKReferenceStationSource?): Boolean { + return rtkSignal == RTKReferenceStationSource.QX_NETWORK_SERVICE + || rtkSignal == RTKReferenceStationSource.CUSTOM_NETWORK_SERVICE + || rtkSignal == RTKReferenceStationSource.NTRIP_NETWORK_SERVICE + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKStartServiceHelper.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKStartServiceHelper.kt new file mode 100644 index 00000000..3eb25856 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKStartServiceHelper.kt @@ -0,0 +1,373 @@ +package dji.v5.ux.accessory + +import android.os.Handler +import android.widget.Toast +import dji.rtk.CoordinateSystem +import dji.sdk.keyvalue.key.* +import dji.sdk.keyvalue.value.product.ProductType +import dji.sdk.keyvalue.value.remotecontroller.RCMode +import dji.sdk.keyvalue.value.rtkbasestation.RTKCustomNetworkSetting +import dji.sdk.keyvalue.value.rtkbasestation.RTKReferenceStationSource +import dji.v5.common.callback.CommonCallbacks +import dji.v5.common.error.IDJIError +import dji.v5.common.utils.RxUtil +import dji.v5.et.create +import dji.v5.et.get +import dji.v5.manager.aircraft.rtk.RTKCenter +import dji.v5.manager.aircraft.rtk.RTKSystemStateListener +import dji.v5.utils.common.* +import dji.v5.ux.R +import dji.v5.ux.core.util.DataProcessor +import dji.v5.ux.core.util.ViewUtil +import io.reactivex.rxjava3.core.Flowable +import java.util.concurrent.atomic.AtomicBoolean + + +/** + * Description :用于实现自动重连RTK逻辑 + * + * @author: Byte.Cai + * date : 2022/8/16 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ +object RTKStartServiceHelper { + private const val TAG = "RTKStartServiceHelper" + + private val rtkCenter = RTKCenter.getInstance() + private val qxRTKManager = RTKCenter.getInstance().qxrtkManager + private val customManager = RTKCenter.getInstance().customRTKManager + private val cmccRtkManager = RTKCenter.getInstance().cmccrtkManager + private var isStartByUser=false + + private var productType: ProductType = ProductType.UNKNOWN + private var rtkDongleConnection = false + private var fcConnected = false + private val rtkModuleAvailableProcessor = DataProcessor.create(false) + private var rtkSource: RTKReferenceStationSource = RTKReferenceStationSource.UNKNOWN + private val isStartRTKing = AtomicBoolean(false) + private val isHasStartRTK = AtomicBoolean(false) + private val handle = Handler() + + + private val rtkSystemStateListener = RTKSystemStateListener { + if (rtkSource != it.rtkReferenceStationSource) { + rtkSource = it.rtkReferenceStationSource + LogUtils.i(TAG, "rtkSource change into:$rtkSource") + //避免未输入账号信息下去启动导致的失败 + if (rtkSource != RTKReferenceStationSource.CUSTOM_NETWORK_SERVICE) { + startRtkService() + } + } + } + + init { + //观测RTK模块的连接情况 + observerRTKNoduleAvailable() + //观测RTKSource的变化 + rtkCenter.addRTKSystemStateListener(rtkSystemStateListener) + } + + private fun observerRTKNoduleAvailable() { + RxUtil.addListener( + KeyTools.createKey( + ProductKey.KeyProductType), this).subscribe { + if (it != ProductType.UNRECOGNIZED && productType != it) { + LogUtils.i(TAG, "productType=$it") + productType = it + updateData() + } + + } + RxUtil.addListener( + KeyTools.createKey( + RtkMobileStationKey.KeyIsRTKDongleConnect), this).subscribe { + if (rtkDongleConnection != it) { + LogUtils.i(TAG, "rtkDongleConnection=$it") + rtkDongleConnection = it + updateData() + } + + } + + RxUtil.addListener( + KeyTools.createKey( + FlightControllerKey.KeyConnection), this).subscribe { + if (fcConnected != it) { + LogUtils.i(TAG, "fcConnected=$it") + fcConnected = it + updateData() + } + + } + } + + @Synchronized + private fun updateData() { + val isRtkModuleAvailable = when (productType) { + ProductType.DJI_MAVIC_3_ENTERPRISE_SERIES -> + // 外接RTK的判断RTK Dongle连接状态 + rtkDongleConnection && fcConnected + else -> + // 其他行业飞机内置RTK的飞机都是true + fcConnected + } + rtkModuleAvailableProcessor.onNext(isRtkModuleAvailable) + + if (isRtkModuleAvailable && !isHasStartRTK.get()) { + startRtkService() + } + } + + @Synchronized + fun startRtkService(isStartByUser:Boolean=false) { + this.isStartByUser =isStartByUser + LogUtils.i(TAG, "startRtkService") + if (!rtkModuleAvailableProcessor.value) { + LogUtils.e(TAG, "rtkModule is unAvailable,startRtkServiceIfNeed fail!") + return + } + if (!isNeedStartRtkNetworkService()) { + LogUtils.e(TAG, "don not need start rtk Service!") + return + } + LogUtils.i(TAG, "rtkSource=$rtkSource") + when (rtkSource) { + RTKReferenceStationSource.CUSTOM_NETWORK_SERVICE -> startRtkCustomNetworkService() + RTKReferenceStationSource.QX_NETWORK_SERVICE -> startQxRtkService() + RTKReferenceStationSource.NTRIP_NETWORK_SERVICE -> startCMCCRtkService() + RTKReferenceStationSource.BASE_STATION -> { + LogUtils.i(TAG, "D-RTK2 固件底层已实现自动重连,不需要外部手动重连") + } + else -> { + LogUtils.e(TAG, "UnKnown rtkSource:$rtkSource") + } + } + } + + + @Synchronized + private fun startCMCCRtkService() { + val rtkNetworkCoordinateSystem = RTKUtil.getNetRTKCoordinateSystem(RTKReferenceStationSource.NTRIP_NETWORK_SERVICE) + setStartRTKState(true) + isHasStartRTK.set(false) + LogUtils.i(TAG, "startCMCCRtkService,rtkNetworkCoordinateSystem=$rtkNetworkCoordinateSystem") + if (rtkNetworkCoordinateSystem == null) { + setStartRTKState(false) + LogUtils.e(TAG, "getCMCCRtk CoordinateSystem == null,startCMCCRtkService finish!") + return + } + rtkNetworkCoordinateSystem.let { + LogUtils.i(TAG, "startCMCCRtkService,coordinateName=$rtkNetworkCoordinateSystem") + cmccRtkManager.stopNetworkRTKService(object : CommonCallbacks.CompletionCallback { + override fun onSuccess() { + cmccRtkManager.startNetworkRTKService(rtkNetworkCoordinateSystem, object : + CommonCallbacks.CompletionCallback { + override fun onSuccess() { + LogUtils.i(TAG, "startCMCCRtkService success") + setStartRTKState(false) + isHasStartRTK.set(true) + } + + override fun onFailure(error: IDJIError) { + LogUtils.e(TAG, "startCMCCRtkService fail:rtkNetworkCoordinateSystem=$rtkNetworkCoordinateSystem,error=$error") + setStartRTKState(false) + isHasStartRTK.set(false) + if (isStartByUser) { + showToast(StringUtils.getResStr(R.string.uxsdk_rtk_setting_menu_setting_fail)) + } + + } + + }) + } + + override fun onFailure(error: IDJIError) { + LogUtils.e(TAG, "stopNetworkRTKService fail:$error") + isHasStartRTK.set(false) + setStartRTKState(false) + + + } + + }) + + } + } + + private fun showToast(msg: String) { + ViewUtil.showToast(ContextUtil.getContext(), msg, Toast.LENGTH_SHORT) + } + + /** + * 启动千寻RTK + */ + @Synchronized + private fun startQxRtkService() { + var rtkNetworkCoordinateSystem = RTKUtil.getNetRTKCoordinateSystem(RTKReferenceStationSource.QX_NETWORK_SERVICE) + LogUtils.i(TAG, "startQxRtkService rtkNetworkCoordinateSystem=$rtkNetworkCoordinateSystem") + if (rtkNetworkCoordinateSystem != null) { + startQxRtkService(rtkNetworkCoordinateSystem) + } else { + RTKCenter.getInstance().qxrtkManager.getNetworkRTKCoordinateSystem(object : + CommonCallbacks.CompletionCallbackWithParam { + override fun onSuccess(t: CoordinateSystem?) { + t?.let { startQxRtkService(it) } + } + + override fun onFailure(error: IDJIError) { + //未实现 + } + }) + } + } + + private fun startQxRtkService(coordinateSystem: CoordinateSystem) { + setStartRTKState(true) + isHasStartRTK.set(false) + + qxRTKManager.stopNetworkRTKService(object : CommonCallbacks.CompletionCallback { + override fun onSuccess() { + qxRTKManager.startNetworkRTKService(coordinateSystem, object : + CommonCallbacks.CompletionCallback { + override fun onSuccess() { + LogUtils.i(TAG, "startQxRtkService success") + setStartRTKState(false) + isHasStartRTK.set(true) + + } + + override fun onFailure(error: IDJIError) { + LogUtils.e(TAG, "startQxRtkService fail:$error") + if (isStartByUser) { + showToast(StringUtils.getResStr(R.string.uxsdk_rtk_setting_menu_setting_fail)) + } + setStartRTKState(false) + isHasStartRTK.set(false) + + + } + }) + } + + override fun onFailure(error: IDJIError) { + LogUtils.e(TAG, "stopNetworkRTKService fail:$error") + isHasStartRTK.set(false) + setStartRTKState(false) + + + } + + }) + } + + + /** + * 从本地缓存中获取自定义网络RTK配置信息启动自定义网络RTK + */ + @Synchronized + private fun startRtkCustomNetworkService() { + isHasStartRTK.set(false) + setStartRTKState(true) + LogUtils.i(TAG, "startRtkCustomNetworkService") + val rtkCustomNetworkSetting: RTKCustomNetworkSetting? = RTKUtil.getRtkCustomNetworkSetting() + if (rtkCustomNetworkSetting == null) { + setStartRTKState(false) + LogUtils.e(TAG, "get rtkCustomNetworkSetting == null,startRtkCustomNetworkService finish!") + return + } + rtkCustomNetworkSetting.let { + LogUtils.i(TAG, "rtkCustomNetworkSetting=$it") + customManager.stopNetworkRTKService(object : CommonCallbacks.CompletionCallback { + override fun onSuccess() { + customManager.customNetworkRTKSettings = it + customManager.startNetworkRTKService(object : + CommonCallbacks.CompletionCallback { + override fun onSuccess() { + LogUtils.i(TAG, "startRtkCustomNetworkService success") + setStartRTKState(false) + isHasStartRTK.set(true) + + } + + override fun onFailure(error: IDJIError) { + LogUtils.e(TAG, "startRtkCustomNetworkService fail:$error") + setStartRTKState(false) + isHasStartRTK.set(false) + if (isStartByUser) { + ViewUtil.showToast(ContextUtil.getContext(),R.string.uxsdk_rtk_setting_menu_customer_rtk_save_failed_tips,Toast.LENGTH_SHORT) + } + + } + + }) + } + + override fun onFailure(error: IDJIError) { + LogUtils.e(TAG, "stopNetworkRTKService fail:$error") + setStartRTKState(false) + isHasStartRTK.set(false) + + + } + + }) + } + + + } + + + /** + * 是否允许启动网络RTK (未判断网络数据模式) + */ + private fun isNeedStartRtkNetworkService(): Boolean { + val isConnected: Boolean = FlightControllerKey.KeyConnection.create().get(false) + return (isConnected + && isNetworkRTK(rtkSource) + && NetworkUtils.isNetworkAvailable() + && !isChannelB() + && rtkModuleAvailableProcessor.value) + && !isStartRTKing.get() + } + + + //后续供其他RTK相关Widget使用 + val rtkModuleAvailable: Flowable + get() = rtkModuleAvailableProcessor.toFlowable() + + /** + * 判断一个差分数据源是否是网络RTK + */ + fun isNetworkRTK(source: RTKReferenceStationSource?): Boolean { + return when (source) { + RTKReferenceStationSource.QX_NETWORK_SERVICE, + RTKReferenceStationSource.CUSTOM_NETWORK_SERVICE, + RTKReferenceStationSource.NTRIP_NETWORK_SERVICE, + -> true + else -> false + } + } + + /** + * 是否为B控,非双控机型返回false + */ + fun isChannelB(): Boolean { + return RCMode.CHANNEL_B == RemoteControllerKey.KeyRcMachineMode.create().get(RCMode.UNKNOWN) + } + + private fun setStartRTKState(isRTKStart: Boolean) { + if (isRTKStart) { + isStartRTKing.set(true) + handle.postDelayed({ + LogUtils.e(TAG, "start rtk service timeout") + isStartRTKing.set(false) + }, 15 * 1000) + } else { + isStartRTKing.set(false) + handle.removeCallbacksAndMessages(null) + } + } + + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKStationConnectWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKStationConnectWidget.kt new file mode 100644 index 00000000..b8a70683 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKStationConnectWidget.kt @@ -0,0 +1,393 @@ +package dji.v5.ux.accessory + +import android.content.Context +import android.os.Looper +import android.text.SpannableStringBuilder +import android.text.Spanned +import android.text.TextPaint +import android.text.method.LinkMovementMethod +import android.text.style.ClickableSpan +import android.text.style.ForegroundColorSpan +import android.util.AttributeSet +import android.view.View +import android.widget.Button +import android.widget.ImageView +import android.widget.TextView +import android.widget.Toast +import androidx.constraintlayout.widget.ConstraintLayout +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import dji.sdk.keyvalue.value.rtkbasestation.RTKStationConnetState +import dji.sdk.keyvalue.value.rtkbasestation.RTKStationInfo +import dji.v5.manager.aircraft.rtk.RTKCenter +import dji.v5.manager.aircraft.rtk.station.ConnectedRTKStationInfo +import dji.v5.utils.common.LogUtils +import dji.v5.utils.common.StringUtils +import dji.v5.ux.R +import dji.v5.ux.accessory.data.DJIRTKBaseStationConnectInfo +import dji.v5.ux.accessory.data.RtkStationScanAdapter +import dji.v5.ux.accessory.item.RtkGuidanceView +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.extension.hide +import dji.v5.ux.core.extension.show +import io.reactivex.rxjava3.core.Observable +import io.reactivex.rxjava3.disposables.Disposable +import java.util.concurrent.TimeUnit + +/** + * Description :D-RTK2 扫描连接Widget + * + * @author: Byte.Cai + * date : 2022/9/1 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ +private const val TAG = "RTKStationConnectWidget" + +class RTKStationConnectWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, +) : ConstraintLayoutWidget(context, attrs, defStyleAttr), RtkStationScanAdapter.OnItemClickListener, View.OnClickListener { + private var rtkStationScanAdapter: RtkStationScanAdapter + private val stationList = ArrayList() + private val searchBt: Button = findViewById(R.id.bt_rtk_signal_search_again) + private val checkReasonTv: TextView = findViewById(R.id.tv_rtk_signal_problem_checked_reason) + private val searchIv: ImageView = findViewById(R.id.iv_rtk_signal_search_iv) + private val stationListView: RecyclerView = findViewById(R.id.rl_rtk_signal_searching_list) + private val stationScanningView: ConstraintLayout = findViewById(R.id.cl_rtk_has_found) + private val stationHasNotFoundView: ConstraintLayout = findViewById(R.id.cl_rtk_not_found) + private var connectState = RTKStationConnetState.UNKNOWN + private val scanHandler = android.os.Handler(Looper.getMainLooper()) + private var scanTimeOutDisposable: Disposable? = null + private var isMotorOn = false + private var firstEnter = false + private val SCAN_TIME_OUT = 5.0 + + private val widgetModel by lazy { + RTKStationConnectWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + RTKCenter.getInstance() + ) + } + + init { + //初始化stationTRTK列表 + val layoutManager = LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false) + stationListView.layoutManager = layoutManager + rtkStationScanAdapter = RtkStationScanAdapter(getContext(), stationList) + stationListView.adapter = rtkStationScanAdapter + searchBt.setOnClickListener(this) + searchIv.setOnClickListener(this) + rtkStationScanAdapter.setOnItemClickListener(this) + initCheckReasonContent() + + } + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + inflate(context, R.layout.uxsdk_widget_rtk_connect_status_layout, this) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + firstEnter = true + } + + /** + * 初始化CheckReason View的属性 + */ + private fun initCheckReasonContent() { + val reason: String = StringUtils.getResStr(R.string.uxsdk_rtk_base_station_not_found_reason) + val description: String = StringUtils.getResStr(R.string.uxsdk_rtk_connect_description) + //设置mCheckReasonTv的部分内容可点击属性 + val spannableStringBuilder = SpannableStringBuilder() + spannableStringBuilder.append(reason).append(" ").append(description) + //mCheckReasonTv的部分内容点击事件 + val clickableSpan: ClickableSpan = object : ClickableSpan() { + override fun onClick(view: View) { + //RTK引导界面 + val guidanceView = RtkGuidanceView(context) + guidanceView.showPopupWindow(view) + } + + override fun updateDrawState(ds: TextPaint) { + ds.isUnderlineText = false + } + } + //点击范围为description部分 + spannableStringBuilder.setSpan(clickableSpan, reason.length, spannableStringBuilder.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) + //设置可点击部分的字体颜色 + val foregroundColorSpan = ForegroundColorSpan(resources.getColor(R.color.uxsdk_blue_highlight)) + spannableStringBuilder.setSpan(foregroundColorSpan, reason.length + 1, spannableStringBuilder.length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) + //设置为超链接方式 + checkReasonTv.movementMethod = LinkMovementMethod.getInstance() + checkReasonTv.text = spannableStringBuilder + } + + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun onClick(v: View?) { + when (v?.id) { + R.id.iv_rtk_signal_search_iv, + R.id.bt_rtk_signal_search_again, + -> startScanning() + } + } + + override fun reactToModelChanges() { + addReaction(widgetModel.connectedRTKStationInfo.observeOn(SchedulerProvider.ui()).subscribe { + handleReconnectedStationInfo(it) + }) + addReaction(widgetModel.isMotorOn.subscribe { + isMotorOn = it + }) + addReaction(widgetModel.stationConnectStatus.observeOn(SchedulerProvider.ui()).subscribe { + updateConnectStatus(it) + }) + addReaction(widgetModel.stationList.observeOn(SchedulerProvider.ui()).subscribe { + handleStationRTKList(it) + }) + + } + + override fun getIdealDimensionRatioString(): String? { + return getString(R.string.uxsdk_widget_rtk_keep_status_ratio) + } + + + private fun updateRefreshUI(boolean: Boolean) { + //底部的重新扫描按钮是否可点击 + searchBt.isClickable = boolean + searchBt.setBackgroundResource(if (boolean) R.drawable.uxsdk_bg_white_radius else R.drawable.uxsdk_bg_gray_radius) + searchIv.visibility = if (boolean) visibility else GONE + } + + private fun handleStationRTKList(list: List?) { + //过滤重复的数据,防止界面重新刷新 + if (checkNeedUpdateUI(list)) { + stationList.clear() + LogUtils.i(TAG, "has found rtk,clear stationList") + list?.let { + for (i in it) { + LogUtils.i(TAG, "stationName=${i.rtkStationName},signalLevel=${i.signalLevel}") + stationList.add(i) + } + } + searchIv.setImageResource(R.drawable.uxsdk_ic_refresh) + rtkStationScanAdapter.notifyDataSetChanged() + } + } + + private fun updateConnectStatus(rtkBaseStationConnectState: RTKStationConnetState?) { + if (rtkBaseStationConnectState == null) { + return + } + + LogUtils.i(TAG, "Current station status is $rtkBaseStationConnectState") + when (rtkBaseStationConnectState) { + RTKStationConnetState.IDLE, + RTKStationConnetState.UNKNOWN, + -> { + if (firstEnter) { + LogUtils.i(TAG, "first enter,startScanning auto") + firstEnter = false + updateConnectStatus(RTKStationConnetState.SCANNING) + //这里延时2秒发送扫描命令,避免针对已连上RTK的设备(固件底层会自动重连),再次扫描固件自动重连逻辑会被破坏 + scanHandler.postDelayed({ + startScanning() + }, 2000) + } else { + searchIv.setImageResource(R.drawable.uxsdk_ic_refresh) + } + } + RTKStationConnetState.DISCONNECTED -> { + stationHasNotFoundView.hide() + stationScanningView.show() + searchIv.setImageResource(R.drawable.uxsdk_ic_refresh) + Toast.makeText(context, "Station has disconnected", Toast.LENGTH_SHORT).show() + } + RTKStationConnetState.SCANNING -> { + stationHasNotFoundView.hide() + stationScanningView.show() + searchIv.setImageResource(R.drawable.uxsdk_rotate_progress_circle) + LogUtils.i(TAG, "scan rtk ing...") + + } + RTKStationConnetState.CONNECTED -> { + LogUtils.i(TAG, "rtk has connected") + stationHasNotFoundView.hide() + stationScanningView.show() + searchIv.setImageResource(R.drawable.uxsdk_ic_refresh) + //将连接成功的基站放在列表首页 + if (stationList.remove(selectedRTKStationConnectInfo)) { + stationList.add(0, selectedRTKStationConnectInfo) + } + rtkStationScanAdapter.notifyDataSetChanged() + + } + else -> { + stationHasNotFoundView.hide() + stationScanningView.show() + searchIv.setImageResource(R.drawable.uxsdk_ic_refresh) + } + } + connectState = rtkBaseStationConnectState + //返回连接状态,更新UI + selectedRTKStationConnectInfo.refresh(rtkBaseStationConnectState) + //飞行过程中不允许点击扫描按钮 + updateRefreshUI(!isMotorOn) + + } + + + private fun checkNeedUpdateUI(list: List?): Boolean { + if (list?.size != stationList.size) { + return true + } + if (!stationList.containsAll(list) || !list.containsAll(stationList)) { + return true + } + return false + } + + + /** + * 选中某个基站,注意这里selectedRTKStationConnectInfo不能初始化为null + */ + private var selectedRTKStationConnectInfo: DJIRTKBaseStationConnectInfo = DJIRTKBaseStationConnectInfo() + override fun onItemClick(view: View?, position: Int) { + selectedRTKStationConnectInfo = stationList[position] + LogUtils.i(TAG, "click and connecting rtk:$selectedRTKStationConnectInfo") + //连接某一个基站时,将其他基站的连接状态重置为空闲,因为一次只能连接一个基站 + for (stationInfo in stationList) { + stationInfo.connectStatus = RTKStationConnetState.IDLE + } + selectedRTKStationConnectInfo.refresh(RTKStationConnetState.CONNECTING) + startConnectStation(selectedRTKStationConnectInfo) + + } + + private fun DJIRTKBaseStationConnectInfo.refresh(connectState: RTKStationConnetState?) { + connectState?.let { + LogUtils.i(TAG, "connectState=$connectState") + this.connectStatus = it + } + rtkStationScanAdapter.notifyDataSetChanged() + + } + + + private fun startConnectStation(selectedRTKStationConnectInfo: DJIRTKBaseStationConnectInfo) { + selectedRTKStationConnectInfo.run { + addDisposable(widgetModel.startConnectToRTKStation(baseStationId).observeOn(SchedulerProvider.ui()).subscribe({ + LogUtils.i(TAG, "$rtkStationName connect success") + }, { + //连接失败,恢复未连接状态 + selectedRTKStationConnectInfo.refresh(RTKStationConnetState.IDLE) + Toast.makeText(context, StringUtils.getResStr(R.string.uxsdk_rtk_base_station_connect_fail), Toast.LENGTH_SHORT).show() + LogUtils.e(TAG, "${selectedRTKStationConnectInfo.rtkStationName}connect fail!!!") + })) + } + } + + private fun startScanning() { + LogUtils.i(TAG, "startScanning now") + //添加计时器 + scanTimeOut() + //清除已有的基站列表 + stationList.clear() + rtkStationScanAdapter.notifyDataSetChanged() + //发送命令开始扫描 + addDisposable(widgetModel.startSearchStationRTK().observeOn(SchedulerProvider.ui()).subscribe({ + stationHasNotFoundView.hide() + stationScanningView.show() + }, { + stationHasNotFoundView.show() + stationScanningView.hide() + Toast.makeText(context, StringUtils.getResStr(R.string.uxsdk_rtk_base_station_search_false_and_try_again), Toast.LENGTH_SHORT).show() + LogUtils.e(TAG, "startSearchStationRTK fail:${it.localizedMessage}") + + })) + //某些情况下不会返回状态,需要手动更新状态 + updateConnectStatus(RTKStationConnetState.SCANNING) + } + + + private fun scanTimeOut() { + disposeTimeout(scanTimeOutDisposable) + scanTimeOutDisposable = Observable.timer(SCAN_TIME_OUT.toLong(), TimeUnit.SECONDS) + .observeOn(SchedulerProvider.ui()).subscribe({ + if (!isHasFoundRTK()) { + LogUtils.e(TAG, "scanTimeOut ,stop search station RTK") + //扫描到基站列表超时,则停止扫描;同时展示RTK找不到的布局, + stationHasNotFoundView.show() + stationScanningView.hide() + widgetModel.stopSearchStationRTK() + //停止扫码不会返回状态,需要手动更新状态 + updateConnectStatus(RTKStationConnetState.IDLE) + } else { + LogUtils.i(TAG, "scan finish,has found rtk") + //扫描到基站,则隐藏基站未找到的界面,显示基站列表页,同时更新对应刷新Image Icon为刷新图片 + stationHasNotFoundView.hide() + stationScanningView.show() + //停止扫描 + widgetModel.stopSearchStationRTK() + searchIv.setImageResource(R.drawable.uxsdk_ic_refresh) + + } + }, { + LogUtils.e(TAG, it.localizedMessage) + disposeTimeout(scanTimeOutDisposable) + }) + scanTimeOutDisposable?.let { + if (!it.isDisposed) { + addDisposable(it) + } + } + } + + + private fun isHasFoundRTK(): Boolean { + return connectState == RTKStationConnetState.CONNECTED || connectState == RTKStationConnetState.CONNECTING || stationList.isNotEmpty() + } + + /** + * 关闭计时器 + */ + private fun disposeTimeout(timeOutDisposable: Disposable?) { + timeOutDisposable?.let { + if (!it.isDisposed) { + it.dispose() + } + } + } + + + private fun handleReconnectedStationInfo(infoConnected: ConnectedRTKStationInfo?) { + infoConnected?.run { + //第一次连接过基站后,再次重启飞机或者重启App固件会帮忙自动连接基站。这里就是为了构建自动重连的基站信息 + if (selectedRTKStationConnectInfo.baseStationId == 0) { + LogUtils.i(TAG, "RTK Station has reconnected and remove scanHandler message") + selectedRTKStationConnectInfo = DJIRTKBaseStationConnectInfo(stationId, signalLevel, stationName, RTKStationConnetState.CONNECTED) + scanHandler.removeCallbacksAndMessages(null) + updateConnectStatus(RTKStationConnetState.CONNECTED) + handleStationRTKList(arrayListOf(selectedRTKStationConnectInfo)) + } + } + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKStationConnectWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKStationConnectWidgetModel.kt new file mode 100644 index 00000000..30402472 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKStationConnectWidgetModel.kt @@ -0,0 +1,161 @@ +package dji.v5.ux.accessory + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.value.rtkbasestation.RTKStationConnetState +import dji.sdk.keyvalue.value.rtkbasestation.RTKStationInfo +import dji.v5.common.callback.CommonCallbacks +import dji.v5.common.error.IDJIError +import dji.v5.common.error.RxError +import dji.v5.manager.aircraft.rtk.station.ConnectedRTKStationInfo +import dji.v5.manager.aircraft.rtk.station.ConnectedRTKStationInfoListener +import dji.v5.manager.aircraft.rtk.station.RTKStationConnectStatusListener +import dji.v5.manager.aircraft.rtk.station.SearchRTKStationListener +import dji.v5.manager.interfaces.IRTKCenter +import dji.v5.ux.accessory.data.DJIRTKBaseStationConnectInfo +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.* +import io.reactivex.rxjava3.processors.BehaviorProcessor +import io.reactivex.rxjava3.schedulers.Schedulers +import java.util.ArrayList + +/** + * Description :Widget Model for the [RTKStationConnectWidget] used to define + * the underlying logic and communication + * + * @author: Byte.Cai + * date : 2022/9/1 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ +class RTKStationConnectWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, + val rtkCenter: IRTKCenter, +) : WidgetModel(djiSdkModel, keyedStore) { + private val rtkStationManager = rtkCenter.rtkStationManager + private val rtkStationConnectStateProcessor: DataProcessor = + DataProcessor.create(RTKStationConnetState.UNKNOWN) + + private val stationListProcessor: DataProcessor> = + DataProcessor.create(arrayListOf()) + + private val connectedRTKStationInfoProcessor: BehaviorProcessor = + BehaviorProcessor.create() + private val isMotorOnProcessor: DataProcessor = DataProcessor.create(false) + private val stationConnectStatusListener = + RTKStationConnectStatusListener { rtkBaseStationConnectState -> + rtkStationConnectStateProcessor.onNext(rtkBaseStationConnectState) + } + + private val connectedRTKStationInfoListener = + ConnectedRTKStationInfoListener { + connectedRTKStationInfoProcessor.onNext(it) + } + private val searchStationListener = + SearchRTKStationListener { newConnectInfoList -> + val convertToDJIRTKBaseStationConnectInfo = convertToDJIRTKBaseStationConnectInfo(newConnectInfoList) + stationListProcessor.onNext(convertToDJIRTKBaseStationConnectInfo) + } + + val isMotorOn: Flowable + get() = isMotorOnProcessor.toFlowable() + + val stationConnectStatus: Flowable + get() = rtkStationConnectStateProcessor.toFlowable() + + val connectedRTKStationInfo: Flowable + get() = connectedRTKStationInfoProcessor.observeOn(SchedulerProvider.computation()).onBackpressureLatest() + + val stationList: Flowable> + get() = stationListProcessor.toFlowable() + + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAreMotorsOn), isMotorOnProcessor) + rtkStationManager.addRTKStationConnectStatusListener(stationConnectStatusListener) + rtkStationManager.addConnectedRTKStationInfoListener(connectedRTKStationInfoListener) + rtkStationManager.addSearchRTKStationListener(searchStationListener) + } + + override fun inCleanup() { + rtkStationManager.removeRTKStationConnectStatusListener(stationConnectStatusListener) + rtkStationManager.removeConnectedRTKStationInfoListener(connectedRTKStationInfoListener) + rtkStationManager.removeSearchRTKStationListener(searchStationListener) + } + + fun startConnectToRTKStation(stationId: Int): Single { + return Single.create(SingleOnSubscribe { + rtkStationManager.startConnectToRTKStation(stationId, object : + CommonCallbacks.CompletionCallback { + override fun onSuccess() { + it.onSuccess(true) + } + + override fun onFailure(error: IDJIError) { + it.onError(RxError(error)) + } + + }) + }).subscribeOn(Schedulers.computation()) + + } + + fun startSearchStationRTK(): Single { + return Single.create(SingleOnSubscribe { + rtkStationManager.startSearchRTKStation(object : + CommonCallbacks.CompletionCallback { + override fun onSuccess() { + it.onSuccess(true) + } + + override fun onFailure(error: IDJIError) { + it.onError(RxError(error)) + } + + }) + }).subscribeOn(Schedulers.computation()) + } + + fun stopSearchStationRTK(): Single { + return Single.create(SingleOnSubscribe { + rtkStationManager.startSearchRTKStation(object : + CommonCallbacks.CompletionCallback { + override fun onSuccess() { + it.onSuccess(true) + } + + override fun onFailure(error: IDJIError) { + it.onError(RxError(error)) + } + + }) + }).subscribeOn(Schedulers.computation()) + } + + + private fun convertToDJIRTKBaseStationConnectInfo(list: List?): ArrayList { + val djiRTKBaseStationConnectInfoList = ArrayList() + list?.let { + for (i in list) { + val djirtkBaseStationConnectInfo = i.toDJIRTKBaseStationConnectInfo() + djiRTKBaseStationConnectInfoList.add(djirtkBaseStationConnectInfo) + } + } + return djiRTKBaseStationConnectInfoList + + } + + private fun RTKStationInfo.toDJIRTKBaseStationConnectInfo(): DJIRTKBaseStationConnectInfo { + val baseStationId = this.stationId + val name = this.stationName + val signalLevel = this.signalLevel + return DJIRTKBaseStationConnectInfo(baseStationId, signalLevel, name) + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKTypeSwitchWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKTypeSwitchWidget.kt new file mode 100644 index 00000000..f0b25560 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKTypeSwitchWidget.kt @@ -0,0 +1,447 @@ +package dji.v5.ux.accessory + +import android.content.Context +import android.text.TextUtils +import android.util.AttributeSet +import android.widget.Button +import android.widget.LinearLayout +import android.widget.TextView +import android.widget.Toast +import dji.rtk.CoordinateSystem +import dji.sdk.keyvalue.value.rtkbasestation.RTKCustomNetworkSetting +import dji.sdk.keyvalue.value.rtkbasestation.RTKReferenceStationSource +import dji.v5.common.callback.CommonCallbacks +import dji.v5.common.error.IDJIError +import dji.v5.manager.aircraft.rtk.RTKCenter +import dji.v5.manager.areacode.AreaCodeManager +import dji.v5.utils.common.LogUtils +import dji.v5.utils.common.StringUtils +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.extension.hide +import dji.v5.ux.core.extension.isFastClick +import dji.v5.ux.core.extension.show +import dji.v5.ux.core.util.ViewUtil +import dji.v5.ux.util.RtkSettingWatcher + +/** + * Description :基站启动页 + * + * @author: Byte.Cai + * date : 2022/8/1 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ +private const val TAG = "RTKTypeSwitchWidget" + +open class RTKTypeSwitchWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, +) : ConstraintLayoutWidget(context, attrs, defStyleAttr), RtkSettingWatcher.OnEditTextEmptyChangedListener { + private val rtkTypeCell: DescSpinnerCell = findViewById(R.id.cell_rtk_type) + private val coordinateSystemCell: DescSpinnerCell = findViewById(R.id.cell_coordinate_system) + private val edHost: TextView = findViewById(R.id.net_rtk_ntrip_host) + private val edPort: TextView = findViewById(R.id.net_rtk_ntrip_port) + private val edUser: TextView = findViewById(R.id.net_rtk_ntrip_user) + private val edMountPoint: TextView = findViewById(R.id.net_rtk_ntrip_mountpoint) + private val edPassword: TextView = findViewById(R.id.net_rtk_ntrip_pwd) + private val btSaveRtkInfo: Button = findViewById(R.id.btn_set_net_rtk_info) + private val customSetting: LinearLayout = findViewById(R.id.ll_rtk_custom_detail_view) + + private var rtkSourceList: List = ArrayList() + private var coordinateSystemList: List = arrayListOf() + private var isMotorsOn = false + private var currentRTKSource: RTKReferenceStationSource = RTKReferenceStationSource.UNKNOWN + private val textWatcher = RtkSettingWatcher(this) + private val INITIAL_INDEX: Int = -1 + private var lastSelectedRTKTypeIndex: Int = INITIAL_INDEX + private var lastSelectedCoordinateSystemIndex: Int = INITIAL_INDEX + + private val widgetModel by lazy { + RTKTypeSwitchWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + AreaCodeManager.getInstance(), RTKCenter.getInstance()) + } + + private val rtkTypeSelectListener = object : DescSpinnerCell.OnItemSelectedListener { + override fun onItemSelected(position: Int) { + if (position == lastSelectedRTKTypeIndex) { + return + } + // B控不可以打开网络RTK。 + if (RTKStartServiceHelper.isChannelB() && RTKStartServiceHelper.isNetworkRTK(rtkSourceList[position])) { + //回滚之前的选择,并提示用户 + rtkTypeCell.select(lastSelectedRTKTypeIndex) + Toast.makeText(getContext(), getTip(position), Toast.LENGTH_SHORT).show() + return + } + //电机起转后,并且选择过服务类型,则不允许再次切换RTK类型 + if (isMotorsOn && lastSelectedRTKTypeIndex != -1) { + rtkTypeCell.select(lastSelectedRTKTypeIndex) + val tip = StringUtils.getResStr(R.string.uxsdk_rtk_setting_menu_esc_beeping_tip) + Toast.makeText(getContext(), tip, Toast.LENGTH_SHORT).show() + return + } + setRTKType(position) + } + + } + + private val coordinateSelectListener = object : DescSpinnerCell.OnItemSelectedListener { + override fun onItemSelected(position: Int) { + if (position == lastSelectedCoordinateSystemIndex || coordinateSystemList.isEmpty() || position >= coordinateSystemList.size || position < 0) { + return + } + lastSelectedCoordinateSystemIndex = position + val coordinate = coordinateSystemList[position] + RTKUtil.saveRTKCoordinateSystem(currentRTKSource, coordinate) + LogUtils.i(TAG, "select:$coordinate, reStartRtkService now!(Thread.currentThread().name${Thread.currentThread().name})") + RTKStartServiceHelper.startRtkService(true) + } + } + + + init { + edHost.addTextChangedListener(textWatcher) + edUser.addTextChangedListener(textWatcher) + edPassword.addTextChangedListener(textWatcher) + edMountPoint.addTextChangedListener(textWatcher) + edPort.addTextChangedListener(textWatcher) + btSaveRtkInfo.setOnClickListener { + if (!btSaveRtkInfo.isFastClick()) { + saveRtkCustomUserInfo() + } + } + //读取默认的配置,并启动RTK + LogUtils.i(TAG, "RTKTypeSwitchWidget init,startRtkService now!(Thread.currentThread().name=${Thread.currentThread().name})") + RTKStartServiceHelper.startRtkService() + } + + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + inflate(context, R.layout.uxsdk_widget_rtk_type_switch, this) + } + + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + edHost.removeTextChangedListener(textWatcher) + edUser.removeTextChangedListener(textWatcher) + edMountPoint.removeTextChangedListener(textWatcher) + edPort.removeTextChangedListener(textWatcher) + edPassword.removeTextChangedListener(textWatcher) + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.isMotorsOn.subscribe { + isMotorsOn = it + }) + addReaction(widgetModel.rtkSource.observeOn(SchedulerProvider.ui()).subscribe { + LogUtils.i(TAG, "currentRTKSource=$it") + //获取RTK服务类型,并切换UI + currentRTKSource = it + updateRTKView() + initDefaultNetRtkUI() + }) + addReaction(widgetModel.supportReferenceStationList.observeOn(SchedulerProvider.ui()).subscribe { + //更新支持的RTK列表 + if (it.isNotEmpty() && !rtkSourceList.containsAll(it)) { + LogUtils.i(TAG, "supportReferenceStationList=$it") + rtkSourceList = it + val referenceStationSourceNames = getReferenceStationSourceNames(it) + rtkTypeCell.setEntries(referenceStationSourceNames) + rtkTypeCell.addOnItemSelectedListener(rtkTypeSelectListener) + initDefaultNetRtkUI() + } + }) + + addReaction(widgetModel.coordinateSystemList.observeOn(SchedulerProvider.ui()).subscribe { + LogUtils.i(TAG, "coordinateSystemList=$it") + //更新坐标系 + if (it.isNotEmpty() && !coordinateSystemList.containsAll(it)) { + LogUtils.i(TAG, "coordinateSystemList=$it") + coordinateSystemList = it + coordinateSystemCell.addOnItemSelectedListener(null) + coordinateSystemCell.setEntries(getCoordinateSystemName(it)) + coordinateSystemCell.addOnItemSelectedListener(coordinateSelectListener) + initDefaultNetRtkUI() + } + }) + + //进入App后初始化用户上次选择 + initDefaultCustomSetting() + + } + + override fun getIdealDimensionRatioString(): String? { + return getString(R.string.uxsdk_widget_rtk_keep_status_ratio) + } + + private fun setRTKType(position: Int) { + if (rtkSourceList.isEmpty() || position >= rtkSourceList.size || position < 0) { + return + } + val rtkSource: RTKReferenceStationSource = rtkSourceList[position] + LogUtils.i(TAG, "selected $rtkSource") + rtkTypeCell.isEnabled = false + + RTKCenter.getInstance().setRTKReferenceStationSource(rtkSource, object : CommonCallbacks.CompletionCallback { + override fun onSuccess() { + lastSelectedRTKTypeIndex = position + rtkTypeCell.isEnabled = true + } + + override fun onFailure(error: IDJIError) { + rtkTypeCell.isEnabled = true + //切换RTK服务类型失败,回滚到上次选择 + for ((index, source) in rtkSourceList.withIndex()) { + if (source == currentRTKSource) { + rtkTypeCell.select(index) + } + } + } + + }) + } + + + private fun updateRTKView() { + val rtkSwitchDec = StringUtils.getResStr(R.string.uxsdk_rtk_setting_menu_switch_des_info) + var rtkSwitchDecDetail = "" + when (currentRTKSource) { + RTKReferenceStationSource.BASE_STATION -> { + customSetting.hide() + coordinateSystemCell.hide() + rtkSwitchDecDetail = StringUtils.getResStr(R.string.uxsdk_rtk_setting_menu_base_gps_input_desc) + } + RTKReferenceStationSource.QX_NETWORK_SERVICE, + RTKReferenceStationSource.NTRIP_NETWORK_SERVICE, + -> { + if (!RTKStartServiceHelper.isChannelB()) { + customSetting.hide() + coordinateSystemCell.show() + } else { + customSetting.hide() + coordinateSystemCell.hide() + } + rtkSwitchDecDetail = StringUtils.getResStr(R.string.uxsdk_rtk_setting_menu_station_net_rtk_desc) + } + RTKReferenceStationSource.CUSTOM_NETWORK_SERVICE -> { + if (!RTKStartServiceHelper.isChannelB()) { + customSetting.show() + coordinateSystemCell.hide() + } else { + customSetting.hide() + coordinateSystemCell.hide() + } + rtkSwitchDecDetail = StringUtils.getResStr(R.string.uxsdk_rtk_setting_menu_station_net_rtk_desc) + } + else -> { + customSetting.hide() + coordinateSystemCell.hide() + } + } + if (TextUtils.isEmpty(rtkSwitchDecDetail)) { + rtkTypeCell.setSDescText(rtkSwitchDec) + } else { + rtkTypeCell.setSDescText(rtkSwitchDec + "\n" + rtkSwitchDecDetail) + } + } + + private fun getReferenceStationSourceNames(list: List): List { + return list.map { + val res = when (it) { + RTKReferenceStationSource.BASE_STATION -> + R.string.uxsdk_rtk_setting_menu_type_rtk_station + RTKReferenceStationSource.CUSTOM_NETWORK_SERVICE -> + R.string.uxsdk_rtk_setting_menu_type_custom_rtk + RTKReferenceStationSource.QX_NETWORK_SERVICE -> + R.string.uxsdk_rtk_setting_menu_type_qx_rtk + RTKReferenceStationSource.NTRIP_NETWORK_SERVICE -> + R.string.uxsdk_rtk_setting_menu_type_cmcc_rtk + else -> + R.string.uxsdk_rtk_setting_menu_type_rtk_none + } + StringUtils.getResStr(res) + } + + } + + private fun getCoordinateSystemName(list: List): List { + return list.map { + val coordinateName: String = when (it) { + CoordinateSystem.CGCS2000 -> + CoordinateSystem.CGCS2000.name + CoordinateSystem.WGS84 -> + CoordinateSystem.WGS84.name + else -> { + LogUtils.e(TAG, "UnSupport CoordinateSystem:$it") + CoordinateSystem.UNKNOWN.name + } + } + coordinateName + } + } + + private fun getTip(position: Int): String { + return if (rtkSourceList[position] == RTKReferenceStationSource.QX_NETWORK_SERVICE || rtkSourceList[position] == RTKReferenceStationSource.NTRIP_NETWORK_SERVICE) { + StringUtils.getResStr(R.string.uxsdk_rtk_channel_b_not_support_net_rtk) + } else { + StringUtils.getResStr(R.string.uxsdk_rtk_channel_b_not_support_net_custom_rtk) + } + } + + override fun `isTextEmptyChanged`() { + //检查RTK设置项的填写状态,并更新设置button的状态 + var shouldEnableButton = true + if (TextUtils.isEmpty(edUser.text)) { + shouldEnableButton = false + } + if (TextUtils.isEmpty(edHost.text)) { + shouldEnableButton = false + } + if (TextUtils.isEmpty(edMountPoint.text)) { + shouldEnableButton = false + } + if (TextUtils.isEmpty(edPort.text)) { + shouldEnableButton = false + } + if (TextUtils.isEmpty(edPassword.text)) { + shouldEnableButton = false + } + //根据各项填写情况,更新保存按钮的值 + if (shouldEnableButton) { + btSaveRtkInfo.isEnabled = true + btSaveRtkInfo.setTextColor(resources.getColor(R.color.uxsdk_setting_menu_rtk_tiny_green)) + } else { + btSaveRtkInfo.isEnabled = false + btSaveRtkInfo.setTextColor(resources.getColor(R.color.uxsdk_setting_menu_rtk_txt_gray)) + + } + } + + private fun saveRtkCustomUserInfo() { + // 检查输入是否有效 + var isHostValid = true + var isPortValid = true + var isUserValid = true + var isPwdValid = true + var isMountPointValid = true + val host: String = edHost.text.toString() + if (TextUtils.isEmpty(host)) { + isHostValid = false + } + + val portStr: String = edPort.text.toString() + var port = -1 + if (!TextUtils.isEmpty(portStr) && TextUtils.isDigitsOnly(portStr)) { + port = portStr.toInt() + if (port < 0) { + isPortValid = false + } + } else { + isPortValid = false + } + + val user: String = edUser.text.toString() + if (TextUtils.isEmpty(user)) { + isUserValid = false + } + + val pw: String = edPassword.text.toString() + if (TextUtils.isEmpty(pw)) { + isPwdValid = false + } + + val mountPint: String = edMountPoint.text.toString() + if (TextUtils.isEmpty(mountPint)) { + isMountPointValid = false + } + + + // 参数无效,select设为true时,EditText边框设为红色 + edHost.isSelected = !isHostValid + edPort.isSelected = !isPortValid + edUser.isSelected = !isUserValid + edPassword.isSelected = !isPwdValid + edMountPoint.isSelected = !isMountPointValid + + val isParamsValid = (isHostValid && isMountPointValid + && isPortValid && isUserValid && isPwdValid) + if (!isParamsValid) { + ViewUtil.showToast(context, R.string.uxsdk_rtk_setting_menu_customer_rtk_save_failed_tips, Toast.LENGTH_SHORT) + return + } + startRtkCustomNetwork(host, port, user, pw, mountPint) + + } + + private fun startRtkCustomNetwork(host: String, port: Int, user: String, pw: String, mountPint: String) { + val rtkSetting = RTKCustomNetworkSetting() + rtkSetting.serverAddress = host + rtkSetting.port = port + rtkSetting.userName = user + rtkSetting.password = pw + rtkSetting.mountPoint = mountPint + RTKUtil.saveRtkCustomNetworkSetting(rtkSetting) + LogUtils.i(TAG, "rtkSetting=$rtkSetting,startRtkCustomNetwork now!(Thread.currentThread().name${Thread.currentThread().name})") + RTKStartServiceHelper.startRtkService(true) + } + + /** + * 初始化用户设置的自定义网络RTK设置的信息 + */ + private fun initDefaultCustomSetting() { + RTKUtil.getRtkCustomNetworkSetting()?.run { + LogUtils.i(TAG, "getRtkCustomNetworkSetting=$this") + edMountPoint.text = mountPoint + edHost.text = serverAddress + edPassword.text = password + edUser.text = userName + edPort.text = port.toString() + } + isTextEmptyChanged() + } + + private fun initDefaultNetRtkUI() { + //初始化用户上次选择的RTK服务类型 + if (currentRTKSource != RTKReferenceStationSource.UNKNOWN && rtkSourceList.isNotEmpty()) { + for ((index, rtkSource) in rtkSourceList.withIndex()) { + if (rtkSource == currentRTKSource) { + lastSelectedRTKTypeIndex = index + rtkTypeCell.select(index) + } + } + } + + //初始化用户上次选择的坐标系 + val netRTKCoordinateSystem = RTKUtil.getNetRTKCoordinateSystem(currentRTKSource) + for ((index, coordinate) in coordinateSystemList.withIndex()) { + if (netRTKCoordinateSystem == coordinate) { + lastSelectedCoordinateSystemIndex = index + coordinateSystemCell.select(index) + } + + } + + } + + +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKTypeSwitchWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKTypeSwitchWidgetModel.kt new file mode 100644 index 00000000..a13169d7 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKTypeSwitchWidgetModel.kt @@ -0,0 +1,201 @@ +package dji.v5.ux.accessory + +import dji.rtk.CoordinateSystem +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.key.ProductKey +import dji.sdk.keyvalue.utils.ProductUtil +import dji.sdk.keyvalue.value.product.ProductType +import dji.sdk.keyvalue.value.rtkbasestation.RTKReferenceStationSource +import dji.v5.common.utils.RxUtil +import dji.v5.manager.KeyManager +import dji.v5.manager.aircraft.rtk.RTKSystemStateListener +import dji.v5.manager.areacode.AreaCode +import dji.v5.manager.areacode.AreaCodeChangeListener +import dji.v5.manager.areacode.AreaCodeManager +import dji.v5.manager.interfaces.IAreaCodeManager +import dji.v5.manager.interfaces.INetworkRTKManager +import dji.v5.manager.interfaces.IRTKCenter +import dji.v5.utils.common.LogUtils +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Flowable + +/** + * Description : + * + * @author: Byte.Cai + * date : 2022/8/15 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ + +class RTKTypeSwitchWidgetModel( + djiSdkModel: DJISDKModel, + uxKeyManager: ObservableInMemoryKeyedStore, + val areaCodeManager: IAreaCodeManager, + val rtkCenter: IRTKCenter, +) : WidgetModel(djiSdkModel, uxKeyManager) { + + companion object { + private const val TAG = "RTKTypeSwitchWidgetModel" + private const val CUSTOM_RTK_SETTING_CACHE = "customRTKSettingCache" + } + + private val supportReferenceStationListProcessor: DataProcessor> = DataProcessor.create(ArrayList()) + private val areaCodeProcessor: DataProcessor = DataProcessor.create(AreaCode.UNKNOWN.code) + private val productTypeProcessor: DataProcessor = DataProcessor.create(ProductType.UNKNOWN) + private val rtkSourceProcessor: DataProcessor = DataProcessor.create(RTKReferenceStationSource.UNKNOWN) + private val coordinateSystemListProcessor: DataProcessor> = DataProcessor.create(arrayListOf()) + private val isMotorOnProcessor: DataProcessor = DataProcessor.create(false) + private var qxRTKManager: INetworkRTKManager? = null + private var customNetworkRTKManager: INetworkRTKManager? = null + private var currentRtkSource: RTKReferenceStationSource = RTKReferenceStationSource.UNKNOWN + private val areaCodeChangeListener = AreaCodeChangeListener { _, result -> + areaCodeProcessor.onNext(result.areaCode) + updateSupportReferenceStationList() + } + + + private val rtkSystemStateListener = RTKSystemStateListener { + val rtkSource = it.rtkReferenceStationSource + var coordinateSystemList: List = arrayListOf() + when (rtkSource) { + RTKReferenceStationSource.QX_NETWORK_SERVICE, + RTKReferenceStationSource.NTRIP_NETWORK_SERVICE, + -> { + coordinateSystemList = arrayListOf(CoordinateSystem.WGS84, CoordinateSystem.CGCS2000) + } + + else -> { + //Do Nothing + } + } + if (currentRtkSource != rtkSource) { + currentRtkSource = rtkSource + rtkSourceProcessor.onNext(rtkSource) + coordinateSystemListProcessor.onNext(coordinateSystemList) + + } + } + + + val isMotorsOn: Flowable + get() = isMotorOnProcessor.toFlowable() + + val rtkSource: Flowable + get() = rtkSourceProcessor.toFlowable() + + val coordinateSystemList: Flowable> + get() = coordinateSystemListProcessor.toFlowable() + + val supportReferenceStationList: Flowable> + get() = supportReferenceStationListProcessor.toFlowable() + + init { + qxRTKManager = rtkCenter.qxrtkManager + customNetworkRTKManager = rtkCenter.customRTKManager + } + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAreMotorsOn + ), isMotorOnProcessor + ) + addDisposable(RxUtil.addListener( + KeyTools.createKey( + ProductKey.KeyProductType + ), this + ).subscribe { + productTypeProcessor.onNext(it) + updateSupportReferenceStationList() + }) + areaCodeManager.addAreaCodeChangeListener(areaCodeChangeListener) + rtkCenter.addRTKSystemStateListener(rtkSystemStateListener) + + } + + override fun inCleanup() { + areaCodeManager.removeAreaCodeChangeListener(areaCodeChangeListener) + rtkCenter.removeRTKSystemStateListener(rtkSystemStateListener) + KeyManager.getInstance().cancelListen(this) + } + + private fun updateSupportReferenceStationList() { + if (ProductType.DJI_MAVIC_3_ENTERPRISE_SERIES == productTypeProcessor.value) { + when (areaCodeProcessor.value) { + AreaCode.CHINA.code -> { + supportReferenceStationListProcessor.onNext(getSupportReferenceStationSource(true)) + } + + else -> { + supportReferenceStationListProcessor.onNext(getSupportReferenceStationSource(false)) + } + } + } else { + supportReferenceStationListProcessor.onNext(getSupportReferenceStationSource(isInChina())) + } + } + + + /** + * 获取支持的差分数据源 + */ + private fun getSupportReferenceStationSource(supportNetworkRTK: Boolean): List { + return if (ProductUtil.isM3EProduct() || ProductUtil.isM4EProduct() || ProductUtil.isM4DProduct()) { + getMavicSupportReferenceStationSource(supportNetworkRTK) + } else { + getDefaultSupportReferenceStationSource(supportNetworkRTK) + } + } + + + private fun getMavicSupportReferenceStationSource(supportNetworkRTK: Boolean): MutableList { + return if (supportNetworkRTK) { + mutableListOf( + RTKReferenceStationSource.NONE, + RTKReferenceStationSource.BASE_STATION, + RTKReferenceStationSource.NTRIP_NETWORK_SERVICE, + RTKReferenceStationSource.CUSTOM_NETWORK_SERVICE + ) + } else { + mutableListOf( + RTKReferenceStationSource.NONE, + RTKReferenceStationSource.BASE_STATION, + RTKReferenceStationSource.CUSTOM_NETWORK_SERVICE + ) + } + } + + private fun getDefaultSupportReferenceStationSource(supportNetworkRTK: Boolean): MutableList { + LogUtils.i(TAG, "supportNetworkRTK=$supportNetworkRTK") + return if (supportNetworkRTK) { + mutableListOf( + RTKReferenceStationSource.NONE, + RTKReferenceStationSource.BASE_STATION, + RTKReferenceStationSource.QX_NETWORK_SERVICE, + RTKReferenceStationSource.NTRIP_NETWORK_SERVICE, + RTKReferenceStationSource.CUSTOM_NETWORK_SERVICE + ) + } else { + mutableListOf( + RTKReferenceStationSource.NONE, + RTKReferenceStationSource.BASE_STATION, + RTKReferenceStationSource.CUSTOM_NETWORK_SERVICE + ) + } + } + + + /** + * 是否在中国 + */ + private fun isInChina(): Boolean { + val countryCode = AreaCodeManager.getInstance().areaCode.areaCode + return AreaCode.CHINA.code.equals(countryCode) + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKUtil.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKUtil.kt new file mode 100644 index 00000000..e25463b5 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKUtil.kt @@ -0,0 +1,129 @@ +package dji.v5.ux.accessory + +import android.text.TextUtils +import android.view.View +import dji.rtk.CoordinateSystem +import dji.sdk.keyvalue.value.rtkbasestation.RTKCustomNetworkSetting +import dji.sdk.keyvalue.value.rtkbasestation.RTKReferenceStationSource +import dji.sdk.keyvalue.value.rtkmobilestation.RTKPositioningSolution +import dji.v5.manager.aircraft.rtk.RTKCenter +import dji.v5.utils.common.ContextUtil +import dji.v5.utils.common.DjiSharedPreferencesManager +import dji.v5.utils.common.JsonUtil +import dji.v5.utils.common.LogUtils +import dji.v5.ux.R +import dji.v5.ux.core.extension.getString + +/** + * Description : + * + * @author: Byte.Cai + * date : 2022/5/24 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ + +object RTKUtil { + private const val TAG = "RTKUtil" + private const val USER_RTK_NETWORK_SERVICE_SETTINGS = "user_rtk_network_service_settings" + private const val USER_RTK_REFERENCE_SOURCE = "user_rtk_reference_source" + private const val USER_RTK_NETWORK_COORDINATE_SYSTEM_CMCC = "user_rtk_network_coordinate_system_cmcc" + private const val USER_RTK_NETWORK_COORDINATE_SYSTEM_QX = "user_rtk_network_coordinate_system_qx" + fun getRTKTypeName(view: View, rtkReferenceStationSource: RTKReferenceStationSource?): String { + view.run { + if (rtkReferenceStationSource == null) { + return getString(R.string.uxsdk_rtk_type_unknown_rtk); + } + return when (rtkReferenceStationSource) { + RTKReferenceStationSource.QX_NETWORK_SERVICE -> getString(R.string.uxsdk_rtk_type_nrtk) + RTKReferenceStationSource.BASE_STATION -> getString(R.string.uxsdk_rtk_type_rtk_mobile_station) + RTKReferenceStationSource.CUSTOM_NETWORK_SERVICE -> getString(R.string.uxsdk_rtk_type_custom_rtk) + RTKReferenceStationSource.NTRIP_NETWORK_SERVICE -> getString(R.string.uxsdk_rtk_type_cmcc_rtk) + else -> getString(R.string.uxsdk_rtk_type_unknown_rtk) + } + } + + } + + fun getRTKStatusName(view: View, positioningSolution: RTKPositioningSolution?): String { + view.run { + if (positioningSolution == null) { + return getString(R.string.uxsdk_rtk_solution_unknown) + } + return when (positioningSolution) { + RTKPositioningSolution.NONE -> getString(R.string.uxsdk_rtk_solution_none) + RTKPositioningSolution.SINGLE_POINT -> getString(R.string.uxsdk_rtk_solution_single) + RTKPositioningSolution.FLOAT -> getString(R.string.uxsdk_rtk_solution_float) + RTKPositioningSolution.FIXED_POINT -> getString(R.string.uxsdk_rtk_solution_fixed) + RTKPositioningSolution.UNKNOWN -> getString(R.string.uxsdk_rtk_solution_unknown) + else -> getString(R.string.uxsdk_rtk_solution_unknown) + } + } + } + + fun getNetRTKCoordinateSystem(rtkReferenceStationSource: RTKReferenceStationSource): CoordinateSystem? { + var coordinateSystem = "" + when (rtkReferenceStationSource) { + RTKReferenceStationSource.NTRIP_NETWORK_SERVICE -> { + coordinateSystem = DjiSharedPreferencesManager.getString(ContextUtil.getContext(), + USER_RTK_NETWORK_COORDINATE_SYSTEM_CMCC, "") + } + RTKReferenceStationSource.QX_NETWORK_SERVICE -> { + coordinateSystem = DjiSharedPreferencesManager.getString(ContextUtil.getContext(), USER_RTK_NETWORK_COORDINATE_SYSTEM_QX, "") + } + else -> { + LogUtils.e(TAG, "getNetRTKCoordinateSystem error,unSupport rtkReferenceStationSource:$rtkReferenceStationSource") + } + } + return if (TextUtils.isEmpty(coordinateSystem)) null else getCoordinateName(coordinateSystem) + + } + + fun saveRTKCoordinateSystem(rtkReferenceStationSource: RTKReferenceStationSource, coordinateSystem: CoordinateSystem) { + when (rtkReferenceStationSource) { + RTKReferenceStationSource.QX_NETWORK_SERVICE -> { + DjiSharedPreferencesManager.putString(ContextUtil.getContext(), USER_RTK_NETWORK_COORDINATE_SYSTEM_QX, coordinateSystem.name) + } + + RTKReferenceStationSource.NTRIP_NETWORK_SERVICE -> { + DjiSharedPreferencesManager.putString(ContextUtil.getContext(), USER_RTK_NETWORK_COORDINATE_SYSTEM_CMCC, coordinateSystem.name) + } + else -> { + LogUtils.e(TAG, "saveRTKCoordinateSystem error,unSupport rtkReferenceStationSource:$rtkReferenceStationSource") + } + } + } + + + fun saveRtkCustomNetworkSetting(settings: RTKCustomNetworkSetting) { + DjiSharedPreferencesManager.putString(ContextUtil.getContext(), USER_RTK_NETWORK_SERVICE_SETTINGS, settings.toString()) + } + + fun getRtkCustomNetworkSetting(): RTKCustomNetworkSetting? { + val localSetting = DjiSharedPreferencesManager.getString(ContextUtil.getContext(), USER_RTK_NETWORK_SERVICE_SETTINGS, "") + return if (!TextUtils.isEmpty(localSetting)) { + JsonUtil.toBean(localSetting, RTKCustomNetworkSetting::class.java) + } else RTKCenter.getInstance().customRTKManager.customNetworkRTKSettings + ?: RTKCustomNetworkSetting( + "", + 0, + "", + "", + "" + ) + + } + + private fun getCoordinateName(value: String): CoordinateSystem { + return when (value) { + CoordinateSystem.CGCS2000.name -> + CoordinateSystem.CGCS2000 + CoordinateSystem.WGS84.name -> + CoordinateSystem.WGS84 + else -> { + //如果未设置过坐标系,则默认使用CGCS2000作为启动的坐标系 + CoordinateSystem.CGCS2000 + } + } + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKWidget.kt new file mode 100644 index 00000000..b19f0fc2 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKWidget.kt @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.accessory + +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.View +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.annotation.DrawableRes +import androidx.annotation.StyleRes +import androidx.core.content.res.use +import dji.v5.utils.common.LogUtils +import dji.v5.ux.R +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* + +private const val TAG = "RTKWidget" + +/** + * This widget contains multiple widgets to control and get information related to RTK. + */ +open class RTKWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ConstraintLayoutWidget(context, attrs, defStyleAttr) { + //region Fields + private val rtkDialogSeparator: View = findViewById(R.id.rtk_dialog_separator) + + private val widgetModel by lazy { + RTKWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance() + ) + } + + /** + * Get the RTK Enabled Widget so it can be customized. + */ + @get:JvmName("getRTKEnabledWidget") + val rtkEnabledWidget: RTKEnabledWidget = findViewById(R.id.widget_rtk_enabled) + + /** + * Get the RTK Satellite Status Widget so it can be customized. + */ + @get:JvmName("getRTKSatelliteStatusWidget") + val rtkSatelliteStatusWidget: RTKSatelliteStatusWidget = findViewById(R.id.widget_rtk_satellite_status) + + /** + * Get the RTK Type Switch Widget so it can be customized. + */ + @get:JvmName("getRTKTypeSwitchWidget") + val rtkTypeSwitchWidget: RTKTypeSwitchWidget = findViewById(R.id.widget_rtk_type_switch) + + + + + /** + * The color for the separator line views + */ + var rtkSeparatorsColor: Int + @JvmName("getRTKSeparatorsColor") + @ColorInt + get() = rtkSatelliteStatusWidget.rtkSeparatorsColor + @JvmName("setRTKSeparatorsColor") + set(@ColorInt color) { + rtkSatelliteStatusWidget.rtkSeparatorsColor = color + rtkDialogSeparator.setBackgroundColor(color) + } + //endregion + + //region Constructor + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + inflate(context, R.layout.uxsdk_widget_rtk, this) + } + + init { + LogUtils.i(TAG, "init") + attrs?.let { initAttributes(context, it) } + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + LogUtils.i(TAG, "onAttachedToWindow") + + if (!isInEditMode) { + widgetModel.setup() + LogUtils.i(TAG, "widgetModel.setup()") + + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + //do nothing + } + + + + + //region Customization + override fun getIdealDimensionRatioString(): String { + return resources.getString(R.string.uxsdk_widget_rtk_ratio) + } + + + + //Initialize all customizable attributes + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.RTKWidget).use { typedArray -> + typedArray.getColorAndUse(R.styleable.RTKWidget_uxsdk_rtkSeparatorsColor) { + rtkSeparatorsColor = it + } + } + } + //endregion + + + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + + /** + * Class defines the widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * RTK enabled update + */ + data class RTKEnabledUpdated(val isRTKEnabled: Boolean) : ModelState() + + } + //endregion + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKWidgetModel.kt new file mode 100644 index 00000000..bc49b28a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/RTKWidgetModel.kt @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.accessory + +import dji.sdk.keyvalue.key.DJIKey +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.key.RtkMobileStationKey +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Flowable + +private const val TAG = "RTKWidgetModel" + +/** + * Widget Model for the [RTKWidget] used to define + * the underlying logic and communication + */ +class RTKWidgetModel( + djiSdkModel: DJISDKModel, + uxKeyManager: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, uxKeyManager) { + + //region Fields + private val rtkEnabledProcessor: DataProcessor = DataProcessor.create(false) + //endregion + + //region Data + /** + * Get whether the RTK is enabled. + */ + val rtkEnabled: Flowable + @JvmName("getRTKEnabled") + get() = rtkEnabledProcessor.toFlowable() + + + //region Lifecycle + override fun inSetup() { + val rtkEnabledKey: DJIKey = KeyTools.createKey( + RtkMobileStationKey.KeyRTKEnable) + bindDataProcessor(rtkEnabledKey, rtkEnabledProcessor) + } + + override fun inCleanup() { + // do nothing + } + + override fun updateStates() { + // Nothing to update + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/data/DJIRTKBaseStationConnectInfo.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/data/DJIRTKBaseStationConnectInfo.kt new file mode 100644 index 00000000..ece063a5 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/data/DJIRTKBaseStationConnectInfo.kt @@ -0,0 +1,26 @@ +package dji.v5.ux.accessory.data + +import dji.sdk.keyvalue.value.rtkbasestation.BaseStationDeviceType +import dji.sdk.keyvalue.value.rtkbasestation.RTKStationInfo +import dji.sdk.keyvalue.value.rtkbasestation.RTKStationConnetState + +/** + * Description :驱动UI的数据模型,基于RTKBaseStationConnectInfo新增一个连接状态属性 + * + * @author: Byte.Cai + * date : 2022/3/6 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ +class DJIRTKBaseStationConnectInfo( + var baseStationId: Int, + var signalLevel: Int, + var rtkStationName: String, + var connectStatus: RTKStationConnetState = RTKStationConnetState.IDLE +) : RTKStationInfo(baseStationId, signalLevel, rtkStationName, BaseStationDeviceType.BS_RTK2) { + constructor() : this(0, 0, "") + + override fun toString(): String { + return super.toString() + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/data/RtkStationScanAdapter.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/data/RtkStationScanAdapter.kt new file mode 100644 index 00000000..a65d1e60 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/data/RtkStationScanAdapter.kt @@ -0,0 +1,149 @@ +package dji.v5.ux.accessory.data + +import android.content.Context +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.ImageView +import android.widget.TextView +import androidx.annotation.DrawableRes +import androidx.recyclerview.widget.RecyclerView +import dji.sdk.keyvalue.value.rtkbasestation.RTKStationConnetState +import dji.v5.utils.common.LogUtils +import dji.v5.ux.R + +/** + * Description :基站RTK的Adapter,展示扫码到的基站情况 + * + * @author: Byte.Cai + * date : 2022/3/6 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ +class RtkStationScanAdapter(val context: Context, list: List?) : + RecyclerView.Adapter() { + private val TAG = "RtkStationScanAdapter" + + private val LEVEL_0 = 0 + private val LEVEL_1 = 1 + private val LEVEL_2 = 2 + private val LEVEL_3 = 3 + private val LEVEL_4 = 4 + private var baseStationInfoList: List? = list + + + override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RtkViewHolder { + val view: View = LayoutInflater.from(context).inflate(R.layout.uxsdk_widget_rtk_connect_status_item, parent, false) + return RtkViewHolder(view) + } + + override fun onBindViewHolder(holder: RtkViewHolder, position: Int) { + baseStationInfoList?.get(position)?.let { info -> + holder.mRtkStationNameTv.text = info.rtkStationName + holder.mConnectSignalIv.setBackgroundResource(getSignalLevelDrawable(info.signalLevel)) + holder.itemView.setOnClickListener { + val pos = holder.layoutPosition + val isConnecting = checkConnecting() + val hasConnected = checkConnected(pos) + if (!isConnecting && !hasConnected) { + //上一笔连接还没结束或者基站已连接则不响应新的连接请求 + mOnItemClickListener?.onItemClick(holder.itemView, pos) + } else if (checkConnecting()) { + LogUtils.e(TAG, "The station is currently connecting, please try to connect later!") + } else { + LogUtils.e(TAG, "The station has connected!") + } + } + when (info.connectStatus) { + RTKStationConnetState.CONNECTING -> { + holder.mConnectStatusIv.visible() + holder.mConnectStatusIv.setImageResource(R.drawable.uxsdk_rotate_progress_circle) + } + RTKStationConnetState.CONNECTED -> { + holder.mConnectStatusIv.visible() + holder.mConnectStatusIv.setImageResource(R.drawable.uxsdk_ic_confirm) + } + else -> { + holder.mConnectStatusIv.gone() + } + } + + } + } + + override fun getItemId(position: Int): Long { + return position.toLong() + } + + override fun getItemCount(): Int { + return if (baseStationInfoList == null) 0 else baseStationInfoList!!.size + } + + interface OnItemClickListener { + fun onItemClick(view: View?, position: Int) + } + + private var mOnItemClickListener: OnItemClickListener? = null + + fun setOnItemClickListener(onItemClickListener: OnItemClickListener?) { + mOnItemClickListener = onItemClickListener + } + + @DrawableRes + fun getSignalLevelDrawable(signalLevel: Int): Int { + LogUtils.i(TAG, "getSignalLevelDrawable,signalLevel=$signalLevel") + return when (signalLevel) { + LEVEL_0 -> R.drawable.uxsdk_ic_topbar_signal_level_0 + LEVEL_1 -> R.drawable.uxsdk_ic_topbar_signal_level_1 + LEVEL_2 -> R.drawable.uxsdk_ic_topbar_signal_level_2 + LEVEL_3 -> R.drawable.uxsdk_ic_topbar_signal_level_3 + LEVEL_4 -> R.drawable.uxsdk_ic_topbar_signal_level_4 + else -> R.drawable.uxsdk_ic_topbar_signal_level_5 + } + } + + + class RtkViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + var mConnectStatusIv: ImageView + var mRtkStationNameTv: TextView + var mConnectSignalIv: ImageView + + init { + mConnectStatusIv = itemView.findViewById(R.id.connect_status_iv) + mRtkStationNameTv = itemView.findViewById(R.id.station_name_tv) + mConnectSignalIv = itemView.findViewById(R.id.connect_signal_iv) + mConnectStatusIv.visibility = View.GONE + } + } + + fun View.visible() { + this.visibility = View.VISIBLE + } + + fun View.gone() { + this.visibility = View.GONE + } + + private fun checkConnecting(): Boolean { + baseStationInfoList?.let { + for (station in it) { + if (station.connectStatus == RTKStationConnetState.CONNECTING) { + return true + } + } + return false + } + return false + } + + private fun checkConnected(position: Int): Boolean { + baseStationInfoList?.run { + val stationInfo = get(position) + if (stationInfo.connectStatus == RTKStationConnetState.CONNECTED) { + return true + } + return false + } + return false + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/item/RtkGuidanceView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/item/RtkGuidanceView.java new file mode 100644 index 00000000..7814afc3 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/item/RtkGuidanceView.java @@ -0,0 +1,332 @@ +package dji.v5.ux.accessory.item; + +import android.animation.Animator; +import android.content.Context; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.PopupWindow; +import android.widget.TextView; + +import androidx.annotation.ColorRes; +import androidx.annotation.IntDef; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.constraintlayout.widget.Constraints; + +import com.airbnb.lottie.LottieAnimationView; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import dji.v5.utils.common.LogUtils; +import dji.v5.utils.common.StringUtils; +import dji.v5.ux.R; + + +public class RtkGuidanceView extends ConstraintLayout implements View.OnClickListener { + + @IntDef({ + GuidanceMode.STEP_RESET, + GuidanceMode.STEP_FIRST, + GuidanceMode.STEP_SECOND, + GuidanceMode.STEP_THIRD, + }) + + @Retention(RetentionPolicy.SOURCE) + private @interface GuidanceMode { + int STEP_RESET = 0; + int STEP_FIRST = 1; + int STEP_SECOND = 2; + int STEP_THIRD = 3; + + } + + //顶部导航栏控件 + private View mNavigationLayout; + private TextView mStepFirstTv; + private TextView mStepSecondTv; + private TextView mStepThirdTv; + private ImageView mStepFirstIv; + private ImageView mStepSecondIv; + private View mStepStartDivider; + private View mStepEndDivider; + //左边动画控件 + private LottieAnimationView mLottieAnimationView; + private View mReplayView; + private Button mReplayBtn; + private TextView mLottieTip; + //左边文字控件 + private TextView mTitleTv; + private TextView mContentTv; + private View mImageView; + private TextView mImageDescTv; + private Button mPreviousBtn; + private Button mNextBtn; + + private PopupWindow mPopupWindow; + + private int mStep; //0——重置、1——步骤1、2——步骤2、3——步骤3 + private String[] mTitleStr; + private String[] mContentStr; + private int[] mAnimationRes; + private String[] mImageAssetsFolderStr; + private boolean mStartAnimation; + private Runnable mTipRunnable; + + + public RtkGuidanceView(Context context) { + this(context, null); + } + + public RtkGuidanceView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public RtkGuidanceView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context); + } + + private void init(Context context) { + LayoutInflater.from(context).inflate(R.layout.uxsdk_rtk_guidance_layout, this, true); + initView(); + initWidgetParams(); + initParams(context); + initListener(); + } + + private void initView() { + //顶部导航栏控件 + mNavigationLayout = findViewById(R.id.rtk_guidance_step_navigation); + mStepFirstTv = findViewById(R.id.rtk_guidance_step_first_number); + mStepSecondTv = findViewById(R.id.rtk_guidance_step_second_number); + mStepThirdTv = findViewById(R.id.rtk_guidance_step_third_number); + mStepFirstIv = findViewById(R.id.rtk_guidance_step_first_image); + mStepSecondIv = findViewById(R.id.rtk_guidance_step_second_image); + mStepStartDivider = findViewById(R.id.rtk_guidance_start_divider); + mStepEndDivider = findViewById(R.id.rtk_guidance_end_divider); + + //左边动画控件 + mLottieAnimationView = findViewById(R.id.rtk_guidance_lottie_animation); + mReplayView = findViewById(R.id.rtk_guidance_replay_view); + mReplayBtn = findViewById(R.id.rtk_guidance_replay_btn); + mLottieTip = findViewById(R.id.rtk_guidance_lottie_tip); + + //左边文字控件 + mTitleTv = findViewById(R.id.rtk_guidance_step_title); + mContentTv = findViewById(R.id.rtk_guidance_step_content); + mImageView = findViewById(R.id.rtk_guidance_step_image); + mImageDescTv = findViewById(R.id.rtk_guidance_step_image_desc); + mPreviousBtn = findViewById(R.id.rtk_guidance_step_previous); + mNextBtn = findViewById(R.id.rtk_guidance_step_next); + } + + private void initListener() { + findViewById(R.id.rtk_guidance_close).setOnClickListener(this); + findViewById(R.id.rtk_guidance_step_previous).setOnClickListener(this); + findViewById(R.id.rtk_guidance_step_next).setOnClickListener(this); + findViewById(R.id.rtk_guidance_replay_btn).setOnClickListener(this); + } + + private void initWidgetParams() { + setLayoutParams(new Constraints.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT)); + setBackgroundResource(R.color.uxsdk_white); + mLottieAnimationView.addAnimatorListener(new Animator.AnimatorListener() { + @Override + public void onAnimationStart(Animator animation) { + updateReplayView(false); + } + + @Override + public void onAnimationEnd(Animator animation) { + updateReplayView(true); + } + + @Override + public void onAnimationCancel(Animator animation) { + //动画取消,无需操作 + } + + @Override + public void onAnimationRepeat(Animator animation) { + updateReplayView(false); + } + }); + } + + private void initParams(Context context) { + mStep = GuidanceMode.STEP_FIRST; + mTitleStr = context.getResources().getStringArray(R.array.uxsdk_rtk_guidance_title); + mContentStr = context.getResources().getStringArray(R.array.uxsdk_rtk_guidance_content); + mAnimationRes = new int[]{ + R.raw.uxsdk_rtk_guidance_reset, + R.raw.uxsdk_rtk_guidance_step1, + R.raw.uxsdk_rtk_guidance_step2, + R.raw.uxsdk_rtk_guidance_step3 + }; + mImageAssetsFolderStr = new String[]{ + "rtk_guidance_reset_images", + "rtk_guidance_step1_images", + "rtk_guidance_step2_images", + "rtk_guidance_step3_images" + }; + } + + private void updateView() { + //更新视图可见性 + updateVisibility(); + //更新顶部导航栏 + if (mStep != GuidanceMode.STEP_RESET) { + mStepFirstTv.setVisibility(mStep <= GuidanceMode.STEP_FIRST ? VISIBLE : GONE); + mStepSecondTv.setVisibility(mStep <= GuidanceMode.STEP_SECOND ? VISIBLE : GONE); + + updateSelectedTopView(mStepSecondTv, mStep < GuidanceMode.STEP_SECOND); + updateSelectedTopView(mStepThirdTv, mStep < GuidanceMode.STEP_THIRD); + + mStepFirstIv.setVisibility(mStep > GuidanceMode.STEP_FIRST ? VISIBLE : GONE); + mStepSecondIv.setVisibility(mStep > GuidanceMode.STEP_SECOND ? VISIBLE : GONE); + + mStepStartDivider.setBackgroundResource(mStep == GuidanceMode.STEP_FIRST ? R.color.uxsdk_gray : R.color.uxsdk_blue); + mStepEndDivider.setBackgroundResource(mStep <= GuidanceMode.STEP_SECOND ? R.color.uxsdk_gray : R.color.uxsdk_blue); + } + //更新左边动画 + mLottieAnimationView.setImageAssetsFolder(mImageAssetsFolderStr[mStep]); + mLottieAnimationView.setAnimation(mAnimationRes[mStep]); + mLottieAnimationView.playAnimation(); + //在步骤2中更新右边动画中 tip 视图的显示 + updateLottieTipView(); + //更新右边文案 + mTitleTv.setText(mTitleStr[mStep]); + mContentTv.setText(mContentStr[mStep]); + mNextBtn.setText(StringUtils.getResStr(mStep == GuidanceMode.STEP_RESET + || mStep == GuidanceMode.STEP_THIRD ? R.string.uxsdk_rtk_guidance_btn_finish : R.string.uxsdk_rtk_guidance_btn_next)); + } + + private void updateVisibility() { + mNavigationLayout.setVisibility(mStep == GuidanceMode.STEP_RESET ? INVISIBLE : VISIBLE); + mImageView.setVisibility(mStep == GuidanceMode.STEP_SECOND ? VISIBLE : INVISIBLE); + mImageDescTv.setVisibility(mStep == GuidanceMode.STEP_SECOND ? VISIBLE : INVISIBLE); + mPreviousBtn.setVisibility(mStep == GuidanceMode.STEP_RESET + || mStep == GuidanceMode.STEP_FIRST ? GONE : VISIBLE); + } + + /** + * 更新顶部步骤view + * + * @param textView 步骤view + * @param isSelected 是否被选中 + */ + private void updateSelectedTopView(TextView textView, boolean isSelected) { + textView.setBackgroundResource(isSelected ? + R.drawable.uxsdk_bg_rtk_guidance_step_oval_gray : + R.drawable.uxsdk_bg_rtk_guidance_step_oval_blue_solid); + textView.setTextColor(isSelected ? + getResColor(R.color.uxsdk_black) : + getResColor(R.color.uxsdk_white)); + } + + /** + * 更新动画上方提示语 + */ + private void updateLottieTipView() { + removeCallbacks(mTipRunnable); + mLottieTip.setVisibility(GONE); + if (mStep == GuidanceMode.STEP_RESET) { + delayedUpdateResetTipView(); + } + } + + /** + * 延迟更新动画上方提示语——重置成功 + */ + private void delayedUpdateResetTipView() { + mTipRunnable = () -> { + mLottieTip.setText(R.string.uxsdk_rtk_guidance_reset_tip); + mLottieTip.setVisibility(mStartAnimation ? VISIBLE : GONE); + if (mStartAnimation) { + mStartAnimation = false; + postDelayed(mTipRunnable, 2500); + } + }; + mStartAnimation = true; + //重置在14秒后显示重置成功 + postDelayed(mTipRunnable, 14000); + } + + public void updateReplayView(boolean isShow) { + int visible = isShow ? VISIBLE : GONE; + mReplayView.setVisibility(visible); + mReplayBtn.setVisibility(visible); + } + + @Override + protected void onDetachedFromWindow() { + removeCallbacks(mTipRunnable); + mStep = GuidanceMode.STEP_FIRST; + //停止动画 + if (mLottieAnimationView != null && mLottieAnimationView.isAnimating()) { + mLottieAnimationView.cancelAnimation(); + } + super.onDetachedFromWindow(); + } + + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == R.id.rtk_guidance_close) { + closePopupWindow(); + } else if (id == R.id.rtk_guidance_step_previous) { + mStep--; + updateView(); + } else if (id == R.id.rtk_guidance_step_next) { + if (mStep != GuidanceMode.STEP_RESET && mStep != GuidanceMode.STEP_THIRD) { + mStep++; + updateView(); + } else { + closePopupWindow(); + } + } else if (id == R.id.rtk_guidance_replay_btn) { + mLottieAnimationView.playAnimation(); + updateLottieTipView(); + } + } + + + private void closePopupWindow() { + if (mPopupWindow != null) { + mPopupWindow.dismiss(); + } + } + + public void showPopupWindow(View parent) { + showPopupWindow(parent, GuidanceMode.STEP_FIRST); + } + + public void showPopupWindow(View parent, int guidanceMode) { + if (guidanceMode < GuidanceMode.STEP_RESET || guidanceMode > GuidanceMode.STEP_THIRD) { + return; + } + mStep = guidanceMode; + if (mPopupWindow == null) { + mPopupWindow = new PopupWindow(this, ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.MATCH_PARENT, true); + } + updateView(); + mPopupWindow.setClippingEnabled(false); + mPopupWindow.showAtLocation(parent, Gravity.NO_GRAVITY, 0, 0); + } + + + public int getResColor(@ColorRes int resId) { + if (getContext() != null) { + return getContext().getResources().getColor(resId); + } + return 0; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/item/TitleValueCell.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/item/TitleValueCell.kt new file mode 100644 index 00000000..2acb7b83 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/accessory/item/TitleValueCell.kt @@ -0,0 +1,68 @@ +package dji.v5.ux.accessory.item + +import android.content.Context +import android.util.AttributeSet +import android.widget.FrameLayout +import android.widget.TextView +import dji.v5.ux.R + + +/** + * Description :垂直显示标题和值的控件 + * + * @author: Byte.Cai + * date : 2022/9/7 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ + +class TitleValueCell @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, +) : FrameLayout(context, attrs, defStyleAttr) { + + private var tvTitle: TextView + private var tvValue: TextView + + + init { + val ta = context.obtainStyledAttributes(attrs, R.styleable.FpvTitleValueCell, defStyleAttr, 0) + val title = ta.getString(R.styleable.FpvTitleValueCell_uxsdk_title) + val value = ta.getString(R.styleable.FpvTitleValueCell_uxsdk_value) + val layoutId = ta.getResourceId(R.styleable.FpvTitleValueCell_uxsdk_layout, R.layout.uxsdk_fpv_top_bar_popover_title_value_cell) + if (layoutId == 0) { + throw IllegalArgumentException("layout can not be null.") + } + inflate(context, layoutId, this) + + ta.recycle() + + tvTitle = findViewById(R.id.tv_title) + tvValue = findViewById(R.id.tv_value) + tvTitle.text = title + tvValue.text = value + } + + var title: CharSequence? + get() = tvTitle.text + set(value) { + if (value != tvTitle.text) { + tvTitle.text = value + } + } + var value: CharSequence? + get() = tvValue.text + set(value) { + if (value != tvValue.text) { + tvValue.text = value + } + } + + fun setValueTextColor(color: Int) { + tvValue.setTextColor(color) + } + + fun setTitleTextColor(color: Int) { + tvTitle.setTextColor(color) + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/ui/ProgressRingView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/ui/ProgressRingView.java new file mode 100644 index 00000000..9799a8e8 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/ui/ProgressRingView.java @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.ui; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.SweepGradient; +import android.util.AttributeSet; +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.AnimationUtils; + +import androidx.annotation.ColorInt; + +import dji.v5.ux.R; + +/** + * Ring progress bar. + * The view shows circular animation to indicate progress. + */ +public class ProgressRingView extends View { + + private RectF boundaries; + private Paint paint; + private Animation indeterminateAnimation; + private Shader progressGradient; + private boolean indeterminate; + private int ringColor = Color.WHITE; + private int height; + private int width; + + public ProgressRingView(Context context) { + super(context, null, 0); + } + + public ProgressRingView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public ProgressRingView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initView(context); + } + + private void initView(Context context) { + boundaries = new RectF(); + + paint = new Paint(Paint.ANTI_ALIAS_FLAG); + paint.setStyle(Paint.Style.FILL_AND_STROKE); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeCap(Paint.Cap.SQUARE); + paint.setColor(ringColor); + + if (!isInEditMode()) { + indeterminateAnimation = AnimationUtils.loadAnimation(context, R.anim.uxsdk_anim_rotate); + indeterminateAnimation.setAnimationListener(new Animation.AnimationListener() { + + @Override + public void onAnimationStart(Animation animation) { + indeterminate = true; + if (progressGradient != null) { + paint.setShader(progressGradient); + } + } + + @Override + public void onAnimationRepeat(Animation animation) { + // Nothing to do here + } + + @Override + public void onAnimationEnd(Animation animation) { + paint.setShader(null); + invalidate(); + } + }); + } + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + + // StrokeWidth percentage + // Color + + float strokeWidth = w * .08f; + paint.setStrokeWidth(strokeWidth / 2); + width = w; + height = h; + initProgressGradient(w, h); + float padding = strokeWidth / 2; + boundaries.top = padding; + boundaries.left = padding; + boundaries.bottom = getMeasuredWidth() - padding; + boundaries.right = getMeasuredHeight() - padding; + } + + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + canvas.drawArc(boundaries, 0, 360, false, paint); + } + + /** + * Set the color of the progress ring. + * + * @param color integer value + */ + public void setRingColor(@ColorInt int color) { + ringColor = color; + paint.setColor(color); + initProgressGradient(width, height); + invalidate(); + } + + /** + * Check if the ring is currently animating. + * + * @return boolean value + */ + public boolean isIndeterminate() { + return indeterminate; + } + + /** + * Start/Stop the ring animation. + * + * @param indeterminate boolean value + * true - to start animation + * false - to stop animation + */ + public void setIndeterminate(boolean indeterminate) { + if (indeterminate == this.indeterminate) return; + + this.indeterminate = indeterminate; + if (indeterminate) { + startAnimation(indeterminateAnimation); + } else { + clearAnimation(); + indeterminateAnimation.cancel(); + indeterminateAnimation.reset(); + } + } + + private void initProgressGradient(int w, int h) { + progressGradient = null; + float cx = w / 2f; + float cy = h / 2f; + int[] colors = {ringColor, Color.TRANSPARENT, Color.TRANSPARENT}; + float[] positions = {0, 0.7f, 1}; + + progressGradient = new SweepGradient(cx, cy, colors, positions); + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/util/CameraActionSound.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/util/CameraActionSound.java new file mode 100644 index 00000000..7b669dac --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/util/CameraActionSound.java @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.util; + +import android.content.Context; + +import androidx.annotation.NonNull; +import dji.v5.ux.R; +import dji.v5.ux.core.util.AudioUtil; +import io.reactivex.rxjava3.disposables.Disposable; + +/** + * Class used as a util for playing sounds of + * capture photo and record video + */ +public class CameraActionSound { + private final Context context; + private ShutterSoundCount shutterCount; + + public CameraActionSound(Context con) { + context = con; + } + + private int shutterCountSound(ShutterSoundCount value) { + int soundId; + switch (value) { + case ONE: + soundId = R.raw.uxsdk_shutter_1; + break; + case THREE: + soundId = R.raw.uxsdk_shutter_3; + break; + case FIVE: + soundId = R.raw.uxsdk_shutter_5; + break; + case SEVEN: + soundId = R.raw.uxsdk_shutter_7; + break; + case TEN: + soundId = R.raw.uxsdk_shutter_10; + break; + case FOURTEEN: + soundId = R.raw.uxsdk_shutter_14; + break; + + case UNKNOWN: + default: + soundId = R.raw.uxsdk_shutter_3; + break; + } + return soundId; + } + + /** + * Set the count of photos based on current mode + * + * @param count int value + */ + public void setShutterCount(@NonNull ShutterSoundCount count) { + shutterCount = count; + } + + /** + * Play sound for Capture Photo + * + * @return Disposable + */ + @NonNull + public Disposable playCapturePhoto() { + return AudioUtil.playSoundInBackground(context, shutterCountSound(shutterCount)); + + } + + /** + * Play sound for start record video + * + * @return Disposable + */ + @NonNull + public Disposable playStartRecordVideo() { + return AudioUtil.playSoundInBackground(context, R.raw.uxsdk_video_voice); + } + + /** + * Play sound for stop record video + * + * @return Disposable + */ + @NonNull + public Disposable playStopRecordVideo() { + return AudioUtil.playSoundInBackground(context, R.raw.uxsdk_end_video_record); + } + + /** + * Enum for shutter sound count + */ + public enum ShutterSoundCount { + /** + * Single photo shutter sound + */ + ONE(1), + /** + * Three photos shutter sound + */ + THREE(3), + /** + * Five photos shutter sound + */ + FIVE(5), + /** + * Seven photos shutter sound + */ + SEVEN(7), + /** + * Ten photos shutter sound + */ + TEN(10), + /** + * Fourteen photos shutter sound + */ + FOURTEEN(14), + /** + * Will default to one shutter sound + */ + UNKNOWN(1); + + private int value; + + ShutterSoundCount(int value) { + this.value = value; + } + + /** + * Returns the enum constant of this type with the input integer value. + * + * @param value The input integer value + * @return The enum constant of this type + */ + public static ShutterSoundCount find(int value) { + ShutterSoundCount result = UNKNOWN; + for (int i = 0; i < getValues().length; i++) { + if (getValues()[i]._equals(value)) { + result = getValues()[i]; + break; + } + } + return result; + } + + /** + * Returns the real value of an enum value. + * + * @return integer The real value. + */ + public int value() { + return this.value; + } + + /** + * Compares the input integer value with the real value of an enum value. + * + * @param b The input integer value. + * @return boolean The compared result. + */ + private boolean _equals(int b) { + return value == b; + } + + private static ShutterSoundCount[] values; + + public static ShutterSoundCount[] getValues() { + if (values == null) { + values = values(); + } + return values; + } + + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/util/CameraResource.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/util/CameraResource.java new file mode 100644 index 00000000..a48759a4 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/util/CameraResource.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.util; + +import dji.sdk.keyvalue.value.camera.CameraShootPhotoMode; +import dji.sdk.keyvalue.value.camera.PhotoPanoramaMode; +import dji.v5.ux.R; + +public class CameraResource { + + public static int getPhotoModeImgResId(final int mode, final int value) { + if (CameraShootPhotoMode.HDR.value() == mode) { + return R.drawable.uxsdk_ic_photo_mode_hdr; + } else if (CameraShootPhotoMode.BURST.value() == mode) { + return getImgResIdFromBurstMode(value); + } else if (CameraShootPhotoMode.RAW_BURST.value() == mode) { + return getImgResIdFromRawBurstMode(value); + } else if (CameraShootPhotoMode.AEB.value() == mode) { + return getImgResIdFromAebMode(value); + } else if (CameraShootPhotoMode.INTERVAL.value() == mode) { + return getImgResIdFromIntervalMode(value); + } else if (CameraShootPhotoMode.VISION_BOKEH.value() == mode) { + return R.drawable.uxsdk_ic_photo_mode_shallow_focus; + } else if (CameraShootPhotoMode.VISION_PANO.value() == mode) { + return getImgResIdFromVisionPanoMode(value); + } else if (CameraShootPhotoMode.EHDR.value() == mode) { + return R.drawable.uxsdk_ic_photo_mode_nor; + } else if (CameraShootPhotoMode.HYPER_LIGHT.value() == mode) { + return R.drawable.uxsdk_ic_photo_mode_nor; + } else { + return R.drawable.uxsdk_ic_photo_mode_nor; + } + } + + private static int getImgResIdFromBurstMode(int value) { + if (value == 14) { + return R.drawable.uxsdk_ic_photo_mode_continuous_14; + } else if (value == 10) { + return R.drawable.uxsdk_ic_photo_mode_continuous_10; + } else if (value == 7) { + return R.drawable.uxsdk_ic_photo_mode_continuous_7; + } else if (value == 5) { + return R.drawable.uxsdk_ic_photo_mode_continuous_5; + } else { + return R.drawable.uxsdk_ic_photo_mode_continuous_3; + } + } + + private static int getImgResIdFromRawBurstMode(int value) { + if (value == 255) { + return R.drawable.uxsdk_ic_photo_mode_raw_burst_infinity; + } else if (value == 14) { + return R.drawable.uxsdk_ic_photo_mode_raw_burst_14; + } else if (value == 10) { + return R.drawable.uxsdk_ic_photo_mode_raw_burst_10; + } else if (value == 7) { + return R.drawable.uxsdk_ic_photo_mode_raw_burst_7; + } else if (value == 5) { + return R.drawable.uxsdk_ic_photo_mode_raw_burst_5; + } else { + return R.drawable.uxsdk_ic_photo_mode_raw_burst_3; + } + } + + private static int getImgResIdFromAebMode(int value) { + if (value == 7) { + return R.drawable.uxsdk_ic_photo_mode_aeb_continuous_7; + } else if (value == 5) { + return R.drawable.uxsdk_ic_photo_mode_aeb_continuous_5; + } else { + return R.drawable.uxsdk_ic_photo_mode_aeb_continuous_3; + } + } + + private static int getImgResIdFromIntervalMode(int value) { + if (value == 60) { + return R.drawable.uxsdk_ic_photo_mode_timepause_60s; + } else if (value == 30) { + return R.drawable.uxsdk_ic_photo_mode_timepause_30s; + } else if (value == 20) { + return R.drawable.uxsdk_ic_photo_mode_timepause_20s; + } else if (value == 15) { + return R.drawable.uxsdk_ic_photo_mode_timepause_15s; + } else if (value == 10) { + return R.drawable.uxsdk_ic_photo_mode_timepause_10s; + } else if (value == 7) { + return R.drawable.uxsdk_ic_photo_mode_timepause_7s; + } else if (value == 4) { + return R.drawable.uxsdk_ic_photo_mode_timepause_4s; + } else if (value == 3) { + return R.drawable.uxsdk_ic_photo_mode_timepause_3s; + } else if (value == 2) { + return R.drawable.uxsdk_ic_photo_mode_timepause_2s; + } else { + return R.drawable.uxsdk_ic_photo_mode_timepause_5s; + } + } + + private static int getImgResIdFromVisionPanoMode(int value) { + if (PhotoPanoramaMode.MODE_3x1.value() == value) { + return R.drawable.uxsdk_ic_photo_mode_pano_3x1; + } else if (PhotoPanoramaMode.MODE_1x3.value() == value) { + return R.drawable.uxsdk_ic_photo_mode_pano_180; + } else if (PhotoPanoramaMode.MODE_3x3.value() == value) { + return R.drawable.uxsdk_ic_photo_mode_pano_3x3; + } else if (PhotoPanoramaMode.MODE_SUPER_RESOLUTION.value() == value) { + return R.drawable.uxsdk_ic_photo_mode_nor; + } else if (PhotoPanoramaMode.MODE_SPHERE.value() == value) { + return R.drawable.uxsdk_ic_photo_mode_pano_sphere; + } else { + return R.drawable.uxsdk_ic_photo_mode_pano_180; + } + } + + private CameraResource() { + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/autoexposurelock/AutoExposureLockWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/autoexposurelock/AutoExposureLockWidget.java new file mode 100644 index 00000000..d30d822e --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/autoexposurelock/AutoExposureLockWidget.java @@ -0,0 +1,467 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.autoexposurelock; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.ColorInt; +import androidx.annotation.DrawableRes; +import androidx.annotation.MainThread; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StyleRes; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.SchedulerProvider; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.UxErrorHandle; +import dji.v5.ux.core.util.ViewUtil; + +/** + * Auto Exposure Lock Widget will display the current state of exposure lock. + *

+ * When locked the exposure of the camera will remain constant. + * Changing the exposure parameters manually will release the lock. + */ +public class AutoExposureLockWidget extends ConstraintLayoutWidget implements View.OnClickListener, ICameraIndex { + + //region Fields + private static final String TAG = "AutoExposureLockWidget"; + private ImageView foregroundImageView; + private TextView titleTextView; + private AutoExposureLockWidgetModel widgetModel; + private Drawable autoExposureLockDrawable; + private Drawable autoExposureUnlockDrawable; + private ColorStateList lockDrawableTint; + private ColorStateList unlockDrawableTint; + //endregion + + //region Lifecycle + public AutoExposureLockWidget(@NonNull Context context) { + super(context); + } + + public AutoExposureLockWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public AutoExposureLockWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_widget_auto_exposure_lock, this); + if (getBackground() == null) { + setBackgroundResource(R.drawable.uxsdk_background_black_rectangle); + } + foregroundImageView = findViewById(R.id.auto_exposure_lock_widget_foreground_image_view); + titleTextView = findViewById(R.id.auto_exposure_lock_widget_title_text_view); + if (!isInEditMode()) { + widgetModel = + new AutoExposureLockWidgetModel(DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()); + } + initDefaults(); + if (attrs != null) { + initAttributes(context, attrs); + } + setOnClickListener(this); + } + + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.isAutoExposureLockOn().observeOn(SchedulerProvider.ui()).subscribe(this::onAELockChange)); + } + + @Override + public void onClick(View v) { + if (v == this) { + setAutoExposureLock(); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + if (!isInEditMode()) { + widgetModel.cleanup(); + } + super.onDetachedFromWindow(); + } + + //endregion + + //region private methods + @MainThread + private void onAELockChange(boolean isLocked) { + if (isLocked) { + foregroundImageView.setImageDrawable(autoExposureLockDrawable); + if (lockDrawableTint != null) ViewUtil.tintImage(foregroundImageView, lockDrawableTint); + } else { + foregroundImageView.setImageDrawable(autoExposureUnlockDrawable); + if (unlockDrawableTint != null) + ViewUtil.tintImage(foregroundImageView, unlockDrawableTint); + } + } + + private void setAutoExposureLock() { + addDisposable(widgetModel.toggleAutoExposureLock() + .observeOn(SchedulerProvider.ui()) + .subscribe(() -> { + // Do nothing + }, UxErrorHandle.logErrorConsumer(TAG, "set auto exposure lock: "))); + } + + private void checkAndUpdateAELock() { + if (!isInEditMode()) { + addDisposable(widgetModel.isAutoExposureLockOn().firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(this::onAELockChange, UxErrorHandle.logErrorConsumer(TAG, "Update AE Lock "))); + } + } + + private void initDefaults() { + autoExposureLockDrawable = getResources().getDrawable(R.drawable.uxsdk_ic_auto_exposure_lock); + autoExposureUnlockDrawable = getResources().getDrawable(R.drawable.uxsdk_ic_auto_exposure_unlock); + setTitleTextColor(getResources().getColorStateList(R.color.uxsdk_color_selector_auto_exposure_lock)); + } + + private void initAttributes(@NonNull Context context, @NonNull AttributeSet attrs) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AutoExposureLockWidget); + if (!isInEditMode()) { + updateCameraSource(ComponentIndexType.find(typedArray.getInt(R.styleable.AutoExposureLockWidget_uxsdk_cameraIndex, 0)), CameraLensType.find(typedArray.getInt(R.styleable.AutoExposureLockWidget_uxsdk_lensType, 0))); + } + ColorStateList colorStateList = typedArray.getColorStateList(R.styleable.AutoExposureLockWidget_uxsdk_widgetTitleTextColor); + if (colorStateList != null) { + setTitleTextColor(colorStateList); + } + + int colorResource = typedArray.getColor(R.styleable.AutoExposureLockWidget_uxsdk_widgetTitleTextColor, INVALID_COLOR); + if (colorResource != INVALID_COLOR) { + setTitleTextColor(colorResource); + } + + colorStateList = typedArray.getColorStateList(R.styleable.AutoExposureLockWidget_uxsdk_autoExposureUnlockDrawableTint); + if (colorStateList != null) { + setAutoExposureUnlockIconTint(colorStateList); + } + + colorResource = typedArray.getColor(R.styleable.AutoExposureLockWidget_uxsdk_autoExposureUnlockDrawableTint, INVALID_COLOR); + if (colorResource != INVALID_COLOR) { + setAutoExposureUnlockIconTint(colorResource); + } + colorStateList = typedArray.getColorStateList(R.styleable.AutoExposureLockWidget_uxsdk_autoExposureLockDrawableTint); + if (colorStateList != null) { + setAutoExposureLockIconTint(colorStateList); + } + colorResource = typedArray.getColor(R.styleable.AutoExposureLockWidget_uxsdk_autoExposureLockDrawableTint, INVALID_COLOR); + if (colorResource != INVALID_COLOR) { + setAutoExposureLockIconTint(colorResource); + } + int textAppearance = typedArray.getResourceId(R.styleable.AutoExposureLockWidget_uxsdk_widgetTitleTextAppearance, INVALID_RESOURCE); + if (textAppearance != INVALID_RESOURCE) { + setTitleTextAppearance(textAppearance); + } + + if (typedArray.getDrawable(R.styleable.AutoExposureLockWidget_uxsdk_autoExposureLockDrawable) != null) { + autoExposureLockDrawable = typedArray.getDrawable(R.styleable.AutoExposureLockWidget_uxsdk_autoExposureLockDrawable); + } + if (typedArray.getDrawable(R.styleable.AutoExposureLockWidget_uxsdk_autoExposureUnlockDrawable) != null) { + autoExposureUnlockDrawable = typedArray.getDrawable(R.styleable.AutoExposureLockWidget_uxsdk_autoExposureUnlockDrawable); + } + + typedArray.recycle(); + } + //endregion + + //region customization + @NonNull + @Override + public String getIdealDimensionRatioString() { + return getResources().getString(R.string.uxsdk_widget_auto_exposure_lock_ratio); + } + + @NonNull + public ComponentIndexType getCameraIndex() { + return widgetModel.getCameraIndex(); + } + + @NonNull + @Override + public CameraLensType getLensType() { + return widgetModel.getLensType(); + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + widgetModel.updateCameraSource(cameraIndex, lensType); + } + + /** + * Set drawable for auto exposure lock in locked state + * + * @param resourceId to be used + */ + public void setAutoExposureLockIcon(@DrawableRes int resourceId) { + setAutoExposureLockIcon(getResources().getDrawable(resourceId)); + } + + /** + * Set drawable for auto exposure lock in locked state + * + * @param drawable to be used + */ + public void setAutoExposureLockIcon(@Nullable Drawable drawable) { + this.autoExposureLockDrawable = drawable; + checkAndUpdateAELock(); + } + + /** + * Get current drawable resource for auto exposure lock in locked state + * + * @return Drawable + */ + @Nullable + public Drawable getAutoExposureLockDrawable() { + return autoExposureLockDrawable; + } + + /** + * Set resource for auto exposure lock in unlocked state + * + * @param resourceId to be used + */ + public void setAutoExposureUnlockIcon(@DrawableRes int resourceId) { + setAutoExposureUnlockIcon(getResources().getDrawable(resourceId)); + } + + /** + * Set drawable for auto exposure lock in unlocked state + * + * @param drawable to be used + */ + public void setAutoExposureUnlockIcon(@Nullable Drawable drawable) { + this.autoExposureUnlockDrawable = drawable; + checkAndUpdateAELock(); + } + + /** + * Get current drawable resource for auto exposure lock in unlocked state + * + * @return Drawable + */ + @Nullable + public Drawable getAutoExposureUnlockDrawable() { + return autoExposureUnlockDrawable; + } + + /** + * Get current text color state list of widget title + * + * @return ColorStateList used + */ + @Nullable + public ColorStateList getTitleTextColors() { + return titleTextView.getTextColors(); + } + + /** + * Get the current color of title text + * + * @return integer value representing color + */ + @ColorInt + public int getTitleTextColor() { + return titleTextView.getCurrentTextColor(); + } + + /** + * Set text color state list to the widget title + * + * @param colorStateList to be used + */ + public void setTitleTextColor(@Nullable ColorStateList colorStateList) { + titleTextView.setTextColor(colorStateList); + } + + /** + * Set the color of title text + * + * @param color integer value + */ + public void setTitleTextColor(@ColorInt int color) { + titleTextView.setTextColor(color); + } + + /** + * Set text appearance of the widget title + * + * @param textAppearance to be used + */ + public void setTitleTextAppearance(@StyleRes int textAppearance) { + titleTextView.setTextAppearance(getContext(), textAppearance); + } + + /** + * Get current background of icon + * + * @return Drawable + */ + @NonNull + public Drawable getIconBackground() { + return foregroundImageView.getBackground(); + } + + /** + * Set background to icon + * + * @param resourceId to be used + */ + public void setIconBackground(@DrawableRes int resourceId) { + setIconBackground(getResources().getDrawable(resourceId)); + } + + /** + * Set background to icon + * + * @param drawable to be used + */ + public void setIconBackground(@Nullable Drawable drawable) { + foregroundImageView.setBackground(drawable); + } + + /** + * Get current background of title text + * + * @return Drawable + */ + @Nullable + public Drawable getTitleBackground() { + return titleTextView.getBackground(); + } + + /** + * Set background to title text + * + * @param resourceId to be used + */ + public void setTitleBackground(@DrawableRes int resourceId) { + setTitleBackground(getResources().getDrawable(resourceId)); + } + + /** + * Set background to title text + * + * @param drawable to be used + */ + public void setTitleBackground(@Nullable Drawable drawable) { + titleTextView.setBackground(drawable); + } + + @Override + public void setEnabled(boolean enabled) { + titleTextView.setEnabled(enabled); + foregroundImageView.setEnabled(enabled); + super.setEnabled(enabled); + } + + /** + * Get the color tint for exposure settings unlocked icon + * + * @return ColorStateList used as color tint + */ + @Nullable + public ColorStateList getAutoExposureUnlockIconTint() { + return unlockDrawableTint; + } + + /** + * Set the color of tint for exposure settings unlocked icon + * + * @param color int value + */ + public void setAutoExposureUnlockIconTint(@ColorInt int color) { + setAutoExposureUnlockIconTint(ColorStateList.valueOf(color)); + } + + /** + * Set the color of tint for the exposure settings unlocked icon + * + * @param colorStateList to be used + */ + public void setAutoExposureUnlockIconTint(@Nullable ColorStateList colorStateList) { + unlockDrawableTint = colorStateList; + checkAndUpdateAELock(); + } + + /** + * Get the color tint for exposure settings locked icon + * + * @return ColorStateList used as color tint + */ + @Nullable + public ColorStateList getAutoExposureLockIconTint() { + return lockDrawableTint; + } + + /** + * Set the color of tint for exposure settings locked icon + * + * @param color int value + */ + public void setAutoExposureLockIconTint(@ColorInt int color) { + setAutoExposureLockIconTint(ColorStateList.valueOf(color)); + } + + /** + * Set the color of tint for the exposure settings locked icon + * + * @param colorStateList to be used + */ + public void setAutoExposureLockIconTint(@Nullable ColorStateList colorStateList) { + lockDrawableTint = colorStateList; + checkAndUpdateAELock(); + } + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/autoexposurelock/AutoExposureLockWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/autoexposurelock/AutoExposureLockWidgetModel.java new file mode 100644 index 00000000..12ceedfa --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/autoexposurelock/AutoExposureLockWidgetModel.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.autoexposurelock; + +import androidx.annotation.NonNull; +import dji.sdk.keyvalue.key.CameraKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; + +/** + * Auto Exposure Lock Widget Model + *

+ * Widget Model for the {@link AutoExposureLockWidget} used to define the + * underlying logic and communication + */ +public class AutoExposureLockWidgetModel extends WidgetModel implements ICameraIndex { + //region Fields + private final DataProcessor autoExposureLockBooleanProcessor; + private ComponentIndexType cameraIndex = ComponentIndexType.LEFT_OR_MAIN; + private CameraLensType lensType = CameraLensType.CAMERA_LENS_ZOOM; + //endregion + + public AutoExposureLockWidgetModel(@NonNull DJISDKModel djiSdkModel, + @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + autoExposureLockBooleanProcessor = DataProcessor.create(false); + } + + //region Data + + /** + * Check if the auto exposure lock is enabled + * + * @return Flowable with boolean true - enabled false - disabled + */ + public Flowable isAutoExposureLockOn() { + return autoExposureLockBooleanProcessor.toFlowable(); + } + + //endregion + + //region Actions + + @NonNull + public ComponentIndexType getCameraIndex() { + return cameraIndex; + } + + @NonNull + @Override + public CameraLensType getLensType() { + return lensType; + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + this.cameraIndex = cameraIndex; + this.lensType = lensType; + restart(); + } + + /** + * Set auto exposure lock the opposite of its current state + * + * @return Completable representing success and failure of action + */ + public Completable toggleAutoExposureLock() { + return djiSdkModel.setValue(KeyTools.createCameraKey(CameraKey.KeyAELockEnabled, cameraIndex, lensType), !autoExposureLockBooleanProcessor.getValue()); + } + //endregion + + //region Lifecycle + @Override + protected void inSetup() { + KeyTools.createCameraKey(CameraKey.KeyAELockEnabled, cameraIndex, lensType); + bindDataProcessor(KeyTools.createCameraKey(CameraKey.KeyAELockEnabled, cameraIndex, lensType), autoExposureLockBooleanProcessor); + } + + @Override + protected void inCleanup() { + // nothing to clean + } + + @Override + protected void updateStates() { + // No States + } + + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/CameraCaptureWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/CameraCaptureWidget.java new file mode 100644 index 00000000..e6d5e094 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/CameraCaptureWidget.java @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracapture; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; + +import java.util.HashMap; +import java.util.Map; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.constraintlayout.widget.Constraints; +import dji.sdk.keyvalue.value.camera.CameraMode; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.ux.R; +import dji.v5.ux.cameracore.widget.cameracapture.recordvideo.RecordVideoWidget; +import dji.v5.ux.cameracore.widget.cameracapture.shootphoto.ShootPhotoWidget; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.SchedulerProvider; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.UxErrorHandle; + +/** + * Camera Capture Widget + *

+ * Widget can be used to shoot photo and record video. It reacts to change in {@link CameraMode} + * It encloses {@link ShootPhotoWidget} and {@link RecordVideoWidget} for respective modes + */ +public class CameraCaptureWidget extends ConstraintLayoutWidget implements ICameraIndex { + + //region Fields + private static final String TAG = "CameraCaptureWidget"; + private CameraCaptureWidgetModel widgetModel; + private Map widgetMap; + //endregion + + //region Lifecycle + public CameraCaptureWidget(Context context) { + super(context); + } + + public CameraCaptureWidget(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public CameraCaptureWidget(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + widgetMap = new HashMap<>(); + if (!isInEditMode()) { + addViewByMode(CameraMode.PHOTO_NORMAL, new ShootPhotoWidget(context)); + addViewByMode(CameraMode.VIDEO_NORMAL, new RecordVideoWidget(context)); + widgetModel = new CameraCaptureWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + if (!isInEditMode()) { + widgetModel.cleanup(); + } + super.onDetachedFromWindow(); + } + + @Override + protected void reactToModelChanges() { + addReaction( + widgetModel.getCameraMode() + .observeOn(SchedulerProvider.ui()) + .subscribe( + this::onCameraModeChange, + UxErrorHandle.logErrorConsumer(TAG, "Camera Mode Change: "))); + } + + @NonNull + @Override + public String getIdealDimensionRatioString() { + return getResources().getString(R.string.uxsdk_widget_default_ratio); + } + //endregion + + @NonNull + public ComponentIndexType getCameraIndex() { + return widgetModel.getCameraIndex(); + } + + @NonNull + @Override + public CameraLensType getLensType() { + return widgetModel.getLensType(); + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + widgetModel.updateCameraSource(cameraIndex, lensType); + ShootPhotoWidget shootPhotoWidget = getShootPhotoWidget(); + if (shootPhotoWidget != null) { + shootPhotoWidget.updateCameraSource(cameraIndex, lensType); + } + RecordVideoWidget recordVideoWidget = getRecordVideoWidget(); + if (recordVideoWidget != null) { + recordVideoWidget.updateCameraSource(cameraIndex, lensType); + } + } + + //region private helpers + private void onCameraModeChange(CameraMode cameraMode) { + for (View view : widgetMap.values()) { + if (view != null) view.setVisibility(INVISIBLE); + } + View currentView = widgetMap.get(cameraMode); + if (currentView != null) { + widgetMap.get(cameraMode).setVisibility(VISIBLE); + } + } + //endregion + + //region customizations + + /** + * Add view to be shown based on camera mode + * + * @param cameraMode instance of camera mode + * @param view the view to be shown for camera mode + */ + public void addViewByMode(@NonNull CameraMode cameraMode, @NonNull View view) { + if (widgetMap.get(cameraMode) != null) { + removeView(widgetMap.get(cameraMode)); + } + widgetMap.put(cameraMode, view); + view.setVisibility(INVISIBLE); + addView(view); + LayoutParams lp = new Constraints.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + view.setLayoutParams(lp); + } + + /** + * Remove the view based on camera mode + * + * @param cameraMode for which the view should be removed + */ + public void removeViewByMode(@NonNull CameraMode cameraMode) { + if (widgetMap.get(cameraMode) == null) return; + removeView(widgetMap.get(cameraMode)); + widgetMap.remove(cameraMode); + } + + /** + * Get the view that will be shown based on camera mode + * + * @param cameraMode for which the view is shown + * @return View for the mode + */ + @Nullable + public View getViewByMode(@NonNull CameraMode cameraMode) { + return widgetMap.get(cameraMode); + } + + /** + * Get shoot photo widget + * + * @return instance of {@link ShootPhotoWidget} + */ + @Nullable + public ShootPhotoWidget getShootPhotoWidget() { + if (widgetMap.get(CameraMode.PHOTO_NORMAL) == null || !(widgetMap.get(CameraMode.PHOTO_NORMAL) instanceof ShootPhotoWidget)) { + return null; + } + return (ShootPhotoWidget) widgetMap.get(CameraMode.PHOTO_NORMAL); + } + + /** + * Get record video widget + * + * @return instance of {@link RecordVideoWidget} + */ + @Nullable + public RecordVideoWidget getRecordVideoWidget() { + if (widgetMap.get(CameraMode.VIDEO_NORMAL) == null || !(widgetMap.get(CameraMode.VIDEO_NORMAL) instanceof RecordVideoWidget)) { + return null; + } + return (RecordVideoWidget) widgetMap.get(CameraMode.VIDEO_NORMAL); + } + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/CameraCaptureWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/CameraCaptureWidgetModel.java new file mode 100644 index 00000000..4a33c5f4 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/CameraCaptureWidgetModel.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracapture; + +import androidx.annotation.NonNull; +import dji.sdk.keyvalue.value.camera.CameraMode; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.module.FlatCameraModule; +import io.reactivex.rxjava3.core.Flowable; + +/** + * Camera Capture Widget Model + *

+ * Widget Model for {@link CameraCaptureWidget} used to define underlying logic + * and communication + */ +public class CameraCaptureWidgetModel extends WidgetModel implements ICameraIndex { + + //region Fields + private FlatCameraModule flatCameraModule; + private ComponentIndexType cameraIndex = ComponentIndexType.LEFT_OR_MAIN; + private CameraLensType lensType = CameraLensType.CAMERA_LENS_ZOOM; + + //region Lifecycle + public CameraCaptureWidgetModel(@NonNull DJISDKModel djiSdkModel, + @NonNull ObservableInMemoryKeyedStore keyedStore) { + super(djiSdkModel, keyedStore); + flatCameraModule = new FlatCameraModule(); + addModule(flatCameraModule); + } + + @Override + protected void inSetup() { + // do nothing + } + + @Override + protected void inCleanup() { + // do nothing + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + this.cameraIndex = cameraIndex; + this.lensType = lensType; + flatCameraModule.updateCameraSource(cameraIndex,lensType); + restart(); + } + + @NonNull + public ComponentIndexType getCameraIndex() { + return cameraIndex; + } + + @NonNull + public CameraLensType getLensType() { + return lensType; + } + + @Override + protected void updateStates() { + // Empty function + } + //endregion + + //region Data + + /** + * Get the current camera Mode + * + * @return Flowable with {@link CameraMode} instance + */ + public Flowable getCameraMode() { + return flatCameraModule.getCameraModeDataProcessor().toFlowable(); + } + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/recordvideo/CameraSDVideoStorageState.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/recordvideo/CameraSDVideoStorageState.java new file mode 100644 index 00000000..5d9475f0 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/recordvideo/CameraSDVideoStorageState.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracapture.recordvideo; + +import dji.sdk.keyvalue.value.camera.CameraSDCardState; +import dji.sdk.keyvalue.value.camera.CameraStorageLocation; +import dji.sdk.keyvalue.value.camera.SSDOperationState; + +/** + * Class represents storage state for SD card and internal storage + * when camera is in record video mode + */ +public class CameraSDVideoStorageState extends CameraVideoStorageState { + + private CameraSDCardState sdCardOperationState; + + public CameraSDVideoStorageState(CameraStorageLocation storageLocation, int availableRecordingTimeInSeconds, CameraSDCardState sdCardOperationState) { + super(storageLocation, availableRecordingTimeInSeconds); + this.sdCardOperationState = sdCardOperationState; + } + + /** + * Get the operation state of current storage + * + * @return instance of {@link SSDOperationState} representing state for SDCard or internal Storage + */ + public CameraSDCardState getSdCardOperationState() { + return sdCardOperationState; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CameraSDVideoStorageState)) return false; + if (!super.equals(o)) return false; + CameraSDVideoStorageState that = (CameraSDVideoStorageState) o; + return getSdCardOperationState() == that.getSdCardOperationState(); + } + + @Override + public int hashCode() { + return 31 * getSdCardOperationState().value(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/recordvideo/CameraSSDVideoStorageState.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/recordvideo/CameraSSDVideoStorageState.java new file mode 100644 index 00000000..3fea7578 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/recordvideo/CameraSSDVideoStorageState.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracapture.recordvideo; + + +import dji.sdk.keyvalue.value.camera.CameraStorageLocation; +import dji.sdk.keyvalue.value.camera.SSDOperationState; + +/** + * Class represents SSD Storage state for Record Video Mode + */ +public class CameraSSDVideoStorageState extends CameraVideoStorageState { + + private SSDOperationState ssdOperationState; + + public CameraSSDVideoStorageState(CameraStorageLocation storageLocation, int availableRecordingTimeInSeconds, SSDOperationState ssdOperationState) { + super(storageLocation, availableRecordingTimeInSeconds); + this.ssdOperationState = ssdOperationState; + } + + /** + * Get operation state of SSD + * + * @return {@link SSDOperationState} + */ + public SSDOperationState getSsdOperationState() { + return ssdOperationState; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CameraSSDVideoStorageState)) return false; + if (!super.equals(o)) return false; + CameraSSDVideoStorageState that = (CameraSSDVideoStorageState) o; + return getSsdOperationState() == that.getSsdOperationState(); + } + + @Override + public int hashCode() { + return 31 * getSsdOperationState().value(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/recordvideo/CameraVideoStorageState.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/recordvideo/CameraVideoStorageState.java new file mode 100644 index 00000000..38f25a63 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/recordvideo/CameraVideoStorageState.java @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracapture.recordvideo; + +import dji.sdk.keyvalue.value.camera.CameraStorageLocation; + +/** + * Class represents the storage state when camera is in Record Video Mode + * The state determines the storage location and the available space + * in terms of duration in seconds + */ +public abstract class CameraVideoStorageState { + private final CameraStorageLocation storageLocation; + private final int availableRecordingTimeInSeconds; + + protected CameraVideoStorageState(CameraStorageLocation storageLocation, int availableRecordingTimeInSeconds) { + this.storageLocation = storageLocation; + this.availableRecordingTimeInSeconds = availableRecordingTimeInSeconds; + } + + /** + * Get the current storage location + * + * @return instance of CameraStorageLocation + */ + public CameraStorageLocation getStorageLocation() { + return storageLocation; + } + + /** + * Get the duration in seconds that can be recorded before running out of storage + * + * @return integer value representing seconds + */ + public int getAvailableRecordingTimeInSeconds() { + return availableRecordingTimeInSeconds; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CameraVideoStorageState)) return false; + CameraVideoStorageState that = (CameraVideoStorageState) o; + return getAvailableRecordingTimeInSeconds() == that.getAvailableRecordingTimeInSeconds() && + getStorageLocation() == that.getStorageLocation(); + } + + @Override + public int hashCode() { + int result = 31 * getStorageLocation().value(); + result = result + 31 * getAvailableRecordingTimeInSeconds(); + return result; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/recordvideo/RecordVideoWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/recordvideo/RecordVideoWidget.java new file mode 100644 index 00000000..eee7bbdc --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/recordvideo/RecordVideoWidget.java @@ -0,0 +1,669 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracapture.recordvideo; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.ImageView; +import android.widget.TextView; + +import java.util.HashMap; +import java.util.Map; + +import androidx.annotation.ColorInt; +import androidx.annotation.Dimension; +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StyleRes; +import dji.sdk.keyvalue.value.camera.CameraSDCardState; +import dji.sdk.keyvalue.value.camera.CameraStorageLocation; +import dji.sdk.keyvalue.value.camera.SSDOperationState; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.ux.R; +import dji.v5.ux.cameracore.util.CameraActionSound; +import dji.v5.ux.cameracore.widget.cameracapture.recordvideo.RecordVideoWidgetModel.RecordingState; +import dji.v5.ux.cameracore.widget.cameracontrols.RemoteControllerButtonDownModel; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.SchedulerProvider; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.CameraUtil; +import dji.v5.ux.core.util.UxErrorHandle; +import io.reactivex.rxjava3.core.Completable; + +/** + * Record Video Widget + *

+ * Widget can be used for recording video. The widget displays the current video mode. It also + * displays the storage state and errors associated with it. + */ +public class RecordVideoWidget extends ConstraintLayoutWidget implements OnClickListener, ICameraIndex { + + //region Fields + private static final String TAG = "RecordVideoWidget"; + private RecordVideoWidgetModel widgetModel; + private RemoteControllerButtonDownModel buttonDownModel; + private ImageView centerImageView; + private TextView videoTimerTextView; + private ImageView storageStatusOverlayImageView; + private Map storageInternalIconMap; + private Map storageSSDIconMap; + private Map storageSDCardIconMap; + private Drawable recordVideoStartDrawable; + private Drawable recordVideoStopDrawable; + private CameraActionSound cameraActionSound; + //endregion + + //region Lifecycle + public RecordVideoWidget(Context context) { + super(context); + } + + public RecordVideoWidget(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public RecordVideoWidget(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_widget_record_video, this); + centerImageView = findViewById(R.id.image_view_center); + videoTimerTextView = findViewById(R.id.text_view_video_record_time); + storageStatusOverlayImageView = findViewById(R.id.image_view_storage_status_overlay); + storageInternalIconMap = new HashMap<>(); + storageSSDIconMap = new HashMap<>(); + storageSDCardIconMap = new HashMap<>(); + centerImageView.setOnClickListener(this); + cameraActionSound = new CameraActionSound(context); + if (!isInEditMode()) { + widgetModel = new RecordVideoWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + buttonDownModel = new RemoteControllerButtonDownModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + } + initDefaults(); + if (attrs != null) { + initAttributes(context, attrs); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + buttonDownModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + if (!isInEditMode()) { + widgetModel.cleanup(); + buttonDownModel.cleanup(); + } + super.onDetachedFromWindow(); + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.getRecordingTimeInSeconds() + .observeOn(SchedulerProvider.ui()) + .subscribe(this::updateRecordingTime, UxErrorHandle.logErrorConsumer(TAG, "record time: "))); + addReaction(widgetModel.getRecordingState() + .observeOn(SchedulerProvider.ui()) + .subscribe(recordingState -> onIsRecordingVideoChange(recordingState, true), UxErrorHandle.logErrorConsumer(TAG, "is recording: "))); + addReaction(widgetModel.getCameraVideoStorageState() + .observeOn(SchedulerProvider.ui()) + .subscribe(this::updateCameraForegroundResource, UxErrorHandle.logErrorConsumer(TAG, "camera storage update: "))); + addReaction(buttonDownModel.isRecordButtonDownProcessor().toFlowable() + .observeOn(SchedulerProvider.ui()) + .subscribe(aBoolean -> { + if (aBoolean == Boolean.TRUE) { + actionOnRecording(); + } + })); + } + + @NonNull + @Override + public String getIdealDimensionRatioString() { + return getResources().getString(R.string.uxsdk_widget_default_ratio); + } + + @NonNull + public ComponentIndexType getCameraIndex() { + return widgetModel.getCameraIndex(); + } + + @NonNull + @Override + public CameraLensType getLensType() { + return widgetModel.getLensType(); + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + if (!isInEditMode()) { + widgetModel.updateCameraSource(cameraIndex, lensType); + } + } + + @Override + public void onClick(View v) { + if (v.equals(centerImageView)) { + actionOnRecording(); + } + } + + private void actionOnRecording() { + if (!widgetModel.isVideoMode()) { + return; + } + widgetModel.getRecordingState().firstOrError().flatMapCompletable(recordingState -> { + if (recordingState == RecordingState.RECORDING_IN_PROGRESS) { + return widgetModel.stopRecordVideo(); + } else if (recordingState == RecordingState.RECORDING_STOPPED || recordingState == RecordingState.RECORDING_NOT_STARED) { + return widgetModel.startRecordVideo(); + } else { + return Completable.complete(); + } + }).observeOn(SchedulerProvider.ui()).subscribe(() -> { + }, UxErrorHandle.logErrorConsumer(TAG, "START STOP VIDEO")); + } + + //region private helpers + private void initDefaults() { + recordVideoStartDrawable = getResources().getDrawable(R.drawable.uxsdk_selector_start_record_video); + recordVideoStopDrawable = getResources().getDrawable(R.drawable.uxsdk_selector_stop_record_video); + setInternalStorageIcon(StorageIconState.NOT_INSERTED, R.drawable.uxsdk_ic_internal_storage_not_inserted); + setInternalStorageIcon(StorageIconState.SLOW, R.drawable.uxsdk_ic_internal_storage_slow); + setInternalStorageIcon(StorageIconState.FULL, R.drawable.uxsdk_ic_internal_storage_full); + setSDCardStorageIcon(StorageIconState.NOT_INSERTED, R.drawable.uxsdk_ic_sdcard_not_inserted); + setSDCardStorageIcon(StorageIconState.SLOW, R.drawable.uxsdk_ic_sdcard_slow); + setSDCardStorageIcon(StorageIconState.FULL, R.drawable.uxsdk_ic_sdcard_full); + setSSDStorageIcon(StorageIconState.NOT_INSERTED, R.drawable.uxsdk_ic_ssd_not_inserted); + setSSDStorageIcon(StorageIconState.FULL, R.drawable.uxsdk_ic_ssd_full); + setVideoTimerTextColor(Color.WHITE); + } + + private void initAttributes(@NonNull Context context, @NonNull AttributeSet attrs) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RecordVideoWidget); + updateCameraSource(ComponentIndexType.find(typedArray.getInt(R.styleable.RecordVideoWidget_uxsdk_cameraIndex, 0)), + CameraLensType.find(typedArray.getInt(R.styleable.RecordVideoWidget_uxsdk_lensType, 0))); + + int textAppearance = typedArray.getResourceId(R.styleable.RecordVideoWidget_uxsdk_timerTextAppearance, INVALID_RESOURCE); + if (textAppearance != INVALID_RESOURCE) { + setTimerTextAppearance(textAppearance); + } + setVideoTimerTextColor(typedArray.getColor(R.styleable.RecordVideoWidget_uxsdk_timerTextColor, Color.WHITE)); + if (typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_timerTextBackground) != null) { + setVideoTimerTextBackground(typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_timerTextBackground)); + } + setVideoTimerTextSize(typedArray.getDimension(R.styleable.RecordVideoWidget_uxsdk_timerTextSize, 12)); + if (typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_foregroundIconBackground) != null) { + setForegroundIconBackground(typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_foregroundIconBackground)); + } + + initRecordVideoDrawable(typedArray); + initInternalStorageIcon(typedArray); + initSDCardStorageIcon(typedArray); + initSSDStorageIcon(typedArray); + typedArray.recycle(); + } + + private void initSSDStorageIcon(TypedArray typedArray) { + if (typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_ssdNotInsertedIcon) != null) { + setSSDStorageIcon(StorageIconState.NOT_INSERTED, typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_ssdNotInsertedIcon)); + } + if (typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_ssdFullIcon) != null) { + setSSDStorageIcon(StorageIconState.FULL, typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_ssdFullIcon)); + } + if (typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_ssdSlowIcon) != null) { + setSSDStorageIcon(StorageIconState.SLOW, typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_ssdSlowIcon)); + } + } + + private void initSDCardStorageIcon(TypedArray typedArray) { + if (typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_sdCardNotInsertedIcon) != null) { + setSDCardStorageIcon(StorageIconState.NOT_INSERTED, typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_sdCardNotInsertedIcon)); + } + if (typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_sdCardFullIcon) != null) { + setSDCardStorageIcon(StorageIconState.FULL, typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_sdCardFullIcon)); + } + if (typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_sdCardSlowIcon) != null) { + setSDCardStorageIcon(StorageIconState.SLOW, typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_sdCardSlowIcon)); + } + + } + + private void initInternalStorageIcon(TypedArray typedArray) { + if (typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_internalStorageNotInsertedIcon) != null) { + setInternalStorageIcon(StorageIconState.NOT_INSERTED, typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_internalStorageNotInsertedIcon)); + } + if (typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_internalStorageFullIcon) != null) { + setInternalStorageIcon(StorageIconState.FULL, typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_internalStorageFullIcon)); + } + if (typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_internalStorageSlowIcon) != null) { + setInternalStorageIcon(StorageIconState.SLOW, typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_internalStorageSlowIcon)); + } + } + + private void initRecordVideoDrawable(TypedArray typedArray) { + if (typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_recordStartIcon) != null) { + recordVideoStartDrawable = typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_recordStartIcon); + } + if (typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_recordStopIcon) != null) { + recordVideoStopDrawable = typedArray.getDrawable(R.styleable.RecordVideoWidget_uxsdk_recordStopIcon); + } + } + + private void updateCameraForegroundResource(CameraVideoStorageState cameraVideoStorageState) { + Drawable foregroundResource = null; + if (cameraVideoStorageState instanceof CameraSDVideoStorageState) { + if (cameraVideoStorageState.getStorageLocation() == CameraStorageLocation.SDCARD) { + foregroundResource = updateResourceWithStorageInSDCard(cameraVideoStorageState); + } else if (cameraVideoStorageState.getStorageLocation() == CameraStorageLocation.INTERNAL) { + foregroundResource = updateResourceWithStorageInternal(cameraVideoStorageState); + } + } else if (cameraVideoStorageState instanceof CameraSSDVideoStorageState) { + if (((CameraSSDVideoStorageState) cameraVideoStorageState).getSsdOperationState() + == SSDOperationState.NOT_FOUND) { + foregroundResource = getSSDStorageIcon(StorageIconState.NOT_INSERTED); + } else if (((CameraSSDVideoStorageState) cameraVideoStorageState).getSsdOperationState() + == SSDOperationState.FULL) { + foregroundResource = getSSDStorageIcon(StorageIconState.FULL); + } + } + + storageStatusOverlayImageView.setImageDrawable(foregroundResource); + } + + private Drawable updateResourceWithStorageInSDCard(CameraVideoStorageState cameraVideoStorageState) { + Drawable foregroundResource = null; + if (((CameraSDVideoStorageState) cameraVideoStorageState).getSdCardOperationState() + == CameraSDCardState.NOT_INSERTED) { + foregroundResource = getSDCardStorageIcon(StorageIconState.NOT_INSERTED); + } else if (((CameraSDVideoStorageState) cameraVideoStorageState).getSdCardOperationState() + == CameraSDCardState.FULL) { + foregroundResource = getSDCardStorageIcon(StorageIconState.FULL); + } else if (((CameraSDVideoStorageState) cameraVideoStorageState).getSdCardOperationState() + == CameraSDCardState.SLOW) { + foregroundResource = getSDCardStorageIcon(StorageIconState.SLOW); + } + return foregroundResource; + } + + private Drawable updateResourceWithStorageInternal(CameraVideoStorageState cameraVideoStorageState) { + Drawable foregroundResource = null; + if (((CameraSDVideoStorageState) cameraVideoStorageState).getSdCardOperationState() + == CameraSDCardState.NOT_INSERTED) { + foregroundResource = getInternalStorageIcon(StorageIconState.NOT_INSERTED); + } else if (((CameraSDVideoStorageState) cameraVideoStorageState).getSdCardOperationState() + == CameraSDCardState.FULL) { + foregroundResource = getInternalStorageIcon(StorageIconState.FULL); + } else if (((CameraSDVideoStorageState) cameraVideoStorageState).getSdCardOperationState() + == CameraSDCardState.SLOW) { + foregroundResource = getInternalStorageIcon(StorageIconState.SLOW); + } + return foregroundResource; + } + + private void updateRecordingTime(int seconds) { + videoTimerTextView.setText(CameraUtil.formatVideoTime(getResources(), seconds)); + } + + private void onIsRecordingVideoChange(RecordingState recordingState, boolean playSound) { + boolean isRecordingVideo = recordingState == RecordingState.RECORDING_IN_PROGRESS; + Drawable recordStart = recordVideoStartDrawable; + Drawable recordStop = recordVideoStopDrawable; + centerImageView.setImageDrawable(isRecordingVideo ? recordStop : recordStart); + videoTimerTextView.setVisibility(isRecordingVideo ? View.VISIBLE : View.INVISIBLE); + storageStatusOverlayImageView.setVisibility(isRecordingVideo ? View.GONE : View.VISIBLE); + if (playSound) { + if (recordingState == RecordingState.RECORDING_IN_PROGRESS) { + cameraActionSound.playStartRecordVideo(); + } else if (recordingState == RecordingState.RECORDING_STOPPED) { + cameraActionSound.playStopRecordVideo(); + } + } + } + + private void checkAndUpdateCameraForegroundResource() { + if (!isInEditMode()) { + addDisposable(widgetModel.getCameraVideoStorageState().firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(this::updateCameraForegroundResource, + UxErrorHandle.logErrorConsumer(TAG, "check and update camera foreground resource: "))); + } + } + + private void checkAndUpdateCenterImageView() { + if (!isInEditMode()) { + addDisposable(widgetModel.getRecordingState().firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(recordingState -> onIsRecordingVideoChange(recordingState, false), + UxErrorHandle.logErrorConsumer(TAG, "check and update camera foreground resource: "))); + } + } + //endregion + + //region customizations + + /** + * Get the current start recording video icon + * + * @return Drawable currently used + */ + @Nullable + public Drawable getRecordVideoStartDrawable() { + return recordVideoStartDrawable; + } + + /** + * Set the start record video icon + * + * @param resourceId to be used + */ + public void setRecordVideoStartDrawable(@DrawableRes int resourceId) { + setRecordVideoStartDrawable(getResources().getDrawable(resourceId)); + } + + /** + * Set the start record video icon + * + * @param drawable to be used + */ + public void setRecordVideoStartDrawable(@Nullable Drawable drawable) { + recordVideoStartDrawable = drawable; + checkAndUpdateCenterImageView(); + } + + /** + * Get the current stop video recording icon + * + * @return Drawable currently used + */ + @Nullable + public Drawable getRecordVideoStopDrawable() { + return recordVideoStopDrawable; + } + + /** + * Set stop video recording icon + * + * @param resourceId to be used + */ + public void setRecordVideoStopDrawable(@DrawableRes int resourceId) { + setRecordVideoStopDrawable(getResources().getDrawable(resourceId)); + } + + /** + * Set stop video recording icon + * + * @param drawable to be used + */ + public void setRecordVideoStopDrawable(@Nullable Drawable drawable) { + recordVideoStopDrawable = drawable; + checkAndUpdateCenterImageView(); + } + + /** + * Set the icon for internal storage based on storage icon state + * + * @param storageIconState for which icon is used + * @param resourceId to be used + */ + public void setInternalStorageIcon(@NonNull StorageIconState storageIconState, @DrawableRes int resourceId) { + setInternalStorageIcon(storageIconState, getResources().getDrawable(resourceId)); + } + + /** + * Set the icon for internal storage based on storage icon state + * + * @param storageIconState for which icon is used + * @param drawable to be used + */ + public void setInternalStorageIcon(@NonNull StorageIconState storageIconState, @Nullable Drawable drawable) { + storageInternalIconMap.put(storageIconState, drawable); + checkAndUpdateCameraForegroundResource(); + } + + /** + * Get the icon for internal storage based on storage icon state + * + * @param storageIconState for which icon is used + * @return Drawable currently used + */ + @Nullable + public Drawable getInternalStorageIcon(@NonNull StorageIconState storageIconState) { + return storageInternalIconMap.get(storageIconState); + } + + /** + * Set the icon for SD card storage based on storage icon state + * + * @param storageIconState for which icon is used + * @param resourceId to be used + */ + public void setSDCardStorageIcon(@NonNull StorageIconState storageIconState, @DrawableRes int resourceId) { + setSDCardStorageIcon(storageIconState, getResources().getDrawable(resourceId)); + } + + /** + * Set the icon for SD card storage based on storage icon state + * + * @param storageIconState for which icon is used + * @param drawable to be used + */ + public void setSDCardStorageIcon(@NonNull StorageIconState storageIconState, @Nullable Drawable drawable) { + storageSDCardIconMap.put(storageIconState, drawable); + checkAndUpdateCameraForegroundResource(); + } + + /** + * Get the icon for SD card storage based on storage icon state + * + * @param storageIconState for which icon is used + * @return Drawable currently used + */ + @Nullable + public Drawable getSDCardStorageIcon(@NonNull StorageIconState storageIconState) { + return storageSDCardIconMap.get(storageIconState); + } + + /** + * Set the icon for SSD storage based on storage icon state + * + * @param storageIconState for which icon should be used + * @param resourceId to be used + */ + public void setSSDStorageIcon(@NonNull StorageIconState storageIconState, @DrawableRes int resourceId) { + setSSDStorageIcon(storageIconState, getResources().getDrawable(resourceId)); + } + + /** + * Set the icon for SSD storage based on storage icon state + * + * @param storageIconState for which icon should be used + * @param drawable Drawable to be used + */ + public void setSSDStorageIcon(@NonNull StorageIconState storageIconState, @Nullable Drawable drawable) { + storageSSDIconMap.put(storageIconState, drawable); + checkAndUpdateCameraForegroundResource(); + } + + /** + * Get the icon for SSD storage based on storage icon state + * + * @param storageIconState for which icon is used + * @return Drawable currently used + */ + @Nullable + public Drawable getSSDStorageIcon(@NonNull StorageIconState storageIconState) { + return storageSSDIconMap.get(storageIconState); + } + + /** + * Set the background of the foreground icon + * + * @param resourceId to be used as background + */ + public void setForegroundIconBackground(@DrawableRes int resourceId) { + storageStatusOverlayImageView.setBackgroundResource(resourceId); + } + + /** + * Set background of the foreground icon + * + * @param drawable to be used as background + */ + public void setForegroundIconBackground(@Nullable Drawable drawable) { + storageStatusOverlayImageView.setBackground(drawable); + } + + /** + * Get current background of foreground icon + * + * @return Drawable being used + */ + public Drawable getForegroundIconBackground() { + return storageStatusOverlayImageView.getBackground(); + } + + /** + * Set the background of the video record duration text + * + * @param resourceId to be used + */ + public void setVideoTimerTextBackground(@DrawableRes int resourceId) { + videoTimerTextView.setBackgroundResource(resourceId); + } + + /** + * Set the background of the video record duration text + * + * @param drawable to be used + */ + public void setVideoTimerTextBackground(@Nullable Drawable drawable) { + videoTimerTextView.setBackground(drawable); + } + + /** + * Get the color state list currently used for video record duration text + * + * @return ColorSateList + */ + @Nullable + public ColorStateList getVideoTimerTextColors() { + return videoTimerTextView.getTextColors(); + } + + /** + * Set the color state list for video record duration text + * + * @param colorStateList to be used + */ + public void setVideoTimerTextColors(@Nullable ColorStateList colorStateList) { + videoTimerTextView.setTextColor(colorStateList); + } + + /** + * Get the current text color of video record duration text + * + * @return integer value representing color + */ + @ColorInt + public int getVideoTimerTextColor() { + return videoTimerTextView.getCurrentTextColor(); + } + + /** + * Set the text color of video record duration text + * + * @param color integer value representing color + */ + public void setVideoTimerTextColor(@ColorInt int color) { + videoTimerTextView.setTextColor(color); + } + + /** + * Get the current text size of video record duration text + * + * @return float value representing text size + */ + @Dimension + public float getVideoTimerTextSize() { + return videoTimerTextView.getTextSize(); + } + + /** + * Set the text size of video record duration text + * + * @param textSize float value + */ + public void setVideoTimerTextSize(@Dimension float textSize) { + videoTimerTextView.setTextSize(textSize); + } + + /** + * Set the text appearance for video record duration text + * + * @param textAppearance to be used + */ + public void setTimerTextAppearance(@StyleRes int textAppearance) { + videoTimerTextView.setTextAppearance(getContext(), textAppearance); + } + //endregion + + /** + * Enum indicating storage error state + */ + public enum StorageIconState { + /** + * The storage is slow + */ + SLOW, + + /** + * The storage is full + */ + FULL, + + /** + * The storage is not inserted + */ + NOT_INSERTED + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/recordvideo/RecordVideoWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/recordvideo/RecordVideoWidgetModel.java new file mode 100644 index 00000000..352ae891 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/recordvideo/RecordVideoWidgetModel.java @@ -0,0 +1,330 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracapture.recordvideo; + +import java.util.ArrayList; + +import androidx.annotation.NonNull; +import dji.sdk.keyvalue.key.CameraKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.value.camera.CameraSDCardState; +import dji.sdk.keyvalue.value.camera.CameraStorageInfo; +import dji.sdk.keyvalue.value.camera.CameraStorageInfos; +import dji.sdk.keyvalue.value.camera.CameraStorageLocation; +import dji.sdk.keyvalue.value.camera.CameraType; +import dji.sdk.keyvalue.value.camera.SSDOperationState; +import dji.sdk.keyvalue.value.camera.VideoFrameRate; +import dji.sdk.keyvalue.value.camera.VideoResolution; +import dji.sdk.keyvalue.value.camera.VideoResolutionFrameRate; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.module.FlatCameraModule; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; + +/** + * Record Video Widget Model + *

+ * Widget Model for {@link RecordVideoWidget} used to define underlying + * logic and communication + */ +public class RecordVideoWidgetModel extends WidgetModel implements ICameraIndex { + + private static final int INVALID_AVAILABLE_RECORDING_TIME = -1; + private static final int MAX_VIDEO_TIME_THRESHOLD_MINUTES = 29; + private static final int SECONDS_PER_MIN = 60; + + private final DataProcessor cameraVideoStorageState; + private final DataProcessor isRecording; + private final DataProcessor cameraDisplayName; + private final DataProcessor cameraType; + private final DataProcessor recordingTimeInSeconds; + private final DataProcessor recordedVideoParameters; + private final DataProcessor nonSSDRecordedVideoParameters; + private final DataProcessor ssdRecordedVideoParameters; + private final DataProcessor storageLocation; + private final DataProcessor sdCardState; + private final DataProcessor storageState; + private final DataProcessor innerStorageState; + private final DataProcessor ssdState; + private final DataProcessor cameraStorageInfos; + private final DataProcessor recordingStateProcessor; + private final FlatCameraModule flatCameraModule; + private ComponentIndexType cameraIndex = ComponentIndexType.LEFT_OR_MAIN; + private CameraLensType lensType = CameraLensType.CAMERA_LENS_ZOOM; + private boolean lastIsRecording = false; + //endregion + + //region Constructor + public RecordVideoWidgetModel(@NonNull DJISDKModel djiSdkModel, + @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + CameraSDVideoStorageState cameraSDVideoStorageState = new CameraSDVideoStorageState( + CameraStorageLocation.SDCARD, + 0, + CameraSDCardState.NOT_INSERTED); + cameraVideoStorageState = DataProcessor.create(cameraSDVideoStorageState); + isRecording = DataProcessor.create(false); + cameraDisplayName = DataProcessor.create(""); + cameraType = DataProcessor.create(CameraType.NOT_SUPPORTED); + recordingTimeInSeconds = DataProcessor.create(0); + VideoResolutionFrameRate resolutionAndFrameRate = new VideoResolutionFrameRate( + VideoResolution.UNKNOWN, + VideoFrameRate.UNKNOWN); + recordedVideoParameters = DataProcessor.create(resolutionAndFrameRate); + nonSSDRecordedVideoParameters = DataProcessor.create(resolutionAndFrameRate); + ssdRecordedVideoParameters = DataProcessor.create(resolutionAndFrameRate); + storageLocation = DataProcessor.create(CameraStorageLocation.SDCARD); + sdCardState = DataProcessor.create(CameraSDCardState.UNKNOWN_ERROR); + storageState = DataProcessor.create(CameraSDCardState.NORMAL); + innerStorageState = DataProcessor.create(CameraSDCardState.UNKNOWN_ERROR); + ssdState = DataProcessor.create(SSDOperationState.UNKNOWN); + cameraStorageInfos = DataProcessor.create(new CameraStorageInfos(CameraStorageLocation.UNKNOWN, new ArrayList<>())); + recordingStateProcessor = DataProcessor.create(RecordingState.UNKNOWN); + flatCameraModule = new FlatCameraModule(); + addModule(flatCameraModule); + } + //endregion + + //region Lifecycle + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createKey(CameraKey.KeyIsRecording, cameraIndex), isRecording, newValue -> { + if (newValue == null) { + recordingStateProcessor.onNext(RecordingState.UNKNOWN); + return; + } + if (lastIsRecording && !newValue) { //只有从ture变化为false时,才发stopped + recordingStateProcessor.onNext(RecordingState.RECORDING_STOPPED); + } else if (newValue) { + recordingStateProcessor.onNext(RecordingState.RECORDING_IN_PROGRESS); + } else { + recordingStateProcessor.onNext(RecordingState.RECORDING_NOT_STARED); + } + lastIsRecording = newValue; + }); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyRecordingTime, cameraIndex), recordingTimeInSeconds); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyCameraType, cameraIndex), cameraType, type -> cameraDisplayName.onNext(type.name())); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyCameraStorageLocation, cameraIndex), storageLocation); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyCameraSDCardState, cameraIndex), sdCardState); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyInternalStorageState, cameraIndex), innerStorageState); + bindDataProcessor(KeyTools.createKey(CameraKey.KeySSDOperationState, cameraIndex), ssdState); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyCameraStorageInfos, cameraIndex), cameraStorageInfos); + + // Resolution and Frame Rates + bindDataProcessor(KeyTools.createCameraKey(CameraKey.KeyVideoResolutionFrameRate, cameraIndex, lensType), nonSSDRecordedVideoParameters); + bindDataProcessor(KeyTools.createCameraKey(CameraKey.KeySSDVideoResolutionFrameRate, cameraIndex, lensType), ssdRecordedVideoParameters); + } + + @Override + protected void inCleanup() { + // Do nothing + } + + @Override + protected void updateStates() { + updateVideoStorageState(); + if (isRecording.getValue()) { + checkIsOverRecordTime(recordingTimeInSeconds.getValue()); + } + } + + @Override + protected void onProductConnectionChanged(boolean isConnected) { + super.onProductConnectionChanged(isConnected); + if (!isConnected) { + recordingStateProcessor.onNext(RecordingState.UNKNOWN); + } + } + + public boolean isVideoMode() { + return flatCameraModule.getCameraModeDataProcessor().getValue().isVideoMode(); + } + + /** + * Get the current camera video storage state + * + * @return Flowable with {@link CameraVideoStorageState} instance + */ + public Flowable getCameraVideoStorageState() { + return cameraVideoStorageState.toFlowable(); + } + + /** + * Check the recording state of the camera + * + * @return Flowable with {@link RecordingState} value + */ + public Flowable getRecordingState() { + return recordingStateProcessor.toFlowable(); + } + + /** + * Get the display name of the camera which the model is reacting to + * + * @return Flowable with string of camera name + */ + public Flowable getCameraDisplayName() { + return cameraDisplayName.toFlowable(); + } + + /** + * Get the duration of on going video recording in seconds + * + * @return Flowable with integer value representing seconds + */ + public Flowable getRecordingTimeInSeconds() { + return recordingTimeInSeconds.toFlowable(); + } + + @NonNull + public ComponentIndexType getCameraIndex() { + return cameraIndex; + } + + @NonNull + @Override + public CameraLensType getLensType() { + return lensType; + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + this.cameraIndex = cameraIndex; + this.lensType = lensType; + flatCameraModule.updateCameraSource(cameraIndex,lensType); + restart(); + } + //endregion + + //region Actions + + /** + * Start video recording + * + * @return Completable to determine the status of the action + */ + public Completable startRecordVideo() { + if (isRecording.getValue()) { + return Completable.complete(); + } + return djiSdkModel.performActionWithOutResult(KeyTools.createKey(CameraKey.KeyStartRecord, cameraIndex)); + } + + /** + * Stop video recording + * + * @return Completable to determine the status of the action + */ + public Completable stopRecordVideo() { + if (!isRecording.getValue()) { + return Completable.complete(); + } + + return djiSdkModel.performActionWithOutResult(KeyTools.createKey(CameraKey.KeyStopRecord, cameraIndex)); + } + //endregion + + //region Helpers + private void updateVideoStorageState() { + CameraStorageLocation currentStorageLocation = storageLocation.getValue(); + if (CameraStorageLocation.UNKNOWN.equals(currentStorageLocation)) { + return; + } + + int availableRecordingTime = getAvailableRecordingTime(); + + CameraVideoStorageState newCameraVideoStorageState = null; + if (CameraStorageLocation.SDCARD.equals(currentStorageLocation)) { + if (!CameraSDCardState.UNKNOWN_ERROR.equals(sdCardState.getValue())) { + newCameraVideoStorageState = new CameraSDVideoStorageState(currentStorageLocation, availableRecordingTime, sdCardState.getValue()); + } else if (!CameraSDCardState.UNKNOWN_ERROR.equals(storageState.getValue())) { + newCameraVideoStorageState = new CameraSDVideoStorageState(currentStorageLocation, availableRecordingTime, storageState.getValue()); + } + recordedVideoParameters.onNext(nonSSDRecordedVideoParameters.getValue()); + } else if (CameraStorageLocation.INTERNAL.equals(currentStorageLocation)) { + newCameraVideoStorageState = new CameraSDVideoStorageState(currentStorageLocation, availableRecordingTime, innerStorageState.getValue()); + } + + if (newCameraVideoStorageState != null) { + cameraVideoStorageState.onNext(newCameraVideoStorageState); + } + } + + private int getAvailableRecordingTime() { + CameraStorageInfo info = cameraStorageInfos.getValue().getCurrentCameraStorageInfo(); + if (info == null) { + return INVALID_AVAILABLE_RECORDING_TIME; + } + Integer availableVideoDuration = info.getAvailableVideoDuration(); + return availableVideoDuration == null ? INVALID_AVAILABLE_RECORDING_TIME : availableVideoDuration; + } + + /** + * Determine if the time is exceeded, and close the video in + * {@link RecordVideoWidgetModel#MAX_VIDEO_TIME_THRESHOLD_MINUTES} minutes. + * + * @param recordTime The time to check. + */ + private void checkIsOverRecordTime(int recordTime) { + if (recordTime > (MAX_VIDEO_TIME_THRESHOLD_MINUTES * SECONDS_PER_MIN)) { + stopRecordVideo(); + } + } + + //endregion + + //region Classes + + /** + * The recording state of the camera. + */ + public enum RecordingState { + + /** + * No product is connected, or the recording state is unknown. + */ + UNKNOWN, + + RECORDING_NOT_STARED, + + /** + * The camera is recording video. + */ + RECORDING_IN_PROGRESS, + + /** + * The camera is not recording video. + */ + RECORDING_STOPPED + + + } + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraAEBPhotoState.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraAEBPhotoState.java new file mode 100644 index 00000000..2d04bd86 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraAEBPhotoState.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracapture.shootphoto; + +import dji.sdk.keyvalue.value.camera.CameraShootPhotoMode; +import dji.sdk.keyvalue.value.camera.PhotoAEBPhotoCount; + +/** + * Camera AEB Photo State + *

+ * Class represents camera photo state. It will be returned when device is in + * CameraShootPhotoMode AEB mode. + * It will also return the aeb count + */ +public class CameraAEBPhotoState extends CameraPhotoState { + + private PhotoAEBPhotoCount photoAEBCount; + + public CameraAEBPhotoState(CameraShootPhotoMode shootPhotoMode, PhotoAEBPhotoCount photoAEBCount) { + super(shootPhotoMode); + this.photoAEBCount = photoAEBCount; + } + + /** + * Get AEB photo count + */ + public PhotoAEBPhotoCount getPhotoAEBCount() { + return photoAEBCount; + } + + + @Override + public boolean equals(Object obj) { + if (obj instanceof CameraAEBPhotoState) { + return ((CameraAEBPhotoState) obj).getShootPhotoMode() == this.getShootPhotoMode() + && ((CameraAEBPhotoState) obj).getPhotoAEBCount() == this.getPhotoAEBCount(); + } + return false; + } + + @Override + public int hashCode() { + int result = 31 * getShootPhotoMode().value(); + result = result + 31 * getPhotoAEBCount().value(); + return result; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraBurstPhotoState.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraBurstPhotoState.java new file mode 100644 index 00000000..913d9396 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraBurstPhotoState.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracapture.shootphoto; + +import androidx.annotation.NonNull; +import dji.sdk.keyvalue.value.camera.CameraShootPhotoMode; +import dji.sdk.keyvalue.value.camera.PhotoBurstCount; + +/** + * Camera Burst Photo State + *

+ * Class represents camera photo state. It will be returned when device is in + * CameraShootPhotoMode photo burst mode. + * It will also return the burst count. + */ +public class CameraBurstPhotoState extends CameraPhotoState { + + private PhotoBurstCount photoBurstCount; + + public CameraBurstPhotoState(@NonNull CameraShootPhotoMode shootPhotoMode, @NonNull PhotoBurstCount photoBurstCount) { + super(shootPhotoMode); + this.photoBurstCount = photoBurstCount; + } + + /** + * Get the burst count + * + * @return PhotoBurstCount + */ + public PhotoBurstCount getPhotoBurstCount() { + return photoBurstCount; + } + + + @Override + public boolean equals(Object obj) { + if (obj instanceof CameraBurstPhotoState) { + return ((CameraBurstPhotoState) obj).getShootPhotoMode() == this.getShootPhotoMode() + && ((CameraBurstPhotoState) obj).getPhotoBurstCount() == this.getPhotoBurstCount(); + } + return false; + } + + @Override + public int hashCode() { + int result = 31 * getShootPhotoMode().value(); + result = result + 31 * getPhotoBurstCount().value(); + return result; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraIntervalPhotoState.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraIntervalPhotoState.java new file mode 100644 index 00000000..7011383a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraIntervalPhotoState.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracapture.shootphoto; + +import androidx.annotation.NonNull; +import dji.sdk.keyvalue.value.camera.CameraShootPhotoMode; + +/** + * Camera Interval Photo State + *

+ * Class represents camera photo state. It will be returned when device is in + * CameraShootPhotoMode interval mode. + * It will also return the capture count and interval duration in seconds + */ +public class CameraIntervalPhotoState extends CameraPhotoState { + + private int captureCount; + private int timeIntervalInSeconds; + + public CameraIntervalPhotoState(@NonNull CameraShootPhotoMode shootPhotoMode, int captureCount, int timeIntervalInSeconds) { + super(shootPhotoMode); + this.captureCount = captureCount; + this.timeIntervalInSeconds = timeIntervalInSeconds; + } + + /** + * Get capture count + * + * @return int value + */ + public int getCaptureCount() { + return captureCount; + } + + /** + * Get time interval in seconds + * + * @return int value + */ + public int getTimeIntervalInSeconds() { + return timeIntervalInSeconds; + } + + + @Override + public boolean equals(Object obj) { + if (obj instanceof CameraIntervalPhotoState) { + return ((CameraIntervalPhotoState) obj).getShootPhotoMode() == this.getShootPhotoMode() + && ((CameraIntervalPhotoState) obj).getCaptureCount() == this.getCaptureCount() + && ((CameraIntervalPhotoState) obj).getTimeIntervalInSeconds() == this.getTimeIntervalInSeconds(); + } + return false; + } + + @Override + public int hashCode() { + int result = 31 * getShootPhotoMode().value(); + result = result + 31 * getCaptureCount(); + result = result + 31 * getTimeIntervalInSeconds(); + return result; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraPanoramaPhotoState.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraPanoramaPhotoState.java new file mode 100644 index 00000000..dc820047 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraPanoramaPhotoState.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracapture.shootphoto; + +import androidx.annotation.NonNull; +import dji.sdk.keyvalue.value.camera.CameraShootPhotoMode; +import dji.sdk.keyvalue.value.camera.PhotoPanoramaMode; + +/** + * Camera Panorama Photo State + *

+ * Class represents camera photo state. It will be returned when device is in + * CameraShootPhotoMode panorama mode. + * It will also return the value of PhotoPanoramaMode + */ +public class CameraPanoramaPhotoState extends CameraPhotoState { + private PhotoPanoramaMode photoPanoramaMode; + + public CameraPanoramaPhotoState(@NonNull CameraShootPhotoMode shootPhotoMode, @NonNull PhotoPanoramaMode photoPanoramaMode) { + super(shootPhotoMode); + this.photoPanoramaMode = photoPanoramaMode; + } + + /** + * Get the current panorama mode value + * + * @return instance of PhotoPanoramaMode + */ + public PhotoPanoramaMode getPhotoPanoramaMode() { + return photoPanoramaMode; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof CameraPanoramaPhotoState) { + return ((CameraPanoramaPhotoState) obj).getShootPhotoMode() == this.getShootPhotoMode() + && ((CameraPanoramaPhotoState) obj).getPhotoPanoramaMode() == this.getPhotoPanoramaMode(); + } + return false; + } + + @Override + public int hashCode() { + int result = 31 * getShootPhotoMode().value(); + result = result + 31 * getPhotoPanoramaMode().value(); + return result; + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraPhotoState.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraPhotoState.java new file mode 100644 index 00000000..a8a54fdf --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraPhotoState.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracapture.shootphoto; + +import androidx.annotation.NonNull; +import dji.sdk.keyvalue.value.camera.CameraShootPhotoMode; + +/** + * Camera Photo State + *

+ * Class will be returned representing CameraShootPhotoMode + */ +public class CameraPhotoState { + private CameraShootPhotoMode shootPhotoMode; + + public CameraPhotoState(CameraShootPhotoMode shootPhotoMode) { + this.shootPhotoMode = shootPhotoMode; + } + + /** + * Get the current shoot photo phone + * + * @return instance of CameraShootPhotoMode + */ + @NonNull + public CameraShootPhotoMode getShootPhotoMode() { + return shootPhotoMode; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof CameraPhotoState) { + return ((CameraPhotoState) obj).getShootPhotoMode() == this.getShootPhotoMode(); + } + return false; + } + + @Override + public int hashCode() { + return 31 * shootPhotoMode.value(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraPhotoStorageState.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraPhotoStorageState.java new file mode 100644 index 00000000..92171d2f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraPhotoStorageState.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracapture.shootphoto; + +import dji.sdk.keyvalue.value.camera.CameraStorageLocation; + +/** + * Class represents the storage state when camera is in Shoot Photo Mode + * The state determines the storage location and the available space + * in terms of capture count + */ +public abstract class CameraPhotoStorageState { + private final CameraStorageLocation storageLocation; + private final long availableCaptureCount; + + protected CameraPhotoStorageState(CameraStorageLocation storageLocation, long availableCaptureCount) { + this.storageLocation = storageLocation; + this.availableCaptureCount = availableCaptureCount; + } + + /** + * Get the current storage location + * + * @return instance of CameraStorageLocation + */ + public CameraStorageLocation getStorageLocation() { + return storageLocation; + } + + /** + * Get the number of photos that can be clicked before running out of storage + * + * @return long value representing count of photos + */ + public long getAvailableCaptureCount() { + return availableCaptureCount; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CameraPhotoStorageState)) return false; + CameraPhotoStorageState that = (CameraPhotoStorageState) o; + return availableCaptureCount == that.availableCaptureCount && + storageLocation == that.storageLocation; + } + + + @Override + public int hashCode() { + int result = 31 * storageLocation.value(); + result = result + 31 * (int) availableCaptureCount; + return result; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraSDPhotoStorageState.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraSDPhotoStorageState.java new file mode 100644 index 00000000..a9058a74 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraSDPhotoStorageState.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracapture.shootphoto; + +import dji.sdk.keyvalue.value.camera.CameraStorageLocation; +import dji.sdk.keyvalue.value.camera.SDCardLoadState; + +/** + * Class represents storage state for SD card and internal storage + * when camera is in shoot photo mode + * + */ +public class CameraSDPhotoStorageState extends CameraPhotoStorageState { + private SDCardLoadState storageOperationState; + + public CameraSDPhotoStorageState(CameraStorageLocation storageLocation, long availableCaptureCount, SDCardLoadState storageOperationState) { + super(storageLocation, availableCaptureCount); + this.storageOperationState = storageOperationState; + } + + /** + * Get the operation state of current storage + * + * @return instance of CameraSDCardState + * representing state for SDCard or internal Storage + */ + public SDCardLoadState getStorageOperationState() { + return storageOperationState; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CameraSDPhotoStorageState)) return false; + if (!super.equals(o)) return false; + CameraSDPhotoStorageState that = (CameraSDPhotoStorageState) o; + return storageOperationState == that.storageOperationState; + } + + + @Override + public int hashCode() { + int result = 31 * storageOperationState.value(); + result = result + 31 * getStorageLocation().value(); + result = result + 31 * (int) getAvailableCaptureCount(); + return result; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraSSDPhotoStorageState.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraSSDPhotoStorageState.java new file mode 100644 index 00000000..eba804c0 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/CameraSSDPhotoStorageState.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracapture.shootphoto; + +import dji.sdk.keyvalue.value.camera.CameraStorageLocation; +import dji.sdk.keyvalue.value.camera.SSDOperationState; + +/** + * Class represents SSD Storage state for Shoot Photo Mode + */ +public class CameraSSDPhotoStorageState extends CameraPhotoStorageState { + private SSDOperationState storageOperationState; + + public CameraSSDPhotoStorageState(CameraStorageLocation storageLocation, long availableCaptureCount, SSDOperationState storageOperationState) { + super(storageLocation, availableCaptureCount); + this.storageOperationState = storageOperationState; + } + + /** + * Get operation state of SSD + * + * @return {@link SSDOperationState} + */ + public SSDOperationState getStorageOperationState() { + return storageOperationState; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof CameraSSDPhotoStorageState)) return false; + if (!super.equals(o)) return false; + CameraSSDPhotoStorageState that = (CameraSSDPhotoStorageState) o; + return storageOperationState == that.storageOperationState; + } + + @Override + public int hashCode() { + return 31 * storageOperationState.value(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/ShootPhotoWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/ShootPhotoWidget.java new file mode 100644 index 00000000..68219cf4 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/ShootPhotoWidget.java @@ -0,0 +1,641 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracapture.shootphoto; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.util.Pair; +import android.view.View; +import android.widget.ImageView; + +import java.util.HashMap; +import java.util.Map; + +import androidx.annotation.ColorInt; +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import dji.sdk.keyvalue.value.camera.CameraShootPhotoMode; +import dji.sdk.keyvalue.value.camera.CameraStorageLocation; +import dji.sdk.keyvalue.value.camera.SDCardLoadState; +import dji.sdk.keyvalue.value.camera.SSDOperationState; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.ux.R; +import dji.v5.ux.cameracore.ui.ProgressRingView; +import dji.v5.ux.cameracore.util.CameraActionSound; +import dji.v5.ux.cameracore.util.CameraResource; +import dji.v5.ux.cameracore.widget.cameracontrols.RemoteControllerButtonDownModel; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.SchedulerProvider; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.UxErrorHandle; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.core.Single; +import io.reactivex.rxjava3.disposables.Disposable; + +/** + * Shoot Photo Widget + *

+ * Widget can be used for shooting photo. The widget displays the current photo mode. It also + * displays the storage state and errors associated with it. + */ +public class ShootPhotoWidget extends ConstraintLayoutWidget implements View.OnClickListener, ICameraIndex { + //region Fields + private static final String TAG = "ShootPhotoWidget"; + private ShootPhotoWidgetModel widgetModel; + private RemoteControllerButtonDownModel buttonDownModel; + private ProgressRingView borderProgressRingView; + private ImageView centerImageView; + private ImageView storageStatusOverlayImageView; + private Drawable startShootPhotoDrawable; + private Drawable stopShootPhotoDrawable; + @ColorInt + private int progressRingColor; + private Map storageInternalIconMap; + private Map storageSSDIconMap; + private Map storageSDCardIconMap; + private CameraActionSound cameraActionSound; + //endregion + + //region Lifecycle + public ShootPhotoWidget(Context context) { + super(context); + } + + public ShootPhotoWidget(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public ShootPhotoWidget(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_widget_shoot_photo, this); + borderProgressRingView = findViewById(R.id.progress_ring_view_border); + centerImageView = findViewById(R.id.image_view_center); + storageStatusOverlayImageView = findViewById(R.id.image_view_storage_status_overlay); + storageInternalIconMap = new HashMap<>(); + storageSSDIconMap = new HashMap<>(); + storageSDCardIconMap = new HashMap<>(); + cameraActionSound = new CameraActionSound(context); + if (!isInEditMode()) { + centerImageView.setOnClickListener(this); + widgetModel = new ShootPhotoWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + buttonDownModel = new RemoteControllerButtonDownModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + } + initDefaults(); + if (attrs != null) { + initAttributes(context, attrs); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + buttonDownModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + if (!isInEditMode()) { + widgetModel.cleanup(); + buttonDownModel.cleanup(); + } + super.onDetachedFromWindow(); + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.isShootingPhoto().observeOn(SchedulerProvider.ui()) + .subscribe(this::onIsShootingPhotoChange, UxErrorHandle.logErrorConsumer(TAG, "isShootingPhoto: "))); + addReaction(reactToCanStartOrStopShootingPhoto()); + addReaction(reactToPhotoStateAndPhotoStorageState()); + addReaction(buttonDownModel.isShutterButtonDownProcessor().toFlowable() + .observeOn(SchedulerProvider.ui()) + .subscribe(aBoolean -> { + if (aBoolean == Boolean.TRUE) { + actionOnShootingPhoto(); + } + })); + } + + @NonNull + @Override + public String getIdealDimensionRatioString() { + return getContext().getResources().getString(R.string.uxsdk_widget_default_ratio); + } + + @NonNull + public ComponentIndexType getCameraIndex() { + return widgetModel.getCameraIndex(); + } + + @NonNull + @Override + public CameraLensType getLensType() { + return widgetModel.getLensType(); + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + if (!isInEditMode()) { + widgetModel.updateCameraSource(cameraIndex, lensType); + } + } + + @Override + public void onClick(View v) { + if (v.equals(centerImageView)) { + actionOnShootingPhoto(); + } + } + + private void actionOnShootingPhoto() { + if (!widgetModel.isPhotoMode()) { + return; + } + + Single stop = widgetModel.canStopShootingPhoto().firstOrError(); + Single start = widgetModel.canStartShootingPhoto().firstOrError(); + + addDisposable(Single.zip(stop, start, Pair::new).flatMapCompletable(pairs -> { + if (pairs.first) { + return widgetModel.stopShootPhoto(); + } else if (pairs.second) { + return widgetModel.startShootPhoto(); + } + return Completable.complete(); + }).observeOn(SchedulerProvider.ui()) + .subscribe(() -> { + }, UxErrorHandle.logErrorConsumer(TAG, "Start Stop Shoot Photo"))); + } + //endregion + + //region private helpers + private Drawable getCameraResourceDrawable(int resourceId) { + return getResources().getDrawable(resourceId); + } + + private void updateCameraForegroundResource(@NonNull CameraPhotoState cameraPhotoState, @NonNull CameraPhotoStorageState cameraPhotoStorageState) { + Drawable foregroundDrawable = updateCameraActionSound(cameraPhotoState); + + if (cameraPhotoStorageState instanceof CameraSDPhotoStorageState) { + CameraSDPhotoStorageState sdStorageState = (CameraSDPhotoStorageState) cameraPhotoStorageState; + if (cameraPhotoStorageState.getStorageLocation() == CameraStorageLocation.SDCARD) { + foregroundDrawable = updateResourceWithStorageInSDCard(sdStorageState); + } else if (cameraPhotoStorageState.getStorageLocation() == CameraStorageLocation.INTERNAL) { + foregroundDrawable = updateResourceWithStorageInternal(sdStorageState); + } + } else if (cameraPhotoStorageState instanceof CameraSSDPhotoStorageState) { + CameraSSDPhotoStorageState ssdStorageState = (CameraSSDPhotoStorageState) cameraPhotoStorageState; + if (ssdStorageState.getStorageOperationState() == SSDOperationState.NOT_FOUND) { + foregroundDrawable = getSSDStorageIcon(StorageIconState.NOT_INSERTED); + } else if (ssdStorageState.getStorageOperationState() == SSDOperationState.FULL) { + foregroundDrawable = getSSDStorageIcon(StorageIconState.FULL); + } + } + + storageStatusOverlayImageView.setImageDrawable(foregroundDrawable); + } + + private Drawable updateResourceWithStorageInternal(CameraSDPhotoStorageState sdStorageState) { + Drawable foregroundDrawable = null; + if (sdStorageState.getStorageOperationState() == SDCardLoadState.NOT_INSERTED) { + foregroundDrawable = getInternalStorageIcon(StorageIconState.NOT_INSERTED); + } + return foregroundDrawable; + } + + private Drawable updateResourceWithStorageInSDCard(CameraSDPhotoStorageState sdStorageState) { + Drawable foregroundDrawable = null; + if (sdStorageState.getStorageOperationState() == SDCardLoadState.NOT_INSERTED) { + foregroundDrawable = getSDCardStorageIcon(StorageIconState.NOT_INSERTED); + } + return foregroundDrawable; + } + + private Drawable updateCameraActionSound(CameraPhotoState cameraPhotoState) { + Drawable foregroundDrawable = null; + if (cameraPhotoState instanceof CameraPanoramaPhotoState) { + foregroundDrawable = getCameraResourceDrawable(CameraResource.getPhotoModeImgResId(cameraPhotoState.getShootPhotoMode().value(), + ((CameraPanoramaPhotoState) cameraPhotoState).getPhotoPanoramaMode().value())); + cameraActionSound.setShutterCount(CameraActionSound.ShutterSoundCount.ONE); + } else if (cameraPhotoState instanceof CameraAEBPhotoState) { + int photoCount = ((CameraAEBPhotoState) cameraPhotoState).getPhotoAEBCount().value(); + foregroundDrawable = getCameraResourceDrawable(CameraResource.getPhotoModeImgResId(cameraPhotoState.getShootPhotoMode().value(), + photoCount)); + cameraActionSound.setShutterCount(CameraActionSound.ShutterSoundCount.find(photoCount)); + } else if (cameraPhotoState instanceof CameraBurstPhotoState) { + int photoCount = ((CameraBurstPhotoState) cameraPhotoState).getPhotoBurstCount().value(); + foregroundDrawable = getCameraResourceDrawable(CameraResource.getPhotoModeImgResId(cameraPhotoState.getShootPhotoMode().value(), + photoCount)); + cameraActionSound.setShutterCount(CameraActionSound.ShutterSoundCount.find(photoCount)); + } else if (cameraPhotoState instanceof CameraIntervalPhotoState) { + foregroundDrawable = getCameraResourceDrawable(CameraResource.getPhotoModeImgResId(cameraPhotoState.getShootPhotoMode().value(), + ((CameraIntervalPhotoState) cameraPhotoState).getTimeIntervalInSeconds())); + cameraActionSound.setShutterCount(CameraActionSound.ShutterSoundCount.ONE); + } else { + if (cameraPhotoState.getShootPhotoMode() != CameraShootPhotoMode.NORMAL) { + foregroundDrawable = getCameraResourceDrawable(CameraResource.getPhotoModeImgResId(cameraPhotoState.getShootPhotoMode().value(), + 0)); + cameraActionSound.setShutterCount(CameraActionSound.ShutterSoundCount.ONE); + } + } + return foregroundDrawable; + } + + private void onIsShootingPhotoChange(boolean isShootingPhoto) { + + borderProgressRingView.setIndeterminate(isShootingPhoto); + if (isShootingPhoto) { + cameraActionSound.playCapturePhoto(); + } + } + + private Disposable reactToPhotoStateAndPhotoStorageState() { + return Flowable.combineLatest(widgetModel.getCameraPhotoState(), widgetModel.getCameraStorageState(), Pair::new) + .observeOn(SchedulerProvider.ui()) + .subscribe(values -> updateCameraForegroundResource(values.first, values.second), + UxErrorHandle.logErrorConsumer(TAG, "reactToPhotoStateAndPhotoStorageState ")); + } + + private Disposable reactToCanStartOrStopShootingPhoto() { + return Flowable.combineLatest(widgetModel.canStartShootingPhoto(), widgetModel.canStopShootingPhoto(), Pair::new) + .observeOn(SchedulerProvider.ui()) + .subscribe(values -> updateImages(values.first, values.second), + UxErrorHandle.logErrorConsumer(TAG, "reactToCanStartOrStopShootingPhoto: ")); + } + + private void checkAndUpdatePhotoStateAndPhotoStorageState() { + if (!isInEditMode()) { + addDisposable(Flowable.combineLatest(widgetModel.getCameraPhotoState(), + widgetModel.getCameraStorageState(), + Pair::new) + .firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(values -> updateCameraForegroundResource(values.first, values.second), + UxErrorHandle.logErrorConsumer(TAG, "checkAndUpdatePhotoStateAndPhotoStorageState "))); + } + } + + private void checkAndUpdateCanStartOrStopShootingPhoto() { + if (!isInEditMode()) { + addDisposable(Flowable.combineLatest( + widgetModel.canStartShootingPhoto(), + widgetModel.canStopShootingPhoto(), + Pair::new) + .firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(values -> updateImages(values.first, values.second), + UxErrorHandle.logErrorConsumer(TAG, "checkAndUpdateCanStartOrStopShootingPhoto: "))); + } + } + + private void updateImages(boolean canStartShootingPhoto, boolean canStopShootingPhoto) { + if (!canStopShootingPhoto) { + enableAction(canStartShootingPhoto); + centerImageView.setImageDrawable(startShootPhotoDrawable); + } else { + enableAction(true); + centerImageView.setImageDrawable(stopShootPhotoDrawable); + } + + storageStatusOverlayImageView.setVisibility(canStopShootingPhoto ? View.GONE : View.VISIBLE); + borderProgressRingView.setRingColor(progressRingColor); + } + + private void enableAction(boolean isEnabled) { + centerImageView.setEnabled(isEnabled); + } + + private void initDefaults() { + startShootPhotoDrawable = getResources().getDrawable(R.drawable.uxsdk_shape_circle); + stopShootPhotoDrawable = getResources().getDrawable(R.drawable.uxsdk_ic_shutter_stop); + setProgressRingColor(Color.WHITE); + setInternalStorageIcon(StorageIconState.NOT_INSERTED, R.drawable.uxsdk_ic_internal_storage_not_inserted); + setInternalStorageIcon(StorageIconState.SLOW, R.drawable.uxsdk_ic_internal_storage_slow); + setInternalStorageIcon(StorageIconState.FULL, R.drawable.uxsdk_ic_internal_storage_full); + setSDCardStorageIcon(StorageIconState.NOT_INSERTED, R.drawable.uxsdk_ic_sdcard_not_inserted); + setSDCardStorageIcon(StorageIconState.SLOW, R.drawable.uxsdk_ic_sdcard_slow); + setSDCardStorageIcon(StorageIconState.FULL, R.drawable.uxsdk_ic_sdcard_full); + setSSDStorageIcon(StorageIconState.NOT_INSERTED, R.drawable.uxsdk_ic_ssd_not_inserted); + setSSDStorageIcon(StorageIconState.FULL, R.drawable.uxsdk_ic_ssd_full); + } + + private void initAttributes(Context context, AttributeSet attrs) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ShootPhotoWidget); + updateCameraSource(ComponentIndexType.find(typedArray.getInt(R.styleable.ShootPhotoWidget_uxsdk_cameraIndex, 0)), CameraLensType.UNKNOWN); + + setForegroundIconBackground(typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_foregroundIconBackground)); + setProgressRingColor(typedArray.getColor(R.styleable.ShootPhotoWidget_uxsdk_progressRingColor, Color.WHITE)); + + initShootPhotoDrawable(typedArray); + initInternalStorageIcon(typedArray); + initSSDStorageIcon(typedArray); + initSDCardStorageIcon(typedArray); + typedArray.recycle(); + } + + private void initSSDStorageIcon(TypedArray typedArray) { + if (typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_ssdNotInsertedIcon) != null) { + setSSDStorageIcon(StorageIconState.NOT_INSERTED, typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_ssdNotInsertedIcon)); + } + if (typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_ssdFullIcon) != null) { + setSSDStorageIcon(StorageIconState.FULL, typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_ssdFullIcon)); + } + if (typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_ssdSlowIcon) != null) { + setSSDStorageIcon(StorageIconState.SLOW, typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_ssdSlowIcon)); + } + } + + private void initSDCardStorageIcon(TypedArray typedArray) { + if (typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_sdCardNotInsertedIcon) != null) { + setSDCardStorageIcon(StorageIconState.NOT_INSERTED, typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_sdCardNotInsertedIcon)); + } + if (typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_sdCardFullIcon) != null) { + setSDCardStorageIcon(StorageIconState.FULL, typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_sdCardFullIcon)); + } + if (typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_sdCardSlowIcon) != null) { + setSDCardStorageIcon(StorageIconState.SLOW, typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_sdCardSlowIcon)); + } + } + + private void initInternalStorageIcon(TypedArray typedArray) { + if (typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_internalStorageNotInsertedIcon) != null) { + setInternalStorageIcon(StorageIconState.NOT_INSERTED, typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_internalStorageNotInsertedIcon)); + } + if (typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_internalStorageFullIcon) != null) { + setInternalStorageIcon(StorageIconState.FULL, typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_internalStorageFullIcon)); + } + if (typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_internalStorageSlowIcon) != null) { + setInternalStorageIcon(StorageIconState.SLOW, typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_internalStorageSlowIcon)); + } + } + + private void initShootPhotoDrawable(TypedArray typedArray) { + if (typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_shootPhotoStartIcon) != null) { + startShootPhotoDrawable = typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_shootPhotoStartIcon); + } + if (typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_shootPhotoStopIcon) != null) { + stopShootPhotoDrawable = typedArray.getDrawable(R.styleable.ShootPhotoWidget_uxsdk_shootPhotoStopIcon); + } + } + //endregion + + //region customizations + + /** + * Get the current start shooting photo icon + * + * @return Drawable currently used + */ + public Drawable getStartShootPhotoDrawable() { + return startShootPhotoDrawable; + } + + /** + * Set the start shoot photo icon + * + * @param resourceId to be used + */ + public void setStartShootPhotoDrawable(@DrawableRes int resourceId) { + setStartShootPhotoDrawable(getResources().getDrawable(resourceId)); + } + + /** + * Set the start shoot photo icon + * + * @param drawable to be used + */ + public void setStartShootPhotoDrawable(@Nullable Drawable drawable) { + startShootPhotoDrawable = drawable; + checkAndUpdateCanStartOrStopShootingPhoto(); + } + + /** + * Get the current stop shooting photo icon + * + * @return Drawable currently used + */ + @Nullable + public Drawable getStopShootPhotoDrawable() { + return stopShootPhotoDrawable; + } + + /** + * Set stop shoot photo icon + * + * @param resourceId to be used + */ + public void setStopShootPhotoDrawable(@DrawableRes int resourceId) { + setStopShootPhotoDrawable(getResources().getDrawable(resourceId)); + } + + /** + * Set stop shoot photo icon + * + * @param drawable to be used + */ + public void setStopShootPhotoDrawable(@Nullable Drawable drawable) { + stopShootPhotoDrawable = drawable; + checkAndUpdateCanStartOrStopShootingPhoto(); + } + + /** + * Set the icon for internal storage based on storage icon state + * + * @param storageIconState for which icon is used + * @param resourceId to be used + */ + public void setInternalStorageIcon(@NonNull StorageIconState storageIconState, @DrawableRes int resourceId) { + setInternalStorageIcon(storageIconState, getResources().getDrawable(resourceId)); + } + + /** + * Set the icon for internal storage based on storage icon state + * + * @param storageIconState for which icon is used + * @param drawable to be used + */ + public void setInternalStorageIcon(@NonNull StorageIconState storageIconState, @Nullable Drawable drawable) { + storageInternalIconMap.put(storageIconState, drawable); + checkAndUpdatePhotoStateAndPhotoStorageState(); + } + + /** + * Get the icon for internal storage based on storage icon state + * + * @param storageIconState for which icon is used + * @return Drawable currently used + */ + @Nullable + public Drawable getInternalStorageIcon(@NonNull StorageIconState storageIconState) { + return storageInternalIconMap.get(storageIconState); + } + + /** + * Set the icon for SD card storage based on storage icon state + * + * @param storageIconState for which icon is used + * @param resourceId to be used + */ + public void setSDCardStorageIcon(@NonNull StorageIconState storageIconState, @DrawableRes int resourceId) { + setSDCardStorageIcon(storageIconState, getResources().getDrawable(resourceId)); + } + + /** + * Set the icon for SD card storage based on storage icon state + * + * @param storageIconState for which icon is used + * @param drawable to be used + */ + public void setSDCardStorageIcon(@NonNull StorageIconState storageIconState, @Nullable Drawable drawable) { + storageSDCardIconMap.put(storageIconState, drawable); + checkAndUpdatePhotoStateAndPhotoStorageState(); + } + + /** + * Get the icon for SD card storage based on storage icon state + * + * @param storageIconState for which icon is used + * @return Drawable currently used + */ + @Nullable + public Drawable getSDCardStorageIcon(@NonNull StorageIconState storageIconState) { + return storageSDCardIconMap.get(storageIconState); + } + + /** + * Set the icon for SSD storage based on storage icon state + * + * @param storageIconState for which icon should be used + * @param resourceId to be used + */ + public void setSSDStorageIcon(@NonNull StorageIconState storageIconState, @DrawableRes int resourceId) { + setSSDStorageIcon(storageIconState, getResources().getDrawable(resourceId)); + } + + /** + * Set the icon for SSD storage based on storage icon state + * + * @param storageIconState for which icon should be used + * @param drawable Drawable to be used + */ + public void setSSDStorageIcon(@NonNull StorageIconState storageIconState, @Nullable Drawable drawable) { + storageSSDIconMap.put(storageIconState, drawable); + checkAndUpdatePhotoStateAndPhotoStorageState(); + } + + /** + * Get the icon for SSD storage based on storage icon state + * + * @param storageIconState for which icon is used + * @return Drawable currently used + */ + @Nullable + public Drawable getSSDStorageIcon(@NonNull StorageIconState storageIconState) { + return storageSSDIconMap.get(storageIconState); + } + + /** + * Get current background of foreground icon + * + * @return Drawable being used + */ + @Nullable + public Drawable getForegroundIconBackground() { + return storageStatusOverlayImageView.getBackground(); + } + + /** + * Set the background of the foreground icon + * + * @param resourceId to be used as background + */ + public void setForegroundIconBackground(@DrawableRes int resourceId) { + storageStatusOverlayImageView.setBackgroundResource(resourceId); + } + + /** + * Set background of the foreground icon + * + * @param drawable to be used as background + */ + public void setForegroundIconBackground(@Nullable Drawable drawable) { + storageStatusOverlayImageView.setBackground(drawable); + } + + /** + * Get the color of the progress ring + * + * @return integer representing color + */ + @ColorInt + public int getProgressRingColor() { + return progressRingColor; + } + + /** + * Set the color of the progress ring + * + * @param color integer value + */ + public void setProgressRingColor(@ColorInt int color) { + progressRingColor = color; + checkAndUpdateCanStartOrStopShootingPhoto(); + } + //endregion + + /** + * Enum indicating storage error state + */ + public enum StorageIconState { + /** + * The storage is slow + */ + SLOW, + + /** + * The storage is full + */ + FULL, + + /** + * The storage is not inserted + */ + NOT_INSERTED + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/ShootPhotoWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/ShootPhotoWidgetModel.java new file mode 100644 index 00000000..facdd866 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracapture/shootphoto/ShootPhotoWidgetModel.java @@ -0,0 +1,458 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracapture.shootphoto; + +import java.util.ArrayList; + +import androidx.annotation.NonNull; +import dji.sdk.keyvalue.key.CameraKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.utils.ProductUtil; +import dji.sdk.keyvalue.value.camera.CameraMode; +import dji.sdk.keyvalue.value.camera.CameraShootPhotoMode; +import dji.sdk.keyvalue.value.camera.CameraStorageInfo; +import dji.sdk.keyvalue.value.camera.CameraStorageInfos; +import dji.sdk.keyvalue.value.camera.CameraStorageLocation; +import dji.sdk.keyvalue.value.camera.CameraType; +import dji.sdk.keyvalue.value.camera.PhotoAEBPhotoCount; +import dji.sdk.keyvalue.value.camera.PhotoAEBSettings; +import dji.sdk.keyvalue.value.camera.PhotoBurstCount; +import dji.sdk.keyvalue.value.camera.PhotoIntervalShootSettings; +import dji.sdk.keyvalue.value.camera.PhotoPanoramaMode; +import dji.sdk.keyvalue.value.camera.SDCardLoadState; +import dji.sdk.keyvalue.value.camera.SSDOperationState; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.manager.KeyManager; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.module.FlatCameraModule; +import dji.v5.ux.core.util.CameraUtil; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; + +/** + * Shoot Photo Widget Model + *

+ * Widget Model for {@link ShootPhotoWidget} used to define underlying + * logic and communication + */ +public class ShootPhotoWidgetModel extends WidgetModel implements ICameraIndex { + + //region Constants + private static final int INVALID_AVAILABLE_CAPTURE_COUNT = -1; + //endregion + + //region Public data + private final DataProcessor cameraPhotoState; + private final DataProcessor cameraStorageState; + private final DataProcessor isShootingPhoto; + private final DataProcessor isStoringPhoto; + private final DataProcessor canStartShootingPhoto; + private final DataProcessor shootPhotoNotAllowed; + private final DataProcessor canStopShootingPhoto; + private final DataProcessor cameraDisplayName; + private final DataProcessor isShootingInterval; + private final DataProcessor cameraType; + //endregion + + //region Internal data + private final DataProcessor isShootingPanorama; + private final DataProcessor aebSettings; + private final DataProcessor aebCount; + private final DataProcessor burstCount; + private final DataProcessor rawBurstCount; + private final DataProcessor timeIntervalSettings; + private final DataProcessor panoramaMode; + private final DataProcessor storageInfosProcessor; + private final DataProcessor storageLocation; + private final DataProcessor sdCardState; + private final DataProcessor innerStorageState; + private final DataProcessor ssdState; + private final DataProcessor sdAvailableCaptureCount; + private final DataProcessor innerStorageAvailableCaptureCount; + private final DataProcessor rawPhotoBurstCaptureCount; + private final DataProcessor isProductConnected; + //endregion + + //region Other fields + private final PhotoIntervalShootSettings defaultIntervalSettings; + private ComponentIndexType cameraIndex = ComponentIndexType.LEFT_OR_MAIN; + private CameraLensType lensType = CameraLensType.UNKNOWN; + private FlatCameraModule flatCameraModule; + //endregion + + //region Constructor + public ShootPhotoWidgetModel(@NonNull DJISDKModel djiSdkModel, + @NonNull ObservableInMemoryKeyedStore keyedStore) { + super(djiSdkModel, keyedStore); + defaultIntervalSettings = new PhotoIntervalShootSettings(); + CameraPhotoState photoState = new CameraPhotoState(CameraShootPhotoMode.UNKNOWN); + + this.cameraPhotoState = DataProcessor.create(photoState); + CameraSDPhotoStorageState cameraSDStorageState = new CameraSDPhotoStorageState( + CameraStorageLocation.SDCARD, 0, SDCardLoadState.NOT_INSERTED); + cameraStorageState = DataProcessor.create(cameraSDStorageState); + canStartShootingPhoto = DataProcessor.create(false); + shootPhotoNotAllowed = DataProcessor.create(true); + canStopShootingPhoto = DataProcessor.create(false); + cameraDisplayName = DataProcessor.create(""); + aebSettings = DataProcessor.create(new PhotoAEBSettings()); + aebCount = DataProcessor.create(PhotoAEBPhotoCount.UNKNOWN); + burstCount = DataProcessor.create(PhotoBurstCount.UNKNOWN); + rawBurstCount = DataProcessor.create(PhotoBurstCount.UNKNOWN); + timeIntervalSettings = DataProcessor.create(defaultIntervalSettings); + panoramaMode = DataProcessor.create(PhotoPanoramaMode.UNKNOWN); + isShootingPhoto = DataProcessor.create(false); + isShootingInterval = DataProcessor.create(false); + cameraType = DataProcessor.create(CameraType.NOT_SUPPORTED); + isShootingPanorama = DataProcessor.create(false); + isStoringPhoto = DataProcessor.create(false); + storageLocation = DataProcessor.create(CameraStorageLocation.SDCARD); + sdCardState = DataProcessor.create(SDCardLoadState.UNKNOWN); + innerStorageState = DataProcessor.create(SDCardLoadState.UNKNOWN); + ssdState = DataProcessor.create(SSDOperationState.UNKNOWN); + sdAvailableCaptureCount = DataProcessor.create(INVALID_AVAILABLE_CAPTURE_COUNT); + innerStorageAvailableCaptureCount = DataProcessor.create(INVALID_AVAILABLE_CAPTURE_COUNT); + rawPhotoBurstCaptureCount = DataProcessor.create(INVALID_AVAILABLE_CAPTURE_COUNT); + isProductConnected = DataProcessor.create(false); + storageInfosProcessor = DataProcessor.create(new CameraStorageInfos(CameraStorageLocation.UNKNOWN, new ArrayList<>())); + flatCameraModule = new FlatCameraModule(); + addModule(flatCameraModule); + } + //endregion + + //region Data + + /** + * Get the current shoot photo mode + * + * @return Flowable with {@link CameraPhotoState} instance + */ + public Flowable getCameraPhotoState() { + return cameraPhotoState.toFlowable(); + } + + /** + * Get the current camera photo storage location + * + * @return Flowable with {@link CameraPhotoStorageState} instance + */ + public Flowable getCameraStorageState() { + return cameraStorageState.toFlowable(); + } + + /** + * Check if the device is currently shooting photo + * + * @return Flowable with boolean value + * true - if camera is shooting photo false - camera is not shooting photo + */ + public Flowable isShootingPhoto() { + return isShootingPhoto.toFlowable(); + } + + /** + * Check if the device is currently in the process of storing photo + * + * @return Flowable with boolean value + * true - if device is storing photo false - device is not storing photo + */ + public Flowable isStoringPhoto() { + return isStoringPhoto.toFlowable(); + } + + /** + * Check if the device is ready to shoot photo. + * + * @return Flowable with boolean value + * true - device ready false - device not ready + */ + public Flowable canStartShootingPhoto() { + return canStartShootingPhoto.toFlowable(); + } + + /** + * Check if the device is currently shooting photo and is ready to stop + * + * @return Flowable with boolean value + * true - can stop shooting false - can not stop shooting photo + */ + public Flowable canStopShootingPhoto() { + return canStopShootingPhoto.toFlowable(); + } + + @NonNull + public ComponentIndexType getCameraIndex() { + return cameraIndex; + } + + @NonNull + @Override + public CameraLensType getLensType() { + return lensType; + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + this.cameraIndex = cameraIndex; + this.lensType = lensType; + flatCameraModule.updateCameraSource(cameraIndex,lensType); + restart(); + } + + /** + * Get the display name of the camera which the model is reacting to + * + * @return Flowable with string of camera name + */ + public Flowable getCameraDisplayName() { + return cameraDisplayName.toFlowable(); + } + //endregion + + //region Actions + + /** + * Start shooting photo + * + * @return Completable to determine the status of the action + */ + public Completable startShootPhoto() { + if (!canStartShootingPhoto.getValue()) { + return Completable.complete(); + } + return djiSdkModel.performActionWithOutResult(KeyTools.createKey(CameraKey.KeyStartShootPhoto, cameraIndex)); + } + + /** + * Stop shooting photo + * + * @return Completable to determine the status of the action + */ + public Completable stopShootPhoto() { + if (!canStopShootingPhoto.getValue()) { + return Completable.complete(); + } + return djiSdkModel.performActionWithOutResult(KeyTools.createKey(CameraKey.KeyStopShootPhoto, cameraIndex)); + } + //endregion + + //region Lifecycle + @Override + protected void inSetup() { + // Product connection + bindDataProcessor(KeyTools.createKey(CameraKey.KeyConnection, cameraIndex), isProductConnected, newValue -> onCameraConnected((boolean) newValue)); + + // Photo mode + bindDataProcessor(KeyTools.createKey(CameraKey.KeyAEBSettings, cameraIndex), aebSettings, photoAEBSettings -> { + aebCount.onNext(photoAEBSettings.getCount()); + }); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyPhotoBurstCount, cameraIndex), burstCount); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyRawBurstCount, cameraIndex), rawBurstCount); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyPhotoIntervalShootSettings, cameraIndex), timeIntervalSettings); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyPhotoPanoramaMode, cameraIndex), panoramaMode); + + // Is shooting photo state + bindDataProcessor(KeyTools.createKey(CameraKey.KeyIsShootingPhoto, cameraIndex), isShootingPhoto); + + // Is storing photo state + bindDataProcessor(KeyTools.createKey(CameraKey.KeyCameraStoringFile, cameraIndex), isStoringPhoto); + + // Can start shooting photo + // can't take photo when product is not connected + bindDataProcessor(KeyTools.createKey(CameraKey.KeyShootPhotoNotAllowed, cameraIndex), shootPhotoNotAllowed, aBoolean -> { + canStartShootingPhoto.onNext(!aBoolean); + }); + + // Can stop shooting photo + bindDataProcessor(KeyTools.createKey(CameraKey.KeyCameraShootingContinuousPhotos, cameraIndex), isShootingInterval, this::onCanStopShootingPhoto); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyIsShootingPhotoPanorama, cameraIndex), isShootingPanorama, newValue -> onCanStopShootingPhoto((boolean) newValue)); + + // Display name + bindDataProcessor(KeyTools.createKey(CameraKey.KeyCameraType, cameraIndex), cameraType, type -> cameraDisplayName.onNext(type.name())); + + // Storage + bindDataProcessor(KeyTools.createKey(CameraKey.KeyCameraStorageInfos, cameraIndex), storageInfosProcessor, cameraStorageInfos -> { + storageLocation.onNext(cameraStorageInfos.getCurrentStorageType()); + + CameraStorageInfo internalInfo = cameraStorageInfos.getCameraStorageInfoByLocation(CameraStorageLocation.INTERNAL); + if (internalInfo != null) { + innerStorageState.onNext(internalInfo.getStorageState()); + sdAvailableCaptureCount.onNext(internalInfo.getAvailablePhotoCount()); + } + + CameraStorageInfo sdcardInfo = cameraStorageInfos.getCameraStorageInfoByLocation(CameraStorageLocation.SDCARD); + if (sdcardInfo != null) { + sdCardState.onNext(sdcardInfo.getStorageState()); + innerStorageAvailableCaptureCount.onNext(sdcardInfo.getAvailablePhotoCount()); + } + }); + bindDataProcessor(KeyTools.createKey(CameraKey.KeySSDOperationState, cameraIndex), ssdState); + bindDataProcessor(KeyTools.createKey(CameraKey.KeySDCardAvailablePhotoCount, cameraIndex), sdAvailableCaptureCount); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyInternalStorageAvailablePhotoCount, cameraIndex), innerStorageAvailableCaptureCount); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyH1PhotoBurstCount, cameraIndex), rawPhotoBurstCaptureCount); + } + + @Override + protected void inCleanup() { + // do nothing + } + + @Override + protected void updateStates() { + updateCameraPhotoState(); + updateCameraStorageState(); + } + + public boolean isPhotoMode(){ + return flatCameraModule.getCameraModeDataProcessor().getValue().isPhotoMode() + || (flatCameraModule.getCameraModeDataProcessor().getValue() == CameraMode.VIDEO_NORMAL && isSupportShootPhoto()); + } + + private boolean isSupportShootPhoto(){ + CameraType cameraType = KeyManager.getInstance().getValue(KeyTools.createKey(CameraKey.KeyCameraType ,cameraIndex) ,CameraType.NOT_SUPPORTED); + return cameraType == CameraType.M3T || cameraType == CameraType.M3E || cameraType == CameraType.M3M || cameraType == CameraType.ZENMUSE_H20T; + } + + //region Helpers + private void updateCameraPhotoState() { + CameraPhotoState state = null; + CameraShootPhotoMode shootPhotoMode = flatCameraModule.getShootPhotoModeProcessor().getValue(); + switch (shootPhotoMode) { + case NORMAL: + case HDR: + case HYPER_LIGHT: + //case SHALLOW_FOCUS: + case EHDR: + state = new CameraPhotoState(shootPhotoMode); + break; + case BURST: + if (!PhotoBurstCount.UNKNOWN.equals(burstCount.getValue())) { + state = new CameraBurstPhotoState( + shootPhotoMode, + burstCount.getValue()); + } + break; + case RAW_BURST: + if (!PhotoBurstCount.UNKNOWN.equals(rawBurstCount.getValue())) { + state = new CameraBurstPhotoState( + shootPhotoMode, + rawBurstCount.getValue() + ); + } + break; + case AEB: + if (!PhotoAEBPhotoCount.UNKNOWN.equals(aebCount.getValue())) { + state = new CameraAEBPhotoState( + shootPhotoMode, + aebCount.getValue() + ); + } + break; + case INTERVAL: + PhotoIntervalShootSettings intervalSettings = timeIntervalSettings.getValue(); + if (!defaultIntervalSettings.equals(timeIntervalSettings.getValue())) { + state = new CameraIntervalPhotoState( + shootPhotoMode, + intervalSettings.getCount(), + intervalSettings.getInterval().intValue() + ); + } + break; + case PANO_APP: + if (!PhotoPanoramaMode.UNKNOWN.equals(panoramaMode.getValue())) { + state = new CameraPanoramaPhotoState( + shootPhotoMode, + panoramaMode.getValue() + ); + } + break; + default: + break; + } + + if (state != null) { + this.cameraPhotoState.onNext(state); + } + } + + private void updateCameraStorageState() { + CameraStorageLocation currentStorageLocation = storageLocation.getValue(); + if (CameraStorageLocation.UNKNOWN.equals(currentStorageLocation)) { + return; + } + + CameraShootPhotoMode currentShootPhotoMode = flatCameraModule.getShootPhotoModeProcessor().getValue(); + long availableCaptureCount = getAvailableCaptureCount(currentStorageLocation, currentShootPhotoMode); + CameraPhotoStorageState newCameraPhotoStorageState = null; + if (currentShootPhotoMode == CameraShootPhotoMode.RAW_BURST) { + newCameraPhotoStorageState = new CameraSSDPhotoStorageState(CameraStorageLocation.UNKNOWN, availableCaptureCount, ssdState.getValue()); + } else if (CameraStorageLocation.SDCARD.equals(currentStorageLocation)) { + if (!SDCardLoadState.UNKNOWN.equals(sdCardState.getValue())) { + newCameraPhotoStorageState = new CameraSDPhotoStorageState(currentStorageLocation, availableCaptureCount, sdCardState.getValue()); + } + } else if (CameraStorageLocation.INTERNAL.equals(currentStorageLocation)) { + newCameraPhotoStorageState = new CameraSDPhotoStorageState(currentStorageLocation, availableCaptureCount, innerStorageState.getValue()); + } + + if (newCameraPhotoStorageState != null) { + cameraStorageState.onNext(newCameraPhotoStorageState); + } + } + + private long getAvailableCaptureCount(CameraStorageLocation storageLocation, + CameraShootPhotoMode shootPhotoMode) { + if (shootPhotoMode == CameraShootPhotoMode.RAW_BURST) { + return rawPhotoBurstCaptureCount.getValue(); + } + + switch (storageLocation) { + case SDCARD: + return sdAvailableCaptureCount.getValue(); + case INTERNAL: + return innerStorageAvailableCaptureCount.getValue(); + case UNKNOWN: + default: + return INVALID_AVAILABLE_CAPTURE_COUNT; + } + } + + private void onCanStopShootingPhoto(boolean canStopShootingPhoto) { + this.canStopShootingPhoto.onNext(canStopShootingPhoto); + } + + private void onCameraConnected(boolean isCameraConnected) { + if (!isCameraConnected) { + // Reset storage state + sdCardState.onNext(SDCardLoadState.UNKNOWN); + innerStorageState.onNext(SDCardLoadState.UNKNOWN); + ssdState.onNext(SSDOperationState.UNKNOWN); + } + } + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/CameraControlsWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/CameraControlsWidget.java new file mode 100644 index 00000000..8bc9bbc7 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/CameraControlsWidget.java @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracontrols; + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.ux.R; +import dji.v5.ux.cameracore.widget.cameracapture.CameraCaptureWidget; +import dji.v5.ux.cameracore.widget.cameracontrols.camerasettingsindicator.CameraSettingsMenuIndicatorWidget; +import dji.v5.ux.cameracore.widget.cameracontrols.exposuresettingsindicator.ExposureSettingsIndicatorWidget; +import dji.v5.ux.cameracore.widget.cameracontrols.photovideoswitch.PhotoVideoSwitchWidget; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; + +/** + * Compound widget which combines the state and interaction related to camera. + * It includes {@link CameraSettingsMenuIndicatorWidget}, {@link ExposureSettingsIndicatorWidget}, + * {@link PhotoVideoSwitchWidget} and {@link CameraCaptureWidget}. + *

+ * The widget gives access to all the child widgets. + */ +public class CameraControlsWidget extends ConstraintLayoutWidget implements ICameraIndex { + + //region Fields + private CameraSettingsMenuIndicatorWidget cameraSettingsMenuIndicatorWidget; + private PhotoVideoSwitchWidget photoVideoSwitchWidget; + private CameraCaptureWidget cameraCaptureWidget; + private ExposureSettingsIndicatorWidget exposureSettingsIndicatorWidget; + //endregion + + //region Lifecycle + public CameraControlsWidget(@NonNull Context context) { + super(context); + } + + public CameraControlsWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public CameraControlsWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_widget_camera_controls, this); + setBackgroundResource(R.drawable.uxsdk_background_black_rectangle); + cameraCaptureWidget = findViewById(R.id.widget_camera_control_camera_capture); + photoVideoSwitchWidget = findViewById(R.id.widget_camera_control_photo_video_switch); + exposureSettingsIndicatorWidget = findViewById(R.id.widget_camera_control_camera_exposure_settings); + cameraSettingsMenuIndicatorWidget = findViewById(R.id.widget_camera_control_camera_settings_menu); + } + + @Override + protected void reactToModelChanges() { + //Do Nothing + } + + @NonNull + @Override + public String getIdealDimensionRatioString() { + return getResources().getString(R.string.uxsdk_widget_camera_controls_ratio); + } + + @NonNull + @Override + public ComponentIndexType getCameraIndex() { + return cameraCaptureWidget.getCameraIndex(); + } + + @NonNull + @Override + public CameraLensType getLensType() { + return cameraCaptureWidget.getLensType(); + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + cameraCaptureWidget.updateCameraSource(cameraIndex, lensType); + photoVideoSwitchWidget.updateCameraSource(cameraIndex, lensType); + exposureSettingsIndicatorWidget.updateCameraSource(cameraIndex, lensType); + } + + /** + * Get the camera capture widget + * + * @return {@link CameraCaptureWidget} + */ + @NonNull + public CameraCaptureWidget getCameraCaptureWidget() { + return cameraCaptureWidget; + } + + /** + * Get the camera settings menu widget + * + * @return {@link CameraSettingsMenuIndicatorWidget} + */ + @NonNull + public CameraSettingsMenuIndicatorWidget getCameraSettingsMenuIndicatorWidget() { + return cameraSettingsMenuIndicatorWidget; + } + + /** + * Get the exposure settings widget + * + * @return {@link ExposureSettingsIndicatorWidget} + */ + @NonNull + public ExposureSettingsIndicatorWidget getExposureSettingsIndicatorWidget() { + return exposureSettingsIndicatorWidget; + } + + /** + * Get the photo video switch widget + * + * @return {@link PhotoVideoSwitchWidget} + */ + @NonNull + public PhotoVideoSwitchWidget getPhotoVideoSwitchWidget() { + return photoVideoSwitchWidget; + } + + /** + * Show/Hide {@link CameraSettingsMenuIndicatorWidget} + * + * @param isVisible boolean true - visible false - gone + */ + public void setCameraSettingsMenuIndicatorWidgetVisibility(boolean isVisible) { + cameraSettingsMenuIndicatorWidget.setVisibility(isVisible ? VISIBLE : GONE); + } + + /** + * Check if {@link CameraSettingsMenuIndicatorWidget} is visible + * + * @return boolean true - visible false - gone + */ + public boolean isCameraSettingsMenuIndicatorWidgetVisible() { + return cameraSettingsMenuIndicatorWidget.getVisibility() == VISIBLE; + } + + /** + * Show/Hide {@link PhotoVideoSwitchWidget} + * + * @param isVisible boolean true - visible false - gone + */ + public void setPhotoVideoSwitchWidgetVisibility(boolean isVisible) { + photoVideoSwitchWidget.setVisibility(isVisible ? VISIBLE : GONE); + } + + /** + * Check if {@link PhotoVideoSwitchWidget} is Visible + * + * @return boolean true - visible false - gone + */ + public boolean isPhotoVideoSwitchWidgetVisible() { + return photoVideoSwitchWidget.getVisibility() == VISIBLE; + } + + /** + * Show/Hide {@link CameraCaptureWidget} + * + * @param isVisible boolean true - visible false - gone + */ + public void setCameraCaptureWidgetVisibility(boolean isVisible) { + cameraCaptureWidget.setVisibility(isVisible ? VISIBLE : GONE); + } + + /** + * Check if {@link CameraCaptureWidget} is visible + * + * @return boolean true - visible false - gone + */ + public boolean isCameraCaptureWidgetVisible() { + return cameraCaptureWidget.getVisibility() == VISIBLE; + } + + /** + * Show/Hide {@link ExposureSettingsIndicatorWidget} + * + * @param isVisible boolean true - visible false - gone + */ + public void setExposureSettingsIndicatorWidgetVisibility(boolean isVisible) { + exposureSettingsIndicatorWidget.setVisibility(isVisible ? VISIBLE : GONE); + } + + /** + * Check if {@link ExposureSettingsIndicatorWidget} + * + * @return boolean true - visible false - gone + */ + public boolean isExposureSettingsIndicatorWidgetVisible() { + return exposureSettingsIndicatorWidget.getVisibility() == VISIBLE; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/RemoteControllerButtonDownModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/RemoteControllerButtonDownModel.kt new file mode 100644 index 00000000..17622f68 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/RemoteControllerButtonDownModel.kt @@ -0,0 +1,34 @@ +package dji.v5.ux.cameracore.widget.cameracontrols + +import dji.sdk.keyvalue.key.RemoteControllerKey +import dji.v5.et.create +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor + +/** + * Class Description + * + * @author Hoker + * @date 2021/12/13 + * + * Copyright (c) 2021, DJI All Rights Reserved. + */ +open class RemoteControllerButtonDownModel constructor( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + + val isShutterButtonDownProcessor: DataProcessor = DataProcessor.create(false) + val isRecordButtonDownProcessor: DataProcessor = DataProcessor.create(false) + + override fun inSetup() { + bindDataProcessor(RemoteControllerKey.KeyShutterButtonDown.create(), isShutterButtonDownProcessor) + bindDataProcessor(RemoteControllerKey.KeyRecordButtonDown.create(), isRecordButtonDownProcessor) + } + + override fun inCleanup() { + //暂未实现 + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/camerasettingsindicator/CameraSettingsMenuIndicatorWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/camerasettingsindicator/CameraSettingsMenuIndicatorWidget.java new file mode 100644 index 00000000..9c35efb9 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/camerasettingsindicator/CameraSettingsMenuIndicatorWidget.java @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracontrols.camerasettingsindicator; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.ColorInt; +import androidx.annotation.Dimension; +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import dji.v5.ux.R; +import dji.v5.ux.cameracore.widget.cameracontrols.CameraControlsWidget; +import dji.v5.ux.core.base.widget.FrameLayoutWidget; +import dji.v5.ux.core.communication.OnStateChangeCallback; + +/** + * Camera Settings Menu Indicator Widget + *

+ * The widget is part of the {@link CameraControlsWidget}. + * Tapping the widget can be used to open the camera settings panel + */ +public class CameraSettingsMenuIndicatorWidget extends FrameLayoutWidget implements View.OnClickListener { + + //region Fields + private TextView foregroundTextView; + private OnStateChangeCallback stateChangeCallback = null; + //endregion + + //region Lifecycle + public CameraSettingsMenuIndicatorWidget(@NonNull Context context) { + super(context); + } + + public CameraSettingsMenuIndicatorWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public CameraSettingsMenuIndicatorWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_widget_camera_settings_menu_indicator, this); + foregroundTextView = findViewById(R.id.text_view_menu); + setOnClickListener(this); + + if (attrs != null) { + initAttributes(context, attrs); + } + } + + @Override + protected void reactToModelChanges() { + // No Code + } + + @NonNull + @Override + public String getIdealDimensionRatioString() { + return getResources().getString(R.string.uxsdk_widget_default_ratio); + } + + @Override + public void onClick(View v) { + if (stateChangeCallback != null) { + stateChangeCallback.onStateChange(null); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + initializeListener(); + } + + @Override + protected void onDetachedFromWindow() { + destroyListener(); + super.onDetachedFromWindow(); + } + + //endregion + + //region private methods + + private void initializeListener() { + //暂未实现 + } + + private void destroyListener() { + stateChangeCallback = null; + } + + private void initAttributes(Context context, AttributeSet attrs) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CameraSettingsMenuIndicatorWidget); + + setLabelTextSize(typedArray.getDimension(R.styleable.CameraSettingsMenuIndicatorWidget_uxsdk_settingsTextSize, 12)); + setLabelTextColor(typedArray.getColor(R.styleable.CameraSettingsMenuIndicatorWidget_uxsdk_settingsTextColor, Color.WHITE)); + setLabelTextBackground(typedArray.getDrawable(R.styleable.CameraSettingsMenuIndicatorWidget_uxsdk_settingsTextBackground)); + typedArray.recycle(); + } + + //endregion + + //region customizations + + /** + * Set callback for when the widget is tapped. + * This can be used to link the widget to //TODO camera settings menu panel + * + * @param stateChangeCallback listener to handheld callback + */ + public void setStateChangeCallback(@NonNull OnStateChangeCallback stateChangeCallback) { + this.stateChangeCallback = stateChangeCallback; + } + + /** + * Get the color of the widget label text + * + * @return integer color value + */ + @ColorInt + public int getLabelTextColor() { + return foregroundTextView.getCurrentTextColor(); + } + + /** + * Set the color of the widget label text + * + * @param color integer value to be used + */ + public void setLabelTextColor(@ColorInt int color) { + foregroundTextView.setTextColor(color); + } + + /** + * Set the background of the widget label + * + * @param resourceId to be used + */ + public void setLabelTextBackground(@DrawableRes int resourceId) { + foregroundTextView.setBackgroundResource(resourceId); + } + + /** + * Set the background of the widget label + * + * @param drawable to be used + */ + public void setLabelTextBackground(@Nullable Drawable drawable) { + foregroundTextView.setBackground(drawable); + } + + /** + * Get the background of the widget label + * + * @return Drawable + */ + @Nullable + public Drawable getLabelBackground() { + return foregroundTextView.getBackground(); + } + + /** + * Get the text size of the widget label + * + * @return float value representing text size + */ + @Dimension + public float getLabelTextSize() { + return foregroundTextView.getTextSize(); + } + + /** + * Set the text size of the widget label + * + * @param textSize float value representing text size + */ + public void setLabelTextSize(@Dimension float textSize) { + foregroundTextView.setTextSize(textSize); + } + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettings/ExposureModeSettingModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettings/ExposureModeSettingModel.kt new file mode 100644 index 00000000..34de4d80 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettings/ExposureModeSettingModel.kt @@ -0,0 +1,66 @@ +package dji.v5.ux.cameracore.widget.cameracontrols.exposuresettings + +import dji.sdk.keyvalue.key.CameraKey +import dji.sdk.keyvalue.value.camera.CameraExposureMode +import dji.sdk.keyvalue.value.common.CameraLensType +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.value.common.ComponentIndexType +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.ICameraIndex +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Completable + +/** + * Class Description + * + * @author Hoker + * @date 2021/10/19 + * + * Copyright (c) 2021, DJI All Rights Reserved. + */ +open class ExposureModeSettingModel constructor( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore), ICameraIndex { + + val exposureModeProcessor: DataProcessor = DataProcessor.create(CameraExposureMode.UNKNOWN) + val exposureModeRangeProcessor: DataProcessor> = DataProcessor.create(listOf()) + + private var cameraIndex = ComponentIndexType.LEFT_OR_MAIN + private var lensType = CameraLensType.CAMERA_LENS_ZOOM + + override fun inSetup() { + bindDataProcessor( + KeyTools.createCameraKey( + CameraKey.KeyExposureMode, cameraIndex, lensType), exposureModeProcessor) + bindDataProcessor( + KeyTools.createCameraKey( + CameraKey.KeyExposureModeRange, cameraIndex, lensType), exposureModeRangeProcessor) + } + + override fun inCleanup() { + //暂未实现 + } + + override fun updateStates() { + //暂未实现 + } + + override fun getCameraIndex() = cameraIndex + + override fun getLensType() = lensType + + override fun updateCameraSource(cameraIndex: ComponentIndexType, lensType: CameraLensType) { + this.cameraIndex = cameraIndex + this.lensType = lensType + restart() + } + + fun setExposureMode(mode: CameraExposureMode): Completable { + return djiSdkModel.setValue( + KeyTools.createCameraKey( + CameraKey.KeyExposureMode, cameraIndex, lensType), mode) + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettings/ExposureModeSettingWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettings/ExposureModeSettingWidget.kt new file mode 100644 index 00000000..ab7130c9 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettings/ExposureModeSettingWidget.kt @@ -0,0 +1,155 @@ +package dji.v5.ux.cameracore.widget.cameracontrols.exposuresettings + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import dji.sdk.keyvalue.value.camera.CameraExposureMode +import dji.sdk.keyvalue.value.common.CameraLensType +import dji.sdk.keyvalue.value.common.ComponentIndexType +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.ICameraIndex +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.UxErrorHandle +import dji.v5.ux.databinding.UxsdkPanelNdvlBinding +import dji.v5.ux.databinding.UxsdkWidgetExposureModeSettingBinding +import io.reactivex.rxjava3.functions.Action + +/** + * Class Description + * + * @author Hoker + * @date 2021/10/19 + * + * Copyright (c) 2021, DJI All Rights Reserved. + */ +open class ExposureModeSettingWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, +) : ConstraintLayoutWidget(context, attrs, defStyleAttr), + View.OnClickListener, ICameraIndex { + + private lateinit var binding: UxsdkWidgetExposureModeSettingBinding + + private val widgetModel by lazy { + ExposureModeSettingModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()) + } + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + binding = UxsdkWidgetExposureModeSettingBinding.inflate(LayoutInflater.from(context), this) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + binding.layoutCameraModeA.setOnClickListener(this) + binding.layoutCameraModeS.setOnClickListener(this) + binding.layoutCameraModeM.setOnClickListener(this) + binding.layoutCameraModeP.setOnClickListener(this) + binding.layoutCameraModeP.isSelected = true + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun getCameraIndex() = widgetModel.getCameraIndex() + + override fun getLensType() = widgetModel.getLensType() + + override fun updateCameraSource(cameraIndex: ComponentIndexType, lensType: CameraLensType) = widgetModel.updateCameraSource(cameraIndex, lensType) + + override fun reactToModelChanges() { + addReaction(widgetModel.exposureModeProcessor.toFlowable().observeOn(SchedulerProvider.ui()).subscribe { + updateExposureMode(it) + }) + addReaction(widgetModel.exposureModeRangeProcessor.toFlowable().observeOn(SchedulerProvider.ui()).subscribe { + updateExposureModeRange(it) + }) + } + + override fun getIdealDimensionRatioString(): String? { + return null + } + + override fun onClick(v: View?) { + + val previousExposureMode: CameraExposureMode = widgetModel.exposureModeProcessor.value + var exposureMode: CameraExposureMode = CameraExposureMode.UNKNOWN + + when (v?.id) { + R.id.layout_camera_mode_p -> exposureMode = CameraExposureMode.PROGRAM + R.id.layout_camera_mode_a -> exposureMode = CameraExposureMode.APERTURE_PRIORITY + R.id.layout_camera_mode_s -> exposureMode = CameraExposureMode.SHUTTER_PRIORITY + R.id.layout_camera_mode_m -> exposureMode = CameraExposureMode.MANUAL + else -> { + //do nothing + } + } + + if (exposureMode == previousExposureMode) { + return + } + + updateExposureMode(exposureMode) + + addDisposable( + widgetModel.setExposureMode(exposureMode) + .observeOn(SchedulerProvider.ui()) + .subscribe(Action { }, UxErrorHandle.errorConsumer({ + restoreToCurrentExposureMode() + }, this.toString(), "setExposureMode: ")) + ) + } + + private fun updateExposureModeRange(range: List) { + binding.layoutCameraModeA.isEnabled = rangeContains(range, CameraExposureMode.APERTURE_PRIORITY) + binding.layoutCameraModeS.isEnabled = rangeContains(range, CameraExposureMode.SHUTTER_PRIORITY) + binding.layoutCameraModeM.isEnabled = rangeContains(range, CameraExposureMode.MANUAL) + binding.layoutCameraModeP.isEnabled = rangeContains(range, CameraExposureMode.PROGRAM) + } + + private fun updateExposureMode(mode: CameraExposureMode) { + binding.layoutCameraModeA.isSelected = false + binding.layoutCameraModeS.isSelected = false + binding.layoutCameraModeM.isSelected = false + binding.layoutCameraModeP.isSelected = false + + when (mode) { + CameraExposureMode.PROGRAM -> binding.layoutCameraModeP.isSelected = true + CameraExposureMode.SHUTTER_PRIORITY -> binding.layoutCameraModeS.isSelected = true + CameraExposureMode.APERTURE_PRIORITY -> binding.layoutCameraModeA.isSelected = true + CameraExposureMode.MANUAL -> binding.layoutCameraModeM.isSelected = true + else -> { + //do something + } + } + } + + private fun restoreToCurrentExposureMode() { + updateExposureMode(widgetModel.exposureModeProcessor.value) + } + + private fun rangeContains(range: List?, value: CameraExposureMode): Boolean { + if (range == null) { + return false + } + for (item in range) { + if (item == value) { + return true + } + } + return false + } + + sealed class ModelState +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettings/ExposureSettingsPanel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettings/ExposureSettingsPanel.kt new file mode 100644 index 00000000..7e6bba7e --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettings/ExposureSettingsPanel.kt @@ -0,0 +1,53 @@ +package dji.v5.ux.cameracore.widget.cameracontrols.exposuresettings + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import dji.sdk.keyvalue.value.common.CameraLensType +import dji.sdk.keyvalue.value.common.ComponentIndexType +import dji.v5.ux.R +import dji.v5.ux.core.base.ICameraIndex +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.databinding.UxsdkPanelExposureSettingBinding + +/** + * Class Description + * + * @author Hoker + * @date 2021/10/19 + * + * Copyright (c) 2021, DJI All Rights Reserved. + */ +open class ExposureSettingsPanel @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ConstraintLayoutWidget(context, attrs, defStyleAttr), + ICameraIndex { + + private lateinit var binding: UxsdkPanelExposureSettingBinding + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + binding = UxsdkPanelExposureSettingBinding.inflate(LayoutInflater.from(context), this) + } + + override fun reactToModelChanges() { + //暂未实现 + } + + override fun getCameraIndex() = binding.exposureSettingWidget.getCameraIndex() + + override fun getLensType() = binding.exposureSettingWidget.getLensType() + + override fun updateCameraSource(cameraIndex: ComponentIndexType, lensType: CameraLensType) { + binding.exposureSettingWidget.updateCameraSource(cameraIndex, lensType) + binding.isoAndEiSettingWidget.updateCameraSource(cameraIndex, lensType) + } + + override fun getIdealDimensionRatioString(): String? { + return null + } + + sealed class ModelState +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettings/ISOAndEISettingModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettings/ISOAndEISettingModel.kt new file mode 100644 index 00000000..db8a32c3 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettings/ISOAndEISettingModel.kt @@ -0,0 +1,110 @@ +package dji.v5.ux.cameracore.widget.cameracontrols.exposuresettings + +import dji.sdk.keyvalue.key.CameraKey +import dji.sdk.keyvalue.value.camera.* +import dji.sdk.keyvalue.value.common.CameraLensType +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.value.common.ComponentIndexType +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.ICameraIndex +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.CameraUtil +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Completable + +/** + * Class Description + * + * @author Hoker + * @date 2021/11/2 + * + * Copyright (c) 2021, DJI All Rights Reserved. + */ +open class ISOAndEISettingModel constructor( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore), ICameraIndex { + + private var cameraIndex = ComponentIndexType.LEFT_OR_MAIN + private var lensType = CameraLensType.CAMERA_LENS_ZOOM + + val exposureSettingsProcessor: DataProcessor = DataProcessor.create(CameraExposureSettings()) + val ISOProcessor: DataProcessor = DataProcessor.create(CameraISO.UNKNOWN) + val ISORangeProcessor: DataProcessor> = DataProcessor.create(listOf()) + val exposureSensitivityModeProcessor: DataProcessor = DataProcessor.create(ExposureSensitivityMode.UNKNOWN) + val eiValueProcessor: DataProcessor = DataProcessor.create(EIType.UNKNOWN) + val eiRecommendedValueProcessor: DataProcessor = DataProcessor.create(EIType.UNKNOWN) + val eiValueRangeProcessor: DataProcessor> = DataProcessor.create(listOf()) + val exposureModeProcessor: DataProcessor = DataProcessor.create(CameraExposureMode.UNKNOWN) + val cameraModeProcessor: DataProcessor = DataProcessor.create(CameraWorkMode.UNKNOWN) + val flatCameraModeProcessor: DataProcessor = DataProcessor.create(CameraFlatMode.UNKNOWN) + + override fun inSetup() { + bindDataProcessor( + KeyTools.createCameraKey( + CameraKey.KeyISO, cameraIndex, lensType), ISOProcessor) + bindDataProcessor( + KeyTools.createCameraKey( + CameraKey.KeyExposureSettings, cameraIndex, lensType), exposureSettingsProcessor) + bindDataProcessor( + KeyTools.createCameraKey( + CameraKey.KeyISORange, cameraIndex, lensType), ISORangeProcessor) + bindDataProcessor( + KeyTools.createCameraKey( + CameraKey.KeyExposureSensitivityMode, cameraIndex, lensType), exposureSensitivityModeProcessor) + bindDataProcessor( + KeyTools.createCameraKey( + CameraKey.KeyEI, cameraIndex, lensType), eiValueProcessor) + bindDataProcessor( + KeyTools.createCameraKey( + CameraKey.KeyRecommendedEI, cameraIndex, lensType), eiRecommendedValueProcessor) + bindDataProcessor( + KeyTools.createCameraKey( + CameraKey.KeyEIRange, cameraIndex, lensType), eiValueRangeProcessor) + bindDataProcessor( + KeyTools.createCameraKey( + CameraKey.KeyCameraWorkMode, cameraIndex, lensType), cameraModeProcessor) + bindDataProcessor( + KeyTools.createCameraKey( + CameraKey.KeyCameraFlatMode, cameraIndex, lensType), flatCameraModeProcessor) + bindDataProcessor( + KeyTools.createCameraKey( + CameraKey.KeyExposureMode, cameraIndex, lensType), exposureModeProcessor) + } + + override fun inCleanup() { + //暂未实现 + } + + override fun getCameraIndex() = cameraIndex + + override fun getLensType() = lensType + + override fun updateCameraSource(cameraIndex: ComponentIndexType, lensType: CameraLensType) { + this.cameraIndex = cameraIndex + this.lensType = lensType + restart() + } + + fun setISO(iso: CameraISO): Completable { + return djiSdkModel.setValue( + KeyTools.createCameraKey( + CameraKey.KeyISO, cameraIndex, lensType), iso) + } + + fun setEI(ei: EIType): Completable { + return djiSdkModel.setValue( + KeyTools.createCameraKey( + CameraKey.KeyEI, cameraIndex, lensType), ei) + } + + fun isEIEnable(): Boolean { + return exposureSensitivityModeProcessor.value == ExposureSensitivityMode.EI + } + + fun isRecordVideoEIMode(): Boolean { + return ((!CameraUtil.isPictureMode(flatCameraModeProcessor.value) || cameraModeProcessor.value == CameraWorkMode.RECORD_VIDEO) + && isEIEnable()) + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettings/ISOAndEISettingWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettings/ISOAndEISettingWidget.kt new file mode 100644 index 00000000..2209f3ae --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettings/ISOAndEISettingWidget.kt @@ -0,0 +1,361 @@ +package dji.v5.ux.cameracore.widget.cameracontrols.exposuresettings + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import dji.sdk.keyvalue.value.camera.CameraExposureMode +import dji.sdk.keyvalue.value.camera.CameraExposureSettings +import dji.sdk.keyvalue.value.camera.CameraISO +import dji.sdk.keyvalue.value.camera.EIType +import dji.sdk.keyvalue.value.common.CameraLensType +import dji.sdk.keyvalue.value.common.ComponentIndexType +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.ICameraIndex +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.ui.HorizontalSeekBar +import dji.v5.ux.core.util.AudioUtil +import dji.v5.ux.core.util.CameraUtil +import dji.v5.ux.core.util.UxErrorHandle +import dji.v5.ux.databinding.UxsdkWidgetIsoEiSettingBinding +import io.reactivex.rxjava3.functions.Action + +/** + * Class Description + * + * @author Hoker + * @date 2021/11/2 + * + * Copyright (c) 2021, DJI All Rights Reserved. + */ +open class ISOAndEISettingWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ConstraintLayoutWidget(context, attrs, defStyleAttr), + View.OnClickListener, HorizontalSeekBar.OnSeekBarChangeListener, ICameraIndex { + + private val LOCKED_ISO_VALUE = "500" + + private var isISOAutoSelected = false + private var isISOAutoSupported = false + private var isISOSeekBarEnabled = false + private val isISOLocked = false + private var isSeekBarTracking = false + private var uiCameraISO = 0 + + //去掉auto + private var uiIsoValueArray: Array = arrayOf() + private var eiValueArray: IntArray = intArrayOf() + + private lateinit var binding: UxsdkWidgetIsoEiSettingBinding + + private val widgetModel by lazy { + ISOAndEISettingModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()) + } + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + binding = UxsdkWidgetIsoEiSettingBinding.inflate(LayoutInflater.from(context), this) + } + + override fun reactToModelChanges() { + + // ISO part + addReaction(widgetModel.exposureModeProcessor.toFlowable().observeOn(SchedulerProvider.ui()).subscribe { + onExposureModeUpdated(it) + updateISOEnableStatus() + }) + addReaction(widgetModel.ISOProcessor.toFlowable().observeOn(SchedulerProvider.ui()).subscribe { + onISOUpdated(it) + }) + addReaction(widgetModel.ISORangeProcessor.toFlowable().observeOn(SchedulerProvider.ui()).subscribe { + updateISORangeValue(it.toTypedArray()) + updateISOEnableStatus() + updateISORangeUI() + }) + addReaction(widgetModel.exposureSettingsProcessor.toFlowable().observeOn(SchedulerProvider.ui()).subscribe { + val exposureParameters = it as CameraExposureSettings + uiCameraISO = exposureParameters.iso + updateISORangeUI() + }) + + // EI part + addReaction(widgetModel.eiValueProcessor.toFlowable().observeOn(SchedulerProvider.ui()).subscribe { + + }) + addReaction(widgetModel.eiValueRangeProcessor.toFlowable().observeOn(SchedulerProvider.ui()).subscribe { + + }) + addReaction(widgetModel.eiRecommendedValueProcessor.toFlowable().observeOn(SchedulerProvider.ui()).subscribe { + + }) + + // mode + addReaction(widgetModel.exposureSensitivityModeProcessor.toFlowable().observeOn(SchedulerProvider.ui()).subscribe { + updateWidgetUI() + }) + addReaction(widgetModel.cameraModeProcessor.toFlowable().observeOn(SchedulerProvider.ui()).subscribe { + updateWidgetUI() + }) + addReaction(widgetModel.flatCameraModeProcessor.toFlowable().observeOn(SchedulerProvider.ui()).subscribe { + updateWidgetUI() + }) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + + // Initialize ISO array + val res = context.resources + val valueArray = res.getIntArray(R.array.uxsdk_iso_values) + uiIsoValueArray = arrayOfNulls(valueArray.size) + + if (!isInEditMode) { + for (i in valueArray.indices) { + uiIsoValueArray[i] = CameraISO.find(valueArray[i]) + } + updateISORangeValue(uiIsoValueArray) + } + + // ISO seekBar + isISOSeekBarEnabled = false + binding.seekbarIso.progress = 0 + binding.seekbarIso.enable(false) + binding.seekbarIso.addOnSeekBarChangeListener(this) + binding.seekbarIso.isBaselineVisibility = false + binding.seekbarIso.setMinValueVisibility(true) + binding.seekbarIso.setMaxValueVisibility(true) + binding.seekbarIso.setMinusVisibility(false) + binding.seekbarIso.setPlusVisibility(false) + binding.buttonIsoAuto.setOnClickListener(this) + + // EI seekBar + binding.seekbarEi.addOnSeekBarChangeListener(this) + binding.seekbarEi.visibility = GONE + binding.seekbarEi.setMinValueVisibility(true) + binding.seekbarEi.setMaxValueVisibility(true) + binding.seekbarEi.setMinusVisibility(false) + binding.seekbarEi.setPlusVisibility(false) + + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun getCameraIndex() = widgetModel.getCameraIndex() + + override fun getLensType() = widgetModel.getLensType() + + override fun updateCameraSource(cameraIndex: ComponentIndexType, lensType: CameraLensType) = widgetModel.updateCameraSource(cameraIndex, lensType) + + override fun getIdealDimensionRatioString(): String? { + return null + } + + override fun onProgressChanged(view: HorizontalSeekBar, progress: Int, isFromUI: Boolean) { + if (view == binding.seekbarIso) { + if (isISOLocked) { + binding.seekbarIso.text = LOCKED_ISO_VALUE + } else { + if (uiIsoValueArray.isNotEmpty()) { + uiCameraISO = CameraUtil.convertISOToInt(uiIsoValueArray[progress]) + binding.seekbarIso.text = uiCameraISO.toString() + } + } + } else { + if (progress < eiValueArray.size) { + binding.seekbarEi.text = eiValueArray[progress].toString() + } + } + } + + override fun onStartTrackingTouch(view: HorizontalSeekBar, progress: Int) { + isSeekBarTracking = true + } + + override fun onStopTrackingTouch(view: HorizontalSeekBar, progress: Int) { + isSeekBarTracking = false + AudioUtil.playSoundInBackground(context, R.raw.uxsdk_camera_ev_center) + if (view == binding.seekbarIso) { + if (uiIsoValueArray.isNotEmpty()) { + val newISO = uiIsoValueArray[progress] + newISO?.let { + updateISOToCamera(it) + } + } + } else { + if (progress < eiValueArray.size) { + updateEIToCamera(eiValueArray[progress]) + } + } + } + + override fun onPlusClicked(view: HorizontalSeekBar) { + //暂未实现 + } + + override fun onMinusClicked(view: HorizontalSeekBar) { + //暂未实现 + } + + override fun onClick(v: View?) { + if (v == binding.buttonIsoAuto) { + isISOAutoSelected = !isISOAutoSelected + setAutoISO(isISOAutoSelected) + } + } + + private fun updateWidgetUI() { + if (widgetModel.isRecordVideoEIMode()) { + binding.textviewIsoTitle.setText(R.string.uxsdk_camera_ei) + binding.seekbarIsoLayout.visibility = GONE + binding.seekbarEi.visibility = VISIBLE + } else { + binding.textviewIsoTitle.setText(R.string.uxsdk_camera_exposure_iso_title) + binding.seekbarIsoLayout.visibility = VISIBLE + binding.seekbarEi.visibility = GONE + } + } + + private fun onISOUpdated(iso: CameraISO) { + if (iso == CameraISO.ISO_FIXED) { + updateISOLocked() + } + } + + private fun onExposureModeUpdated(exposureMode: CameraExposureMode) { + if (exposureMode != CameraExposureMode.MANUAL) { + isISOAutoSelected = true + setAutoISO(isISOAutoSelected) + } else { + isISOAutoSelected = false + } + + } + + private fun updateISORangeValue(array: Array) { + isISOAutoSupported = checkAutoISO(array) + val newISOValues: Array = if (isISOAutoSupported) { + arrayOfNulls(array.size - 1) + } else { + arrayOfNulls(array.size) + } + + // remove the auto value + var i = 0 + var j = 0 + while (i < array.size) { + if (array[i] != CameraISO.ISO_AUTO) { + newISOValues[j] = array[i] + j++ + } + i++ + } + uiIsoValueArray = newISOValues + } + + private fun updateISORangeUI() { + // Workaround where ISO range updates to single value in AUTO mode + if (uiIsoValueArray.isNotEmpty()) { + val minCameraISO = CameraUtil.convertISOToInt(uiIsoValueArray[0]) + binding.seekbarIso.setMinValueText(minCameraISO.toString()) + val maxCameraISO = CameraUtil.convertISOToInt(uiIsoValueArray[uiIsoValueArray.size - 1]) + binding.seekbarIso.setMaxValueText(maxCameraISO.toString()) + binding.seekbarIso.max = uiIsoValueArray.size - 1 + isISOSeekBarEnabled = true + updateISOValue(uiIsoValueArray, uiCameraISO) + // Auto button has relationship with ISO range, so need update this button here. + updateAutoISOButton() + } else { + isISOSeekBarEnabled = false + } + } + + private fun updateISOEnableStatus() { + binding.seekbarIso.enable(!isISOAutoSelected && isISOSeekBarEnabled) + } + + private fun checkAutoISO(array: Array): Boolean { + for (iso in array) { + if (iso == CameraISO.ISO_AUTO) { + return true + } + } + return false + } + + private fun updateISOValue(array: Array, value: Int) { + val progress: Int = getISOIndex(array, value) + binding.seekbarIso.progress = progress + } + + private fun updateAutoISOButton() { + if (isISOAutoSupported && isISOSeekBarEnabled && !widgetModel.isRecordVideoEIMode() && CameraUtil.isAutoISOSupportedByProduct()) { + binding.buttonIsoAuto.visibility = VISIBLE + } else { + binding.buttonIsoAuto.visibility = GONE + } + } + + private fun getISOIndex(array: Array, isoValue: Int): Int { + var index = -1 + val iso = CameraUtil.convertIntToISO(isoValue) + for (i in array.indices) { + if (iso == array[i]) { + index = i + break + } + } + return index + } + + private fun setAutoISO(isAuto: Boolean) { + var newISO: CameraISO? = null + if (isAuto) { + newISO = CameraISO.ISO_AUTO + } else { + if (binding.seekbarIso.progress < uiIsoValueArray.size) { + newISO = uiIsoValueArray[binding.seekbarIso.progress] + } + } + newISO?.let { + updateISOToCamera(it) + } + } + + private fun updateISOToCamera(iso: CameraISO) { + addDisposable( + widgetModel.setISO(iso).observeOn(SchedulerProvider.ui()).subscribe(Action { }, UxErrorHandle.errorConsumer({ + binding.seekbarIso.restorePreviousProgress() + }, this.toString(), "updateISOToCamera: ")) + ) + } + + private fun updateEIToCamera(ei: Int) { + addDisposable( + widgetModel.setEI(EIType.find(ei)).observeOn(SchedulerProvider.ui()).subscribe(Action { }, UxErrorHandle.errorConsumer({ + binding.seekbarIso.restorePreviousProgress() + }, this.toString(), "updateEIToCamera: ")) + ) + } + + // By referring to DJIGo4 in both iOS and Android version + // Showing the ISO_FIXED as locked value 500 + private fun updateISOLocked() { + binding.buttonIsoAuto.visibility = GONE + binding.seekbarIso.enable(false) + binding.seekbarIso.progress = binding.seekbarIso.max / 2 - 1 + } + + sealed class ModelState +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettingsindicator/ExposureSettingsIndicatorWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettingsindicator/ExposureSettingsIndicatorWidget.java new file mode 100644 index 00000000..5c3f6ada --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettingsindicator/ExposureSettingsIndicatorWidget.java @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracontrols.exposuresettingsindicator; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageView; + +import java.util.HashMap; +import java.util.Map; + +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import dji.sdk.keyvalue.value.camera.CameraExposureMode; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.SchedulerProvider; +import dji.v5.ux.core.base.widget.FrameLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.UxErrorHandle; + +/** + * Widget indicates the current exposure mode. + * Tapping on the widget can be linked to open exposure settings + */ +public class ExposureSettingsIndicatorWidget extends FrameLayoutWidget implements View.OnClickListener, ICameraIndex { + + //region Fields + private static final String TAG = "ExposureSetIndicWidget"; + private ImageView foregroundImageView; + private ExposureSettingsIndicatorWidgetModel widgetModel; + private Map exposureModeDrawableHashMap; + private int stateChangeResourceId; + //endregion + + //region Lifecycle + public ExposureSettingsIndicatorWidget(@NonNull Context context) { + super(context); + } + + public ExposureSettingsIndicatorWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public ExposureSettingsIndicatorWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_widget_exposure_settings_indicator, this); + foregroundImageView = findViewById(R.id.image_view_exposure_settings_indicator); + + if (!isInEditMode()) { + initDefaults(); + widgetModel = new ExposureSettingsIndicatorWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + } + + setOnClickListener(this); + + if (attrs != null) { + initAttributes(context, attrs); + } + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.getExposureMode().observeOn(SchedulerProvider.ui()).subscribe(this::updateUI)); + } + + @NonNull + @Override + public String getIdealDimensionRatioString() { + return getResources().getString(R.string.uxsdk_widget_default_ratio); + } + + @Override + public void onClick(View v) { + updateViewState(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + if (!isInEditMode()) { + widgetModel.cleanup(); + } + super.onDetachedFromWindow(); + } + //endregion + + //region private methods + private void checkAndUpdateUI() { + if (!isInEditMode()) { + addDisposable(widgetModel.getExposureMode() + .firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(this::updateUI, UxErrorHandle.logErrorConsumer(TAG, "get exposure mode"))); + } + } + + private void updateViewState() { + if (stateChangeResourceId != INVALID_RESOURCE && this.getRootView() != null) { + View view = this.getRootView().findViewById(stateChangeResourceId); + if (view == null) { + return; + } + view.setVisibility(view.isShown() ? View.GONE : View.VISIBLE); + } + } + + + private void initDefaults() { + exposureModeDrawableHashMap = new HashMap<>(); + + exposureModeDrawableHashMap.put(CameraExposureMode.APERTURE_PRIORITY, getResources().getDrawable(R.drawable.uxsdk_ic_exposure_settings_aperture)); + exposureModeDrawableHashMap.put(CameraExposureMode.SHUTTER_PRIORITY, getResources().getDrawable(R.drawable.uxsdk_ic_exposure_settings_shutter)); + exposureModeDrawableHashMap.put(CameraExposureMode.MANUAL, getResources().getDrawable(R.drawable.uxsdk_ic_exposure_settings_manual)); + exposureModeDrawableHashMap.put(CameraExposureMode.PROGRAM, getResources().getDrawable(R.drawable.uxsdk_ic_exposure_settings_program)); + exposureModeDrawableHashMap.put(CameraExposureMode.UNKNOWN, getResources().getDrawable(R.drawable.uxsdk_ic_exposure_settings_normal)); + } + + private void initAttributes(Context context, AttributeSet attrs) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ExposureSettingsIndicatorWidget); + if (!isInEditMode()) { + updateCameraSource(ComponentIndexType.find(typedArray.getInt(R.styleable.ExposureSettingsIndicatorWidget_uxsdk_cameraIndex, 0)) + , CameraLensType.find(typedArray.getInt(R.styleable.ExposureSettingsIndicatorWidget_uxsdk_lensType, 0))); + } + stateChangeResourceId = + typedArray.getResourceId(R.styleable.ExposureSettingsIndicatorWidget_uxsdk_onStateChange, INVALID_RESOURCE); + Drawable drawable = typedArray.getDrawable(R.styleable.ExposureSettingsIndicatorWidget_uxsdk_aperturePriorityModeDrawable); + if (drawable != null) { + setIconByMode(CameraExposureMode.APERTURE_PRIORITY, drawable); + } + drawable = typedArray.getDrawable(R.styleable.ExposureSettingsIndicatorWidget_uxsdk_shutterPriorityModeDrawable); + if (drawable != null) { + setIconByMode(CameraExposureMode.SHUTTER_PRIORITY, drawable); + } + drawable = typedArray.getDrawable(R.styleable.ExposureSettingsIndicatorWidget_uxsdk_programModeDrawable); + if (drawable != null) { + setIconByMode(CameraExposureMode.PROGRAM, drawable); + } + drawable = typedArray.getDrawable(R.styleable.ExposureSettingsIndicatorWidget_uxsdk_manualModeDrawable); + if (drawable != null) { + setIconByMode(CameraExposureMode.MANUAL, drawable); + } + drawable = typedArray.getDrawable(R.styleable.ExposureSettingsIndicatorWidget_uxsdk_unknownModeDrawable); + if (drawable != null) { + setIconByMode(CameraExposureMode.UNKNOWN, drawable); + } + setIconBackground(typedArray.getDrawable(R.styleable.ExposureSettingsIndicatorWidget_uxsdk_iconBackground)); + typedArray.recycle(); + } + + private void updateUI(CameraExposureMode exposureMode) { + switch (exposureMode) { + case APERTURE_PRIORITY: + foregroundImageView.setImageDrawable(exposureModeDrawableHashMap.get(CameraExposureMode.APERTURE_PRIORITY)); + break; + case SHUTTER_PRIORITY: + foregroundImageView.setImageDrawable(exposureModeDrawableHashMap.get(CameraExposureMode.SHUTTER_PRIORITY)); + break; + case MANUAL: + foregroundImageView.setImageDrawable(exposureModeDrawableHashMap.get(CameraExposureMode.MANUAL)); + break; + case PROGRAM: + foregroundImageView.setImageDrawable(exposureModeDrawableHashMap.get(CameraExposureMode.PROGRAM)); + break; + case UNKNOWN: + default: + foregroundImageView.setImageDrawable(exposureModeDrawableHashMap.get(CameraExposureMode.UNKNOWN)); + } + } + //endregion + + //region customizations + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + widgetModel.updateCameraSource(cameraIndex, lensType); + } + + /** + * Get the index of the camera to which the widget is reacting + * + * @return instance of {@link ComponentIndexType} + */ + @Override + @NonNull + public ComponentIndexType getCameraIndex() { + return widgetModel.getCameraIndex(); + } + + /** + * Get the current type of the lens the widget is reacting to + * + * @return current lens type + */ + @Override + @NonNull + public CameraLensType getLensType() { + return widgetModel.getLensType(); + } + + /** + * Set the icon for exposure mode + * + * @param exposureMode instance of {@link CameraExposureMode} for which icon should be used + * @param resourceId to be used + */ + public void setIconByMode(@NonNull CameraExposureMode exposureMode, @DrawableRes int resourceId) { + setIconByMode(exposureMode, getResources().getDrawable(resourceId)); + } + + /** + * Set the icon for exposure mode + * + * @param exposureMode instance of {@link CameraExposureMode} for which icon should be used + * @param drawable to be used + */ + public void setIconByMode(@NonNull CameraExposureMode exposureMode, @Nullable Drawable drawable) { + exposureModeDrawableHashMap.put(exposureMode, drawable); + checkAndUpdateUI(); + } + + /** + * Get the icon used for the exposure mode + * + * @param exposureMode instance of {@link CameraExposureMode} for which icon is used + * @return Drawable + */ + @Nullable + public Drawable getIconByMode(@NonNull CameraExposureMode exposureMode) { + return exposureModeDrawableHashMap.get(exposureMode); + } + + /** + * Get current background of icon + * + * @return Drawable resource of the background + */ + public Drawable getIconBackground() { + return foregroundImageView.getBackground(); + } + + /** + * Set background to icon + * + * @param resourceId resource id of background + */ + public void setIconBackground(@DrawableRes int resourceId) { + setIconBackground(getResources().getDrawable(resourceId)); + } + + /** + * Set background to icon + * + * @param drawable Drawable to be used as background + */ + public void setIconBackground(@Nullable Drawable drawable) { + foregroundImageView.setBackground(drawable); + } + + public void setStateChangeResourceId(int stateChangeResourceId) { + this.stateChangeResourceId = stateChangeResourceId; + } + + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettingsindicator/ExposureSettingsIndicatorWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettingsindicator/ExposureSettingsIndicatorWidgetModel.java new file mode 100644 index 00000000..b53be33a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/exposuresettingsindicator/ExposureSettingsIndicatorWidgetModel.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracontrols.exposuresettingsindicator; + +import androidx.annotation.NonNull; +import dji.sdk.keyvalue.key.CameraKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.value.camera.CameraExposureMode; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Flowable; + +/** + * Exposure Settings Indicator Widget Model + *

+ * Widget Model for the {@link ExposureSettingsIndicatorWidget} used to define the + * underlying logic and communication + */ +public class ExposureSettingsIndicatorWidgetModel extends WidgetModel implements ICameraIndex { + + //region Fields + private final DataProcessor exposureModeDataProcessor; + private ComponentIndexType cameraIndex = ComponentIndexType.LEFT_OR_MAIN; + private CameraLensType lensType = CameraLensType.CAMERA_LENS_ZOOM; + //endregion + + //region Lifecycle + public ExposureSettingsIndicatorWidgetModel(@NonNull DJISDKModel djiSdkModel, + @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + exposureModeDataProcessor = DataProcessor.create(CameraExposureMode.UNKNOWN); + } + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createCameraKey(CameraKey.KeyExposureMode, cameraIndex, lensType), exposureModeDataProcessor); + } + + @Override + protected void inCleanup() { + // No Clean up needed + } + + @Override + protected void updateStates() { + // No states + } + //endregion + + //region Data + + /** + * Get the current exposure mode + * + * @return {@link CameraExposureMode} + */ + public Flowable getExposureMode() { + return exposureModeDataProcessor.toFlowable(); + } + //endregion + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + this.cameraIndex = cameraIndex; + this.lensType = lensType; + restart(); + } + + @NonNull + public ComponentIndexType getCameraIndex() { + return cameraIndex; + } + + @NonNull + public CameraLensType getLensType() { + return lensType; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/lenscontrol/LensControlModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/lenscontrol/LensControlModel.kt new file mode 100644 index 00000000..c256afad --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/lenscontrol/LensControlModel.kt @@ -0,0 +1,66 @@ +package dji.v5.ux.cameracore.widget.cameracontrols.lenscontrol + +import dji.sdk.keyvalue.key.CameraKey +import dji.sdk.keyvalue.value.camera.CameraVideoStreamSourceType +import dji.sdk.keyvalue.value.common.CameraLensType +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.value.common.ComponentIndexType +import dji.v5.ux.core.base.CameraWidgetModel +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.ICameraIndex +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Completable + +/** + * Class Description + * + * @author Hoker + * @date 2021/12/13 + * + * Copyright (c) 2021, DJI All Rights Reserved. + */ +open class LensControlModel constructor( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : CameraWidgetModel(djiSdkModel, keyedStore), ICameraIndex { + + val cameraVideoStreamSourceProcessor: DataProcessor = DataProcessor.create( + CameraVideoStreamSourceType.UNKNOWN) + private val cameraVideoStreamSourceRangeProcessor: DataProcessor> = DataProcessor.create(listOf()) + val properCameraVideoStreamSourceRangeProcessor: DataProcessor> = DataProcessor.create(listOf()) + + override fun updateCameraSource(cameraIndex: ComponentIndexType, lensType: CameraLensType) { + if (this.cameraIndex == cameraIndex){ + return + } + this.cameraIndex = cameraIndex + restart() + } + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + CameraKey.KeyCameraVideoStreamSource,cameraIndex),cameraVideoStreamSourceProcessor) + bindDataProcessor( + KeyTools.createKey( + CameraKey.KeyCameraVideoStreamSourceRange, cameraIndex),cameraVideoStreamSourceRangeProcessor){ + //部分镜头不在该控件显示 + it.remove(CameraVideoStreamSourceType.MS_NIR_CAMERA) + it.remove(CameraVideoStreamSourceType.MS_G_CAMERA) + it.remove(CameraVideoStreamSourceType.MS_RE_CAMERA) + it.remove(CameraVideoStreamSourceType.MS_R_CAMERA) + properCameraVideoStreamSourceRangeProcessor.onNext(it) + } + } + + override fun inCleanup() { + //暂未实现 + } + + fun setCameraVideoStreamSource(source: CameraVideoStreamSourceType): Completable { + return djiSdkModel.setValue( + KeyTools.createKey( + CameraKey.KeyCameraVideoStreamSource,cameraIndex), source) + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/lenscontrol/LensControlWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/lenscontrol/LensControlWidget.kt new file mode 100644 index 00000000..5fa40c4d --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/lenscontrol/LensControlWidget.kt @@ -0,0 +1,152 @@ +package dji.v5.ux.cameracore.widget.cameracontrols.lenscontrol + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.widget.Button +import dji.sdk.keyvalue.value.camera.CameraVideoStreamSourceType +import dji.sdk.keyvalue.value.common.CameraLensType +import dji.sdk.keyvalue.value.common.ComponentIndexType +import dji.v5.utils.common.StringUtils +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.ICameraIndex +import dji.v5.ux.core.base.SchedulerProvider.ui +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.databinding.UxsdkCameraLensControlWidgetBinding +import dji.v5.ux.databinding.UxsdkPanelNdvlBinding + +/** + * Class Description + * + * @author Hoker + * @date 2021/12/13 + * + * Copyright (c) 2021, DJI All Rights Reserved. + */ +open class LensControlWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ConstraintLayoutWidget(context, attrs, defStyleAttr), + View.OnClickListener, ICameraIndex { + + private lateinit var binding: UxsdkCameraLensControlWidgetBinding + private var firstBtnSource = CameraVideoStreamSourceType.ZOOM_CAMERA + private var secondBtnSource = CameraVideoStreamSourceType.WIDE_CAMERA + + private val widgetModel by lazy { + LensControlModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()) + } + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + binding = UxsdkCameraLensControlWidgetBinding.inflate(LayoutInflater.from(context),this) + } + + override fun reactToModelChanges() { + addReaction(widgetModel.properCameraVideoStreamSourceRangeProcessor.toFlowable().observeOn(ui()).subscribe { + updateBtnView() + }) + addReaction(widgetModel.cameraVideoStreamSourceProcessor.toFlowable().observeOn(ui()).subscribe { + updateBtnView() + }) + binding.firstLenBtn.setOnClickListener(this) + binding.secondLenBtn.setOnClickListener(this) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun getIdealDimensionRatioString(): String? { + return null + } + + override fun onClick(v: View?) { + if (v == binding.firstLenBtn) { + dealLensBtnClicked(firstBtnSource) + } else if (v == binding.secondLenBtn) { + dealLensBtnClicked(secondBtnSource) + } + } + + override fun getCameraIndex() = widgetModel.getCameraIndex() + + override fun getLensType() = widgetModel.getLensType() + + override fun updateCameraSource(cameraIndex: ComponentIndexType, lensType: CameraLensType) { + if (widgetModel.getCameraIndex() == cameraIndex) { + return + } + widgetModel.updateCameraSource(cameraIndex, lensType) + } + + private fun dealLensBtnClicked(source: CameraVideoStreamSourceType) { + if (source == widgetModel.cameraVideoStreamSourceProcessor.value) { + return + } + addDisposable(widgetModel.setCameraVideoStreamSource(source).observeOn(ui()).subscribe()) + } + + private fun updateBtnView() { + val videoSourceRange = widgetModel.properCameraVideoStreamSourceRangeProcessor.value + //单源 + if (videoSourceRange.size <= 1) { + binding.firstLenBtn.visibility = INVISIBLE + binding.secondLenBtn.visibility = INVISIBLE + return + } + binding.firstLenBtn.visibility = VISIBLE + //双源 + if (videoSourceRange.size == 2) { + updateBtnText(binding.firstLenBtn, getProperVideoSource(videoSourceRange,widgetModel.cameraVideoStreamSourceProcessor.value).also { + firstBtnSource = it + }) + binding.secondLenBtn.visibility = INVISIBLE + return + } + //超过2个源 + binding.secondLenBtn.visibility = VISIBLE + updateBtnText(binding.firstLenBtn, getProperVideoSource(videoSourceRange, secondBtnSource).also { + firstBtnSource = it + }) + updateBtnText(binding.secondLenBtn, getProperVideoSource(videoSourceRange, firstBtnSource).also { + secondBtnSource = it + }) + } + + private fun updateBtnText(button: Button, source: CameraVideoStreamSourceType) { + button.text = when (source) { + CameraVideoStreamSourceType.WIDE_CAMERA -> StringUtils.getResStr(R.string.uxsdk_lens_type_wide) + CameraVideoStreamSourceType.ZOOM_CAMERA -> StringUtils.getResStr(R.string.uxsdk_lens_type_zoom) + CameraVideoStreamSourceType.INFRARED_CAMERA -> StringUtils.getResStr(R.string.uxsdk_lens_type_ir) + CameraVideoStreamSourceType.NDVI_CAMERA -> StringUtils.getResStr(R.string.uxsdk_lens_type_ndvi) + CameraVideoStreamSourceType.RGB_CAMERA -> StringUtils.getResStr(R.string.uxsdk_lens_type_rgb) + CameraVideoStreamSourceType.POINT_CLOUD_CAMERA -> StringUtils.getResStr(R.string.uxsdk_lens_type_point_cloud) + else -> "" + } + } + + private fun getProperVideoSource(range: List, exceptSource: CameraVideoStreamSourceType): CameraVideoStreamSourceType { + for (source in range) { + if (source != widgetModel.cameraVideoStreamSourceProcessor.value && source != exceptSource) { + return source + } + } + return exceptSource; + } + + sealed class ModelState +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/photovideoswitch/PhotoVideoSwitchWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/photovideoswitch/PhotoVideoSwitchWidget.java new file mode 100644 index 00000000..71de6717 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/photovideoswitch/PhotoVideoSwitchWidget.java @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracontrols.photovideoswitch; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageView; + +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.ux.R; +import dji.v5.ux.cameracore.widget.cameracontrols.RemoteControllerButtonDownModel; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.SchedulerProvider; +import dji.v5.ux.core.base.widget.FrameLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.UxErrorHandle; + +/** + * Widget can be used to switch between shoot photo mode and record video mode + */ +public class PhotoVideoSwitchWidget extends FrameLayoutWidget implements View.OnClickListener, ICameraIndex { + + //region Fields + private static final String TAG = "PhotoVideoSwitchWidget"; + private ImageView foregroundImageView; + private Drawable photoModeDrawable; + private Drawable videoModeDrawable; + private PhotoVideoSwitchWidgetModel widgetModel; + private RemoteControllerButtonDownModel buttonDownModel; + //endregion + + //region Lifecycle + public PhotoVideoSwitchWidget(@NonNull Context context) { + super(context); + } + + public PhotoVideoSwitchWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public PhotoVideoSwitchWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_widget_photo_video_switch, this); + foregroundImageView = findViewById(R.id.image_view_foreground); + if (!isInEditMode()) { + widgetModel = new PhotoVideoSwitchWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + buttonDownModel = new RemoteControllerButtonDownModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + setOnClickListener(this); + } + photoModeDrawable = getResources().getDrawable(R.drawable.uxsdk_ic_camera_mode_photo); + videoModeDrawable = getResources().getDrawable(R.drawable.uxsdk_ic_camera_mode_video); + if (attrs != null) { + initAttributes(context, attrs); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + buttonDownModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + if (!isInEditMode()) { + widgetModel.cleanup(); + buttonDownModel.cleanup(); + } + super.onDetachedFromWindow(); + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.isEnabled() + .observeOn(SchedulerProvider.ui()) + .subscribe(this::enableWidget)); + addReaction(widgetModel.isPictureMode() + .observeOn(SchedulerProvider.ui()) + .subscribe(this::updateUI)); + addReaction(buttonDownModel.isShutterButtonDownProcessor().toFlowable() + .observeOn(SchedulerProvider.ui()) + .subscribe(aBoolean -> { + if (aBoolean == Boolean.TRUE) { + widgetModel.changeToPhotoMode(); + } + })); + addReaction(buttonDownModel.isRecordButtonDownProcessor().toFlowable() + .observeOn(SchedulerProvider.ui()) + .subscribe(aBoolean -> { + if (aBoolean == Boolean.TRUE) { + widgetModel.changeToVideoMode(); + } + })); + } + + @NonNull + @Override + public String getIdealDimensionRatioString() { + return getResources().getString(R.string.uxsdk_widget_default_ratio); + } + + @Override + public void onClick(View v) { + widgetModel.toggleCameraMode() + .observeOn(SchedulerProvider.ui()) + .subscribe( + () -> { + }, UxErrorHandle.logErrorConsumer(TAG, "Switch camera Mode") + ); + } + + + //region private helpers + private void initAttributes(Context context, AttributeSet attrs) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.PhotoVideoSwitchWidget); + if (!isInEditMode()) { + updateCameraSource(ComponentIndexType.find(typedArray.getInt(R.styleable.PhotoVideoSwitchWidget_uxsdk_cameraIndex, 0)), CameraLensType.UNKNOWN); + } + + if (typedArray.getDrawable(R.styleable.PhotoVideoSwitchWidget_uxsdk_photoModeIcon) != null) { + photoModeDrawable = typedArray.getDrawable(R.styleable.PhotoVideoSwitchWidget_uxsdk_photoModeIcon); + } + + if (typedArray.getDrawable(R.styleable.PhotoVideoSwitchWidget_uxsdk_videoModeIcon) != null) { + videoModeDrawable = typedArray.getDrawable(R.styleable.PhotoVideoSwitchWidget_uxsdk_videoModeIcon); + } + setIconBackground(typedArray.getDrawable(R.styleable.PhotoVideoSwitchWidget_uxsdk_iconBackground)); + + typedArray.recycle(); + } + + private void updateUI(boolean isPictureMode) { + if (isPictureMode) { + foregroundImageView.setImageDrawable(photoModeDrawable); + } else { + foregroundImageView.setImageDrawable(videoModeDrawable); + } + } + + private void enableWidget(Boolean isEnabled) { + setEnabled(isEnabled); + } + + private void checkAndUpdateUI() { + if (!isInEditMode()) { + addDisposable(widgetModel.isPictureMode().firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(this::updateUI, UxErrorHandle.logErrorConsumer(TAG, "Update UI "))); + } + } + //endregion + + //region customization + + @NonNull + public ComponentIndexType getCameraIndex() { + return widgetModel.getCameraIndex(); + } + + @NonNull + @Override + public CameraLensType getLensType() { + return widgetModel.getLensType(); + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + widgetModel.updateCameraSource(cameraIndex, lensType); + } + + /** + * Get photo mode icon + * + * @return Drawable + */ + @Nullable + public Drawable getPhotoModeIcon() { + return photoModeDrawable; + } + + /** + * Set photo mode drawable resource + * + * @param resourceId resource id of photo mode icon + */ + public void setPhotoModeIcon(@DrawableRes int resourceId) { + setPhotoModeIcon(getResources().getDrawable(resourceId)); + } + + /** + * Set photo mode drawable + * + * @param drawable Drawable to be used as photo mode icon + */ + public void setPhotoModeIcon(@Nullable Drawable drawable) { + photoModeDrawable = drawable; + checkAndUpdateUI(); + } + + /** + * Get video mode icon + * + * @return Drawable + */ + @Nullable + public Drawable getVideoModeIcon() { + return videoModeDrawable; + } + + /** + * Set video mode drawable resource + * + * @param resourceId resource id of video mode icon + */ + public void setVideoModeIcon(@DrawableRes int resourceId) { + setVideoModeIcon(getResources().getDrawable(resourceId)); + } + + /** + * Set video mode drawable + * + * @param drawable Drawable to be used as video mode icon + */ + public void setVideoModeIcon(@Nullable Drawable drawable) { + videoModeDrawable = drawable; + checkAndUpdateUI(); + } + + /** + * Get current background of icon + * + * @return Drawable + */ + @Nullable + public Drawable getIconBackground() { + return foregroundImageView.getBackground(); + } + + /** + * Set background to icon + * + * @param resourceId resource id of background + */ + public void setIconBackground(@DrawableRes int resourceId) { + foregroundImageView.setBackgroundResource(resourceId); + } + + /** + * Set background to icon + * + * @param drawable Drawable to be used as background + */ + public void setIconBackground(@Nullable Drawable drawable) { + foregroundImageView.setBackground(drawable); + } + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/photovideoswitch/PhotoVideoSwitchWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/photovideoswitch/PhotoVideoSwitchWidgetModel.java new file mode 100644 index 00000000..0984760d --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/cameracontrols/photovideoswitch/PhotoVideoSwitchWidgetModel.java @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.cameracontrols.photovideoswitch; + +import androidx.annotation.NonNull; +import dji.sdk.keyvalue.key.CameraKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.value.camera.CameraMode; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.module.FlatCameraModule; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; + +/** + * Photo Video Switch Widget Model + *

+ * Widget Model for the {@link PhotoVideoSwitchWidget} used to define the + * underlying logic and communication + */ +public class PhotoVideoSwitchWidgetModel extends WidgetModel implements ICameraIndex { + + //region Fields + private final DataProcessor isCameraConnectedDataProcessor; + private final DataProcessor isRecordingDataProcessor; + private final DataProcessor isShootingDataProcessor; + private final DataProcessor isShootingIntervalDataProcessor; + private final DataProcessor isShootingBurstDataProcessor; + private final DataProcessor isShootingRawBurstDataProcessor; + private final DataProcessor isShootingPanoramaDataProcessor; + private final DataProcessor isEnabledDataProcessor; + private ComponentIndexType cameraIndex = ComponentIndexType.LEFT_OR_MAIN; + private CameraLensType lensType = CameraLensType.UNKNOWN; + private final FlatCameraModule flatCameraModule; + //endregion + + //region Lifecycle + public PhotoVideoSwitchWidgetModel(@NonNull DJISDKModel djiSdkModel, + @NonNull ObservableInMemoryKeyedStore keyedStore) { + super(djiSdkModel, keyedStore); + isCameraConnectedDataProcessor = DataProcessor.create(false); + isRecordingDataProcessor = DataProcessor.create(false); + isShootingDataProcessor = DataProcessor.create(false); + isShootingIntervalDataProcessor = DataProcessor.create(false); + isShootingBurstDataProcessor = DataProcessor.create(false); + isShootingRawBurstDataProcessor = DataProcessor.create(false); + isShootingPanoramaDataProcessor = DataProcessor.create(false); + isEnabledDataProcessor = DataProcessor.create(false); + flatCameraModule = new FlatCameraModule(); + addModule(flatCameraModule); + } + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createKey(CameraKey.KeyConnection, cameraIndex), isCameraConnectedDataProcessor); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyIsRecording, cameraIndex), isRecordingDataProcessor); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyIsShootingPhoto, cameraIndex), isShootingDataProcessor); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyCameraShootingContinuousPhotos, cameraIndex), isShootingIntervalDataProcessor); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyIsShootingBurstPhoto, cameraIndex), isShootingBurstDataProcessor); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyIsShootingRAWBurstPhoto, cameraIndex), isShootingRawBurstDataProcessor); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyIsShootingPhotoPanorama, cameraIndex), isShootingPanoramaDataProcessor); + } + + @Override + protected void inCleanup() { + // do nothing + } + + @Override + protected void updateStates() { + boolean isEnabled = productConnectionProcessor.getValue() + && isCameraConnectedDataProcessor.getValue() + && !isRecordingDataProcessor.getValue() + && !isShootingDataProcessor.getValue() + && !isShootingBurstDataProcessor.getValue() + && !isShootingIntervalDataProcessor.getValue() + && !isShootingRawBurstDataProcessor.getValue() + && !isShootingPanoramaDataProcessor.getValue(); + + isEnabledDataProcessor.onNext(isEnabled); + } + //endregion + + //region Data + + /** + * Check if the widget should be enabled. + * + * @return Flowable with boolean value + */ + public Flowable isEnabled() { + return isEnabledDataProcessor.toFlowable(); + } + + /** + * Get whether the current camera mode is picture mode. + * + * @return Flowable with boolean value + */ + public Flowable isPictureMode() { + return flatCameraModule.getCameraModeDataProcessor().toFlowable().map(cameraMode -> + cameraMode == CameraMode.PHOTO_NORMAL + ); + } + + /** + * Toggle between photo mode and video mode + * + * @return Completable + */ + public Completable toggleCameraMode() { + if (flatCameraModule.getCameraModeDataProcessor().getValue() == CameraMode.PHOTO_NORMAL) { + return flatCameraModule.setCameraMode(djiSdkModel, CameraMode.VIDEO_NORMAL); + } else { + return flatCameraModule.setCameraMode(djiSdkModel, CameraMode.PHOTO_NORMAL); + } + } + + public void changeToPhotoMode() { + CameraMode currentMode = flatCameraModule.getCameraModeDataProcessor().getValue(); + if (currentMode.isPhotoMode() || isSupportChangeMode()){ + return; + } + flatCameraModule.setCameraMode(djiSdkModel, CameraMode.PHOTO_NORMAL).subscribe(); + } + + public void changeToVideoMode() { + CameraMode currentMode = flatCameraModule.getCameraModeDataProcessor().getValue(); + if (currentMode.isVideoMode()){ + return; + } + flatCameraModule.setCameraMode(djiSdkModel, CameraMode.VIDEO_NORMAL).subscribe(); + } + + @NonNull + public ComponentIndexType getCameraIndex() { + return cameraIndex; + } + + + @NonNull + @Override + public CameraLensType getLensType() { + return lensType; + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + this.cameraIndex = cameraIndex; + this.lensType = lensType; + flatCameraModule.updateCameraSource(cameraIndex, lensType); + restart(); + } + + private boolean isSupportChangeMode() { + CameraMode currentMode = flatCameraModule.getCameraModeDataProcessor().getValue(); + return currentMode.isVideoMode() && isRecordingDataProcessor.getValue(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/focusexposureswitch/FocusExposureSwitchWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/focusexposureswitch/FocusExposureSwitchWidget.java new file mode 100644 index 00000000..6a145088 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/focusexposureswitch/FocusExposureSwitchWidget.java @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.focusexposureswitch; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.ImageView; + +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.ux.R; +import dji.v5.ux.cameracore.widget.fpvinteraction.FPVInteractionWidget; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.SchedulerProvider; +import dji.v5.ux.core.base.widget.FrameLayoutWidget; +import dji.v5.ux.core.communication.GlobalPreferencesManager; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.UxErrorHandle; +import dji.v5.ux.core.util.SettingDefinitions.ControlMode; + +/** + * Focus Exposure Switch Widget + *

+ * This widget can be used to switch the {@link ControlMode} between focus and exposure + * When in focus mode the {@link FPVInteractionWidget} will help change the focus point + * When in exposure mode the {@link FPVInteractionWidget} will help change exposure/metering + */ +public class FocusExposureSwitchWidget extends FrameLayoutWidget implements OnClickListener, ICameraIndex { + + //region Fields + private static final String TAG = "FocusExpoSwitchWidget"; + private ImageView focusExposureSwitchImageView; + private FocusExposureSwitchWidgetModel widgetModel; + private Drawable manualFocusDrawable; + private Drawable autoFocusDrawable; + private Drawable spotMeterDrawable; + //endregion + + //region Lifecycle + public FocusExposureSwitchWidget(@NonNull Context context) { + super(context); + } + + public FocusExposureSwitchWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public FocusExposureSwitchWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_widget_focus_exposure_switch, this); + focusExposureSwitchImageView = findViewById(R.id.focus_exposure_switch_image_view); + if (getBackground() == null) { + setBackgroundResource(R.drawable.uxsdk_background_black_rectangle); + } + if (!isInEditMode()) { + widgetModel = new FocusExposureSwitchWidgetModel(DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + GlobalPreferencesManager.getInstance()); + } + + initDefaults(); + if (attrs != null) { + initAttributes(context, attrs); + } + setOnClickListener(this); + } + + private void initDefaults() { + manualFocusDrawable = getResources().getDrawable(R.drawable.uxsdk_ic_focus_switch_manual); + autoFocusDrawable = getResources().getDrawable(R.drawable.uxsdk_ic_focus_switch_auto); + spotMeterDrawable = getResources().getDrawable(R.drawable.uxsdk_ic_metering_switch); + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.isFocusModeChangeSupported() + .observeOn(SchedulerProvider.ui()) + .subscribe(this::updateVisibility)); + addReaction(widgetModel.getControlMode() + .observeOn(SchedulerProvider.ui()) + .subscribe(this::updateUI)); + } + + @Override + public void onClick(View v) { + int id = v.getId(); + if (id == this.getId()) { + addDisposable(widgetModel.switchControlMode() + .observeOn(SchedulerProvider.ui()) + .subscribe(() -> { + //do nothing + }, UxErrorHandle.logErrorConsumer(TAG, "switchControlMode: "))); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + if (!isInEditMode()) { + widgetModel.cleanup(); + } + super.onDetachedFromWindow(); + } + //endregion + + //region private methods + private void updateVisibility(boolean isFocusModeChangeSupported) { + if (isFocusModeChangeSupported) { + setVisibility(VISIBLE); + } else { + setVisibility(GONE); + } + } + + private void updateUI(ControlMode controlMode) { + if (controlMode == ControlMode.SPOT_METER || controlMode == ControlMode.CENTER_METER) { + focusExposureSwitchImageView.setImageDrawable(spotMeterDrawable); + } else if (controlMode == ControlMode.MANUAL_FOCUS) { + focusExposureSwitchImageView.setImageDrawable(manualFocusDrawable); + } else { + focusExposureSwitchImageView.setImageDrawable(autoFocusDrawable); + } + } + + private void checkAndUpdateUI() { + if (!isInEditMode()) { + addDisposable(widgetModel.getControlMode().firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(this::updateUI, UxErrorHandle.logErrorConsumer(TAG, "Update UI "))); + } + } + + private void initAttributes(Context context, AttributeSet attrs) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FocusExposureSwitchWidget); + if (!isInEditMode()) { + updateCameraSource(ComponentIndexType.find(typedArray.getInt(R.styleable.FocusExposureSwitchWidget_uxsdk_cameraIndex, 0)), + CameraLensType.find(typedArray.getInt(R.styleable.FocusExposureSwitchWidget_uxsdk_lensType, 0))); + } + if (typedArray.getDrawable(R.styleable.FocusExposureSwitchWidget_uxsdk_meteringDrawable) != null) { + spotMeterDrawable = typedArray.getDrawable(R.styleable.FocusExposureSwitchWidget_uxsdk_meteringDrawable); + } + if (typedArray.getDrawable(R.styleable.FocusExposureSwitchWidget_uxsdk_manualFocusDrawable) != null) { + manualFocusDrawable = typedArray.getDrawable(R.styleable.FocusExposureSwitchWidget_uxsdk_manualFocusDrawable); + } + if (typedArray.getDrawable(R.styleable.FocusExposureSwitchWidget_uxsdk_autoFocusDrawable) != null) { + autoFocusDrawable = typedArray.getDrawable(R.styleable.FocusExposureSwitchWidget_uxsdk_autoFocusDrawable); + } + setIconBackground(typedArray.getDrawable(R.styleable.FocusExposureSwitchWidget_uxsdk_iconBackground)); + + typedArray.recycle(); + } + //endregion + + //region customization methods + @NonNull + @Override + public String getIdealDimensionRatioString() { + return getResources().getString(R.string.uxsdk_widget_default_ratio); + } + + @NonNull + public ComponentIndexType getCameraIndex() { + return widgetModel.getCameraIndex(); + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + widgetModel.updateCameraSource(cameraIndex, lensType); + } + + @NonNull + public CameraLensType getLensType() { + return widgetModel.getLensType(); + } + + /** + * Get current manual focus icon + * + * @return Drawable + */ + @Nullable + public Drawable getManualFocusIcon() { + return manualFocusDrawable; + } + + /** + * Set manual focus icon + * + * @param resourceId to be used + */ + public void setManualFocusIcon(@DrawableRes int resourceId) { + setManualFocusIcon(getResources().getDrawable(resourceId)); + } + + /** + * Set manual focus icon + * + * @param drawable to be used + */ + public void setManualFocusIcon(@Nullable Drawable drawable) { + manualFocusDrawable = drawable; + checkAndUpdateUI(); + } + + /** + * Get current auto focus icon + * + * @return drawable + */ + @Nullable + public Drawable getAutoFocusIcon() { + return autoFocusDrawable; + } + + /** + * Set auto focus icon + * + * @param resourceId to be used + */ + public void setAutoFocusIcon(@DrawableRes int resourceId) { + setAutoFocusIcon(getResources().getDrawable(resourceId)); + } + + /** + * Set auto focus icon + * + * @param drawable to be used + */ + public void setAutoFocusIcon(@Nullable Drawable drawable) { + autoFocusDrawable = drawable; + checkAndUpdateUI(); + } + + /** + * Get current metering/exposure mode icon + * + * @return Drawable + */ + @Nullable + public Drawable getMeteringIcon() { + return spotMeterDrawable; + } + + /** + * Set metering/exposure mode icon + * + * @param resourceId to be used + */ + public void setMeteringIcon(@DrawableRes int resourceId) { + setMeteringIcon(getResources().getDrawable(resourceId)); + } + + /** + * Set metering/exposure mode icon + * + * @param drawable to be used + */ + public void setMeteringIcon(@Nullable Drawable drawable) { + spotMeterDrawable = drawable; + checkAndUpdateUI(); + } + + /** + * Get current icon background + * + * @return Drawable + */ + @Nullable + public Drawable getIconBackground() { + return focusExposureSwitchImageView.getBackground(); + } + + /** + * Set icon background + * + * @param resourceId to be used + */ + public void setIconBackground(@DrawableRes int resourceId) { + focusExposureSwitchImageView.setBackgroundResource(resourceId); + } + + /** + * Set icon background + * + * @param drawable to be used + */ + public void setIconBackground(@Nullable Drawable drawable) { + focusExposureSwitchImageView.setBackground(drawable); + } + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/focusexposureswitch/FocusExposureSwitchWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/focusexposureswitch/FocusExposureSwitchWidgetModel.java new file mode 100644 index 00000000..85af1c20 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/focusexposureswitch/FocusExposureSwitchWidgetModel.java @@ -0,0 +1,229 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.focusexposureswitch; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.sdk.keyvalue.key.CameraKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.value.camera.CameraFocusMode; +import dji.sdk.keyvalue.value.camera.CameraMeteringMode; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.GlobalPreferenceKeys; +import dji.v5.ux.core.communication.GlobalPreferencesInterface; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.communication.UXKey; +import dji.v5.ux.core.communication.UXKeys; +import dji.v5.ux.core.util.DataProcessor; +import dji.v5.ux.core.util.UxErrorHandle; +import dji.v5.ux.core.util.SettingDefinitions.ControlMode; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; + +/** + * Focus Exposure Switch Widget Model + *

+ * Widget Model for the {@link FocusExposureSwitchWidget} used to define the + * underlying logic and communication + */ +public class FocusExposureSwitchWidgetModel extends WidgetModel implements ICameraIndex { + + //region Fields + private final DataProcessor isFocusModeSupportedDataProcessor; + private final DataProcessor focusModeDataProcessor; + private final DataProcessor meteringModeDataProcessor; + private final DataProcessor controlModeDataProcessor; + private final GlobalPreferencesInterface preferencesManager; + private UXKey controlModeKey; + private ComponentIndexType cameraIndex = ComponentIndexType.LEFT_OR_MAIN; + private CameraLensType lensType = CameraLensType.CAMERA_LENS_ZOOM; + //endregion + + //region Lifecycle + public FocusExposureSwitchWidgetModel(@NonNull DJISDKModel djiSdkModel, + @NonNull ObservableInMemoryKeyedStore keyedStore, + @Nullable GlobalPreferencesInterface preferencesManager) { + super(djiSdkModel, keyedStore); + focusModeDataProcessor = DataProcessor.create(CameraFocusMode.UNKNOWN); + meteringModeDataProcessor = DataProcessor.create(CameraMeteringMode.UNKNOWN); + controlModeDataProcessor = DataProcessor.create(ControlMode.SPOT_METER); + isFocusModeSupportedDataProcessor = DataProcessor.create(false); + if (preferencesManager != null) { + controlModeDataProcessor.onNext(preferencesManager.getControlMode()); + } + this.preferencesManager = preferencesManager; + } + + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createCameraKey(CameraKey.KeyCameraFocusMode, cameraIndex, lensType), focusModeDataProcessor); + bindDataProcessor(KeyTools.createCameraKey(CameraKey.KeyCameraMeteringMode, cameraIndex, lensType), meteringModeDataProcessor); + + controlModeKey = UXKeys.create(GlobalPreferenceKeys.CONTROL_MODE); + bindDataProcessor(controlModeKey, controlModeDataProcessor); + + if (preferencesManager != null) { + preferencesManager.setUpListener(); + } + } + + @Override + protected void inCleanup() { + if (preferencesManager != null) { + preferencesManager.cleanup(); + } + } + + @Override + protected void updateStates() { + updateFocusMode(); + } + + @Override + protected void onProductConnectionChanged(boolean isConnected) { +// super.onProductConnectionChanged(isConnected); +// if (isConnected) { +// isFocusModeSupportedDataProcessor.onNext(djiSdkModel.isKeySupported(KeyTools.createCameraKey(CameraKey.KeyCameraFocusMode,cameraIndex, lensType))); +// } else { +// isFocusModeSupportedDataProcessor.onNext(false); +// } + } + //endregion + + //region Data + + /** + * Check if focus mode change is supported + * + * @return Flowable with boolean true - supported false - not supported + */ + public Flowable isFocusModeChangeSupported() { + return isFocusModeSupportedDataProcessor.toFlowable(); + } + + + /** + * Get control mode + * + * @return Flowable with instance of {@link ControlMode} + */ + public Flowable getControlMode() { + return controlModeDataProcessor.toFlowable(); + } + + @Override + @NonNull + public ComponentIndexType getCameraIndex() { + return cameraIndex; + } + + @Override + @NonNull + public CameraLensType getLensType() { + return lensType; + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + this.cameraIndex = cameraIndex; + this.lensType = lensType; + restart(); + } + + /** + * Switch between exposure/metering mode and focus mode + * + * @return Completable representing the success/failure of the set action. + */ + public Completable switchControlMode() { + ControlMode currentControlMode = controlModeDataProcessor.getValue(); + if (currentControlMode == ControlMode.SPOT_METER || currentControlMode == ControlMode.CENTER_METER) { + return setFocusMode(); + } else { + return setMeteringMode(); + } + } + //endregion + + // region private methods + private void updateFocusMode() { + ControlMode currentControlMode = controlModeDataProcessor.getValue(); + if (currentControlMode != ControlMode.SPOT_METER && currentControlMode != ControlMode.CENTER_METER) { + setFocusMode(); + } + } + + private Completable setMeteringMode() { + if (djiSdkModel.getCacheValue(KeyTools.createCameraKey(CameraKey.KeyCameraMeteringMode, cameraIndex, lensType)) == CameraMeteringMode.REGION) { + return Completable.fromAction(() -> { + preferencesManager.setControlMode(ControlMode.SPOT_METER); + addDisposable(uxKeyManager.setValue(controlModeKey, ControlMode.SPOT_METER) + .subscribe(() -> { + //do nothing + }, UxErrorHandle.logErrorConsumer(tag, "setMeteringMode: "))); + }); + } + return djiSdkModel.setValue(KeyTools.createCameraKey(CameraKey.KeyCameraMeteringMode, cameraIndex, lensType), CameraMeteringMode.REGION) + .doOnComplete( + () -> { + preferencesManager.setControlMode(ControlMode.SPOT_METER); + addDisposable(uxKeyManager.setValue(controlModeKey, ControlMode.SPOT_METER) + .subscribe(() -> { + //do nothing + }, UxErrorHandle.logErrorConsumer(tag, "setMeteringMode: "))); + }).doOnError( + error -> { + // 对焦模式为MF时 + 测光模式为REGION时,继续设置测光模式为REGION会返回失败(已反馈固件) + setFocusMode(); + } + ); + } + + private Completable setFocusMode() { + if (controlModeKey == null || preferencesManager == null) { + return Completable.complete(); + } + LogUtils.d(tag, "In setFocusMode ControlModeKey Value Type " + controlModeKey.getValueType()); + if (focusModeDataProcessor.getValue() == CameraFocusMode.MANUAL) { + preferencesManager.setControlMode(ControlMode.MANUAL_FOCUS); + return uxKeyManager.setValue(controlModeKey, ControlMode.MANUAL_FOCUS); + } else if (focusModeDataProcessor.getValue() == CameraFocusMode.AFC) { + preferencesManager.setControlMode(ControlMode.AUTO_FOCUS_CONTINUE); + return uxKeyManager.setValue(controlModeKey, ControlMode.AUTO_FOCUS_CONTINUE); + } else { + preferencesManager.setControlMode(ControlMode.AUTO_FOCUS); + return uxKeyManager.setValue(controlModeKey, ControlMode.AUTO_FOCUS); + } + } + //endregion + + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/focusmode/FocusModeWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/focusmode/FocusModeWidget.java new file mode 100644 index 00000000..7baf5801 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/focusmode/FocusModeWidget.java @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.focusmode; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.text.SpannableString; +import android.text.SpannableStringBuilder; +import android.text.style.ForegroundColorSpan; +import android.util.AttributeSet; +import android.util.Pair; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.TextView; + +import androidx.annotation.ColorInt; +import androidx.annotation.Dimension; +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import dji.sdk.keyvalue.value.camera.CameraFocusMode; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.utils.common.DisplayUtil; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.SchedulerProvider; +import dji.v5.ux.core.base.widget.FrameLayoutWidget; +import dji.v5.ux.core.communication.GlobalPreferencesManager; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.UxErrorHandle; +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.disposables.Disposable; + +/** + * Widget will display the current focus mode of aircraft camera. + * - MF text highlighted (in green) indicates focus mode is Manual Focus. + * - AF text highlighted (in green) indicates focus mode is Auto Focus. + * - AFC text highlighted (in green) indicates focus mode is Auto Focus Continuous. + *

+ * Interaction: + * Tapping will toggle between AF and MF mode. + */ +public class FocusModeWidget extends FrameLayoutWidget implements OnClickListener, ICameraIndex { + + //region constants + private static final String TAG = "FocusModeWidget"; + //endregion + + //region Fields + private FocusModeWidgetModel widgetModel; + private TextView titleTextView; + private int activeColor; + private int inactiveColor; + //endregion + + //region Lifecycle + public FocusModeWidget(Context context) { + super(context); + } + + public FocusModeWidget(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public FocusModeWidget(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_widget_focus_mode_switch, this); + if (getBackground() == null) { + setBackgroundResource(R.drawable.uxsdk_background_black_rectangle); + } + titleTextView = findViewById(R.id.text_view_camera_control_af); + if (!isInEditMode()) { + widgetModel = new FocusModeWidgetModel(DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + GlobalPreferencesManager.getInstance()); + } + setOnClickListener(this); + activeColor = getResources().getColor(R.color.uxsdk_green); + inactiveColor = getResources().getColor(R.color.uxsdk_white); + if (attrs != null) { + initAttributes(context, attrs); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + if (!isInEditMode()) { + widgetModel.cleanup(); + } + super.onDetachedFromWindow(); + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.isFocusModeChangeSupported() + .observeOn(SchedulerProvider.ui()) + .subscribe(this::updateVisibility)); + addReaction(reactToFocusModeChange()); + } + + + @NonNull + @Override + public String getIdealDimensionRatioString() { + return getResources().getString(R.string.uxsdk_widget_default_ratio); + } + + @SuppressLint("CheckResult") + @Override + public void onClick(View v) { + addReaction(widgetModel.toggleFocusMode() + .observeOn(SchedulerProvider.ui()) + .subscribe(() -> { + }, UxErrorHandle.logErrorConsumer(TAG, "switch focus mode: "))); + } + + //endregion + + //region private helpers + + private void checkAndUpdateUI() { + if (!isInEditMode()) { + addDisposable(Flowable.combineLatest(widgetModel.isAFCEnabled(), widgetModel.getFocusMode(), Pair::new) + .firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(values -> updateUI(values.first, values.second), + UxErrorHandle.logErrorConsumer(TAG, "check and update focus mode: "))); + } + } + + private Disposable reactToFocusModeChange() { + return Flowable.combineLatest(widgetModel.isAFCEnabled(), widgetModel.getFocusMode(), Pair::new) + .observeOn(SchedulerProvider.ui()) + .subscribe(values -> updateUI(values.first, values.second), + UxErrorHandle.logErrorConsumer(TAG, "react to Focus Mode Change: ")); + } + + private void updateVisibility(boolean isFocusModeChangeSupported) { + if (isFocusModeChangeSupported) { + setVisibility(VISIBLE); + } else { + setVisibility(GONE); + } + } + + private void updateUI(boolean isAFCEnabled, CameraFocusMode focusMode) { + int autoFocusTextColor; + int manualFocusTextColor; + if (focusMode == CameraFocusMode.MANUAL) { + manualFocusTextColor = activeColor; + autoFocusTextColor = inactiveColor; + } else { + autoFocusTextColor = activeColor; + manualFocusTextColor = inactiveColor; + } + + String autoFocusText; + if (isAFCEnabled) { + autoFocusText = getResources().getString(R.string.uxsdk_widget_focus_mode_afc); + } else { + autoFocusText = getResources().getString(R.string.uxsdk_widget_focus_mode_auto); + + } + + makeSpannableString(autoFocusText, autoFocusTextColor, manualFocusTextColor); + } + + private void makeSpannableString(String autoFocusText, int autoFocusColor, int manualFocusColor) { + SpannableStringBuilder builder = new SpannableStringBuilder(); + + SpannableString str1 = new SpannableString(autoFocusText); + str1.setSpan(new ForegroundColorSpan(autoFocusColor), 0, str1.length(), 0); + builder.append(str1); + + SpannableString str2 = new SpannableString(getResources().getString(R.string.uxsdk_widget_focus_mode_separator)); + str2.setSpan(new ForegroundColorSpan(inactiveColor), 0, str2.length(), 0); + builder.append(str2); + + SpannableString str3 = new SpannableString(getResources().getString(R.string.uxsdk_widget_focus_mode_manual)); + str3.setSpan(new ForegroundColorSpan(manualFocusColor), 0, str3.length(), 0); + builder.append(str3); + titleTextView.setText(builder, TextView.BufferType.SPANNABLE); + } + + private void initAttributes(Context context, AttributeSet attrs) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FocusModeWidget); + if (!isInEditMode()) { + updateCameraSource(ComponentIndexType.find(typedArray.getInt(R.styleable.FocusModeWidget_uxsdk_cameraIndex, 0)), + CameraLensType.find(typedArray.getInt(R.styleable.FocusModeWidget_uxsdk_lensType, 0))); + } + activeColor = typedArray.getColor(R.styleable.FocusModeWidget_uxsdk_activeModeTextColor, getResources().getColor(R.color.uxsdk_green)); + inactiveColor = typedArray.getColor(R.styleable.FocusModeWidget_uxsdk_inactiveModeTextColor, getResources().getColor(R.color.uxsdk_white)); + Drawable background = typedArray.getDrawable(R.styleable.FocusModeWidget_uxsdk_widgetTitleBackground); + setTitleBackground(background); + float textSize = + typedArray.getDimension(R.styleable.FocusModeWidget_uxsdk_widgetTitleTextSize, INVALID_RESOURCE); + if (textSize != INVALID_RESOURCE) { + setTitleTextSize(DisplayUtil.pxToSp(context, textSize)); + } + typedArray.recycle(); + } + //endregion + + //region customizations + + /** + * Get the index of the camera to which the widget is reacting + * + * @return {@link ComponentIndexType} + */ + @NonNull + public ComponentIndexType getCameraIndex() { + return widgetModel.getCameraIndex(); + } + + /** + * Get the current type of the lens the widget is reacting to + * + * @return current lens type + */ + @NonNull + public CameraLensType getLensType() { + return widgetModel.getLensType(); + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + widgetModel.updateCameraSource(cameraIndex, lensType); + } + + /** + * Get active mode text color + * + * @return color integer + */ + @ColorInt + public int getActiveModeTextColor() { + return activeColor; + } + + /** + * Set active mode text color + * + * @param color color integer + */ + public void setActiveModeTextColor(@ColorInt int color) { + activeColor = color; + checkAndUpdateUI(); + } + + /** + * Get in-active mode text color + * + * @return color integer + */ + @ColorInt + public int getInactiveModeTextColor() { + return inactiveColor; + } + + /** + * Set in-active mode text color + * + * @param color color integer + */ + public void setInactiveModeTextColor(@ColorInt int color) { + inactiveColor = color; + checkAndUpdateUI(); + } + + /** + * Get current background of title text + * + * @return Drawable resource of the background + */ + @Nullable + public Drawable getTitleBackground() { + return titleTextView.getBackground(); + } + + /** + * Set background to title text + * + * @param resourceId resource id of background + */ + public void setTitleBackground(@DrawableRes int resourceId) { + setTitleBackground(getResources().getDrawable(resourceId)); + } + + /** + * Set background to title text + * + * @param drawable Drawable to be used as background + */ + public void setTitleBackground(@Nullable Drawable drawable) { + titleTextView.setBackground(drawable); + } + + /** + * Get current text size + * + * @return text size of the title + */ + @Dimension + public float getTitleTextSize() { + return titleTextView.getTextSize(); + } + + /** + * Sets the text size of the widget text + * + * @param textSize text size float value + */ + public void setTitleTextSize(@Dimension float textSize) { + titleTextView.setTextSize(textSize); + } + + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/focusmode/FocusModeWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/focusmode/FocusModeWidgetModel.java new file mode 100644 index 00000000..19512a7e --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/focusmode/FocusModeWidgetModel.java @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.focusmode; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import dji.sdk.keyvalue.key.CameraKey; +import dji.sdk.keyvalue.key.DJIKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.value.camera.CameraFocusMode; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.GlobalPreferenceKeys; +import dji.v5.ux.core.communication.GlobalPreferencesInterface; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.communication.UXKey; +import dji.v5.ux.core.communication.UXKeys; +import dji.v5.ux.core.util.DataProcessor; +import dji.v5.ux.core.util.UxErrorHandle; +import dji.v5.ux.core.util.SettingDefinitions; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; + +/** + * Focus Mode Widget Model + *

+ * Widget Model for the {@link FocusModeWidget} used to define the + * underlying logic and communication + */ +public class FocusModeWidgetModel extends WidgetModel implements ICameraIndex { + + //region Fields + private final DataProcessor isFocusModeSupportedDataProcessor; + private final DataProcessor focusModeDataProcessor; + private final DataProcessor isAFCSupportedProcessor; + private final DataProcessor isAFCEnabledKeyProcessor; + private final DataProcessor isAFCEnabledProcessor; + private final DataProcessor controlModeProcessor; + private final ObservableInMemoryKeyedStore keyedStore; + private final GlobalPreferencesInterface preferencesManager; + private DJIKey focusModeKey; + private UXKey controlModeKey; + private ComponentIndexType cameraIndex = ComponentIndexType.LEFT_OR_MAIN; + private CameraLensType lensType = CameraLensType.CAMERA_LENS_ZOOM; + //endregion + + //region Lifecycle + public FocusModeWidgetModel(@NonNull DJISDKModel djiSdkModel, + @NonNull ObservableInMemoryKeyedStore keyedStore, + @Nullable GlobalPreferencesInterface preferencesManager) { + super(djiSdkModel, keyedStore); + focusModeDataProcessor = DataProcessor.create(CameraFocusMode.UNKNOWN); + isAFCSupportedProcessor = DataProcessor.create(false); + isAFCEnabledKeyProcessor = DataProcessor.create(false); + isAFCEnabledProcessor = DataProcessor.create(false); + isFocusModeSupportedDataProcessor = DataProcessor.create(false); + controlModeProcessor = DataProcessor.create(SettingDefinitions.ControlMode.SPOT_METER); + if (preferencesManager != null) { + isAFCEnabledKeyProcessor.onNext(preferencesManager.getAFCEnabled()); + updateAFCEnabledProcessor(); + controlModeProcessor.onNext(preferencesManager.getControlMode()); + } + this.preferencesManager = preferencesManager; + this.keyedStore = keyedStore; + } + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createCameraKey(CameraKey.KeyCameraFocusMode,cameraIndex, lensType), focusModeDataProcessor); + bindDataProcessor(KeyTools.createCameraKey(CameraKey.KeyIsAFCSupported,cameraIndex, lensType), isAFCSupportedProcessor); + UXKey afcEnabledKey = UXKeys.create(GlobalPreferenceKeys.AFC_ENABLED); + bindDataProcessor(afcEnabledKey, isAFCEnabledKeyProcessor); + + controlModeKey = UXKeys.create(GlobalPreferenceKeys.CONTROL_MODE); + bindDataProcessor(controlModeKey, controlModeProcessor); + + focusModeKey = KeyTools.createCameraKey(CameraKey.KeyCameraFocusMode,cameraIndex,lensType); + if (preferencesManager != null) { + preferencesManager.setUpListener(); + } + } + + @Override + protected void inCleanup() { + if (preferencesManager != null) { + preferencesManager.cleanup(); + } + } + + @Override + protected void updateStates() { + updateAFCEnabledProcessor(); + } + + private void updateAFCEnabledProcessor() { + isAFCEnabledProcessor.onNext(isAFCEnabledKeyProcessor.getValue() && isAFCSupportedProcessor.getValue()); + } + + @Override + protected void onProductConnectionChanged(boolean isConnected) { +// super.onProductConnectionChanged(isConnected); +// if (isConnected) { +// isFocusModeSupportedDataProcessor.onNext(djiSdkModel.isKeySupported(focusModeKey)); +// } else { +// isFocusModeSupportedDataProcessor.onNext(false); +// } + } + + //endregion + + //region Actions + + @NonNull + public ComponentIndexType getCameraIndex() { + return cameraIndex; + } + + @NonNull + public CameraLensType getLensType() { + return lensType; + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + this.cameraIndex = cameraIndex; + this.lensType = lensType; + restart(); + } + + /** + * Switch between focus modes + * + * @return Completable representing the success/failure of set action + */ + public Completable toggleFocusMode() { + final CameraFocusMode currentFocusMode = focusModeDataProcessor.getValue(); + final CameraFocusMode nextFocusMode = getNextFocusMode(currentFocusMode); + + return djiSdkModel.setValue(focusModeKey, nextFocusMode) + .doOnComplete(() -> onFocusModeUpdate(nextFocusMode)) + .doOnError(error -> focusModeDataProcessor.onNext(currentFocusMode)); + } + + private CameraFocusMode getNextFocusMode(CameraFocusMode currentFocusMode) { + CameraFocusMode nextFocusMode; + if (currentFocusMode == CameraFocusMode.MANUAL) { + if (isAFCEnabledProcessor.getValue()) { + nextFocusMode = CameraFocusMode.AFC; + } else { + nextFocusMode = CameraFocusMode.AF; + } + } else { + nextFocusMode = CameraFocusMode.MANUAL; + } + return nextFocusMode; + } + //endregion + + //region Data + + /** + * Get the current {@link CameraFocusMode} + * + * @return Flowable with instance of FocusMode + */ + public Flowable getFocusMode() { + return focusModeDataProcessor.toFlowable(); + } + + /** + * Check if Auto Focus Continuous(AFC) is enabled + * + * @return Flowable with boolean true - AFC enabled false - AFC not enabled + */ + public Flowable isAFCEnabled() { + return isAFCEnabledProcessor.toFlowable(); + } + + /** + * Check if focus mode change is supported + * + * @return Flowable with boolean true - supported false - not supported + */ + public Flowable isFocusModeChangeSupported() { + return isFocusModeSupportedDataProcessor.toFlowable(); + } + //endregion + + //region Helpers + private void onFocusModeUpdate(CameraFocusMode focusMode) { + if (controlModeProcessor.getValue() == SettingDefinitions.ControlMode.SPOT_METER || + controlModeProcessor.getValue() == SettingDefinitions.ControlMode.CENTER_METER) { + return; + } + + switch (focusMode) { + case AF: + preferencesManager.setControlMode(SettingDefinitions.ControlMode.AUTO_FOCUS); + addDisposable(keyedStore.setValue(controlModeKey, SettingDefinitions.ControlMode.AUTO_FOCUS) + .subscribe(() -> { + //do nothing + }, UxErrorHandle.logErrorConsumer(tag, "setControlModeAutoFocus: "))); + break; + case AFC: + preferencesManager.setControlMode(SettingDefinitions.ControlMode.AUTO_FOCUS_CONTINUE); + addDisposable(keyedStore.setValue(controlModeKey, SettingDefinitions.ControlMode.AUTO_FOCUS_CONTINUE) + .subscribe(() -> { + //do nothing + }, UxErrorHandle.logErrorConsumer(tag, "setControlModeAutoFocusContinuous: "))); + break; + case MANUAL: + preferencesManager.setControlMode(SettingDefinitions.ControlMode.MANUAL_FOCUS); + addDisposable(keyedStore.setValue(controlModeKey, SettingDefinitions.ControlMode.MANUAL_FOCUS) + .subscribe(() -> { + //do nothing + }, UxErrorHandle.logErrorConsumer(tag, "setControlModeManualFocus: "))); + break; + default: + break; + } + } + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/fpvinteraction/ExposureMeteringWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/fpvinteraction/ExposureMeteringWidget.java new file mode 100644 index 00000000..15647886 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/fpvinteraction/ExposureMeteringWidget.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.fpvinteraction; + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.List; + +import dji.sdk.keyvalue.value.camera.CameraExposureCompensation; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.SchedulerProvider; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.ui.VerticalSeekBar; +import dji.v5.ux.core.ui.exposure.ExposeVSeekBar; +import dji.v5.ux.core.util.SettingDefinitions.ControlMode; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.kotlin.Flowables; +import kotlin.collections.CollectionsKt; + +/** + * Displays a metering target on the screen. + */ +public class ExposureMeteringWidget extends ConstraintLayoutWidget implements ICameraIndex { + + //region Fields + /** + * The default x scaling for the center meter icon. + */ + protected static final float DEFAULT_CENTER_METER_SCALE_X = 1.376f; + /** + * The default y scaling for the center meter icon. + */ + protected static final float DEFAULT_CENTER_METER_SCALE_Y = 1f; + + private float centerMeterScaleX = DEFAULT_CENTER_METER_SCALE_X; + private float centerMeterScaleY = DEFAULT_CENTER_METER_SCALE_Y; + private ExposureMeteringWidgetModel widgetModel; + private ExposeVSeekBar mExposeVSeekBar; + + public ExposureMeteringWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public ExposureMeteringWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public ExposureMeteringWidget(@NonNull Context context) { + super(context); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_expose_focus_view, this); + + if (!isInEditMode()) { + widgetModel = new ExposureMeteringWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + } + initSeekBar(); + } + + @Override + protected void reactToModelChanges() { + Disposable d = Flowables.INSTANCE.combineLatest( + widgetModel.exposureCompensationProcessor.toFlowable(), + widgetModel.compensationRangeProcessor.toFlowable()) + .observeOn(SchedulerProvider.ui()).subscribe(cameraExposureCompensationListPair -> { + // 获取EV值列表 + 当前EV值 + List evList = cameraExposureCompensationListPair.component2(); + CameraExposureCompensation ev = cameraExposureCompensationListPair.component1(); + // 判断EV值列表是否有效 + if (evList == null || evList.size() <= 0) { + return; + } + // 判断当前EV值是否有效 + int index = CollectionsKt.indexOf(evList, ev); + if (index < 0) { + return; + } + // 更新SeekBar UI + mExposeVSeekBar.setMax(evList.size() - 1); + mExposeVSeekBar.setProgress(index); + }, throwable -> { + // do nothing + }); + addReaction(d); + } + + @Nullable + @Override + public String getIdealDimensionRatioString() { + return null; + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + if (!isInEditMode()) { + widgetModel.cleanup(); + } + super.onDetachedFromWindow(); + } + + + public void initSeekBar() { + mExposeVSeekBar = findViewById(R.id.expose_level_seekbar); + mExposeVSeekBar.setMax(100); + mExposeVSeekBar.setShowSeekBar(true); + mExposeVSeekBar.setOnChangeListener(new VerticalSeekBar.OnVSBChangeListener() { + @Override + public void onProgressChanged(VerticalSeekBar bar, int value, boolean fromUser) { + if (!fromUser) { + return; + } + invalidate(); + addDisposable(widgetModel.setEV(value) + .observeOn(SchedulerProvider.ui()) + .subscribe(() -> { + // do nothing + })); + } + + @Override + public void onStartTrackingTouch(VerticalSeekBar bar) { + showProgressBar(); + } + + @Override + public void onStopTrackingTouch(VerticalSeekBar bar) { + hideProgressBar(); + } + }); + } + + private void showProgressBar() { + invalidate(); + } + + private void hideProgressBar() { + invalidate(); + } + + /** + * Calculate the next ControlMode and show the icon. + * + * @param controlMode The current ControlMode. + * @param x position of click. + * @param y position of click. + * @param parentWidth The width of the parent view. + * @param parentHeight The height of the parent view. + * @return The next ControlMode. + */ + public ControlMode clickEvent(@NonNull ControlMode controlMode, float x, float y, + float parentWidth, float parentHeight) { + switch (controlMode) { + case CENTER_METER: + case SPOT_METER: + addImageBackground(); + x -= getWidth() / 2f; + y -= getHeight() / 2f; + setX(x); + setY(y); + break; + default: + break; + } + return ControlMode.SPOT_METER; + } + + private void addImageBackground() { + setScaleX(1f); + setScaleY(1f); + } + + /** + * Clears the meter icon. + */ + public void removeImageBackground() { + this.setBackground(null); + } + + /** + * Gets the scaleX of the center meter icon compared to the spot meter icon. For example, if + * center meter icon is twice as wide as the spot meter icon, the scaleX would be 2. + * + * @return The scaleX of the center meter icon + */ + public float getCenterMeterScaleX() { + return centerMeterScaleX; + } + + /** + * Sets the scaleX of the center meter icon compared to the spot meter icon. For example, if + * center meter icon is twice as wide as the spot meter icon, the scaleX would be 2. + * + * @param centerMeterScaleX The scaleX of the center meter icon + */ + public void setCenterMeterScaleX(float centerMeterScaleX) { + this.centerMeterScaleX = centerMeterScaleX; + } + + /** + * Gets the scaleY of the center meter icon compared to the spot meter icon. For example, if + * center meter icon is twice as tall as the spot meter icon, the scaleY would be 2. + * + * @return The scaleY of the center meter icon + */ + public float getCenterMeterScaleY() { + return centerMeterScaleY; + } + + /** + * Sets the scaleY of the center meter icon compared to the spot meter icon. For example, if + * center meter icon is twice as tall as the spot meter icon, the scaleY would be 2. + * + * @param centerMeterScaleY The scaleY of the center meter icon + */ + public void setCenterMeterScaleY(float centerMeterScaleY) { + this.centerMeterScaleY = centerMeterScaleY; + } + + @NonNull + @Override + public ComponentIndexType getCameraIndex() { + return widgetModel.getCameraIndex(); + } + + @NonNull + @Override + public CameraLensType getLensType() { + return widgetModel.getLensType(); + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + widgetModel.updateCameraSource(cameraIndex, lensType); + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/fpvinteraction/ExposureMeteringWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/fpvinteraction/ExposureMeteringWidgetModel.java new file mode 100644 index 00000000..f856a717 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/fpvinteraction/ExposureMeteringWidgetModel.java @@ -0,0 +1,76 @@ +package dji.v5.ux.cameracore.widget.fpvinteraction; + +import java.util.ArrayList; +import java.util.List; + +import androidx.annotation.NonNull; +import dji.sdk.keyvalue.key.CameraKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.value.camera.CameraExposureCompensation; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Completable; + +/** + * Class Description + * + * @author Hoker + * @date 2022/8/2 + *

+ * Copyright (c) 2022, DJI All Rights Reserved. + */ +public class ExposureMeteringWidgetModel extends WidgetModel implements ICameraIndex { + + public final DataProcessor> compensationRangeProcessor = DataProcessor.create(new ArrayList<>()); + public final DataProcessor exposureCompensationProcessor = DataProcessor.create(CameraExposureCompensation.NEG_0EV); + + private ComponentIndexType cameraIndex = ComponentIndexType.LEFT_OR_MAIN; + private CameraLensType lensType = CameraLensType.CAMERA_LENS_ZOOM; + + public ExposureMeteringWidgetModel(@NonNull DJISDKModel djiSdkModel, @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + } + + public Completable setEV(int value) { + if (compensationRangeProcessor.getValue().size() <= value){ + return Completable.complete(); + } + return djiSdkModel.setValue(KeyTools.createCameraKey(CameraKey.KeyExposureCompensation, cameraIndex, lensType), + compensationRangeProcessor.getValue().get(value)); + } + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createCameraKey(CameraKey.KeyExposureCompensationRange, cameraIndex, lensType), compensationRangeProcessor); + bindDataProcessor(KeyTools.createCameraKey(CameraKey.KeyExposureCompensation, cameraIndex, lensType), exposureCompensationProcessor); + } + + @Override + protected void inCleanup() { + //do nothing + } + + @NonNull + @Override + public ComponentIndexType getCameraIndex() { + return cameraIndex; + } + + @NonNull + @Override + public CameraLensType getLensType() { + return lensType; + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + this.cameraIndex = cameraIndex; + this.lensType = lensType; + restart(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/fpvinteraction/FPVInteractionWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/fpvinteraction/FPVInteractionWidget.java new file mode 100644 index 00000000..5b32700a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/fpvinteraction/FPVInteractionWidget.java @@ -0,0 +1,850 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.fpvinteraction; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.util.AttributeSet; +import android.util.Pair; +import android.view.MotionEvent; +import android.view.View; + +import java.util.concurrent.atomic.AtomicBoolean; + +import androidx.annotation.AnimatorRes; +import androidx.annotation.DrawableRes; +import androidx.annotation.FloatRange; +import androidx.annotation.IntRange; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.sdk.keyvalue.value.common.PhysicalSource; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.IGimbalIndex; +import dji.v5.ux.core.base.SchedulerProvider; +import dji.v5.ux.core.base.widget.FrameLayoutWidget; +import dji.v5.ux.core.communication.GlobalPreferencesManager; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.SettingDefinitions; +import dji.v5.ux.core.util.SettingDefinitions.ControlMode; +import dji.v5.ux.core.util.UxErrorHandle; +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.disposables.Disposable; + +/** + * This widget allows the user to interact with the FPVWidget. + *

+ * When this widget is tapped, an icon will appear and the camera will either focus or perform spot + * metering at the tapped area, depending on the current {@link ControlMode}. + *

+ * When the widget is long pressed then dragged, the gimbal controls will appear and the aircraft's + * gimbal will move. The speed at which the gimbal moves is based on the drag distance. + */ +public class FPVInteractionWidget extends FrameLayoutWidget implements View.OnTouchListener, ICameraIndex, IGimbalIndex { + + private static final String TAG = "FPVInteractionWidget"; + private static final int LONG_PRESS_TIME = 500; // Time in milliseconds + private static final float DEFAULT_VELOCITY_FACTOR = 16.0f; + private final Handler handler = new Handler(); + //region Fields + private FocusTargetView focusTargetView; + private ExposureMeteringWidget exposureMeterView; + private GimbalControlView gimbalControlView; + private FPVInteractionWidgetModel widgetModel; + private int relativeViewHeight, relativeViewWidth; + private float oldAbsTargetX, oldAbsTargetY; + private float absTargetX, absTargetY; + private int viewHeight, viewWidth; + private int widthOffset, heightOffset; + private boolean touchFocusEnabled = true; + private boolean spotMeteringEnabled = true; + private boolean gimbalControlEnabled = true; + private float firstX; + private float firstY; + private float moveDeltaX; + private float moveDeltaY; + private float velocityFactor; + private AtomicBoolean isInteractionEnabledAtomic; + private String cameraName; + + private final Runnable longPressed = () -> { + gimbalControlView.show(absTargetX, absTargetY); + firstX = absTargetX; + firstY = absTargetY; + }; + + //region Constructor + public FPVInteractionWidget(@NonNull Context context) { + super(context); + } + + public FPVInteractionWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public FPVInteractionWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_widget_fpv_interaction, this); + focusTargetView = findViewById(R.id.view_focus_target); + exposureMeterView = findViewById(R.id.view_exposure_meter); + gimbalControlView = findViewById(R.id.view_gimbal_control); + setOnTouchListener(this); + velocityFactor = DEFAULT_VELOCITY_FACTOR; + isInteractionEnabledAtomic = new AtomicBoolean(true); + cameraName = ""; + + if (!isInEditMode()) { + widgetModel = new FPVInteractionWidgetModel(DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + GlobalPreferencesManager.getInstance()); + } + + if (attrs != null) { + initAttributes(getContext(), attrs); + } + } + //endregion + + //region Lifecycle + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + if (!isInEditMode()) { + widgetModel.cleanup(); + } + super.onDetachedFromWindow(); + } + + @Override + protected void reactToModelChanges() { + addReaction(reactToUpdateVisibility()); + } + + //region Reaction helpers + private Disposable reactToUpdateVisibility() { + return Flowable.combineLatest(widgetModel.getControlMode(), widgetModel.isAeLocked(), Pair::new) + .observeOn(SchedulerProvider.ui()) + .subscribe(values -> updateViewVisibility(values.first, values.second), + UxErrorHandle.logErrorConsumer(TAG, "reactToUpdateVisibility: ")); + } + + private void updateViewVisibility(ControlMode controlMode, boolean isAeLocked) { + if (controlMode == ControlMode.SPOT_METER || controlMode == ControlMode.CENTER_METER) { + if (isAeLocked) { + exposureMeterView.setVisibility(View.GONE); + } else if (controlMode == ControlMode.SPOT_METER) { + exposureMeterView.setVisibility(View.VISIBLE); + } + focusTargetView.setVisibility(GONE); + } else { + exposureMeterView.setVisibility(GONE); + focusTargetView.setVisibility(VISIBLE); + focusTargetView.setControlMode(controlMode); + } + } + //endregion + + //region User interaction + @Override + public boolean onTouch(View v, MotionEvent event) { + oldAbsTargetX = absTargetX; + oldAbsTargetY = absTargetY; + absTargetX = event.getX(); + absTargetY = event.getY(); + viewHeight = v.getHeight(); + viewWidth = v.getWidth(); + + if (relativeViewWidth == 0 && relativeViewHeight == 0) { + relativeViewWidth = viewWidth; + relativeViewHeight = viewHeight; + } + + // Calculate offset for different aspect ratios + widthOffset = (viewWidth - relativeViewWidth) / 2; + if (widthOffset < 0) { + widthOffset = 0; + } + heightOffset = (viewHeight - relativeViewHeight) / 2; + if (heightOffset < 0) { + heightOffset = 0; + } + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + if (absTargetX > widthOffset && viewWidth - absTargetX > widthOffset && gimbalControlEnabled) { + handler.postDelayed(longPressed, LONG_PRESS_TIME); + } + break; + case MotionEvent.ACTION_UP: + handler.removeCallbacks(longPressed); + if (gimbalControlView.isVisible()) { + if (absTargetX < widthOffset) { + absTargetX = widthOffset + 1F; + } else if (viewWidth - absTargetX < widthOffset) { + absTargetX = viewWidth - widthOffset - 1F; + } + gimbalControlView.hide(); + stopGimbalRotation(); + } else { + float targetX = absTargetX / (float) viewWidth; + float targetY = absTargetY / (float) viewHeight; + addDisposable(Flowable.combineLatest(widgetModel.getControlMode(), widgetModel.isAeLocked(), Pair::new) + .firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe((Pair values) -> updateTarget(values.first, values.second, targetX, targetY), + UxErrorHandle.logErrorConsumer(TAG, "Update Target: "))); + } + break; + case MotionEvent.ACTION_MOVE: + if (absTargetX < widthOffset) { + absTargetX = widthOffset + 1F; + } else if (viewWidth - absTargetX < widthOffset) { + absTargetX = viewWidth - widthOffset - 1F; + } + + if (absTargetY < heightOffset) { + absTargetY = heightOffset + 1F; + } else if (viewHeight - absTargetY < heightOffset) { + absTargetY = viewHeight - heightOffset - 1F; + } + + if (gimbalControlView.isVisible()) { + gimbalControlView.onMove(firstX, firstY, absTargetX, absTargetY, widgetModel.canRotateGimbalYaw()); + rotateGimbal(firstX, firstY, absTargetX, absTargetY); + } + break; + default: + break; + } + + return true; + } + + /** + * Get the index of the gimbal to which the widget is reacting + */ + @Nullable + public ComponentIndexType getGimbalIndex() { + return widgetModel.getCameraIndex(); + } + + /** + * Set the index of gimbal to which the widget should react + * + * @param gimbalIndex index of the gimbal. + */ + public void updateGimbalIndex(@Nullable ComponentIndexType gimbalIndex) { +// if (!isInEditMode()) { +// widgetModel.setGimbalIndex(gimbalIndex); +// } + } + + @NonNull + public ComponentIndexType getCameraIndex() { + return widgetModel.getCameraIndex(); + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + widgetModel.updateCameraSource(cameraIndex, lensType); + exposureMeterView.updateCameraSource(cameraIndex, lensType); + } + + @NonNull + public CameraLensType getLensType() { + return widgetModel.getLensType(); + } + + /** + * Adjust the width and height of the interaction area. This should be called whenever the + * size of the video feed changes. The interaction area will be centered within the view. + * + * @param width The new width of the interaction area. + * @param height The new height of the interaction area. + */ + public void adjustAspectRatio(@IntRange(from = 1) int width, @IntRange(from = 1) int height) { + if (width > 0 && height > 0) { + relativeViewWidth = width; + relativeViewHeight = height; + redraw(); + } + } + //endregion + + //region Helpers + private void updateTarget(ControlMode controlMode, boolean isAeLocked, float targetX, float targetY) { + if (controlMode == ControlMode.SPOT_METER || controlMode == ControlMode.CENTER_METER) { + if (spotMeteringEnabled && isInBounds() && !isAeLocked) { + final ControlMode newControlMode = exposureMeterView.clickEvent(controlMode, absTargetX, absTargetY, viewWidth, viewHeight); + addDisposable(widgetModel.setControlMode(newControlMode) + .observeOn(SchedulerProvider.ui()) + .subscribe(() -> { + //do nothing + }, UxErrorHandle.logErrorConsumer(TAG, "updateTarget: "))); + addDisposable(widgetModel.updateMetering(targetX, targetY) + .observeOn(SchedulerProvider.ui()) + .subscribe(() -> { + // do nothing + }, throwable -> + // 仅仅打印日志,不重新设置测光参数 + UxErrorHandle.logErrorConsumer(TAG, "onExposureMeterSetFail: ").accept(throwable))); + } + } else if (touchFocusEnabled && isInBounds()) { + focusTargetView.clickEvent(absTargetX, absTargetY); + addDisposable(widgetModel.updateFocusTarget(targetX, targetY) + .observeOn(SchedulerProvider.ui()) + .subscribe(() -> { + //do nothing + }, throwable -> onFocusTargetSetFail())); + } + } + + private boolean isInBounds() { + return absTargetX > widthOffset + && viewWidth - absTargetX > widthOffset + && absTargetY > heightOffset + && viewHeight - absTargetY > heightOffset; + } + + private void onFocusTargetSetFail() { + if (oldAbsTargetX > 0 && oldAbsTargetY > 0) { + focusTargetView.clickEvent(oldAbsTargetX, oldAbsTargetY); + } + } + + private void redraw() { + focusTargetView.removeImageBackground(); + exposureMeterView.removeImageBackground(); + } + + /** + * Rotate the gimbal. The speed is determined by the distance from (firstX, firstY) to (x,y) + * divided by the velocity factor. The gimbal will continue rotating until + * {@link FPVInteractionWidget#stopGimbalRotation()} is called. + *

+ * When this method is called after rotation has started, the new coordinates are used to + * update the speed at which the gimbal rotates. + * + * @param firstX The x coordinate of the original point long pressed by the user. + * @param firstY The y coordinate of the original point long pressed by the user. + * @param x The x coordinate the of the point the user dragged the gimbal controls to. + * @param y The y coordinate the of the point the user dragged the gimbal controls to. + */ + private void rotateGimbal(float firstX, float firstY, float x, float y) { + if (widgetModel.canRotateGimbalYaw()) { + toggleGimbalRotateBySpeed(); + moveDeltaX = x - firstX; + } else { + moveDeltaX = 0; + } + moveDeltaY = y - firstY; + } + + /** + * Stop rotating the gimbal. + */ + private void stopGimbalRotation() { + this.moveDeltaX = 0; + this.moveDeltaY = 0; + } + + private void toggleGimbalRotateBySpeed() { + float yawVelocity = moveDeltaX / velocityFactor; + float pitchVelocity = moveDeltaY / velocityFactor; + + if (Math.abs(yawVelocity) >= 1 || Math.abs(pitchVelocity) >= 1) { + addDisposable(widgetModel.rotateGimbalBySpeed(yawVelocity, -pitchVelocity) + .observeOn(SchedulerProvider.ui()) + .subscribe(() -> { + //do nothing + }, UxErrorHandle.logErrorConsumer(TAG, "rotate gimbal: "))); + } + } + + private void updateVisibility() { + if (isInEditMode()) { + return; + } + if (PhysicalSource.FPV_CAM.toString().equals(cameraName) || !isInteractionEnabledAtomic.get()) { + setVisibility(View.GONE); + } else { + setVisibility(View.VISIBLE); + } + } + //endregion + + //region Customization + private void initAttributes(@NonNull Context context, @NonNull AttributeSet attrs) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.FPVInteractionWidget); + + if (!isInEditMode()) { + widgetModel.updateCameraSource(ComponentIndexType.find(typedArray.getInt(R.styleable.FPVInteractionWidget_uxsdk_cameraIndex, 0)), + CameraLensType.find(typedArray.getInt(R.styleable.FPVInteractionWidget_uxsdk_lensType, 0))); + } + + Drawable manualFocusIcon = typedArray.getDrawable(R.styleable.FPVInteractionWidget_uxsdk_manualFocusIcon); + if (manualFocusIcon != null) { + setManualFocusIcon(manualFocusIcon); + } + Drawable autoFocusIcon = typedArray.getDrawable(R.styleable.FPVInteractionWidget_uxsdk_autoFocusIcon); + if (autoFocusIcon != null) { + setAutoFocusIcon(autoFocusIcon); + } + Drawable autoFocusContinuousIcon = typedArray.getDrawable(R.styleable.FPVInteractionWidget_uxsdk_autoFocusContinuousIcon); + if (autoFocusContinuousIcon != null) { + setAutoFocusContinuousIcon(autoFocusContinuousIcon); + } + int focusTargetDuration = typedArray.getInt(R.styleable.FPVInteractionWidget_uxsdk_focusTargetDuration, FocusTargetView.DEFAULT_FOCUS_TARGET_DURATION); + setFocusTargetDuration(focusTargetDuration); + + float centerMeterScaleX = typedArray.getFloat(R.styleable.FPVInteractionWidget_uxsdk_centerMeterScaleX, ExposureMeteringWidget.DEFAULT_CENTER_METER_SCALE_X); + setCenterMeterScaleX(centerMeterScaleX); + float centerMeterScaleY = typedArray.getFloat(R.styleable.FPVInteractionWidget_uxsdk_centerMeterScaleY, ExposureMeteringWidget.DEFAULT_CENTER_METER_SCALE_Y); + setCenterMeterScaleY(centerMeterScaleY); + + Drawable gimbalPointIcon = typedArray.getDrawable(R.styleable.FPVInteractionWidget_uxsdk_gimbalPointIcon); + if (gimbalPointIcon != null) { + setGimbalPointIcon(gimbalPointIcon); + } + Drawable gimbalMoveIcon = typedArray.getDrawable(R.styleable.FPVInteractionWidget_uxsdk_gimbalMoveIcon); + if (gimbalMoveIcon != null) { + setGimbalMoveIcon(gimbalMoveIcon); + } + Drawable gimbalArrowIcon = typedArray.getDrawable(R.styleable.FPVInteractionWidget_uxsdk_gimbalArrowIcon); + if (gimbalArrowIcon != null) { + setGimbalArrowIcon(gimbalArrowIcon); + } + float gimbalVelocityFactor = typedArray.getFloat(R.styleable.FPVInteractionWidget_uxsdk_gimbalVelocityFactor, DEFAULT_VELOCITY_FACTOR); + setGimbalVelocityFactor(gimbalVelocityFactor); + boolean isVibrationEnabled = typedArray.getBoolean(R.styleable.FPVInteractionWidget_uxsdk_vibrationEnabled, true); + setVibrationEnabled(isVibrationEnabled); + int vibrationDuration = typedArray.getInt(R.styleable.FPVInteractionWidget_uxsdk_vibrationDuration, GimbalControlView.DEFAULT_VIBRATION_DURATION); + setVibrationDuration(vibrationDuration); + + setInteractionEnabled(typedArray.getBoolean(R.styleable.FPVInteractionWidget_uxsdk_interactionEnabled, true)); + touchFocusEnabled = typedArray.getBoolean(R.styleable.FPVInteractionWidget_uxsdk_touchFocusEnabled, true); + spotMeteringEnabled = typedArray.getBoolean(R.styleable.FPVInteractionWidget_uxsdk_spotMeteringEnabled, true); + gimbalControlEnabled = typedArray.getBoolean(R.styleable.FPVInteractionWidget_uxsdk_gimbalControlEnabled, true); + + typedArray.recycle(); + } + + @NonNull + @Override + public String getIdealDimensionRatioString() { + return getResources().getString(R.string.uxsdk_widget_fpv_ratio); + } + + /** + * Get the drawable resource for the manual focus icon. + * + * @return The drawable resource for the icon. + */ + @Nullable + public Drawable getManualFocusIcon() { + return focusTargetView.getFocusTargetIcon(ControlMode.MANUAL_FOCUS); + } + + /** + * Set the resource ID for the manual focus icon. + * + * @param resourceId The resource ID of the icon. + */ + public void setManualFocusIcon(@DrawableRes int resourceId) { + setManualFocusIcon(getResources().getDrawable(resourceId)); + } + + /** + * Set the drawable resource for the manual focus icon. + * + * @param icon The drawable resource for the icon. + */ + public void setManualFocusIcon(@Nullable Drawable icon) { + focusTargetView.setFocusTargetIcon(ControlMode.MANUAL_FOCUS, icon); + } + + /** + * Get the drawable resource for the auto focus icon. + * + * @return The drawable resource for the icon. + */ + @Nullable + public Drawable getAutoFocusIcon() { + return focusTargetView.getFocusTargetIcon(ControlMode.AUTO_FOCUS); + } + + /** + * Set the resource ID for the auto focus icon. + * + * @param resourceId The resource ID of the icon. + */ + public void setAutoFocusIcon(@DrawableRes int resourceId) { + setAutoFocusIcon(getResources().getDrawable(resourceId)); + } + + /** + * Set the drawable resource for the auto focus icon. + * + * @param icon The drawable resource for the icon. + */ + public void setAutoFocusIcon(@Nullable Drawable icon) { + focusTargetView.setFocusTargetIcon(ControlMode.AUTO_FOCUS, icon); + } + + /** + * Get the drawable resource for the auto focus continuous icon. + * + * @return The drawable resource for the icon. + */ + @Nullable + public Drawable getAutoFocusContinuousIcon() { + return focusTargetView.getFocusTargetIcon(ControlMode.AUTO_FOCUS_CONTINUE); + } + + /** + * Set the resource ID for the auto focus continuous icon. + * + * @param resourceId The resource ID of the icon. + */ + public void setAutoFocusContinuousIcon(@DrawableRes int resourceId) { + setAutoFocusContinuousIcon(getResources().getDrawable(resourceId)); + } + + /** + * Set the drawable resource for the auto focus continuous icon. + * + * @param icon The drawable resource for the icon. + */ + public void setAutoFocusContinuousIcon(@Nullable Drawable icon) { + focusTargetView.setFocusTargetIcon(ControlMode.AUTO_FOCUS_CONTINUE, icon); + } + + /** + * Sets the animator for the auto focus and auto focus continuous icons. + * + * @param animatorId The id of the animator, or 0 to remove the animation. + */ + public void setAutoFocusAnimator(@AnimatorRes int animatorId) { + focusTargetView.setAutoFocusAnimator(animatorId); + } + + /** + * Gets the duration in milliseconds that the focus target will stay on the screen before + * disappearing. This is the amount of time after the animation completes, if any. + * + * @return The number of milliseconds the focus target will stay on the screen. + */ + public long getFocusTargetDuration() { + return focusTargetView.getFocusTargetDuration(); + } + + /** + * Sets the duration in milliseconds that the focus target will stay on the screen before + * disappearing. This is the amount of time after the animation completes, if any. + * + * @param duration The number of milliseconds the focus target will stay on the screen. + */ + public void setFocusTargetDuration(long duration) { + focusTargetView.setFocusTargetDuration(duration); + } + + /** + * Gets the scaleX of the center meter icon compared to the spot meter icon. For example, if + * center meter icon is twice as wide as the spot meter icon, the scaleX would be 2. + * + * @return The scaleX of the center meter icon + */ + public float getCenterMeterScaleX() { + return exposureMeterView.getCenterMeterScaleX(); + } + + /** + * Sets the scaleX of the center meter icon compared to the spot meter icon. For example, if + * center meter icon is twice as wide as the spot meter icon, the scaleX would be 2. + * + * @param centerMeterScaleX The scaleX of the center meter icon + */ + public void setCenterMeterScaleX(float centerMeterScaleX) { + exposureMeterView.setCenterMeterScaleX(centerMeterScaleX); + } + + /** + * Gets the scaleY of the center meter icon compared to the spot meter icon. For example, if + * center meter icon is twice as tall as the spot meter icon, the scaleY would be 2. + * + * @return The scaleY of the center meter icon + */ + public float getCenterMeterScaleY() { + return exposureMeterView.getCenterMeterScaleY(); + } + + /** + * Sets the scaleY of the center meter icon compared to the spot meter icon. For example, if + * center meter icon is twice as tall as the spot meter icon, the scaleY would be 2. + * + * @param centerMeterScaleY The scaleY of the center meter icon + */ + public void setCenterMeterScaleY(float centerMeterScaleY) { + exposureMeterView.setCenterMeterScaleY(centerMeterScaleY); + } + + /** + * Get the drawable resource for the icon that represents the point at which the gimbal + * started. + * + * @return The drawable resource for the icon. + */ + @Nullable + public Drawable getGimbalPointIcon() { + return gimbalControlView.getGimbalPointIcon(); + } + + /** + * Set the resource ID for the icon that represents the point at which the gimbal started. + * + * @param resourceId The resource ID of the icon. + */ + public void setGimbalPointIcon(@DrawableRes int resourceId) { + setGimbalPointIcon(getResources().getDrawable(resourceId)); + } + + /** + * Set the drawable resource for the icon that represents the point at which the gimbal + * started. + * + * @param gimbalPointIcon The drawable resource for the icon. + */ + public void setGimbalPointIcon(@Nullable Drawable gimbalPointIcon) { + gimbalControlView.setGimbalPointIcon(gimbalPointIcon); + } + + /** + * Get the drawable resource for the icon that represents the point towards which the gimbal + * is moving. + * + * @return The drawable resource for the icon. + */ + @Nullable + public Drawable getGimbalMoveIcon() { + return gimbalControlView.getGimbalMoveIcon(); + } + + /** + * Set the resource ID for the icon that represents the point towards which the gimbal + * is moving. + * + * @param resourceId The resource ID of the icon. + */ + public void setGimbalMoveIcon(@DrawableRes int resourceId) { + setGimbalMoveIcon(getResources().getDrawable(resourceId)); + } + + /** + * Set the drawable resource for the icon that represents the point towards which the gimbal + * is moving. + * + * @param gimbalMoveIcon The drawable resource for the icon. + */ + public void setGimbalMoveIcon(@Nullable Drawable gimbalMoveIcon) { + gimbalControlView.setGimbalMoveIcon(gimbalMoveIcon); + } + + /** + * Get the drawable resource for the icon that represents the direction the gimbal is moving. + * + * @return The drawable resource for the icon. + */ + @Nullable + public Drawable getGimbalArrowIcon() { + return gimbalControlView.getGimbalArrowIcon(); + } + + /** + * Set the resource ID for the icon that represents the direction the gimbal is moving. + * + * @param resourceId The resource ID of the icon. + */ + public void setGimbalArrowIcon(@DrawableRes int resourceId) { + setGimbalArrowIcon(getResources().getDrawable(resourceId)); + } + + /** + * Set the drawable resource for the icon that represents the direction the gimbal is moving. + * + * @param gimbalArrowIcon The drawable resource for the icon. + */ + public void setGimbalArrowIcon(@Nullable Drawable gimbalArrowIcon) { + gimbalControlView.setGimbalArrowIcon(gimbalArrowIcon); + } + + /** + * Gets the velocity factor of the gimbal control view. The distance between the original point + * and the current touch location is divided by this number to calculate the speed of the + * gimbal. Therefore a higher velocity factor will result in a lower gimbal rotation speed. + * The default is 16. + * + * @return The velocity factor of the gimbal control view + */ + public float getGimbalVelocityFactor() { + return velocityFactor; + } + + /** + * Sets the velocity factor of the gimbal control view. The distance between the original point + * and the current touch location is divided by this number to calculate the speed of the + * gimbal. Therefore a higher velocity factor will result in a lower gimbal rotation speed. + * The default is 16. + * + * @param velocityFactor The velocity factor of the gimbal control view + */ + public void setGimbalVelocityFactor(@FloatRange(from = 1) float velocityFactor) { + this.velocityFactor = velocityFactor; + } + + /** + * Get whether the device will vibrate when the gimbal control view appears. + * + * @return `true` if vibration is enabled, `false` otherwise. + */ + public boolean isVibrationEnabled() { + return gimbalControlView.isVibrationEnabled(); + } + + /** + * Set whether the device will vibrate when the gimbal control view appears. + * + * @param vibrationEnabled `true` if vibration is enabled, `false` otherwise. + */ + public void setVibrationEnabled(boolean vibrationEnabled) { + gimbalControlView.setVibrationEnabled(vibrationEnabled); + } + + /** + * Get the duration of the vibration in milliseconds when the gimbal control view appears. + * + * @return The duration of the vibration in milliseconds. + */ + public int getVibrationDuration() { + return gimbalControlView.getVibrationDuration(); + } + + /** + * Set the duration of the vibration in milliseconds when the gimbal control view appears. + * + * @param vibrationDuration The duration of the vibration in milliseconds. + */ + public void setVibrationDuration(@IntRange(from = 0) int vibrationDuration) { + gimbalControlView.setVibrationDuration(vibrationDuration); + } + + /** + * Get whether interaction is enabled. + * + * @return `true` if enabled, `false` if disabled. + */ + public boolean isInteractionEnabled() { + return isInteractionEnabledAtomic.get(); + } + + /** + * Set whether interaction is enabled. + * + * @param isInteractionEnabled `true` to enable, `false` to disable. + */ + public void setInteractionEnabled(boolean isInteractionEnabled) { + isInteractionEnabledAtomic.set(isInteractionEnabled); + updateVisibility(); + } + + /** + * Method to check if Touch to Focus is enabled. + * + * @return `true` if enabled, `false` if disabled. + */ + public boolean isTouchFocusEnabled() { + return touchFocusEnabled; + } + + /** + * Enable or disable Touch to Focus by this method. Enabled by default. + * + * @param isTouchFocusEnabled `true` to enable, `false` to disable. + */ + public void setTouchFocusEnabled(boolean isTouchFocusEnabled) { + this.touchFocusEnabled = isTouchFocusEnabled; + } + + /** + * Method to check if spot metering using touch is enabled. + * + * @return `true` if enabled, `false` if disabled. + */ + public boolean isSpotMeteringEnabled() { + return spotMeteringEnabled; + } + + /** + * Enable or disable spot metering by this method. Enabled by default. + * + * @param isSpotMeteringEnabled `true` to enable, `false` to disable. + */ + public void setSpotMeteringEnabled(boolean isSpotMeteringEnabled) { + this.spotMeteringEnabled = isSpotMeteringEnabled; + } + + /** + * Method to check if gimbal control using touch is enabled. + * + * @return `true` if enabled, `false` if disabled. + */ + public boolean isGimbalControlEnabled() { + return gimbalControlEnabled; + } + + /** + * Enable or disable gimbal control by this method. Enabled by default. + * + * @param isGimbalControlEnabled `true` to enable, `false` to disable. + */ + public void setGimbalControlEnabled(boolean isGimbalControlEnabled) { + this.gimbalControlEnabled = isGimbalControlEnabled; + } + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/fpvinteraction/FPVInteractionWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/fpvinteraction/FPVInteractionWidgetModel.java new file mode 100644 index 00000000..590dbb60 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/fpvinteraction/FPVInteractionWidgetModel.java @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.fpvinteraction; + +import android.graphics.Point; +import android.graphics.PointF; + +import androidx.annotation.FloatRange; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.VisibleForTesting; +import dji.sdk.keyvalue.key.CameraKey; +import dji.sdk.keyvalue.key.DJIKey; +import dji.sdk.keyvalue.key.GimbalKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.value.camera.CameraMeteringMode; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.sdk.keyvalue.value.common.DoublePoint2D; +import dji.sdk.keyvalue.value.common.IntPoint2D; +import dji.sdk.keyvalue.value.gimbal.CtrlInfo; +import dji.sdk.keyvalue.value.gimbal.GimbalSpeedRotation; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.GlobalPreferenceKeys; +import dji.v5.ux.core.communication.GlobalPreferencesInterface; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.communication.UXKey; +import dji.v5.ux.core.communication.UXKeys; +import dji.v5.ux.core.util.DataProcessor; +import dji.v5.ux.core.util.SettingDefinitions; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; + +/** + * Widget Model for the {@link FPVInteractionWidget} used to define + * the underlying logic and communication + */ +public class FPVInteractionWidgetModel extends WidgetModel implements ICameraIndex { + + private final DataProcessor controlModeProcessor; + private final DataProcessor meteringModeProcessor; + private final DataProcessor aeLockedProcessor; + private final DataProcessor isYawAdjustSupportedProcessor; + private final GlobalPreferencesInterface preferencesManager; + private final ObservableInMemoryKeyedStore keyedStore; + //region Fields + private ComponentIndexType cameraIndex = ComponentIndexType.LEFT_OR_MAIN; + private CameraLensType lensIndex = CameraLensType.CAMERA_LENS_WIDE; + private DJIKey focusTargetKey; + private DJIKey meteringPointKey; + private DJIKey meteringModeKey; + private UXKey controlModeKey; + //endregion + + //region Constructor + public FPVInteractionWidgetModel(@NonNull DJISDKModel djiSdkModel, + @NonNull ObservableInMemoryKeyedStore keyedStore, + @Nullable GlobalPreferencesInterface preferencesManager) { + super(djiSdkModel, keyedStore); + meteringModeProcessor = DataProcessor.create(CameraMeteringMode.UNKNOWN); + controlModeProcessor = DataProcessor.create(SettingDefinitions.ControlMode.SPOT_METER); + if (preferencesManager != null) { + controlModeProcessor.onNext(preferencesManager.getControlMode()); + } + aeLockedProcessor = DataProcessor.create(false); + isYawAdjustSupportedProcessor = DataProcessor.create(true); + this.preferencesManager = preferencesManager; + this.keyedStore = keyedStore; + } + //endregion + + //region Lifecycle + @Override + protected void inSetup() { + focusTargetKey = KeyTools.createCameraKey(CameraKey.KeyCameraFocusTarget, cameraIndex, lensIndex); + meteringPointKey = KeyTools.createCameraKey(CameraKey.KeySpotMeteringPoint, cameraIndex, lensIndex); + meteringModeKey = KeyTools.createCameraKey(CameraKey.KeyCameraMeteringMode, cameraIndex, lensIndex); + bindDataProcessor(meteringModeKey, meteringModeProcessor, this::setMeteringMode); + bindDataProcessor(KeyTools.createCameraKey(CameraKey.KeyAELockEnabled, cameraIndex, lensIndex), aeLockedProcessor); + bindDataProcessor(KeyTools.createKey(GimbalKey.KeyYawAdjustSupported, cameraIndex), isYawAdjustSupportedProcessor); + controlModeKey = UXKeys.create(GlobalPreferenceKeys.CONTROL_MODE); + bindDataProcessor(controlModeKey, controlModeProcessor); + + if (preferencesManager != null) { + preferencesManager.setUpListener(); + } + } + + @Override + protected void inCleanup() { + if (preferencesManager != null) { + preferencesManager.cleanup(); + } + } + + @Override + protected void updateStates() { + // do nothing + } + //endregion + + //region Helpers + private void setMeteringMode(CameraMeteringMode meteringMode) { + if (meteringMode == CameraMeteringMode.REGION) { + setControlMode(SettingDefinitions.ControlMode.SPOT_METER); + } else if (meteringMode == CameraMeteringMode.CENTER) { + setControlMode(SettingDefinitions.ControlMode.CENTER_METER); + } + } + //endregion + + //region Data + @Override + @NonNull + public ComponentIndexType getCameraIndex() { + return cameraIndex; + } + + @Override + @NonNull + public CameraLensType getLensType() { + return lensIndex; + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + this.cameraIndex = cameraIndex; + this.lensIndex = lensType; + restart(); + } + + /** + * Set the control mode. + * + * @param controlMode The control mode to set. + * @return Completable representing the success/failure of the set action. + */ + @NonNull + public Completable setControlMode(@NonNull SettingDefinitions.ControlMode controlMode) { + if (preferencesManager != null) { + preferencesManager.setControlMode(controlMode); + } + return keyedStore.setValue(controlModeKey, controlMode); + } + + /** + * Get the control mode. + * + * @return A Flowable that will emit the current control mode. + */ + @NonNull + public Flowable getControlMode() { + return controlModeProcessor.toFlowable(); + } + + /** + * Get whether the automatic exposure is locked. + * + * @return A Flowable that will emit a boolean when the automatic exposure locked state changes. + */ + @NonNull + public Flowable isAeLocked() { + return aeLockedProcessor.toFlowable(); + } + //endregion + + //region Reactions to user input + + /** + * Set the focus target to the location (targetX, targetY). This is a relative coordinate + * represented by a percentage of the width and height of the widget. + * + * @param targetX The relative x coordinate of the focus target represented by a percentage of + * the width. + * @param targetY The relative y coordinate of the focus target represented by a percentage of + * the height. + * @return Completable representing the success/failure of the set action. + */ + @NonNull + public Completable updateFocusTarget(@FloatRange(from = 0, to = 1) float targetX, + @FloatRange(from = 0, to = 1) float targetY) { + return djiSdkModel.setValue(focusTargetKey, createPointF(targetX, targetY)); + } + + /** + * Set the spot metering target to the location (targetX, targetY). This is a relative + * coordinate represented by a percentage of the width and height of the widget. + * + * @param targetX The relative x coordinate of the spot metering target represented by a + * percentage of the width. + * @param targetY The relative y coordinate of the spot metering target represented by a + * percentage of the height. + * @return Completable representing the success/failure of the set action. + */ + @NonNull + public Completable updateMetering(@FloatRange(from = 0, to = 1) float targetX, + @FloatRange(from = 0, to = 1) float targetY) { + if (controlModeProcessor.getValue() == SettingDefinitions.ControlMode.SPOT_METER) { + return djiSdkModel.setValue(meteringPointKey, new DoublePoint2D((double) targetX, (double) targetY)); + } else if (controlModeProcessor.getValue() == SettingDefinitions.ControlMode.CENTER_METER) { + return djiSdkModel.setValue(meteringModeKey, CameraMeteringMode.CENTER); + } + return Completable.complete(); + } + + /** + * Determine whether the gimbal is able to move in the yaw direction. + * + * @return `true` if the current product supports gimbal yaw rotation, `false` otherwise. + */ + public boolean canRotateGimbalYaw() { + return isYawAdjustSupportedProcessor.getValue(); + } + + /** + * Rotate the gimbal using SPEED. + * + * @param yaw The amount to rotate the gimbal in the yaw direction. + * @param pitch The amount to rotate the gimbal in the pitch direction. + * @return Completable representing the success/failure of the set action. + */ + public Completable rotateGimbalBySpeed(double yaw, double pitch) { + return djiSdkModel.performActionWithOutResult(KeyTools.createKey(GimbalKey.KeyRotateBySpeed, cameraIndex), + new GimbalSpeedRotation(pitch, yaw, 0.0, new CtrlInfo())); + } + //endregion + + //region Unit test helpers + + /** + * A wrapper for the {@link PointF} constructor so it can be mocked in unit tests. + * + * @return A PointF object. + */ + @VisibleForTesting + @NonNull + protected DoublePoint2D createPointF(float x, float y) { + return new DoublePoint2D((double) x, (double) y); + } + + /** + * A wrapper for the {@link Point} constructor so it can be mocked in unit tests. + * + * @return A Point object. + */ + @VisibleForTesting + @NonNull + protected IntPoint2D createPoint(int x, int y) { + return new IntPoint2D(x, y); + } + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/fpvinteraction/FocusTargetView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/fpvinteraction/FocusTargetView.java new file mode 100644 index 00000000..8c2ea2ef --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/fpvinteraction/FocusTargetView.java @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.fpvinteraction; + +import android.animation.Animator; +import android.animation.AnimatorInflater; +import android.animation.AnimatorSet; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.widget.FrameLayout; + +import java.util.HashMap; +import java.util.Map; + +import androidx.annotation.AnimatorRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import dji.v5.ux.R; +import dji.v5.ux.core.util.SettingDefinitions.ControlMode; + +/** + * Displays a focus target on the screen with a scaling animation. + */ +public class FocusTargetView extends FrameLayout { + + //region Fields + /** + * The default x scaling for the center meter icon. + */ + protected static final int DEFAULT_FOCUS_TARGET_DURATION = 2500; + + private long focusTargetDuration; + private AnimatorSet scaleAnimatorSet; + private ControlMode controlMode; + private Map iconMap; + //endregion + + //region Constructor + public FocusTargetView(@NonNull Context context) { + super(context); + initView(); + } + + public FocusTargetView(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + initView(); + } + + public FocusTargetView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initView(); + } + + private void initView() { + focusTargetDuration = DEFAULT_FOCUS_TARGET_DURATION; + setAutoFocusAnimator(R.animator.uxsdk_animator_scale); + iconMap = new HashMap<>(); + iconMap.put(ControlMode.AUTO_FOCUS, getResources().getDrawable(R.drawable.uxsdk_ic_focus_target_auto)); + iconMap.put(ControlMode.AUTO_FOCUS_CONTINUE, getResources().getDrawable(R.drawable.uxsdk_ic_focus_target_auto)); + iconMap.put(ControlMode.MANUAL_FOCUS, getResources().getDrawable(R.drawable.uxsdk_ic_focus_target_manual)); + } + //endregion + + /** + * Show focus target, start the scaling animation, then hide the focus target. For manual focus, + * no scaling animation is shown. + * + * @param x position of click. + * @param y position of click. + */ + public void clickEvent(float x, float y) { + addImageBackground(controlMode); + if (getHandler() != null) { + if (controlMode != ControlMode.MANUAL_FOCUS && scaleAnimatorSet != null) { + getHandler().post(scaleAnimatorSet::start); + } else { + getHandler().postDelayed(this::removeImageBackground, focusTargetDuration); + } + } + setX(x - getWidth() / 2f); + setY(y - getHeight() / 2f); + } + + /** + * Set the focus mode + * + * @param controlMode The control mode to set + */ + public void setControlMode(@NonNull ControlMode controlMode) { + this.controlMode = controlMode; + } + + //region Customization + + /** + * Get the drawable resource that will be displayed when the {@link ControlMode} is set to the + * given value. + * + * @param controlMode A ControlMode object. + * @return The drawable resource for the icon. + */ + @Nullable + public Drawable getFocusTargetIcon(@NonNull ControlMode controlMode) { + return iconMap.get(controlMode); + } + + /** + * Set the drawable resource that will be displayed when the {@link ControlMode} is set to the + * given value. + * + * @param controlMode A ControlMode object. + * @param drawable The drawable resource for the icon. + */ + public void setFocusTargetIcon(@NonNull ControlMode controlMode, @Nullable Drawable drawable) { + iconMap.put(controlMode, drawable); + if (this.controlMode == controlMode && getBackground() != null) { + addImageBackground(controlMode); + } + } + + /** + * Sets the animator for the auto focus and auto focus continuous icons. + * + * @param animatorId The id of the animator, or 0 to remove the animation. + */ + public void setAutoFocusAnimator(@AnimatorRes int animatorId) { + if (animatorId == 0) { + scaleAnimatorSet = null; + } else { + scaleAnimatorSet = (AnimatorSet) AnimatorInflater.loadAnimator(getContext(), animatorId); + scaleAnimatorSet.setTarget(this); + scaleAnimatorSet.addListener(new AnimListener()); + } + } + + /** + * Gets the duration in milliseconds that the focus target will stay on the screen before + * disappearing. This is the amount of time after the animation completes, if any. + * + * @return The number of milliseconds the focus target will stay on the screen. + */ + public long getFocusTargetDuration() { + return focusTargetDuration; + } + + /** + * Sets the duration in milliseconds that the focus target will stay on the screen before + * disappearing. This is the amount of time after the animation completes, if any. + * + * @param duration The number of milliseconds the focus target will stay on the screen. + */ + public void setFocusTargetDuration(long duration) { + focusTargetDuration = duration; + } + + /** + * Clears the focus target icon. + */ + public void removeImageBackground() { + int sdk = android.os.Build.VERSION.SDK_INT; + if (sdk < android.os.Build.VERSION_CODES.JELLY_BEAN) { + setBackgroundDrawable(null); + } else { + setBackground(null); + } + } + //endregion + + //region Helpers + private void addImageBackground(ControlMode controlMode) { + setBackground(iconMap.get(controlMode)); + } + + /** + * Listener for animation set + * Clears out background when animations finish + */ + private class AnimListener implements Animator.AnimatorListener { + + @Override + public void onAnimationStart(Animator animation) { + // do nothing + } + + @Override + public void onAnimationEnd(Animator animation) { + if (getHandler() != null) { + getHandler().postDelayed(FocusTargetView.this::removeImageBackground, focusTargetDuration); + } + } + + @Override + public void onAnimationCancel(Animator animation) { + // do nothing + } + + @Override + public void onAnimationRepeat(Animator animation) { + // do nothing + } + } + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/fpvinteraction/GimbalControlView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/fpvinteraction/GimbalControlView.java new file mode 100644 index 00000000..fb6a8d7d --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/cameracore/widget/fpvinteraction/GimbalControlView.java @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.cameracore.widget.fpvinteraction; + +import android.app.Service; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Vibrator; +import android.util.AttributeSet; +import android.widget.FrameLayout; +import android.widget.ImageView; + +import androidx.annotation.IntRange; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.v5.ux.R; + +/** + * Displays controls for rotating the gimbal. + */ +public class GimbalControlView extends FrameLayout { + + //region Fields + /** + * The default duration for the vibration when the gimbal controls appear. + */ + protected static final int DEFAULT_VIBRATION_DURATION = 100; + + private ImageView gimbalPoint; + private ImageView gimbalMove; + private ImageView gimbalArrow; + + private Vibrator vibrator; + private int gimbalArrowW = 0; + private int gimbalArrowH = 0; + + private boolean isVibrationEnabled; + private int vibrationDuration; + //endregion + + //region Constructor + public GimbalControlView(@NonNull Context context) { + super(context); + initView(context); + } + + public GimbalControlView(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + initView(context); + } + + public GimbalControlView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initView(context); + } + + public void initView(Context context) { + inflate(context, R.layout.uxsdk_view_gimbal_control, this); + gimbalPoint = findViewById(R.id.gimbal_control_point); + gimbalMove = findViewById(R.id.gimbal_control_move); + gimbalArrow = findViewById(R.id.gimbal_control_arrow); + + if (!isInEditMode()){ + vibrator = (Vibrator) context.getSystemService(Service.VIBRATOR_SERVICE); + } + isVibrationEnabled = true; + vibrationDuration = DEFAULT_VIBRATION_DURATION; + } + //endregion + + /** + * Show the gimbal controls and vibrate. + * + * @param x position at which to show the gimbal point. + * @param y position at which to show the gimbal point. + */ + public void show(float x, float y) { + gimbalPoint.setX(x - (gimbalPoint.getWidth() / 2f)); + gimbalPoint.setY(y - (gimbalPoint.getHeight() / 2f)); + gimbalMove.setX(x - (gimbalMove.getWidth() / 2f)); + gimbalMove.setY(y - (gimbalMove.getHeight() / 2f)); + gimbalPoint.setVisibility(VISIBLE); + gimbalMove.setVisibility(VISIBLE); + + if (gimbalArrowW == 0) { + gimbalArrowW = gimbalArrow.getWidth(); + gimbalArrowH = gimbalArrow.getHeight(); + } + vibrator.vibrate(vibrationDuration); + } + + /** + * Hide the gimbal controls. + */ + public void hide() { + if (isVisible()) { + gimbalPoint.setVisibility(GONE); + gimbalMove.setVisibility(GONE); + gimbalArrow.setVisibility(GONE); + } + } + + /** + * Get whether the gimbal controls are visible. + * + * @return `true` if the gimbal controls are visible, `false` otherwise. + */ + public boolean isVisible() { + return gimbalPoint.getVisibility() == VISIBLE; + } + + /** + * Move the gimbal move icon to a new position and update the arrow icon's location and + * direction. + * + * @param firstX The location of the gimbal point. + * @param firstY The location of the gimbal point. + * @param x The location the gimbal move icon was moved to. + * @param y The location the gimbal move icon was moved to. + * @param canRotateGimbalYaw Whether the connected gimbal is able to move in the yaw direction. + */ + public void onMove(float firstX, float firstY, float x, float y, boolean canRotateGimbalYaw) { + //move images + if (canRotateGimbalYaw) { + gimbalMove.setX(x - (gimbalMove.getWidth() / 2f)); + } + gimbalMove.setY(y - (gimbalMove.getHeight() / 2f)); + transformArrow(firstX, firstY, x, y, canRotateGimbalYaw); + } + + private void transformArrow(float firstX, float firstY, float x, float y, boolean canRotateGimbalYaw) { + float offsetX = x - firstX; + if (!canRotateGimbalYaw) { + offsetX = 0; + } + float offsetY = y - firstY; + + //distance from (firstX,firstY) to (x,y) + float curDistance = (float) Math.sqrt(offsetX * offsetX + offsetY * offsetY); + //distance from (firstX,firstY) to arrow + float dirDistance = (float) Math.pow(curDistance, 0.7); + + if (dirDistance < gimbalArrowW * 0.6f || curDistance < 1f) { + gimbalArrow.setVisibility(GONE); + } else { + gimbalArrow.setVisibility(VISIBLE); + + //offsets from (firstX,firstY) to arrow + float ratio = dirDistance / curDistance; + float dirOffsetX = offsetX * ratio; + float dirOffsetY = offsetY * ratio; + + //set arrow coordinates + gimbalArrow.setX(firstX + dirOffsetX - gimbalArrowW / 2f); + gimbalArrow.setY(firstY + dirOffsetY - gimbalArrowH / 2f); + + //set arrow opacity + float alpha = Math.min(0.7f, dirDistance / gimbalArrowW / 3); + gimbalArrow.setAlpha(alpha); + + //set arrow rotation + double angrad = Math.asin(dirOffsetY / dirDistance); + if (dirOffsetX < 0) { + angrad = Math.PI - angrad; + } + double angDeg = Math.toDegrees(angrad); + gimbalArrow.setRotation((float) angDeg); + + //set arrow size + float scale = (float) (1f + Math.min(0.5, dirDistance / gimbalArrowW / 10.0)); + gimbalArrow.setScaleX(scale); + gimbalArrow.setScaleY(scale); + } + } + + //region Customization + + /** + * Get the drawable resource for the icon that represents the point at which the gimbal + * started. + * + * @return The drawable resource for the icon. + */ + @Nullable + public Drawable getGimbalPointIcon() { + return gimbalPoint.getDrawable(); + } + + /** + * Set the drawable resource for the icon that represents the point at which the gimbal + * started. + * + * @param gimbalPointIcon The drawable resource for the icon. + */ + public void setGimbalPointIcon(@Nullable Drawable gimbalPointIcon) { + gimbalPoint.setImageDrawable(gimbalPointIcon); + } + + /** + * Get the drawable resource for the icon that represents the point towards which the gimbal + * is moving. + * + * @return The drawable resource for the icon. + */ + @Nullable + public Drawable getGimbalMoveIcon() { + return gimbalMove.getDrawable(); + } + + /** + * Set the drawable resource for the icon that represents the point towards which the gimbal + * is moving. + * + * @param gimbalMoveIcon The drawable resource for the icon. + */ + public void setGimbalMoveIcon(@Nullable Drawable gimbalMoveIcon) { + gimbalMove.setImageDrawable(gimbalMoveIcon); + } + + /** + * Get the drawable resource for the icon that represents the direction the gimbal is moving. + * + * @return The drawable resource for the icon. + */ + @Nullable + public Drawable getGimbalArrowIcon() { + return gimbalArrow.getDrawable(); + } + + /** + * Set the drawable resource for the icon that represents the direction the gimbal is moving. + * + * @param gimbalArrowIcon The drawable resource for the icon. + */ + public void setGimbalArrowIcon(@Nullable Drawable gimbalArrowIcon) { + gimbalArrow.setImageDrawable(gimbalArrowIcon); + } + + /** + * Get whether the device will vibrate when the gimbal control point appears. + * + * @return `true` if vibration is enabled, `false` otherwise. + */ + public boolean isVibrationEnabled() { + return isVibrationEnabled; + } + + /** + * Set whether the device will vibrate when the gimbal control point appears. + * + * @param vibrationEnabled `true` if vibration is enabled, `false` otherwise. + */ + public void setVibrationEnabled(boolean vibrationEnabled) { + isVibrationEnabled = vibrationEnabled; + } + + /** + * Get the duration of the vibration in milliseconds when the gimbal control point appears. + * + * @return The duration of the vibration in milliseconds. + */ + public int getVibrationDuration() { + return vibrationDuration; + } + + /** + * Set the duration of the vibration in milliseconds when the gimbal control point appears. + * + * @param vibrationDuration The duration of the vibration in milliseconds. + */ + public void setVibrationDuration(@IntRange(from = 0) int vibrationDuration) { + this.vibrationDuration = vibrationDuration; + } + + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/BaseFrameLayout.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/BaseFrameLayout.java new file mode 100644 index 00000000..a9ba2ca4 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/BaseFrameLayout.java @@ -0,0 +1,62 @@ +package dji.v5.ux.core.base; + +import android.content.Context; +import android.os.Looper; +import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.BuildConfig; + +public class BaseFrameLayout extends FrameLayout { + + private static final String TAG = BaseFrameLayout.class.getSimpleName(); + + public BaseFrameLayout(@NonNull Context context) { + super(context); + } + + public BaseFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public BaseFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public BaseFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + public void invalidate() { + if (Looper.myLooper() == Looper.getMainLooper()) { + super.invalidate(); + } else { + try { + recordInvalidateCallStack(this); + } catch (Exception e) { + LogUtils.e(TAG,"invalidate runtime error: "+e.getMessage()); + } + } + } + + public static void recordInvalidateCallStack(View view){ + view.postInvalidate(); + if (BuildConfig.DEBUG) { + LogUtils.e("recordInvalidateCallStack","recordInvalidateCallStack"); + } else { + StringBuilder stringBuilder = new StringBuilder(); + for (StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) { + stringBuilder.append(stackTraceElement); + stringBuilder.append("\n"); + } + LogUtils.e("View", " async call invalidate \n" + stringBuilder); + } + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/BaseModule.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/BaseModule.kt new file mode 100644 index 00000000..a97d7cf5 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/BaseModule.kt @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base + +import dji.sdk.keyvalue.key.DJIKey +import io.reactivex.rxjava3.functions.Consumer +import dji.v5.ux.core.util.DataProcessor + +/** + * Base module class for grouping sets of data that are often used together. + * Module生命周期已经刷新,依赖于widgetModel的刷新 + */ +abstract class BaseModule { + + //region Lifecycle + /** + * Setup method for initialization that must be implemented + */ + protected abstract fun setup(widgetModel: WidgetModel) + + /** + * Cleanup method for post-usage destruction that must be implemented + */ + protected abstract fun cleanup() + //endregion + + /** + * Bind the given DJIKey to the given data processor and attach the given consumer to it. + * The data processor and side effect consumer will be invoked with every update to the key. + * The side effect consumer will be called before the data processor is updated. + * + * @param key DJIKey to be bound + * @param dataProcessor DataProcessor to be bound + * @param sideEffectConsumer Consumer to be called along with data processor + */ + protected open fun bindDataProcessor( + widgetModel: WidgetModel, + key: DJIKey, + dataProcessor: DataProcessor, + sideEffectConsumer: Consumer = Consumer {} + ) { + widgetModel.bindDataProcessor(key, dataProcessor, sideEffectConsumer) + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/BaseView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/BaseView.java new file mode 100644 index 00000000..63638bdd --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/BaseView.java @@ -0,0 +1,42 @@ +package dji.v5.ux.core.base; + +import android.content.Context; +import android.os.Looper; +import android.util.AttributeSet; +import android.view.View; + +import androidx.annotation.Nullable; + +import dji.v5.utils.common.LogUtils; + +public class BaseView extends View { + private static final String TAG = BaseView.class.getSimpleName(); + public BaseView(Context context) { + super(context); + } + + public BaseView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public BaseView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public BaseView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + @Override + public void invalidate() { + if (Looper.myLooper() == Looper.getMainLooper()) { + super.invalidate(); + } else { + try { + BaseFrameLayout.recordInvalidateCallStack(this); + } catch (Exception e) { + LogUtils.e(TAG,"invalidate catch runtime error: "+e.getMessage()); + } + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/CameraWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/CameraWidgetModel.java new file mode 100644 index 00000000..d2d497a4 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/CameraWidgetModel.java @@ -0,0 +1,36 @@ +package dji.v5.ux.core.base; + +import androidx.annotation.NonNull; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; + + +public abstract class CameraWidgetModel extends WidgetModel implements ICameraIndex { + + protected ComponentIndexType cameraIndex = ComponentIndexType.LEFT_OR_MAIN; + protected CameraLensType lensType = CameraLensType.CAMERA_LENS_ZOOM; + + protected CameraWidgetModel(@NonNull DJISDKModel djiSdkModel, @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + } + + @NonNull + @Override + public ComponentIndexType getCameraIndex() { + return cameraIndex; + } + + @NonNull + @Override + public CameraLensType getLensType() { + return lensType; + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + this.cameraIndex = cameraIndex; + this.lensType = lensType; + restart(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/CompassCalibrationDialog.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/CompassCalibrationDialog.java new file mode 100644 index 00000000..714f177d --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/CompassCalibrationDialog.java @@ -0,0 +1,287 @@ +package dji.v5.ux.core.base; + +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StyleRes; + + +import dji.sdk.keyvalue.key.FlightControllerKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.utils.ProductUtil; +import dji.sdk.keyvalue.value.common.EmptyMsg; +import dji.sdk.keyvalue.value.flightcontroller.CompassCalibrationState; +import dji.v5.common.callback.CommonCallbacks; +import dji.v5.common.error.IDJIError; +import dji.v5.manager.KeyManager; +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.R; +import dji.v5.ux.core.ui.setting.dialog.BaseDialog; + +import dji.v5.ux.core.util.ViewUtil; + + +/** + * Compass校准弹窗 + * + */ + +public class CompassCalibrationDialog extends BaseDialog implements View.OnClickListener { + + private View rootView; + + private boolean isCalibrating = true; + + private CompassCalibrationState mLastState = CompassCalibrationState.UNKNOWN; + /** + * 指南针校准是否正常结束 + */ + private boolean mFinish; + + private TextView mTitleTv; + private TextView mStepTv; + private ImageView mIllustationIv; + private View mBottomDivider; + private TextView mRightBtn; + private TextView mLeftBtn; + + + private void initView(View view ) { + mTitleTv = view.findViewById(R.id.compass_calibration_title); + mStepTv = view.findViewById(R.id.compass_calibration_step); + mIllustationIv = view.findViewById(R.id.compass_calibration_illustration); + mBottomDivider = view.findViewById(R.id.compass_calibration_bottom_divider); + mRightBtn = view.findViewById(R.id.compass_calibration_right_btn); + mRightBtn.setOnClickListener(this); + mLeftBtn = view.findViewById(R.id.compass_calibration_left_btn); + mLeftBtn.setOnClickListener(this); + } + + private static int[] aircraftCompassIconM30 = new int[] {R.drawable.uxsdk_fpv_compass_horizontal_m30, R.drawable.uxsdk_fpv_compass_vertical_m30}; + private static int[] aircraftCompassIconM300 = new int[] {R.drawable.uxsdk_fpv_compass_horizontal_m300, R.drawable.uxsdk_fpv_compass_vertical_m300}; + private static int[] aircraftCompassIconM3 = new int[] {R.drawable.uxsdk_fpv_compass_horizontal_m3e, R.drawable.uxsdk_fpv_compass_vertical_m3e}; + + public CompassCalibrationDialog(@NonNull Context context) { + this(context, R.style.NoTitleDialog); + } + + public CompassCalibrationDialog(@NonNull Context context, @StyleRes int themeResId) { + super(context, themeResId); + initialize(context); + } + + protected CompassCalibrationDialog(@NonNull Context context, boolean cancelable, @Nullable OnCancelListener cancelListener) { + super(context, cancelable, cancelListener); + initialize(context); + } + + private void initialize(Context context) { + rootView = LayoutInflater.from(context).inflate(R.layout.uxsdk_dialog_compass_calibration, null); + initView(rootView); + + // 初始化先显示水平的图片 + updateNoticeImage(getIllustrationResIdByAircraft(CompassCalibrationState.HORIZONTAL)); + } + + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(rootView); + setCancelable(false); + setCanceledOnTouchOutside(false); + } + + @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + + + KeyManager.getInstance().listen(KeyTools.createKey(FlightControllerKey.KeyIsCompassCalibrating), this, (oldValue, newValue) -> { + isCalibrating = newValue != null; + checkCompassCalibrationState(); + }); + + + KeyManager.getInstance().listen(KeyTools.createKey(FlightControllerKey.KeyCompassCalibrationStatus), this, (oldValue, state) -> { + mFinish = state == CompassCalibrationState.SUCCEEDED || state == CompassCalibrationState.FAILED; + mLastState = state; + if (state != CompassCalibrationState.UNKNOWN && state != CompassCalibrationState.IDLE) { + updateViews(state); + } else { + checkCompassCalibrationState(); + } + }); + + + + KeyManager.getInstance().listen(KeyTools.createKey(FlightControllerKey.KeyConnection), this, (oldValue, connection) -> { + if (connection != null && !connection) { + dismiss(); + } + }); + + } + + /** + * 非正常结束指南针校准时,dismiss 该 dialog(如拨动遥控器档位开关) + */ + private void checkCompassCalibrationState() { + if (!mFinish && !isCalibrating && mLastState == CompassCalibrationState.IDLE) { + dismiss(); + } + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + KeyManager.getInstance().cancelListen(this); + } + + @Override + public int getDialogWidth() { + return (int) getContext().getResources().getDimension(R.dimen.uxsdk_dialog_update_width); + } + + @Override + public int getDialogMaxHeight() { + return AndUtil.getLandScreenHeight(getContext()); + } + + + @Override + public void onClick(View view) { + if (view.getId() == R.id.compass_calibration_left_btn) { + if (isCalibrating) { + KeyManager.getInstance().performAction(KeyTools.createKey(FlightControllerKey.KeyStopCompassCalibration), new CommonCallbacks.CompletionCallbackWithParam() { + @Override + public void onSuccess(EmptyMsg emptyMsg) { + //do something + } + + @Override + public void onFailure(@NonNull IDJIError error) { + // add log + } + }); + } + dismiss(); + } else { + KeyManager.getInstance().performAction(KeyTools.createKey(FlightControllerKey.KeyStopCompassCalibration), new CommonCallbacks.CompletionCallbackWithParam() { + @Override + public void onSuccess(EmptyMsg emptyMsg) { + startCali(); + } + + @Override + public void onFailure(@NonNull IDJIError error) { + // add log + } + }); + } + } + + + private void startCali(){ + KeyManager.getInstance().performAction(KeyTools.createKey(FlightControllerKey.KeyStartCompassCalibration), new CommonCallbacks.CompletionCallbackWithParam() { + @Override + public void onSuccess(EmptyMsg emptyMsg) { + //ViewUtil.showToast(getContext() , R.string.uxsdk_setting_ui_flyc_cali_begin , Toast.LENGTH_SHORT); + } + + @Override + public void onFailure(@NonNull IDJIError error) { + ViewUtil.showToast(getContext() , R.string.uxsdk_app_check_aircraft_connection , Toast.LENGTH_SHORT); + } + }); + } + private void updateViews(CompassCalibrationState status) { + String title; + + if (status == CompassCalibrationState.HORIZONTAL) { + title = getContext().getString(R.string.uxsdk_fpv_checklist_compass_tip_1); + + mTitleTv.setText(title); + + // 跟飞机型号有关 + mStepTv.setVisibility(View.VISIBLE); + mStepTv.setText(getStepResIdByAircraft(status)); + updateNoticeImage(getIllustrationResIdByAircraft(status)); + + mLeftBtn.setText(R.string.uxsdk_fpv_checklist_cancel_cele); + mRightBtn.setVisibility(View.GONE); + mBottomDivider.setVisibility(View.GONE); + } else if (status == CompassCalibrationState.VERTICAL) { + title = getContext().getString(R.string.uxsdk_fpv_checklist_compass_tip_2); + + mTitleTv.setText(title); + + // 跟飞机型号有关 + mStepTv.setVisibility(View.VISIBLE); + mStepTv.setText(getStepResIdByAircraft(status)); + updateNoticeImage(getIllustrationResIdByAircraft(status)); + + mLeftBtn.setText(R.string.uxsdk_fpv_checklist_cancel_cele); + mRightBtn.setVisibility(View.GONE); + mBottomDivider.setVisibility(View.GONE); + } else if (status == CompassCalibrationState.SUCCEEDED) { + mTitleTv.setText(R.string.uxsdk_fpv_compass_adjust_complete); + mStepTv.setVisibility(View.GONE); + updateNoticeImage(R.drawable.uxsdk_setting_ui_success); + mLeftBtn.setText(R.string.uxsdk_app_ok); + mRightBtn.setVisibility(View.GONE); + mBottomDivider.setVisibility(View.GONE); + } else if (status == CompassCalibrationState.FAILED) { + mTitleTv.setText(R.string.uxsdk_fpv_compass_adjust_fail); + mStepTv.setVisibility(View.GONE); + updateNoticeImage(R.drawable.uxsdk_setting_ui_fail); + mLeftBtn.setText(R.string.uxsdk_app_cancel); + mRightBtn.setVisibility(View.VISIBLE); + mBottomDivider.setVisibility(View.VISIBLE); + } + } + + private void updateNoticeImage(@DrawableRes int resId) { + ViewGroup.MarginLayoutParams params = (ViewGroup.MarginLayoutParams)mIllustationIv.getLayoutParams(); + params.topMargin = 0; + params.bottomMargin = 0; + if (resId == R.drawable.uxsdk_setting_ui_success || resId == R.drawable.uxsdk_setting_ui_fail) { + params.topMargin = getContext().getResources().getDimensionPixelSize(R.dimen.uxsdk_dialog_content_margin_top); + params.bottomMargin = getContext().getResources().getDimensionPixelSize(R.dimen.uxsdk_dialog_content_margin_top); + } + mIllustationIv.setImageResource(resId); + } + private int getStepResIdByAircraft(CompassCalibrationState status) { + if (status == CompassCalibrationState.HORIZONTAL) { + return R.string.uxsdk_fpv_checklist_compass_tip_1_desc; + } else { + return R.string.uxsdk_fpv_checklist_compass_tip_2_desc; + } + } + + private int getIllustrationResIdByAircraft(CompassCalibrationState status) { + int[] resIds; + if(ProductUtil.isM30Product()){ + resIds = aircraftCompassIconM30; + } else if (ProductUtil.isM3EProduct() || ProductUtil.isM4EProduct() || ProductUtil.isM4DProduct()) { + resIds = aircraftCompassIconM3; + } else{ + resIds = aircraftCompassIconM300; + } + if(status == CompassCalibrationState.HORIZONTAL) { + return resIds[0]; + } else { + return resIds[1]; + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/CompassStatusWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/CompassStatusWidget.java new file mode 100644 index 00000000..92656b88 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/CompassStatusWidget.java @@ -0,0 +1,301 @@ +package dji.v5.ux.core.base; +/* + * Copyright (c) 2017, DJI All Rights Reserved. + */ + +import android.content.Context; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.SparseLongArray; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.constraintlayout.widget.Group; +import androidx.core.content.ContextCompat; + + +import java.util.ArrayList; +import java.util.List; + +import dji.sdk.keyvalue.key.FlightControllerKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.key.ProductKey; +import dji.sdk.keyvalue.value.common.EmptyMsg; +import dji.sdk.keyvalue.value.flightcontroller.CompassSensorState; +import dji.sdk.keyvalue.value.flightcontroller.CompassState; +import dji.sdk.keyvalue.value.flightcontroller.RedundancySensorUsedStateMsg; +import dji.sdk.keyvalue.value.product.ProductType; +import dji.v5.common.callback.CommonCallbacks; +import dji.v5.common.error.IDJIError; +import dji.v5.manager.KeyManager; +import dji.v5.manager.aircraft.simulator.SimulatorManager; +import dji.v5.ux.R; +import dji.v5.ux.core.util.ViewUtil; + + +public class CompassStatusWidget extends ConstraintLayout { + + private static final int THREE_COMPASS = 3; + + private int[] mCompassStasActionStrIds = new int[] { + R.string.uxsdk_setting_ui_redundancy_sensor_compass_stat_action_0, + R.string.uxsdk_setting_ui_redundancy_sensor_compass_stat_empty, + R.string.uxsdk_setting_ui_redundancy_sensor_compass_stat_empty, + R.string.uxsdk_setting_ui_redundancy_sensor_compass_stat_action_3, + R.string.uxsdk_setting_ui_redundancy_sensor_compass_stat_action_4, + R.string.uxsdk_setting_ui_redundancy_sensor_compass_stat_empty, + R.string.uxsdk_setting_ui_redundancy_sensor_compass_stat_empty, + R.string.uxsdk_setting_ui_redundancy_sensor_compass_stat_action_7, + R.string.uxsdk_setting_ui_redundancy_sensor_compass_stat_action_8, + R.string.uxsdk_setting_ui_redundancy_sensor_compass_stat_action_9 }; + + + Group mSettingUiFlycCompassLy2; + + Group mSettingUiFlycCompassLy3; + + List mSettingUiFlycTitles = new ArrayList<>(); + + List mSettingUiFlyValues = new ArrayList<>(); + + List mSettingUiFlyDescs = new ArrayList<>(); + + + private void initView() { + mSettingUiFlycCompassLy2 = findViewById(R.id.setting_ui_flyc_compass_ly2); + + mSettingUiFlycCompassLy3 = findViewById(R.id.setting_ui_flyc_compass_ly3); + + mSettingUiFlycTitles.add(findViewById(R.id.setting_ui_flyc_compass_1_txt)); + mSettingUiFlycTitles.add(findViewById(R.id.setting_ui_flyc_compass_2_txt)); + mSettingUiFlycTitles.add(findViewById(R.id.setting_ui_flyc_compass_3_txt)); + + + mSettingUiFlyValues.add(findViewById(R.id.setting_ui_flyc_compass_1_progress)); + mSettingUiFlyValues.add(findViewById(R.id.setting_ui_flyc_compass_2_progress)); + mSettingUiFlyValues.add(findViewById(R.id.setting_ui_flyc_compass_3_progress)); + + mSettingUiFlyDescs.add(findViewById(R.id.setting_ui_flyc_compass_1_desc)); + mSettingUiFlyDescs.add(findViewById(R.id.setting_ui_flyc_compass_2_desc)); + mSettingUiFlyDescs.add(findViewById(R.id.setting_ui_flyc_compass_3_desc)); + + findViewById(R.id.setting_menu_compass_calibrate).setOnClickListener(view -> startCompassCalibrating()); + + } + + private boolean mAreMotorOn; + private boolean mSimulatorStarted; + private List mCompassStateList; + private RedundancySensorUsedStateMsg mSensorUsedState; + private CompassCalibrationDialog mCalibrationDialog; + + public CompassStatusWidget(Context context) { + this(context, null); + } + + public CompassStatusWidget(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public CompassStatusWidget(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(context); + } + + private void initialize(Context context) { + inflate(context, R.layout.uxsdk_setting_menu_compass_status_layout, this); + initView(); + mSettingUiFlycTitles.get(0).setSelected(true); + } + + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if(isInEditMode()) { + return; + } + + KeyManager.getInstance().getValue(KeyTools.createKey(ProductKey.KeyProductType), new CommonCallbacks.CompletionCallbackWithParam() { + @Override + public void onSuccess(ProductType productType) { + updateViewsByState(); + } + + @Override + public void onFailure(@NonNull IDJIError error) { + //add log + } + }); + + + KeyManager.getInstance().listen(KeyTools.createKey(FlightControllerKey.KeyCompassState), this, (oldValue, newValue) -> { + mCompassStateList = newValue; + updateViewsByState(); + }); + + + KeyManager.getInstance().listen(KeyTools.createKey(FlightControllerKey.KeyRedundancySensorUsedState), this, (oldValue, newValue) -> { + mSensorUsedState = newValue; + updateSelectedSensor(mSensorUsedState.getMagIndex()); + }); + + + //是否起浆 + KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyAreMotorsOn), new CommonCallbacks.CompletionCallbackWithParam() { + @Override + public void onSuccess(Boolean isOn) { + mAreMotorOn = isOn; + } + + @Override + public void onFailure(@NonNull IDJIError error) { + //add log + } + }); + //是否开启模拟器 + mSimulatorStarted = SimulatorManager.getInstance().isSimulatorEnabled(); + + KeyManager.getInstance().listen(KeyTools.createKey(FlightControllerKey.KeyIsCompassCalibrating), this, (oldValue, newValue) -> { + if (newValue != null && newValue) { + showCompassCalibrationDialog(getContext()); + } + }); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + KeyManager.getInstance().cancelListen(this); + } + + protected void startCompassCalibrating() { + + if (!KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyConnection) ,false)) { + ViewUtil.showToast(getContext() , R.string.uxsdk_app_check_aircraft_connection , Toast.LENGTH_SHORT); + return; + } + if (mAreMotorOn) { + ViewUtil.showToast(getContext() ,R.string.uxsdk_setting_ui_redundance_compass_cal_tip , Toast.LENGTH_SHORT); + } else if (mSimulatorStarted) { + ViewUtil.showToast(getContext() ,R.string.uxsdk_setting_ui_compass_cal_in_sim_tip , Toast.LENGTH_SHORT); + } else if (!isFastClick(R.id.setting_menu_compass_calibrate, 500)) { + KeyManager.getInstance().performAction(KeyTools.createKey(FlightControllerKey.KeyStartCompassCalibration), new CommonCallbacks.CompletionCallbackWithParam() { + @Override + public void onSuccess(EmptyMsg emptyMsg) { + ViewUtil.showToast(getContext() , R.string.uxsdk_setting_ui_flyc_cali_begin , Toast.LENGTH_SHORT); + } + + @Override + public void onFailure(@NonNull IDJIError error) { + ViewUtil.showToast(getContext() , R.string.uxsdk_setting_ui_flyc_cali_failed , Toast.LENGTH_SHORT); + } + }); + } + + + + + } + + private void updateSelectedSensor(int index) { + for (int i = 0; i < THREE_COMPASS; ++i) { + mSettingUiFlycTitles.get(i).setSelected(index == (i+1)); + } + } + + private void updateViewsByState() { + if (mCompassStateList == null) { + return; + } + for (int i = 0; i < mCompassStateList.size(); i++) { + CompassState compassState = mCompassStateList.get(i); + ProgressStatusWidget statusView = mSettingUiFlyValues.get(i); + TextView tvDesc = mSettingUiFlyDescs.get(i); + updateSettingUiFlyCompassLy(i, compassState); + updateCompassStateView(compassState, statusView); + + int compassSensorStateValue = compassState.getCompassSensorState() == CompassSensorState.UNKNOWN + ? 0 : compassState.getCompassSensorState().value(); + if (compassSensorStateValue >= 0 && compassSensorStateValue < mCompassStasActionStrIds.length) { + tvDesc.setText(mCompassStasActionStrIds[compassSensorStateValue]); + } + + if (compassState.getCompassSensorValue() != -1) { + statusView.setValue(String.valueOf(compassState.getCompassSensorValue())); + statusView.mProgressBar.setProgress((int) (compassState.getCompassSensorValue() * 1.0f / 999 * 100)); + } else { + updateCompassSensorErrorStateView(statusView, tvDesc, compassSensorStateValue); + } + + if (TextUtils.isEmpty(tvDesc.getText())){ + tvDesc.setVisibility(GONE); + } + } + // 一个指南针的情况下内置指南针显示为指南针,多个指南针的情况下内置指南针显示为指南针1 + if (mSettingUiFlycCompassLy2.getVisibility() == VISIBLE || mSettingUiFlycCompassLy3.getVisibility() == VISIBLE) { + mSettingUiFlycTitles.get(0).setText(R.string.uxsdk_setting_ui_redundancy_sensor_compass1_label); + } else { + mSettingUiFlycTitles.get(0).setText(R.string.uxsdk_setting_ui_redundancy_sensor_compass); + } + } + + private void updateSettingUiFlyCompassLy(int i, CompassState compassState) { + boolean visible = compassState.getCompassSensorState() != CompassSensorState.DISCONNECTED; + if (i == 1) { + mSettingUiFlycCompassLy2.setVisibility(visible ? VISIBLE : GONE); + } else if (i == 2) { + mSettingUiFlycCompassLy3.setVisibility(visible ? VISIBLE : GONE); + } + } + + private void updateCompassStateView(CompassState compassState, ProgressStatusWidget statusView) { + if (compassState.getCompassSensorState() == CompassSensorState.NORMAL_MODULUS) { + statusView.setProgressDrawable(ContextCompat.getDrawable(getContext(), R.drawable.uxsdk_setting_ui_status_pgb_green)); + } else if (compassState.getCompassSensorState() == CompassSensorState.WEAK_MODULUS) { + statusView.setProgressDrawable(ContextCompat.getDrawable(getContext(), R.drawable.uxsdk_setting_ui_status_pgb_yellow)); + } else if (compassState.getCompassSensorState() == CompassSensorState.SERIOUS_MODULUS) { + statusView.setProgressDrawable(ContextCompat.getDrawable(getContext(), R.drawable.uxsdk_setting_ui_status_pgb_red)); + } + + statusView.mProgressBar.setVisibility(View.VISIBLE); + statusView.mValueView.setVisibility(View.VISIBLE); + } + + private void updateCompassSensorErrorStateView(ProgressStatusWidget statusView, TextView tvDesc, int compassSensorStateValue) { + if (compassSensorStateValue >= 0 && compassSensorStateValue < mCompassStasActionStrIds.length) { + tvDesc.setText(mCompassStasActionStrIds[compassSensorStateValue]); + tvDesc.setVisibility(View.VISIBLE); + if (compassSensorStateValue == 1) { + statusView.mProgressBar.setVisibility(View.GONE); + statusView.mValueView.setVisibility(View.GONE); + } + } else { + tvDesc.setVisibility(View.GONE); + } + } + private SparseLongArray sClickTimes = new SparseLongArray(); + public boolean isFastClick(int viewId, int duration) { + long prevTime = sClickTimes.get(viewId); + long now = System.currentTimeMillis(); + boolean isFast = now - prevTime < duration; + if (!isFast) { + sClickTimes.put(viewId, now); + } + return isFast; + } + + public void showCompassCalibrationDialog(Context context) { + if (mCalibrationDialog == null) { + mCalibrationDialog = new CompassCalibrationDialog(context); + mCalibrationDialog.setOnDismissListener(dialog -> mCalibrationDialog = null); + } + + if (! mCalibrationDialog.isShowing()) { + mCalibrationDialog.show(); + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/DJISDKModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/DJISDKModel.java new file mode 100644 index 00000000..979cae11 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/DJISDKModel.java @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.sdk.keyvalue.key.DJIKey; +import dji.v5.common.utils.RxUtil; +import dji.v5.manager.KeyManager; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.core.Single; + +/** + * Encapsulates communication with SDK KeyManager for SDKKeys. + */ +public class DJISDKModel { + + private DJISDKModel() { + } + + public static DJISDKModel getInstance() { + return SingletonHolder.instance; + } + + /** + * Stops observing changes of all keys registered for the given listener. + * + * @param listener The listener to unregister. + */ + public void removeListener(@NonNull final Object listener) { + RxUtil.removeListener(listener); + } + + /** + * Subscribes the listener object to all changes of value on the given key. + * + * @param key A valid value-based key (get, set and/or action) + * @param listener Listener that is subscribing. + * @return A flowable that emits objects based on a key. + */ + @NonNull + public Flowable addListener(@NonNull final DJIKey key, @NonNull final Object listener) { + return RxUtil.addListener(key, listener); + } + + /** + * Performs a get on a gettable key, pulling the information from the product if + * necessary. + * + * @param key A valid gettable key. + * @return A single that emits one object based on a key. + */ + @NonNull + public Single getValue(@NonNull final DJIKey key) { + return RxUtil.getValue(key); + } + + /** + * Returns the latest known value if available for the key. Does not pull it from + * the product if unavailable. + * + * @param key An instance of DJIKey. + * @return The value associated with the key. + */ + @Nullable + public T getCacheValue(@NonNull final DJIKey key) { + return KeyManager.getInstance().getValue(key); + } + + /** + * Performs a set on a settable key, changing attributes on the connected product. + * + * @param key A valid settable key. + * @param value A value object relevant to the given key. + * @return A completable indicating success/error setting the value. + */ + @NonNull + public Completable setValue(@NonNull final DJIKey key, @NonNull final T value) { + return RxUtil.setValue(key, value); + } + + /** + * Performs an action on an actionable key. + * + * @param key A valid actionable key. + * @param argument Optional arguments relevant to the specific key. + * @return A completable indicating success/error performing the action. + */ + @NonNull + public Completable performActionWithOutResult(@NonNull final DJIKey.ActionKey key, + final Param argument) { + return RxUtil.performActionWithOutResult(key, argument); + } + + @NonNull + public Completable performActionWithOutResult(@NonNull final DJIKey.ActionKey key) { + return performActionWithOutResult(key, null); + } + + /** + * Determines if a key is supported by the connected product. + * + * @param key Key to be check on current product. + * @return `true` if the key is supported. + */ + public boolean isKeySupported(DJIKey key) { + return KeyManager.getInstance().isKeySupported(key); + } + + + private static class SingletonHolder { + private static final DJISDKModel instance = new DJISDKModel(); + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/DividerConstraintLayout.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/DividerConstraintLayout.java new file mode 100644 index 00000000..445a8c58 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/DividerConstraintLayout.java @@ -0,0 +1,118 @@ +package dji.v5.ux.core.base; +/* + * Copyright (c) 2017, DJI All Rights Reserved. + */ + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.util.AttributeSet; + +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.core.content.ContextCompat; + +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.R; + + +public class DividerConstraintLayout extends ConstraintLayout implements DividerLayout{ + + private boolean mTopDividerEnable; + private boolean mBottomDividerEnable; + private int mTopDividerColor; + private int mBottomDividerColor; + private int mTopDividerHeight; + private int mBottomDividerHeight; + private int mTopDividerMarginLeft; + private int mBottomDividerMarginLeft; + private Paint sPaint = new Paint(); + + public DividerConstraintLayout(Context context) { + this(context, null); + } + + public DividerConstraintLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public DividerConstraintLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(context, attrs); + } + + private void initialize(Context context, AttributeSet attrs) { + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DividerConstraintLayout); + mTopDividerEnable = a.getBoolean(R.styleable.DividerConstraintLayout_uxsdk_topDividerEnable, false); + mBottomDividerEnable = a.getBoolean(R.styleable.DividerConstraintLayout_uxsdk_bottomDividerEnable, true); + int defColor = ContextCompat.getColor(getContext(), R.color.uxsdk_white_10_percent); + mTopDividerColor = a.getColor(R.styleable.DividerConstraintLayout_uxsdk_topDividerColor, defColor); + mBottomDividerColor = a.getColor(R.styleable.DividerConstraintLayout_uxsdk_bottomDividerColor, defColor); + mTopDividerHeight = a.getDimensionPixelSize(R.styleable.DividerConstraintLayout_uxsdk_topDividerHeight, AndUtil.dip2px(context, 1)); + mBottomDividerHeight = a.getDimensionPixelSize(R.styleable.DividerConstraintLayout_uxsdk_bottomDividerHeight, AndUtil.dip2px(context, 1)); + mTopDividerMarginLeft = a.getDimensionPixelSize(R.styleable.DividerConstraintLayout_uxsdk_topDividerMarginLeft, 0); + mBottomDividerMarginLeft = a.getDimensionPixelSize(R.styleable.DividerConstraintLayout_uxsdk_bottomDividerMarginLeft, 0); + sPaint.setColor(mBottomDividerColor); + a.recycle(); + setWillNotDraw(false); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (mBottomDividerEnable) { + sPaint.setColor(mBottomDividerColor); + canvas.drawRect(mBottomDividerMarginLeft, (float)getHeight() - mBottomDividerHeight, getWidth(), getHeight(), sPaint); + } + if (mTopDividerEnable) { + sPaint.setColor(mTopDividerColor); + canvas.drawRect(mTopDividerMarginLeft, 0, getWidth(), mTopDividerHeight, sPaint); + } + } + + @Override + public void setTopDividerEnable(boolean enabled) { + mTopDividerEnable = enabled; + invalidate(); + } + + @Override + public void setBottomDividerEnable(boolean enabled) { + mBottomDividerEnable = enabled; + invalidate(); + } + + @Override + public void setTopDividerColor(int color) { + //do nothing + } + + @Override + public void setBottomDividerColor(int color) { + mBottomDividerColor = color; + invalidate(); + } + + @Override + public void setTopDividerHeight(int height) { + //do nothing + } + + @Override + public void setBottomDividerHeight(int height) { + mBottomDividerHeight = height; + invalidate(); + } + + @Override + public void setTopMarginLeft(int marginLeft) { + mTopDividerMarginLeft = marginLeft; + invalidate(); + } + + @Override + public void setBottomMarginLeft(int marginLeft) { + mBottomDividerMarginLeft = marginLeft; + invalidate(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/DividerLayout.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/DividerLayout.java new file mode 100644 index 00000000..52779e83 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/DividerLayout.java @@ -0,0 +1,66 @@ +package dji.v5.ux.core.base; +/* + * WWWWWW||WWWWWW + * W W W||W W W + * || + * ( OO )__________ + * / | \ + * /o o| DJI \ + * \___/||_||__||_|| ** + * || || || || + * _||_|| _||_|| + * (__|__|(__|__| + * + * Copyright (c) 2017, DJI All Rights Reserved. + */ + +public interface DividerLayout { + + /** + * 设置顶部分割线是否可见 + * @param enabled + */ + void setTopDividerEnable(boolean enabled); + + /** + * 设置底部分割线是否可见 + * @param enabled + */ + void setBottomDividerEnable(boolean enabled); + + /** + * 设置顶部分割线颜色 + * @param color + */ + void setTopDividerColor(int color); + + /** + * 设置底部分割线颜色 + * @param color + */ + void setBottomDividerColor(int color); + + /** + * 设置顶部分割线高度 + * @param height + */ + void setTopDividerHeight(int height); + + /** + * 设置底部分线高度 + * @param height + */ + void setBottomDividerHeight(int height); + + /** + * 设置顶部分割线距离左侧的距离 + * @param marginLeft + */ + void setTopMarginLeft(int marginLeft); + + /** + * 设置底部分割线距离左侧的距离 + * @param marginLeft + */ + void setBottomMarginLeft(int marginLeft); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/DividerLinearLayout.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/DividerLinearLayout.java new file mode 100644 index 00000000..36a5bf20 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/DividerLinearLayout.java @@ -0,0 +1,118 @@ +package dji.v5.ux.core.base; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.os.Build; +import android.util.AttributeSet; +import android.widget.LinearLayout; + +import androidx.annotation.Nullable; + +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.R; + + +public class DividerLinearLayout extends LinearLayout implements DividerLayout{ + + private boolean mTopDividerEnable; + private boolean mBottomDividerEnable; + private int mBottomDividerColor; + private int mBottomDividerHeight; + private int mTopDividerMarginLeft; + private int mBottomDividerMarginLeft; + private Paint sPaint = new Paint(); + + public DividerLinearLayout(Context context) { + this(context, null); + } + + public DividerLinearLayout(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public DividerLinearLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(context, attrs); + } + + @SuppressWarnings("unused") + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public DividerLinearLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + initialize(context, attrs); + } + + private void initialize(Context context, AttributeSet attrs) { + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DividerLinearLayout); + mTopDividerEnable = a.getBoolean(R.styleable.DividerLinearLayout_uxsdk_topDividerEnable, false); + mBottomDividerEnable = a.getBoolean(R.styleable.DividerLinearLayout_uxsdk_bottomDividerEnable, true); + int defColor = getResources().getColor(R.color.uxsdk_dic_color_c20_divider); + mBottomDividerColor = a.getColor(R.styleable.DividerLinearLayout_uxsdk_bottomDividerColor, defColor); + mBottomDividerHeight = a.getDimensionPixelSize(R.styleable.DividerLinearLayout_uxsdk_bottomDividerHeight, AndUtil.dip2px(context, 1)); + mTopDividerMarginLeft = a.getDimensionPixelSize(R.styleable.DividerLinearLayout_uxsdk_topDividerMarginLeft, 0); + mBottomDividerMarginLeft = a.getDimensionPixelSize(R.styleable.DividerLinearLayout_uxsdk_bottomDividerMarginLeft, 0); + sPaint.setColor(mBottomDividerColor); + a.recycle(); + setWillNotDraw(false); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (mBottomDividerEnable) { + canvas.drawRect(mBottomDividerMarginLeft, getHeight() - (float)mBottomDividerHeight, getWidth(), getHeight(), sPaint); + } + if (mTopDividerEnable) { + canvas.drawRect(mTopDividerMarginLeft, 0, getWidth(), mBottomDividerHeight, sPaint); + } + } + + @Override + public void setTopDividerEnable(boolean enabled) { + mTopDividerEnable = enabled; + invalidate(); + } + + @Override + public void setBottomDividerEnable(boolean enabled) { + mBottomDividerEnable = enabled; + invalidate(); + } + + @Override + public void setTopDividerColor(int color) { + //add log + } + + @Override + public void setBottomDividerColor(int color) { + mBottomDividerColor = color; + invalidate(); + } + + @Override + public void setTopDividerHeight(int height) { + //add log + } + + @Override + public void setBottomDividerHeight(int height) { + mBottomDividerHeight = height; + invalidate(); + } + + @Override + public void setTopMarginLeft(int marginLeft) { + mTopDividerMarginLeft = marginLeft; + invalidate(); + } + + @Override + public void setBottomMarginLeft(int marginLeft) { + mBottomDividerMarginLeft = marginLeft; + invalidate(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/DividerRelativeLayout.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/DividerRelativeLayout.java new file mode 100644 index 00000000..420ac702 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/DividerRelativeLayout.java @@ -0,0 +1,118 @@ +package dji.v5.ux.core.base; + +import android.annotation.TargetApi; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.os.Build; +import android.util.AttributeSet; +import android.widget.RelativeLayout; + +import androidx.annotation.Nullable; + +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.R; + + +public class DividerRelativeLayout extends RelativeLayout implements DividerLayout { + + private boolean mTopDividerEnable; + private boolean mBottomDividerEnable; + private int mBottomDividerColor; + private int mBottomDividerHeight; + private int mTopDividerMarginLeft; + private int mBottomDividerMarginLeft; + private Paint sPaint = new Paint(); + + public DividerRelativeLayout(Context context) { + this(context, null); + } + + public DividerRelativeLayout(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public DividerRelativeLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(context, attrs); + } + + @SuppressWarnings("unused") + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public DividerRelativeLayout(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + initialize(context, attrs); + } + + private void initialize(Context context, AttributeSet attrs) { + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.DividerRelativeLayout); + mTopDividerEnable = a.getBoolean(R.styleable.DividerRelativeLayout_uxsdk_topDividerEnable, false); + mBottomDividerEnable = a.getBoolean(R.styleable.DividerRelativeLayout_uxsdk_bottomDividerEnable, true); + int defColor = getResources().getColor(R.color.uxsdk_dic_color_c20_divider); + mBottomDividerColor = a.getColor(R.styleable.DividerRelativeLayout_uxsdk_bottomDividerColor, defColor); + mBottomDividerHeight = a.getDimensionPixelSize(R.styleable.DividerRelativeLayout_uxsdk_bottomDividerHeight, AndUtil.dip2px(context, 1)); + mTopDividerMarginLeft = a.getDimensionPixelSize(R.styleable.DividerRelativeLayout_uxsdk_topDividerMarginLeft, 0); + mBottomDividerMarginLeft = a.getDimensionPixelSize(R.styleable.DividerRelativeLayout_uxsdk_bottomDividerMarginLeft, 0); + sPaint.setColor(mBottomDividerColor); + a.recycle(); + setWillNotDraw(false); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (mBottomDividerEnable) { + canvas.drawRect(mBottomDividerMarginLeft, getHeight() - (float)mBottomDividerHeight, getWidth(), getHeight(), sPaint); + } + if (mTopDividerEnable) { + canvas.drawRect(mTopDividerMarginLeft, 0, getWidth(), mBottomDividerHeight, sPaint); + } + } + + @Override + public void setTopDividerEnable(boolean enabled) { + mTopDividerEnable = enabled; + invalidate(); + } + + @Override + public void setBottomDividerEnable(boolean enabled) { + mBottomDividerEnable = enabled; + invalidate(); + } + + @Override + public void setTopDividerColor(int color) { + //add log + } + + @Override + public void setBottomDividerColor(int color) { + mBottomDividerColor = color; + invalidate(); + } + + @Override + public void setTopDividerHeight(int height) { + //add log + } + + @Override + public void setBottomDividerHeight(int height) { + mBottomDividerHeight = height; + invalidate(); + } + + @Override + public void setTopMarginLeft(int marginLeft) { + mTopDividerMarginLeft = marginLeft; + invalidate(); + } + + @Override + public void setBottomMarginLeft(int marginLeft) { + mBottomDividerMarginLeft = marginLeft; + invalidate(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/EditorCell.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/EditorCell.java new file mode 100644 index 00000000..8307adc0 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/EditorCell.java @@ -0,0 +1,260 @@ +package dji.v5.ux.core.base; + +import android.content.Context; +import android.content.res.TypedArray; +import android.text.Editable; +import android.text.TextWatcher; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.View; +import android.view.inputmethod.EditorInfo; +import android.widget.EditText; +import android.widget.TextView; + +import androidx.core.content.ContextCompat; + + +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.R; + +/* + * Copyright (c) 2014, DJI All Rights Reserved. + */ + +public class EditorCell extends DividerConstraintLayout { + + protected EditText mEditor; + protected TextView mSummary; + protected TextView mTitle; + protected TextView mTips; + + private int min; + private int max; + private boolean needChangeValue = false; + + private String mOldValue; + private OnValueChangedListener mListener; + + private boolean isFocusChangeValueCallBack = true; + + public EditorCell(Context context) { + this(context, null); + } + + public EditorCell(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public EditorCell(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(context, attrs, defStyleAttr); + } + + private void initialize(Context context, AttributeSet attrs, int defStyleAttr) { + LayoutInflater.from(context).inflate(R.layout.uxsdk_cell_editor_layout, this, true); + TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.EditorCell, defStyleAttr, 0); + + mEditor = (EditText) findViewById(R.id.editor); + mEditor.setSaveEnabled(false); + mSummary = (TextView) findViewById(R.id.summary); + mTitle = (TextView) findViewById(R.id.title); + mTips = (TextView) findViewById(R.id.tips); + + if (ta.hasValue(R.styleable.EditorCell_uxsdk_title)) { + mTitle.setText(ta.getString(R.styleable.EditorCell_uxsdk_title)); + } else { + mTitle.setVisibility(GONE); + } + + if (ta.hasValue(R.styleable.EditorCell_uxsdk_summary)) { + mSummary.setText(ta.getString(R.styleable.EditorCell_uxsdk_summary)); + } else { + mSummary.setVisibility(GONE); + } + + if (ta.hasValue(R.styleable.EditorCell_uxsdk_tips)) { + mTips.setText(ta.getString(R.styleable.EditorCell_uxsdk_tips)); + } else { + mTips.setVisibility(GONE); + } + + if (ta.hasValue(R.styleable.EditorCell_uxsdk_tipsTextSize)) { + + mTips.setTextSize(TypedValue.COMPLEX_UNIT_PX,ta.getDimensionPixelSize(R.styleable.EditorCell_uxsdk_tipsTextSize, getResources().getDimensionPixelSize(R.dimen.uxsdk_horizontal_margin_medium))); + } + + if (ta.hasValue(R.styleable.EditorCell_uxsdk_titleTextSize)) { + mTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, ta.getDimensionPixelSize(R.styleable.EditorCell_uxsdk_titleTextSize, getResources().getDimensionPixelSize(R.dimen.uxsdk_dic_text_size_18sp))); + } + + if (ta.hasValue(R.styleable.EditorCell_uxsdk_summaryTextSize)) { + mTips.setTextSize(TypedValue.COMPLEX_UNIT_PX, ta.getDimensionPixelSize(R.styleable.EditorCell_uxsdk_summaryTextSize, getResources().getDimensionPixelSize(R.dimen.uxsdk_dic_text_size_16sp))); + } + + min = ta.getInt(R.styleable.EditorCell_uxsdk_minValue, -1); + max = ta.getInt(R.styleable.EditorCell_uxsdk_maxValue, -1); + + if (ta.hasValue(R.styleable.EditorCell_uxsdk_value)) { + mEditor.setText(ta.getString(R.styleable.EditorCell_uxsdk_value)); + } + + if (ta.hasValue(R.styleable.EditorCell_uxsdk_layout)) { + int layout = ta.getResourceId(R.styleable.EditorCell_uxsdk_layout, 0); + if (layout > 0) { + View view = LayoutInflater.from(context).inflate(layout, null); + addView(view); + } + } + + ta.recycle(); + setRegion(); + setMinHeight((int) AndUtil.getItemHeight(getContext())); + } + + public void setValue(int value) { + mEditor.setText(String.valueOf(value)); + mOldValue = null; + } + + public int getValue() { + try { + return Integer.parseInt(mEditor.getText().toString()); + } catch (Exception e) { + return 0; + } + } + + protected void setRegion() { + mEditor.addTextChangedListener(new TextWatcher() { + @Override + public void onTextChanged(CharSequence s, int start, int before, int count) { + //add log + } + + @Override + public void beforeTextChanged(CharSequence s, int start, int count, int after) { + if (mOldValue == null) { + mOldValue = s.toString(); + } + } + + @Override + public void afterTextChanged(Editable s) { + if (s != null && !"".equals(s.toString()) && (min != -1 || max != -1)) { + + int num; + try { + num = Integer.parseInt(s.toString()); + } catch (NumberFormatException e) { + num = min - 1; + } + + if (num < min || num > max) { + mEditor.setTextColor(ContextCompat.getColor(getContext(), R.color.uxsdk_dic_color_c13_red)); + } else { + mEditor.setTextColor(ContextCompat.getColor(getContext(), R.color.uxsdk_edit_cell_text_color)); + } + + } + } + }); + + setClickLister(); + + setOnfocusChange(); + + } + + private void setOnfocusChange() { + mEditor.setOnFocusChangeListener((v, hasFocus) -> { + if (!hasFocus && mOldValue != null && isFocusChangeValueCallBack) { + mEditor.setText(mOldValue); + mOldValue = null; + } + }); + } + + public void setClickLister(){ + mEditor.setOnEditorActionListener((v, actionId, event) -> { + if (actionId == EditorInfo.IME_ACTION_DONE) { + AndUtil.hideSoftInput(v); + int markVal; + try { + markVal = Integer.parseInt(mEditor.getText().toString()); + } catch (NumberFormatException e) { + markVal = 0; + } + setEditText( markVal); + mEditor.setSelection(mEditor.getText().length()); + if (mListener != null) { + mListener.onValueChanged(EditorCell.this, markVal, getValue()); + } + mOldValue = null; + mEditor.clearFocus(); + } + return false; + }); + + } + + private void setEditText(int markVal) { + if (needChangeValue) { + if (markVal < min) { + mEditor.setText(String.valueOf(min)); + } else if (markVal > max) { + mEditor.setText(String.valueOf(max)); + } + } + } + + + public void needChangeValueWhenOutofLimit(boolean enable){ + needChangeValue = enable; + } + + public void setTips(String tips) { + mTips.setText(tips); + } + + public void setMaxValue(int max) { + this.max = max; + } + + public int getMaxValue(){ + return max; + } + + public void setMinValue(int min) { + this.min = min; + } + + public int getMinValue(){ + return min; + } + + public void setOnValueChangedListener(OnValueChangedListener listener) { + mListener = listener; + } + + public boolean isFocusChangeValueCallBack() { + return isFocusChangeValueCallBack; + } + + public void setEnable(boolean enable) { + mEditor.setEnabled(enable); + } + + public void setFocusChangeValueCallBack(boolean isFocusChangeValueCallBack) { + this.isFocusChangeValueCallBack = isFocusChangeValueCallBack; + } + + public interface OnValueChangedListener { + /** + * + * @param inputValue 原始输入值 + * @param validValue 实际有效值,如果输入值超过最小值或最大值则改为最小值或最大值 + */ + void onValueChanged(EditorCell cell, int inputValue, int validValue); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/ICameraIndex.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/ICameraIndex.kt new file mode 100644 index 00000000..93634203 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/ICameraIndex.kt @@ -0,0 +1,37 @@ +package dji.v5.ux.core.base + +import dji.sdk.keyvalue.value.common.CameraLensType +import dji.sdk.keyvalue.value.common.ComponentIndexType + +/** + * Class Description + * + * @author Hoker + * @date 2021/10/20 + * + * Copyright (c) 2021, DJI All Rights Reserved. + */ +interface ICameraIndex { + + /** + * Get the camera index for which the model is reacting. + * + * @return int representing [ComponentIndexType]. + */ + fun getCameraIndex(): ComponentIndexType + + /** + * Get the current type of the lens the widget model is reacting to + * + * @return current lens type. + */ + fun getLensType(): CameraLensType + + /** + * Update camera/lens index to which the model should react. + * + * @param cameraIndex index of the camera. + * @param lensType index of the lens. + */ + fun updateCameraSource(cameraIndex: ComponentIndexType, lensType: CameraLensType) +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/IGimbalIndex.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/IGimbalIndex.kt new file mode 100644 index 00000000..aef4de2a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/IGimbalIndex.kt @@ -0,0 +1,28 @@ +package dji.v5.ux.core.base + +import dji.sdk.keyvalue.value.common.ComponentIndexType + +/** + * Class Description + * + * @author Hoker + * @date 2021/12/9 + * + * Copyright (c) 2021, DJI All Rights Reserved. + */ +interface IGimbalIndex { + + /** + * Get the gimbal index for which the model is reacting. + * + * @return current gimbal index. + */ + fun getGimbalIndex(): ComponentIndexType + + /** + * Set gimbal index to which the model should react. + * + * @param gimbalIndex index of the gimbal. + */ + fun updateGimbalIndex(gimbalIndex: ComponentIndexType) +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/IImuResources.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/IImuResources.java new file mode 100644 index 00000000..2e6df725 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/IImuResources.java @@ -0,0 +1,124 @@ +package dji.v5.ux.core.base; + + +import dji.v5.ux.R; + +/** + * Created by gashion.fang on 2016/7/11. + */ +public class IImuResources { + + private IImuResources(){} + + public static final int MAX_DESC_COUNT = 3; + + public static final int[] RESIDS_PREPARE_DESC = new int[]{ + R.string.uxsdk_setting_ui_imu_prepare_desc1, R.string.uxsdk_setting_ui_imu_prepare_desc2, R.string.uxsdk_setting_ui_imu_prepare_desc3 + }; + + public static final int[] RESIDS_PREPARE_DESC_REMOVE_DESC1 = new int[]{ + R.string.uxsdk_setting_ui_imu_prepare_desc2, R.string.uxsdk_setting_ui_imu_prepare_desc3 + }; + + public static final int[] RESIDS_PROCESS_DESC = new int[]{ + R.string.uxsdk_setting_ui_imu_process_desc1, R.string.uxsdk_setting_ui_imu_process_desc2 + }; + + public static final int[] RESIDS_AIRCRAFT_P4 = new int[]{ + R.drawable.uxsdk_setting_ui_imu_front, R.drawable.uxsdk_setting_ui_imu_behind, R.drawable.uxsdk_setting_ui_imu_right, R.drawable.uxsdk_setting_ui_imu_left, + R.drawable.uxsdk_setting_ui_imu_top, R.drawable.uxsdk_setting_ui_imu_under + }; + + public static final int[] RESIDS_AIRCRAFT_P4S = new int[]{ + R.drawable.uxsdk_setting_ui_imu_p4s_front, R.drawable.uxsdk_setting_ui_imu_p4s_behind, R.drawable.uxsdk_setting_ui_imu_right, R.drawable.uxsdk_setting_ui_imu_left, + R.drawable.uxsdk_setting_ui_imu_top, R.drawable.uxsdk_setting_ui_imu_under + }; + + public static final int[] RESIDS_AIRCRAFT_KUMQUAT = new int[]{ + R.drawable.uxsdk_setting_ui_kumquat_imucali_front, R.drawable.uxsdk_setting_ui_kumquat_imucali_front, R.drawable.uxsdk_setting_ui_kumquat_imucali_right, + R.drawable.uxsdk_setting_ui_kumquat_imucali_left, R.drawable.uxsdk_setting_ui_kumquat_imucali_top, R.drawable.uxsdk_setting_ui_kumquat_imucali_underside + }; + + public static final int[] RESIDS_AIRCRAFT_N3 = new int[]{ + R.drawable.uxsdk_setting_ui_imu_front_n3, R.drawable.uxsdk_setting_ui_imu_behind_n3, R.drawable.uxsdk_setting_ui_imu_right_n3, + R.drawable.uxsdk_setting_ui_imu_left_n3, R.drawable.uxsdk_setting_ui_imu_top_n3, R.drawable.uxsdk_setting_ui_imu_under_n3 + }; + + public static final int[] RESIDS_AIRCRAFT_M600 = new int[]{ + R.drawable.uxsdk_setting_ui_imu_front_m600, R.drawable.uxsdk_setting_ui_imu_below_m600, R.drawable.uxsdk_setting_ui_imu_right_m600, + R.drawable.uxsdk_setting_ui_imu_left_m600, R.drawable.uxsdk_setting_ui_imu_top_m600, R.drawable.uxsdk_setting_ui_imu_top_m600}; + + public static final int[] RESIDS_AIRCRAFT_M600_PRO = new int[]{ + R.drawable.uxsdk_setting_ui_imu_front_m600_pro, R.drawable.uxsdk_setting_ui_imu_below_m600_pro, R.drawable.uxsdk_setting_ui_imu_right_m600_pro, + R.drawable.uxsdk_setting_ui_imu_left_m600_pro, R.drawable.uxsdk_setting_ui_imu_top_m600_pro, R.drawable.uxsdk_setting_ui_imu_top_m600_pro}; + + public static final int[] RESIDS_AIRCRAFT_ORANGE2 = new int[]{ + R.drawable.uxsdk_setting_ui_imu_front_in2, R.drawable.uxsdk_setting_ui_imu_behind_in2, R.drawable.uxsdk_setting_ui_imu_right_in2, + R.drawable.uxsdk_setting_ui_imu_left_in2, R.drawable.uxsdk_setting_ui_imu_top_in2, R.drawable.uxsdk_setting_ui_imu_top_in2 + }; + + public static final int[] RESIDS_AIRCRAFT_M210 = new int[]{ + R.drawable.uxsdk_setting_ui_imu_front_m210, R.drawable.uxsdk_setting_ui_imu_behind_m210, R.drawable.uxsdk_setting_ui_imu_right_m210, + R.drawable.uxsdk_setting_ui_imu_left_m210, R.drawable.uxsdk_setting_ui_imu_top_m210, R.drawable.uxsdk_setting_ui_imu_top_m210 + }; + + public static final int[] RESIDS_AIRCRAFT_M300 = new int[] { + R.drawable.uxsdk_setting_ui_imu_front_m300, R.drawable.uxsdk_setting_ui_imu_behind_m300, R.drawable.uxsdk_setting_ui_imu_right_m300, + R.drawable.uxsdk_setting_ui_imu_left_m300, R.drawable.uxsdk_setting_ui_imu_top_m300, R.drawable.uxsdk_setting_ui_imu_top_m300 + }; + + public static final int[] RESIDS_AIRCRAFT_M320 = new int[] { + R.drawable.uxsdk_setting_ui_imu_front_m320, R.drawable.uxsdk_setting_ui_imu_behind_m320, R.drawable.uxsdk_setting_ui_imu_right_m320, + R.drawable.uxsdk_setting_ui_imu_left_m320, R.drawable.uxsdk_setting_ui_imu_top_m320, R.drawable.uxsdk_setting_ui_imu_top_m320 + }; + + public static final int[] RESIDS_AIRCRAFT_M350 = new int[] { + R.drawable.uxsdk_setting_ui_imu_front_m350, R.drawable.uxsdk_setting_ui_imu_behind_m350, R.drawable.uxsdk_setting_ui_imu_right_m350, + R.drawable.uxsdk_setting_ui_imu_left_m350, R.drawable.uxsdk_setting_ui_imu_top_m350, R.drawable.uxsdk_setting_ui_imu_top_m350 + }; + + public static final int[] RESIDS_AIRCRAFT_M3E = new int[]{ + R.drawable.uxsdk_setting_ui_imucali_front_m3e, + R.drawable.uxsdk_setting_ui_imucali_front_m3e, + R.drawable.uxsdk_setting_ui_imucali_right_m3e, + R.drawable.uxsdk_setting_ui_imucali_left_m3e, + R.drawable.uxsdk_setting_ui_imucali_top_m3e, + R.drawable.uxsdk_setting_ui_imucali_underside_m3e + }; + + public static final int[] RESIDS_AIRCRAFT_M3T = new int[]{ + R.drawable.uxsdk_setting_ui_imucali_front_m3t, + R.drawable.uxsdk_setting_ui_imucali_front_m3t, + R.drawable.uxsdk_setting_ui_imucali_right_m3t, + R.drawable.uxsdk_setting_ui_imucali_left_m3t, + R.drawable.uxsdk_setting_ui_imucali_top_m3t, + R.drawable.uxsdk_setting_ui_imucali_underside_m3t + }; + + public static final int[] RESIDS_AIRCRAFT_M3M = new int[]{ + R.drawable.uxsdk_setting_ui_imucali_front_m3t, + R.drawable.uxsdk_setting_ui_imucali_front_m3t, + R.drawable.uxsdk_setting_ui_imucali_right_m3t, + R.drawable.uxsdk_setting_ui_imucali_left_m3t, + R.drawable.uxsdk_setting_ui_imucali_top_m3t, + R.drawable.uxsdk_setting_ui_imucali_underside_m3t + }; + + public static final int INDEX_SIDE_FRONT = 0x00; // 前面朝下 + public static final int INDEX_SIDE_BEHIND = 0x01; // 后面朝下 + public static final int INDEX_SIDE_RIGHT = 0x02; // 右边朝下 + public static final int INDEX_SIDE_LEFT = 0x03; // 左边朝下 + public static final int INDEX_SIDE_TOP = 0x04; // 底部朝下 + public static final int INDEX_SIDE_UNDER = 0x05; // 顶部朝下 + public static final int INDEX_SIDE_NONE = -1; // 初始值 + + // 校准面的顺序,由于飞控给出来的0-5不符合实际的校准面顺序 + public static final int[] SIDE_SEQUENCE = new int[]{ + INDEX_SIDE_TOP, INDEX_SIDE_RIGHT, INDEX_SIDE_LEFT, INDEX_SIDE_FRONT, INDEX_SIDE_BEHIND, INDEX_SIDE_UNDER + }; + + // M2E校准面的顺序,由于飞控给出来的0-4不符合实际的校准面顺序 + public static final int[] SIDE_SEQUENCE_M2E = new int[]{ + INDEX_SIDE_TOP, INDEX_SIDE_LEFT, INDEX_SIDE_RIGHT, INDEX_SIDE_BEHIND, INDEX_SIDE_UNDER + }; +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/ISignalStrengthReceiver.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/ISignalStrengthReceiver.java new file mode 100644 index 00000000..705c744a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/ISignalStrengthReceiver.java @@ -0,0 +1,8 @@ +package dji.v5.ux.core.base; + +import dji.sdk.keyvalue.value.mobilenetwork.LinkType; +import dji.v5.ux.core.widget.hd.SignalInfo; + +public interface ISignalStrengthReceiver { + void updateSignal(LinkType link, SignalInfo info); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/ImuCalView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/ImuCalView.java new file mode 100644 index 00000000..e18bf393 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/ImuCalView.java @@ -0,0 +1,476 @@ +package dji.v5.ux.core.base; + + +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.ProgressBar; +import android.widget.TextView; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import androidx.annotation.NonNull; +import dji.sdk.keyvalue.key.FlightControllerKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.utils.ProductUtil; +import dji.sdk.keyvalue.value.common.EmptyMsg; +import dji.sdk.keyvalue.value.flightcontroller.IMUCalibrationInfo; +import dji.sdk.keyvalue.value.flightcontroller.IMUCalibrationOrientation; +import dji.sdk.keyvalue.value.flightcontroller.IMUCalibrationState; +import dji.v5.common.callback.CommonCallbacks; +import dji.v5.common.error.IDJIError; +import dji.v5.manager.KeyManager; +import dji.v5.utils.common.AndUtil; +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.R; + +import static dji.v5.ux.core.base.IImuResources.INDEX_SIDE_TOP; +import static dji.v5.ux.core.base.IImuResources.MAX_DESC_COUNT; +import static dji.v5.ux.core.base.IImuResources.RESIDS_AIRCRAFT_M300; +import static dji.v5.ux.core.base.IImuResources.RESIDS_AIRCRAFT_M320; +import static dji.v5.ux.core.base.IImuResources.RESIDS_AIRCRAFT_M3E; +import static dji.v5.ux.core.base.IImuResources.RESIDS_PREPARE_DESC; +import static dji.v5.ux.core.base.IImuResources.RESIDS_PREPARE_DESC_REMOVE_DESC1; +import static dji.v5.ux.core.base.IImuResources.RESIDS_PROCESS_DESC; + + + +public class ImuCalView extends LinearLayout implements View.OnClickListener { + + private static final String TAG = ImuCalView.class.getSimpleName(); + + // title + ImageView mCloseImg = null; + + // process + LinearLayout mProcessLy = null; + ImageView mProcessAirImg = null; + LinearLayout mProcessPageLy = null; + + TextView mPrepareStartTv = null; + + ProgressBar mProecessPgb = null; + TextView mProcessTv = null; + TextView mProcessPageTv = null; + + // status + LinearLayout mStatusLy = null; + ImageView mStatusImg = null; + TextView mStatusDescTv = null; + TextView mStatusOptTv = null; + TextView mStatusRestartTv = null; + + private void initView() { + mCloseImg = findViewById(R.id.imu_cal_close_img); + mCloseImg.setOnClickListener(this); + mProcessLy = findViewById(R.id.imu_cal_process_ly); + mProcessAirImg = findViewById(R.id.imu_cal_left_content_img); + mProcessPageLy = findViewById(R.id.imu_cal_left_botom_ly); + + mPrepareStartTv = findViewById(R.id.imu_cal_start_tv); + mPrepareStartTv.setOnClickListener(this); + + mProecessPgb = findViewById(R.id.imu_cal_pgb); + mProcessTv = findViewById(R.id.imu_cal_pgb_tv); + mProcessPageTv = findViewById(R.id.imu_cal_page_tv); + + mStatusLy = findViewById(R.id.imu_cal_status_ly); + mStatusImg = findViewById(R.id.imu_cal_status_img); + mStatusDescTv = findViewById(R.id.imu_cal_status_tv); + mStatusOptTv = findViewById(R.id.imu_cal_status_opt_tv); + mStatusOptTv.setOnClickListener(this); + + mStatusRestartTv = findViewById(R.id.imu_cal_status_restart_tv); + mStatusRestartTv.setOnClickListener(this); + + } + + // member + private final LinearLayout[] mProcessDescLys = new LinearLayout[MAX_DESC_COUNT]; + private final TextView[] mProcessDescTvs = new TextView[MAX_DESC_COUNT]; + private int[] mPrepareDesc = RESIDS_PREPARE_DESC; + private List mNeedCalIndex; + + private OnImuCalListener mOnImuCalListener = null; + private IMUCalibrationInfo mIMUCalibrationHint; + + int[] sideSequence; + + public ImuCalView(Context context) { + this(context, null); + } + + public ImuCalView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public ImuCalView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + LayoutInflater.from(context).inflate(R.layout.uxsdk_setting_ui_imu_cal_view, this, true); + initView(); + + } + + + + public void setOnImuCalListener(final OnImuCalListener listener) { + mOnImuCalListener = listener; + } + + private void initViews() { + mPrepareDesc = RESIDS_PREPARE_DESC_REMOVE_DESC1; + sideSequence = (ProductUtil.isM3EProduct() || ProductUtil.isM4EProduct() || ProductUtil.isM4DProduct())? IImuResources.SIDE_SEQUENCE_M2E : IImuResources.SIDE_SEQUENCE; + + final int[] descResIds = new int[]{ + R.id.imu_cal_right_desc_ly1, R.id.imu_cal_right_desc_ly2, R.id.imu_cal_right_desc_ly3 + }; + + for (int i = 0; i < MAX_DESC_COUNT; i++) { + mProcessDescLys[i] = (LinearLayout) findViewById(descResIds[i]); + mProcessDescTvs[i] = (TextView) mProcessDescLys[i].findViewById(R.id.setting_ui_imucal_desc_tv); + } + + // prepare ui + showPrepare(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (isInEditMode()) { + return; + } + setKeepScreenOn(true); + initViews(); + + KeyManager.getInstance().listen(KeyTools.createKey(FlightControllerKey.KeyIMUCalibrationInfo) ,this, (oldValue, newValue) ->{ + if (newValue != null) { + updateViews(newValue); + } + }); + + } + + @Override + protected void onDetachedFromWindow() { + // todo 飞机断开连接后关闭对话框 + super.onDetachedFromWindow(); + } + + @Override + public void onClick(View view) { + final int id = view.getId(); + + if (id == R.id.imu_cal_start_tv) { + // 开始校准 + startCalibrate(); + } else if (id == R.id.imu_cal_status_opt_tv) { + // 失败重试 + if (mIMUCalibrationHint != null && mIMUCalibrationHint.getCalibrationState() == IMUCalibrationState.FAILED) { + startCalibrate(); + } else { + closeSelf(0); + } + } else if (id == R.id.imu_cal_close_img) { + // 关闭IMU校准界面 + closeSelf(0); + } else if (id == R.id.imu_cal_status_restart_tv) { + // 重启飞机 + KeyManager.getInstance().performAction(KeyTools.createKey(FlightControllerKey.KeyRebootDevice) , new CommonCallbacks.CompletionCallbackWithParam< EmptyMsg >(){ + + @Override + public void onSuccess(EmptyMsg emptyMsg) { + LogUtils.d(TAG, "rebootDevice success"); + } + + @Override + public void onFailure(@NonNull IDJIError error) { + LogUtils.d(TAG, "rebootDevice failed!" ); + } + }); + + closeSelf(0); + } + } + + private void startCalibrate() { + showProcess(); + KeyManager.getInstance().performAction(KeyTools.createKey(FlightControllerKey.KeyStartIMUCalibration) , new CommonCallbacks.CompletionCallbackWithParam< EmptyMsg >(){ + + @Override + public void onSuccess(EmptyMsg emptyMsg) { + LogUtils.d(TAG, "startCalibrate success!"); + } + + @Override + public void onFailure(@NonNull IDJIError error) { + LogUtils.e(TAG, "startCalibrate failed!" ); + } + }); + + } + + /** + * 操作提示描述: 开始前和校准过程中会动态更新 + * @param descResIds view ids + */ + private void updateDesc(final int[] descResIds) { + final int offset = descResIds.length; + for (int i = 0; i < offset; i++) { + if(mProcessDescLys[i] != null){ + mProcessDescLys[i].setVisibility(VISIBLE); + } + if(mProcessDescTvs[i] != null){ + mProcessDescTvs[i].setText(descResIds[i]); + } + } + for (int i = offset; i < MAX_DESC_COUNT; i++) { + if(mProcessDescLys[i] != null){ + mProcessDescLys[i].setVisibility(GONE); + } + } + } + + /** + * IMU校准回调更新UI + * @param imuCalibrationHint 最新状态 + */ + private void updateViews(IMUCalibrationInfo imuCalibrationHint) { + + // 状态变更的时候才去更新 + if (mIMUCalibrationHint == null || mIMUCalibrationHint.getCalibrationState() != imuCalibrationHint.getCalibrationState()) { + updateStatus(imuCalibrationHint); + } + + if (imuCalibrationHint.getCalibrationState() == IMUCalibrationState.CALIBRATING) { + updatePageIndex(imuCalibrationHint); + int totalProgress = imuCalibrationHint.getOrientationsToCalibrate().size() + + imuCalibrationHint.getOrientationsCalibrated().size(); + updateProgress(100 * imuCalibrationHint.getOrientationsCalibrated().size() / totalProgress); + } else if (imuCalibrationHint.getCalibrationState() == IMUCalibrationState.FAILED) { + mStatusDescTv.setText(getContext().getString(R.string.uxsdk_setting_ui_imu_fail)); + // TODO 添加IMU校准失败的错误码或错误原因 + } else if (imuCalibrationHint.getCalibrationState() == IMUCalibrationState.SUCCESSFUL) { + // 校准成功后拉取下IMU状态刷新其状态值。SDK里面IMU状态直接读的内存中的调参值,如果没有其他地方去拉取的话校准成功后状态还是异常 + //Pilot2Repo.FlightController().IMUCheckStatus().getValueAsync().subscribe(); + } + mIMUCalibrationHint = imuCalibrationHint; + } + + private void updatePageIndex(IMUCalibrationInfo imuCalibrationHint) { + if (mNeedCalIndex == null) { + mNeedCalIndex = new ArrayList<>(); + for (int i = 0; i < imuCalibrationHint.getOrientationsToCalibrate().size(); ++i) { + mNeedCalIndex.add(imuCalibrationHint.getOrientationsToCalibrate().get(i).value()); + } + } + + int total = mNeedCalIndex.size(); + if (total == 0) { + return; + } + + int childCount = mProcessPageLy.getChildCount(); + if (childCount != total) { + if (childCount > total) { + while (childCount-- > total) { + mProcessPageLy.removeViewAt(childCount); + } + } else { + final int radius = AndUtil.dip2px(getContext(), 9); + final int margin = AndUtil.dip2px(getContext(), 5); + while (childCount++ < total) { + final LayoutParams param = new LayoutParams(radius, radius); + param.setMargins(margin, margin, margin, margin); + final View v = LayoutInflater.from(getContext()).inflate(R.layout.uxsdk_setting_circle_view, null); + mProcessPageLy.addView(v, param); + } + } + } + updatePageIndexEx(total , imuCalibrationHint); + } + private void updatePageIndexEx(int total , IMUCalibrationInfo imuCalibrationHint){ + int[] mCalibrationOrder = {0, 1, 2, 3, 4, 5}; + int current = -1; + for (int i = 0; i < total; ++i) { + final View v = mProcessPageLy.getChildAt(i); + int index = getSDKIndex(mCalibrationOrder[i]); + boolean calibrated = false; + for (IMUCalibrationOrientation orientation : imuCalibrationHint.getOrientationsCalibrated()) { + if (orientation.value() == index) { + v.setHovered(false); + v.setSelected(true); + calibrated = true; + break; + } + } + if (!calibrated){ // 尚未校准 + // 取第一个为校准的作为当前校准目标 + if (current == -1) { + current = mCalibrationOrder[i]; + mProcessPageTv.setText(String.format(Locale.US, "%d/%d", i + 1, total)); + v.setHovered(true); + } else { + v.setHovered(false); + } + v.setSelected(false); + } + } + updateCurrentSide(getSDKIndex(current)); + } + + /** + * 获取SDK校准的顺序index + * @param current + * @return + */ + private int getSDKIndex(int current) { + if (current >= 0 && current < sideSequence.length) { + return sideSequence[current]; + } + return INDEX_SIDE_TOP; + } + + private void updateCurrentSide(int currentSide) { + final int resId = getAircraft(currentSide); + if (0 != resId) { + mProcessAirImg.setImageResource(resId); + } + } + + private void updateProgress(int progress) { + if (progress < 0) { + progress = 0; + } else if (progress > 100) { + progress = 100; + } + mProecessPgb.setProgress(progress); + } + + private void updateStatus(IMUCalibrationInfo imuCalibrationHint) { + if (IMUCalibrationState.NONE == imuCalibrationHint.getCalibrationState()) { + showPrepare(); + } else if (IMUCalibrationState.CALIBRATING == imuCalibrationHint.getCalibrationState()) { + showProcess(); + } else if (IMUCalibrationState.SUCCESSFUL == imuCalibrationHint.getCalibrationState()) { + showSuccess(); + } else if (IMUCalibrationState.FAILED == imuCalibrationHint.getCalibrationState()) { + showFail(); + } +// if (imuCalibrationHint.getCalibrationState() == IMUCalibrationState.CALIBRATING) { +// // 告知另外一个控正在校准 +// //MultiRcManager.getInstance().sendMultiRcSyncData(MultiRcSyncDataType.MULTI_RC_IMU_CALIBRATION,new byte[]{1}); +// }else{ +// // 告知另外一个控退出校准(或者校准失败、已结束等) +// //MultiRcManager.getInstance().sendMultiRcSyncData(MultiRcSyncDataType.MULTI_RC_IMU_CALIBRATION,new byte[]{0}); +// } + } + + private void showPrepare() { + mCloseImg.setVisibility(VISIBLE); + mPrepareStartTv.setVisibility(VISIBLE); + + mProcessLy.setVisibility(VISIBLE); + mProcessPageLy.setVisibility(INVISIBLE); + mProcessAirImg.setImageResource(getReadyResId()); + + updateDesc(mPrepareDesc); + + mProecessPgb.setVisibility(GONE); + mProcessTv.setVisibility(GONE); + mProcessPageTv.setVisibility(INVISIBLE); + mStatusLy.setVisibility(GONE); + } + + private void showProcess() { + mCloseImg.setVisibility(GONE); + mPrepareStartTv.setVisibility(GONE); + + mProcessLy.setVisibility(VISIBLE); + mProcessPageLy.setVisibility(VISIBLE); + mProcessAirImg.setImageResource(getAircraft(IMUCalibrationOrientation.BOTTOM_DOWN.value())); + + updateDesc(RESIDS_PROCESS_DESC); + mProecessPgb.setVisibility(VISIBLE); + mProecessPgb.setProgress(0); + mProcessTv.setVisibility(VISIBLE); + mProcessPageTv.setVisibility(VISIBLE); + + mStatusLy.setVisibility(GONE); + } + + private void showSuccess() { + mCloseImg.setVisibility(VISIBLE); + + mProcessLy.setVisibility(GONE); + + mStatusLy.setVisibility(VISIBLE); + mStatusDescTv.setText(R.string.uxsdk_setting_ui_imu_success); + mStatusImg.setBackgroundResource(R.drawable.uxsdk_setting_ui_success); + mStatusOptTv.setText(R.string.uxsdk_setting_ui_imu_back); + mStatusRestartTv.setVisibility(VISIBLE); + } + + private void showFail() { + mCloseImg.setVisibility(VISIBLE); + + mProcessLy.setVisibility(GONE); + + mStatusLy.setVisibility(VISIBLE); + mStatusDescTv.setText(R.string.uxsdk_setting_ui_imu_fail); + mStatusImg.setBackgroundResource(R.drawable.uxsdk_setting_ui_fail); + mStatusOptTv.setText(R.string.uxsdk_setting_ui_imu_retry); + mStatusRestartTv.setVisibility(GONE); + } + + /** + * 根据机型获取示例图片 + * @return resId + */ + private int getReadyResId() { + if(ProductUtil.isM30Product()){ + return R.drawable.uxsdk_setting_ui_imu_ready_m320; + } else if (ProductUtil.isM3EProduct() || ProductUtil.isM4EProduct() || ProductUtil.isM4DProduct()) { + return R.drawable.uxsdk_img_device_home_m3e; + } else{ + return R.drawable.uxsdk_setting_ui_imu_ready_m300; + } + } + + private int getAircraft(final int index) { + int[] resIds; + + if (ProductUtil.isM30Product()) { + resIds = RESIDS_AIRCRAFT_M320; + } else if (ProductUtil.isM3EProduct() || ProductUtil.isM4EProduct() || ProductUtil.isM4DProduct()) { + resIds = RESIDS_AIRCRAFT_M3E; + } else { + resIds = RESIDS_AIRCRAFT_M300; + } + + if (0 <= index && index < resIds.length) { + return resIds[index]; + } else { + return 0; + } + } + + private void closeSelf(final int arg) { + if (null != mOnImuCalListener) { + mOnImuCalListener.onClose(arg); + } + } + + public interface OnImuCalListener { + /** + * 关闭校准对话框 + * @param arg1 + */ + void onClose(final int arg1); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/ImuCalibrateDialog.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/ImuCalibrateDialog.java new file mode 100644 index 00000000..31842201 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/ImuCalibrateDialog.java @@ -0,0 +1,68 @@ +package dji.v5.ux.core.base; + +import android.content.Context; +import android.os.Bundle; +import android.view.Window; +import android.view.WindowManager; + +import dji.v5.ux.R; +import dji.v5.ux.core.ui.setting.dialog.BaseDialog; + + + +/* + * Copyright (c) 2017, DJI All Rights Reserved. + */ + +/** + *

Created by luca on 2017/4/19.

+ */ + +public class ImuCalibrateDialog extends BaseDialog implements ImuCalView.OnImuCalListener { + + public ImuCalibrateDialog(Context context) { + this(context, R.style.NoTitleDialog); + } + + public ImuCalibrateDialog(Context context, int themeResId) { + super(context, themeResId); + init(); + } + + private void init() { + ImuCalView imuCalView = new ImuCalView(getContext()); + imuCalView.setOnImuCalListener(this); + setContentView(imuCalView); + } + + @Override + public void onClose(int arg1) { + dismiss(); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + WindowManager.LayoutParams attrs = getWindow().getAttributes(); + attrs.width = WindowManager.LayoutParams.MATCH_PARENT; + attrs.height = WindowManager.LayoutParams.MATCH_PARENT; + getWindow().setAttributes(attrs); + } + + @Override + public void show() { + + Window window = getWindow(); + // Set the dialog to not focusable. + window.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); + window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN); + + // Show the dialog with NavBar hidden. + super.show(); + + // Set the dialog to focusable again. + window.clearFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/ImuStatusWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/ImuStatusWidget.java new file mode 100644 index 00000000..e0e0b07c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/ImuStatusWidget.java @@ -0,0 +1,282 @@ +package dji.v5.ux.core.base; + + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.constraintlayout.widget.ConstraintLayout; +import androidx.constraintlayout.widget.Group; + + + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + + +import dji.sdk.keyvalue.key.FlightControllerKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.value.flightcontroller.IMUSensorState; +import dji.sdk.keyvalue.value.flightcontroller.IMUState; +import dji.sdk.keyvalue.value.flightcontroller.RedundancySensorUsedStateMsg; +import dji.v5.common.callback.CommonCallbacks; +import dji.v5.common.error.IDJIError; +import dji.v5.manager.KeyManager; +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.util.ViewUtil; + +/** + *

+ * + * @author Create by Luca.Wu@dji.com at 2017/11/27 14:39 + * @version v1.0 + */ + +public class ImuStatusWidget extends ConstraintLayout { + + private static final String TAG = "ImuStatusWidget"; + private int[] IMU_STATE_RES = new int[]{ + R.string.uxsdk_setting_ui_redundancy_sensor_imu_stat_1, + R.string.uxsdk_setting_ui_redundancy_sensor_imu_stat_2, + R.string.uxsdk_setting_ui_redundancy_sensor_imu_stat_3, + R.string.uxsdk_setting_ui_redundancy_sensor_imu_stat_4, + R.string.uxsdk_setting_ui_redundancy_sensor_imu_stat_5, + R.string.uxsdk_setting_ui_redundancy_sensor_imu_stat_6, + R.string.uxsdk_setting_ui_redundancy_sensor_imu_stat_0, + }; + + private static final int ONE_IMU = 1; + private static final int TWO_IMU = 2; + private static final int THREE_IMU = 3; + + private Group mSettingUiFlycImuLy2; + private Group mSettingUiFlycImuLy3; + + private List mSettingUiFlycAccTitles = new ArrayList<>(); + + private List + mSettingUiFlycImuAccs = new ArrayList<>(); + + private List + mSettingUiFlycImuGyros = new ArrayList<>(); + + + private void initView(View view) { + mSettingUiFlycImuLy2 = view.findViewById(R.id.setting_ui_flyc_imu_ly2); + mSettingUiFlycImuLy3 = view.findViewById(R.id.setting_ui_flyc_imu_ly3); + + mSettingUiFlycAccTitles.add(view.findViewById(R.id.setting_ui_flyc_acc_0_title)); + mSettingUiFlycAccTitles.add(view.findViewById(R.id.setting_ui_flyc_acc_1_title)); + mSettingUiFlycAccTitles.add(view.findViewById(R.id.setting_ui_flyc_acc_2_title)); + + mSettingUiFlycImuAccs.add(view.findViewById(R.id.setting_ui_flyc_imu_acc_1)); + mSettingUiFlycImuAccs.add(view.findViewById(R.id.setting_ui_flyc_imu_acc_2)); + mSettingUiFlycImuAccs.add(view.findViewById(R.id.setting_ui_flyc_imu_acc_3)); + + mSettingUiFlycImuGyros.add(view.findViewById(R.id.setting_ui_flyc_imu_gyr_1)); + mSettingUiFlycImuGyros.add(view.findViewById(R.id.setting_ui_flyc_imu_gyr_2)); + mSettingUiFlycImuGyros.add(view.findViewById(R.id.setting_ui_flyc_imu_gyr_3)); + + findViewById(R.id.setting_menu_imu_calibrate).setOnClickListener(view1 -> startCompassCalibrating()); + } + //private KeyPresenter mPresenter; +// private DJIKey mUsedStateKey; + + private int mImuCount; + private List mIMUStateList = new ArrayList<>(); + private boolean mAreMotorOn; + private RedundancySensorUsedStateMsg mSensorUsedState; + + public ImuStatusWidget(Context context) { + this(context, null); + } + + public ImuStatusWidget(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public ImuStatusWidget(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(context); + } + + private void initialize(Context context) { + View view = inflate(context, R.layout.uxsdk_setting_menu_imu_status_layout, this); + initView(view); + + mSettingUiFlycAccTitles.get(0).setSelected(true); + initKeys(); + } + + + private void initKeys() { +// mPresenter = new KeyModel.Builder().setView(this).build().create(); +// mUsedStateKey = FlightControllerKey.create(FlightControllerKey.REDUNDANCY_SENSOR_USED_STATE); + +// mPresenter.addKey(mUsedStateKey); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (isInEditMode()) { + return; + } + //mPresenter.onStart(); + + + KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyIMUCount), new CommonCallbacks.CompletionCallbackWithParam() { + @Override + public void onSuccess(Integer count) { + LogUtils.d(TAG, "listen imu count=" + count); + mImuCount = count; + updateViewByImuCount(); + } + + @Override + public void onFailure(@NonNull IDJIError error) { + LogUtils.d(TAG, "listen imu get error" ); + } + }); + + + KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyAreMotorsOn), new CommonCallbacks.CompletionCallbackWithParam() { + @Override + public void onSuccess(Boolean isOn) { + mAreMotorOn = isOn; + } + + @Override + public void onFailure(@NonNull IDJIError error) { + LogUtils.d(TAG, "get KeyAreMotorsOn error" ); + } + }); + + + + KeyManager.getInstance().listen(KeyTools.createKey(FlightControllerKey.KeyIMUStatus), this, (oldValue, newValue) -> { + mIMUStateList = newValue; + updateSensorsStatus(mSettingUiFlycImuAccs, false); + updateSensorsStatus(mSettingUiFlycImuGyros, true); + }); + + KeyManager.getInstance().listen(KeyTools.createKey(FlightControllerKey.KeyRedundancySensorUsedState), this, (oldValue, newValue) -> { + mSensorUsedState = newValue; + updateSelectedSensor(mSensorUsedState.getGyroIndex()); + }); + +// + } + + @Override + protected void onDetachedFromWindow() { + //mPresenter.onStop(); + KeyManager.getInstance().cancelListen(this); + super.onDetachedFromWindow(); + } + +// @Override +// public void transformValue(DJIKey key, Object value) { +// if (key.equals(mUsedStateKey)) { +// mSensorUsedState = (RedundancySensorUsedState) value; +// } +// } +// +// @Override +// public void updateWidget(DJIKey key, Object value) { +// if (key.equals(mUsedStateKey)) { +// updateSelectedSensor(mSensorUsedState.getGyroIndex()); +// } +// } + + + protected void startCompassCalibrating() { + + if (mAreMotorOn) { + ViewUtil.showToast(getContext() ,R.string.uxsdk_setting_ui_imu_tip , Toast.LENGTH_SHORT); + } else { + if (KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyConnection) ,false)) { + ImuCalibrateDialog dialog = new ImuCalibrateDialog(getContext()); + dialog.show(); + + } else { + ViewUtil.showToast(getContext() , R.string.uxsdk_app_check_aircraft_connection , Toast.LENGTH_SHORT); + } + } + } + + private void updateViewByImuCount() { + if (mImuCount == TWO_IMU) { + mSettingUiFlycImuLy3.setVisibility(View.GONE); + } else if (mImuCount == ONE_IMU) { + mSettingUiFlycImuLy2.setVisibility(View.GONE); + mSettingUiFlycImuLy3.setVisibility(View.GONE); + } else { + mSettingUiFlycImuLy2.setVisibility(View.VISIBLE); + mSettingUiFlycImuLy3.setVisibility(View.VISIBLE); + } + } + + private void updateSelectedSensor(int index) { + for (int i = 0; i < THREE_IMU; ++i) { + mSettingUiFlycAccTitles.get(i).setSelected(index == (i+1)); + } + } + + private void updateSensorsStatus(List viewList, boolean isGyro) { + if (mIMUStateList == null) { + return; + } + for (int i = 0; i < mImuCount; ++i) { + if (i >= mIMUStateList.size()) { + break; + } + IMUState imuState = mIMUStateList.get(i); + IMUSensorState state = isGyro ? imuState.getGyroscopeState() : imuState.getAccelerometerState(); + float value = isGyro ? imuState.getGyroscopeBias().floatValue() : imuState.getAccelerometerBias().floatValue(); + + ProgressStatusWidget statusView = viewList.get(i); + + if (state == IMUSensorState.NORMAL_BIAS) { + statusView.setProgressDrawable(getContext().getResources().getDrawable(R.drawable.uxsdk_setting_ui_status_pgb_green)); + } else if (state == IMUSensorState.MEDIUM_BIAS) { + statusView.setProgressDrawable(getContext().getResources().getDrawable(R.drawable.uxsdk_setting_ui_status_pgb_yellow)); + } else if (state == IMUSensorState.LARGE_BIAS) { + statusView.setProgressDrawable(getContext().getResources().getDrawable(R.drawable.uxsdk_setting_ui_status_pgb_red)); + } + + statusView.mProgressBar.setVisibility(View.VISIBLE); + statusView.mValueView.setVisibility(View.VISIBLE); + // + updateStatus(state , statusView , isGyro , value); + + } + } + + private void updateStatus(IMUSensorState state , ProgressStatusWidget statusView , boolean isGyro , float value ){ + if (state == IMUSensorState.NORMAL_BIAS || state == IMUSensorState.MEDIUM_BIAS || state == IMUSensorState.LARGE_BIAS) { + statusView.setValue(String.format(Locale.US, "%.3f", value)); + if (isGyro) { + statusView.setProgress((int) (value / 0.05f * 100)); + } else { + statusView.setProgress((int) (value / 0.1f * 100)); + } + statusView.mDescView.setVisibility(View.GONE); + } else { + statusView.mProgressBar.setProgress(0); + if (state != null && state.ordinal() >= 0 && state.ordinal() <= IMUSensorState.IN_MOTION.ordinal()) { + statusView.mDescView.setText(IMU_STATE_RES[state.ordinal()]); + statusView.mDescView.setVisibility(View.VISIBLE); + statusView.mProgressBar.setVisibility(View.GONE); + statusView.mValueView.setVisibility(View.GONE); + } else { + statusView.mDescView.setVisibility(View.GONE); + } + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/ProgressStatusWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/ProgressStatusWidget.java new file mode 100644 index 00000000..eecae3e2 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/ProgressStatusWidget.java @@ -0,0 +1,81 @@ +package dji.v5.ux.core.base; + +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.widget.ProgressBar; +import android.widget.TextView; + +import androidx.annotation.Nullable; + +import dji.v5.ux.R; + + +public class ProgressStatusWidget extends DividerLinearLayout { + + public TextView mValueView; + public TextView mDescView; + public ProgressBar mProgressBar; + + public ProgressStatusWidget(Context context) { + this(context, null); + } + + public ProgressStatusWidget(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public ProgressStatusWidget(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(context); + } + + @TargetApi(Build.VERSION_CODES.LOLLIPOP) + public ProgressStatusWidget(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + initialize(context); + } + + private void initialize(Context context) { + LayoutInflater.from(context).inflate(R.layout.uxsdk_widget_progress_bar_layout, this, true); + + if (isInEditMode()) { + return; + } + setBottomDividerEnable(false); + mValueView = (TextView) findViewById(R.id.status_widget_value); + mDescView = (TextView) findViewById(R.id.status_widget_desc); + mProgressBar = (ProgressBar) findViewById(R.id.status_widget_progress); + } + + public String getValue() { + return mValueView.getText().toString(); + } + + public void setValue(String value) { + mValueView.setText(value); + } + + public String getDesc() { + return mDescView.getText().toString(); + } + + public void setDesc(String desc) { + mDescView.setText(desc); + } + + public int getProgress() { + return mProgressBar.getProgress(); + } + + public void setProgress(int progress) { + mProgressBar.setProgress(progress); + } + + public void setProgressDrawable(Drawable drawable) { + mProgressBar.setProgressDrawable(drawable); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/RoundedLinearLayout.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/RoundedLinearLayout.java new file mode 100644 index 00000000..2426d109 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/RoundedLinearLayout.java @@ -0,0 +1,73 @@ +package dji.v5.ux.core.base; + +import android.annotation.TargetApi; +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Shader; +import android.os.Build; +import android.util.AttributeSet; +import android.widget.LinearLayout; + +public class RoundedLinearLayout extends LinearLayout { + // private Paint drawPaint; + // private Paint roundPaint; + + private int mCornerRadius = 10; + private Paint mPaint; + + private RectF bounds = new RectF(0, 0, 1, 1); + + @TargetApi(Build.VERSION_CODES.HONEYCOMB) + public RoundedLinearLayout(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + onInit(); + } + + public RoundedLinearLayout(Context context, AttributeSet attrs) { + super(context, attrs); + onInit(); + } + + public RoundedLinearLayout(Context context) { + super(context); + onInit(); + } + + protected void onInit() { + // drawPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + // drawPaint.setColor(0xffffffff); + // drawPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN)); + // + // roundPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + // roundPaint.setColor(0xffffffff); + + mPaint = new Paint(); + mPaint.setAntiAlias(true); + setWillNotDraw(false); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + bounds = new RectF(0, 0, w, h); + } + + @Override + protected void dispatchDraw(Canvas canvas) { + int width = bounds.width() == 0 ? 1 : (int) bounds.width(); + int height = bounds.height() == 0 ? 1 : (int) bounds.height(); + Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + Canvas c = new Canvas(bitmap); + super.dispatchDraw(c); + + BitmapShader shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP); + + mPaint.setShader(shader); + + canvas.drawRoundRect(bounds, mCornerRadius, mCornerRadius, mPaint); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/SchedulerProvider.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/SchedulerProvider.kt new file mode 100644 index 00000000..58f2241e --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/SchedulerProvider.kt @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base + +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers +import io.reactivex.rxjava3.core.Scheduler +import io.reactivex.rxjava3.schedulers.Schedulers + +/** + * A singleton class is used throughout the UXSDK for getting schedulers. + * The class provides an option to inject custom schedulers using [SchedulerProviderInterface] + */ +object SchedulerProvider { + + /** + * Custom scheduler to be used instead of default schedulers + */ + @JvmStatic + @Volatile + var scheduler: SchedulerProviderInterface? = null + + @JvmStatic + fun io(): Scheduler { + return scheduler?.io() ?: Schedulers.io() + } + + @JvmStatic + fun computation(): Scheduler { + return scheduler?.computation() ?: Schedulers.computation() + } + + @JvmStatic + fun ui(): Scheduler { + return scheduler?.ui() ?: AndroidSchedulers.mainThread() + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/SchedulerProviderInterface.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/SchedulerProviderInterface.kt new file mode 100644 index 00000000..5e41096d --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/SchedulerProviderInterface.kt @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base + +import io.reactivex.rxjava3.core.Scheduler + + +/** + * Interface for creating multiple Schedulers + */ +interface SchedulerProviderInterface { + fun io(): Scheduler + fun computation(): Scheduler + fun ui(): Scheduler +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/SerialNumberTextCell.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/SerialNumberTextCell.kt new file mode 100644 index 00000000..bf1ccc15 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/SerialNumberTextCell.kt @@ -0,0 +1,13 @@ +package dji.v5.ux.core.base + +import android.content.Context +import android.util.AttributeSet + + +class SerialNumberTextCell(context: Context?, attrs: AttributeSet?) : TextCell(context, attrs) { + init { + mTitle.isSingleLine = false + mTitle.layoutParams.width = 0 + mContent.layoutParams.width = LayoutParams.WRAP_CONTENT + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/SignalStrengthCollector.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/SignalStrengthCollector.java new file mode 100644 index 00000000..d2ef34ef --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/SignalStrengthCollector.java @@ -0,0 +1,9 @@ +package dji.v5.ux.core.base; + +public interface SignalStrengthCollector { + public void onCreate(); + + public void onDestroy(); + + public void setSignalStrengthReceiver(ISignalStrengthReceiver receiver); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/SwitcherCell.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/SwitcherCell.java new file mode 100644 index 00000000..0f152dbb --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/SwitcherCell.java @@ -0,0 +1,300 @@ +package dji.v5.ux.core.base; + +import android.content.Context; +import android.content.res.TypedArray; +import android.text.SpannableString; +import android.text.TextUtils; +import android.text.method.LinkMovementMethod; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import android.widget.Toast; +import android.widget.ToggleButton; + +import androidx.core.view.ViewCompat; + +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.R; +import dji.v5.ux.core.util.ViewUtil; + + + +/* + * Copyright (c) 2014, DJI All Rights Reserved. + */ + +/** + * @author Luca.Wu + *

Created by luca on 2017/1/16.

+ */ + +public class SwitcherCell extends DividerConstraintLayout { + + protected ToggleButton mSwitcher; + protected TextView mSummary; + protected TextView mTitle; + protected TextView mDesc; + protected View mDisableHintView; + protected String mDisableHintText; + private View mInfoIcon; + + protected String mPopupHintText; + private OnCheckedChangedListener mListener; + private OnClickListener mPopupHintClickListener; + private OnClickListener mDisableClickListener; + + public SwitcherCell(Context context) { + this(context, null); + } + + public SwitcherCell(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SwitcherCell(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(context, attrs, defStyleAttr); + } + + private void initialize(Context context, AttributeSet attrs, int defStyleAttr) { + LayoutInflater.from(context).inflate(R.layout.uxsdk_cell_switcher_layout, this, true); + TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.SwitcherCell, defStyleAttr, 0); + + mSwitcher = (ToggleButton) findViewById(R.id.toggle_switcher); + mSummary = (TextView) findViewById(R.id.summary); + mTitle = (TextView) findViewById(R.id.title); + mDesc = (TextView) findViewById(R.id.desc); + mDisableHintView = findViewById(R.id.disable_hint_view); + mInfoIcon = findViewById(R.id.info_icon); + + if (ta.hasValue(R.styleable.SwitcherCell_uxsdk_title)) { + mTitle.setText(ta.getString(R.styleable.SwitcherCell_uxsdk_title)); + } else { + mTitle.setVisibility(GONE); + } + + if (ta.hasValue(R.styleable.SwitcherCell_uxsdk_titleTextSize)) { + mTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, ta.getDimension(R.styleable.SwitcherCell_uxsdk_titleTextSize, 16)); + } + + if (ta.hasValue(R.styleable.SwitcherCell_uxsdk_titleColor)) { + mTitle.setTextColor(ta.getColor(R.styleable.SwitcherCell_uxsdk_titleColor, getResources().getColor(R.color.uxsdk_dic_color_c24_white_Transparent6))); + } + + if (ta.hasValue(R.styleable.SwitcherCell_uxsdk_summary)) { + mSummary.setText(ta.getString(R.styleable.SwitcherCell_uxsdk_summary)); + } else { + mSummary.setVisibility(GONE); + } + + if (ta.hasValue(R.styleable.SwitcherCell_uxsdk_summaryTextSize)) { + mSummary.setTextSize(TypedValue.COMPLEX_UNIT_PX, ta.getDimension(R.styleable.SwitcherCell_uxsdk_summaryTextSize, 14)); + } + + if (ta.hasValue(R.styleable.SwitcherCell_uxsdk_summaryColor)) { + mSummary.setTextColor(ta.getColor(R.styleable.SwitcherCell_uxsdk_summaryColor, getResources().getColor(R.color.uxsdk_dic_color_c8_white))); + } + + setupDesc(ta); + + if (ta.hasValue(R.styleable.SwitcherCell_uxsdk_checked)) { + mSwitcher.setChecked(ta.getBoolean(R.styleable.SwitcherCell_uxsdk_checked, false)); + } + + if (ta.hasValue(R.styleable.SwitcherCell_uxsdk_switchToggleBg)) { + mSwitcher.setBackgroundResource(ta.getResourceId(R.styleable.SwitcherCell_uxsdk_switchToggleBg, R.drawable.uxsdk_toggle_green_selector)); + } + + if (ta.hasValue(R.styleable.SwitcherCell_uxsdk_layout)) { + int layout = ta.getResourceId(R.styleable.SwitcherCell_uxsdk_layout, 0); + if (layout > 0) { + View view = LayoutInflater.from(context).inflate(layout, null); + addView(view); + } + } + + setupInfoView(ta); + + ta.recycle(); + + // 避免View再次被初始化时默认执行一次onCheckedChanged方法 + ViewCompat.setSaveFromParentEnabled(this, false); + mSwitcher.setOnCheckedChangeListener((buttonView, isChecked) -> { + if (mListener != null) { + mListener.onCheckedChanged(SwitcherCell.this, isChecked); + } + }); + + setMinHeight((int) AndUtil.getItemHeight(getContext())); + + setListeners(); + } + + private void setupDesc(TypedArray ta) { + if (ta.hasValue(R.styleable.SwitcherCell_uxsdk_desc)) { + mDesc.setText(ta.getString(R.styleable.SwitcherCell_uxsdk_desc)); + } else { + mDesc.setVisibility(GONE); + } + + if (ta.hasValue(R.styleable.SwitcherCell_uxsdk_descColor)) { + mDesc.setTextColor(ta.getColor(R.styleable.SwitcherCell_uxsdk_descColor, getResources().getColor(R.color.uxsdk_dic_color_c24_white_Transparent6))); + } + + if (ta.hasValue(R.styleable.SwitcherCell_uxsdk_descTextSize)) { + mDesc.setTextSize(TypedValue.COMPLEX_UNIT_PX, ta.getDimensionPixelSize(R.styleable.SwitcherCell_uxsdk_descTextSize, getResources().getDimensionPixelSize(R.dimen.uxsdk_dic_text_size_16sp))); + } + + if (ta.hasValue(R.styleable.SwitcherCell_uxsdk_descMarginVertical)) { + int margin = ta.getDimensionPixelSize(R.styleable.SwitcherCell_uxsdk_descMarginVertical, getResources().getDimensionPixelSize(R.dimen.uxsdk_dic_text_size_16sp)); + ViewGroup.LayoutParams lp = mDesc.getLayoutParams(); + if (lp instanceof MarginLayoutParams) { + MarginLayoutParams mlp = (MarginLayoutParams) lp; + mlp.topMargin = margin; + mlp.bottomMargin = margin; + mDesc.setLayoutParams(mlp); + } + } + } + + private void setupInfoView(TypedArray ta){ + if (ta.hasValue(R.styleable.SwitcherCell_uxsdk_disableHint)) { + mDisableHintText = ta.getString(R.styleable.SwitcherCell_uxsdk_disableHint); + } + + boolean showInfoIcon = false; + if (ta.hasValue(R.styleable.SwitcherCell_uxsdk_showInfoHintIcon)) { + showInfoIcon = ta.getBoolean(R.styleable.SwitcherCell_uxsdk_showInfoHintIcon, false); + } + + if (ta.hasValue(R.styleable.SwitcherCell_uxsdk_infoPopupHint)) { + mPopupHintText = ta.getString(R.styleable.SwitcherCell_uxsdk_infoPopupHint); + } + + mInfoIcon.setVisibility(showInfoIcon || !TextUtils.isEmpty(mPopupHintText) ? VISIBLE : GONE); + } + + private void setListeners() { + mDisableHintView.setOnClickListener(v -> { + // 如果控件置灰且有设置提示语,点击时有相关提示 + if (mSwitcher.isEnabled()) { + return; + } + if (mDisableClickListener != null) { + mDisableClickListener.onClick(v); + } else if (!TextUtils.isEmpty(mDisableHintText) && !mSwitcher.isEnabled()) { + ViewUtil.showToast(getContext() , mDisableHintText , Toast.LENGTH_SHORT); + } + }); + mInfoIcon.setOnClickListener(v -> { + if (mPopupHintClickListener != null) { + mPopupHintClickListener.onClick(v); + } else if (!TextUtils.isEmpty(mPopupHintText)) { + // xml 有配置静态的文案则可以直接显示 + + ViewUtil.showToast(getContext() , mPopupHintText , Toast.LENGTH_SHORT); + } + }); + } + + public void setChecked(boolean checked) { + mSwitcher.setChecked(checked); + } + + public boolean isChecked() { + return mSwitcher.isChecked(); + } + + public void setOnCheckedChangedListener(OnCheckedChangedListener listener) { + mListener = listener; + } + + /** + * 重新设置值,不进行回调 + * 在部分使用场景,切换开关状态之后需要检查状态,检查失败需要重置状态,此时不希望有回调 + * + * @param checked + */ + public void resetValue(boolean checked) { + OnCheckedChangedListener listener = mListener; + mListener = null; + setChecked(checked); + mListener = listener; + } + + public interface OnCheckedChangedListener { + /** + * Dispatch the event of ToggleButton + * @param cell instance of view + * @param isChecked checked or not + */ + void onCheckedChanged(SwitcherCell cell, boolean isChecked); + } + + public void updateSummaryText(String text) { + if (mSummary != null) { + if (mSummary.getVisibility() != VISIBLE) { + mSummary.setVisibility(VISIBLE); + } + mSummary.setText(text); + } + } + + public void updateDesc(int text) { + if (mDesc != null) { + mDesc.setText(text); + } + } + + public void updateDesc(CharSequence desc) { + mDesc.setText(desc); + if (desc instanceof SpannableString) { + mDesc.setMovementMethod(LinkMovementMethod.getInstance()); + } + } + + public void updateEnabledStatus(boolean enabled) { + this.setEnabled(enabled); + int textColor = enabled ? getContext().getResources().getColor(R.color.uxsdk_white) : getContext().getResources().getColor(R.color.uxsdk_gray); + mSummary.setTextColor(textColor); + mTitle.setTextColor(textColor); + mInfoIcon.setAlpha(enabled ? 1f : 0.5f); + // HYAPP-10169 + // mDesc.setTextColor(textColor); + setToggleEnabled(enabled); + mDisableHintView.setVisibility(enabled ? GONE : VISIBLE); + if (!enabled) { + mDisableHintView.setMinimumHeight(getMinHeight()); + } + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + mSwitcher.setEnabled(enabled); + } + + public void setToggleEnabled(boolean enabled) { + mSwitcher.setEnabled(enabled); + mSwitcher.setAlpha(enabled ? 1f : 0.5f); + } + + public void setDisableHint(String disableHint) { + mDisableHintText = disableHint; + } + + public void setPopupHint(String popupHint) { + mPopupHintText = popupHint; + } + + public void setOnDisableHintClickListener(OnClickListener listener) { + mDisableClickListener = listener; + } + + public void setOnPopupHintClickListener(OnClickListener listener) { + mPopupHintClickListener = listener; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/TabGroupWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/TabGroupWidget.java new file mode 100644 index 00000000..9ea78ecb --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/TabGroupWidget.java @@ -0,0 +1,287 @@ +package dji.v5.ux.core.base; +/* + * Copyright (c) 2017, DJI All Rights Reserved. + */ + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Typeface; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.TypedValue; +import android.view.Gravity; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.RadioButton; +import android.widget.RadioGroup; + +import androidx.annotation.ColorRes; +import androidx.annotation.DrawableRes; + + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import dji.v5.utils.common.AndUtil; +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.R; + + +public class TabGroupWidget extends RadioGroup implements RadioGroup.OnCheckedChangeListener{ + + private int mPadding; + private int mTextSize; + private int mTextColor; + private CoverStyle mCoverStyle; + private int mCheckedIndex; + private boolean mFixedSize; + private boolean mTextBold; + private List mTabs; + private OnTabChangeListener mOnTabChangeListener; + + + public TabGroupWidget(Context context) { + this(context, null); + } + + public TabGroupWidget(Context context, AttributeSet attrs) { + super(context, attrs); + initialize(context, attrs); + } + + private void initialize(Context context, AttributeSet attrs) { + setOrientation(HORIZONTAL); + super.setOnCheckedChangeListener(this); + + TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.TabGroupWidget, 0, 0); + mFixedSize = ta.getBoolean(R.styleable.TabGroupWidget_uxsdk_fixedSize, true); + mTextSize = ta.getDimensionPixelSize(R.styleable.TabGroupWidget_uxsdk_textSize, AndUtil.dip2px(getContext(), 9)); + mTextColor = ta.getColor(R.styleable.TabGroupWidget_uxsdk_textColor, AndUtil.getResColor(R.color.uxsdk_dic_color_c9_blue)); + mTextBold = ta.getBoolean(R.styleable.TabGroupWidget_uxsdk_textBold, false); + mCoverStyle = CoverStyle.index(ta.getInt(R.styleable.TabGroupWidget_uxsdk_coverStyle, CoverStyle.BLUE.ordinal())); + mPadding = ta.getDimensionPixelSize(R.styleable.TabGroupWidget_uxsdk_tabsPadding, (int) context.getResources().getDimension(R.dimen.uxsdk_3_dp)); + + // 可以设置自定义背景色 + mTabs = new ArrayList(); + if (ta.hasValue(R.styleable.TabGroupWidget_uxsdk_tabs)) { + CharSequence[] entries = ta.getTextArray(R.styleable.TabGroupWidget_uxsdk_tabs); + if (entries != null && entries.length > 0) { + for (CharSequence s: entries) { + mTabs.add(s.toString()); + } + setTabs(); + } + } + + ta.recycle(); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + if (changed && mFixedSize && mTabs.size() > 0) { + // 为了适配crystalsky,不能用weight + int width = getWidth() - getPaddingLeft() - getPaddingRight(); + int eachWidth = width / mTabs.size(); + + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + LinearLayout.LayoutParams layoutParams = (LinearLayout.LayoutParams)child.getLayoutParams(); + layoutParams.width = eachWidth; + child.setLayoutParams(layoutParams); + } + } + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + child.setEnabled(enabled); + } + } + + + @Override + public void setOnCheckedChangeListener(OnCheckedChangeListener listener) { + LogUtils.e("TabGroupWidget", "Please use setOnTabChangeListener instead."); + } + + private void setTabs() { + + removeAllViews(); + for (int i = 0, size = mTabs.size(); i < size; ++i) { + RadioButton tab = new RadioButton(getContext()); + tab.setId(i); + tab.setButtonDrawable(null); + tab.setGravity(Gravity.CENTER); + tab.setText(mTabs.get(i)); + tab.setTextSize(TypedValue.COMPLEX_UNIT_PX, mTextSize); + tab.setPadding(mPadding, mPadding, mPadding, mPadding); + tab.setSingleLine(true); + tab.setEllipsize(TextUtils.TruncateAt.MARQUEE); + if (mTextBold) { + tab.setTypeface(Typeface.DEFAULT, Typeface.BOLD); + } + + initTabBackground(tab, i, size); + + + if (i == mCheckedIndex) { + tab.setChecked(true); + } + setTextColorByType(tab, i == mCheckedIndex); + addView(tab); + } + } + + private void initTabBackground(RadioButton tab, int i, int size) { + if (i == 0) { + tab.setBackgroundResource(mCoverStyle.mResStart); + } else if (i == size - 1) { + tab.setBackgroundResource(mCoverStyle.mResEnd); + } else { + tab.setBackgroundResource(mCoverStyle.mResMid); + } + } + + private void setTextColorByType(RadioButton tab, boolean checked) { + if (checked) { + tab.setTextColor(AndUtil.getResColor(mCoverStyle.mResTextColorChecked)); + } else { + tab.setTextColor(mTextColor); + } + } + + public void setItems(List items) { + mTabs.clear(); + if (items != null && !items.isEmpty()) { + mTabs.addAll(items); + } + setTabs(); + } + + public void setItems(String[] items) { + mTabs.clear(); + if (items != null && items.length > 0) { + mTabs.addAll(Arrays.asList(items)); + } + setTabs(); + } + + @Override + public void onCheckedChanged(RadioGroup group, int checkedId) { + + RadioButton curChild; + for (int i = 0, childCount = getChildCount(); i < childCount; ++i) { + curChild = (RadioButton) getChildAt(i); + if (curChild.getId() == checkedId) { + setTextColorByType(curChild, true); + + if (i != mCheckedIndex) { + RadioButton oldChild = (RadioButton) getChildAt(mCheckedIndex); + setTextColorByType(oldChild, false); + if (mOnTabChangeListener != null) { + mOnTabChangeListener.onTabChanged(mCheckedIndex, i); + } + mCheckedIndex = i; + } + break; + } + } + } + + public void setOnTabChangeListener(OnTabChangeListener onTabChangeListener) { + mOnTabChangeListener = onTabChangeListener; + } + + public int getCheckedIndex() { + return mCheckedIndex; + } + + public void setCheckedIndex(int checkedIndex) { + if (checkedIndex < getChildCount()) { + RadioButton tab = (RadioButton) getChildAt(checkedIndex); + tab.setChecked(true); + } + } + + public void updateTabDefaultNames(int size){ + for(int i = size ; i < getChildCount() ; i ++){ + RadioButton tab = (RadioButton) getChildAt(i); + tab.setVisibility(GONE); + } + } + + public void updateTabNames(List names){ + if(names == null){ + return; + } + + int index = 0; + for(String name : names){ + if (index < getChildCount()) { + RadioButton tab = (RadioButton) getChildAt(index); + tab.setText(name); + tab.setVisibility(VISIBLE); + } + index ++; + } + + for(int i = index ; i < getChildCount() ; i ++){ + RadioButton tab = (RadioButton) getChildAt(i); + tab.setVisibility(GONE); + } + } + + public enum CoverStyle { + /** + * 选中颜色为蓝色 + */ + BLUE(R.color.uxsdk_dic_color_c8_white, R.drawable.uxsdk_tab_item_start_blue_style, R.drawable.uxsdk_tab_item_mid_blue_style, R.drawable.uxsdk_tab_item_end_blue_style), + /** + * 选中颜色为白色 + */ + WHITE(R.color.uxsdk_dic_color_c4_black, R.drawable.uxsdk_tab_item_start_white_style, R.drawable.uxsdk_tab_item_mid_white_style, R.drawable.uxsdk_tab_item_end_white_style), + /** + * 视觉 2.0 新增白色样式,未选中是背景没有描边 + */ + WHITE_V2(R.color.uxsdk_black_95_percent, R.drawable.uxsdk_tab_item_start_white_v2_style, R.drawable.uxsdk_tab_item_mid_white_v2_style, R.drawable.uxsdk_tab_item_end_white_v2_style), + + /** + * 黑色主题 + */ + BLACK(R.color.uxsdk_white, R.drawable.uxsdk_tab_item_start_black_style, R.drawable.uxsdk_tab_item_mid_black_style, R.drawable.uxsdk_tab_item_end_black_style); + + private final int mResTextColorChecked; + private final int mResStart; + private final int mResMid; + private final int mResEnd; + + CoverStyle(@ColorRes int resTextColorChecked, @DrawableRes int resStart, @DrawableRes int resMid, @DrawableRes int redEnd) { + mResTextColorChecked = resTextColorChecked; + mResStart = resStart; + mResMid = resMid; + mResEnd = redEnd; + } + + private static CoverStyle index(int index) { + CoverStyle[] values = values(); + if (index < 0 || index >= values.length) { + return CoverStyle.BLUE; + } + return values[index]; + } + } + + public interface OnTabChangeListener { + /** + * Tab的选中状态改变事件通知 + * @param oldIndex 上一个选中状态的index + * @param newIndex 当前选中的index + */ + void onTabChanged(int oldIndex, int newIndex); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/TabModeWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/TabModeWidget.java new file mode 100644 index 00000000..ae01f51b --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/TabModeWidget.java @@ -0,0 +1,198 @@ +package dji.v5.ux.core.base; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Color; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; + + +import java.util.ArrayList; +import java.util.List; + +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.R; + +/* + * Copyright (c) 2014, DJI All Rights Reserved. + */ + + +public class TabModeWidget extends RoundedLinearLayout implements View.OnClickListener{ + + private int mSelectIndex; + private int mTextSize; + private int mTextColor; + private boolean mFixedSize; + private List mTabs; + private OnTabChangeListener mOnTabChangeListener; + + public TabModeWidget(Context context) { + this(context, null); + } + + public TabModeWidget(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public TabModeWidget(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(context, attrs, defStyleAttr); + } + + private void initialize(Context context, AttributeSet attrs, int defStyleAttr) { + setBackgroundResource(R.drawable.uxsdk_selector_white_round_rect); + TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.TabModeWidget, defStyleAttr, 0); + + mSelectIndex = ta.getInt(R.styleable.TabModeWidget_uxsdk_select, 0); + mTextSize = ta.getDimensionPixelSize(R.styleable.TabModeWidget_uxsdk_textSize, AndUtil.dip2px(getContext(), 9)); + mTextColor = ta.getColor(R.styleable.TabModeWidget_uxsdk_textColor, Color.WHITE); + mFixedSize = ta.getBoolean(R.styleable.TabModeWidget_uxsdk_fixedSize, false); + + // 可以设置自定义背景色 + mTabs = new ArrayList(); + if (ta.hasValue(R.styleable.TabModeWidget_uxsdk_tabs)) { + CharSequence[] entries = ta.getTextArray(R.styleable.TabModeWidget_uxsdk_tabs); + if (entries != null && entries.length > 0) { + for (CharSequence s: entries) { + mTabs.add(s.toString()); + } + setTabs(); + } + } + ta.recycle(); + } + + private void setTabs() { + for (int i = 0; i < mTabs.size(); ++i) { + TextView tab; + if (i == mSelectIndex) { + tab = new TabBuilder().setTabName(mTabs.get(i)) + .setTextSize(mTextSize) + .setTextColor(Color.BLACK) + .setBackground(Color.WHITE) + .build(); + } else { + tab = new TabBuilder().setTabName(mTabs.get(i)) + .setTextSize(mTextSize) + .setTextColor(mTextColor) + .setBackground(Color.TRANSPARENT) + .build(); + } + tab.setOnClickListener(this); + addView(tab); + + if (mFixedSize) { + LayoutParams params = (LayoutParams)tab.getLayoutParams(); + if (params != null) { + params.weight = 1; + params.width = 0; + tab.setLayoutParams(params); + } + } + } + invalidate(); + } + + public void setTabs(int select, List tabs) { + removeAllViews(); + mTabs.clear(); + mTabs.addAll(tabs); + mSelectIndex = select; + setTabs(); + } + + public int getTabSize(){ + return mTabs.size(); + } + + public void setCurrentTab(int tab) { + View child = getChildAt(tab); + if (child != null) { + updateSelectedView(child); + } + } + + public int getCurrentTab() { + return mSelectIndex; + } + + public void setOnTabChangeListener(OnTabChangeListener listener) { + mOnTabChangeListener = listener; + } + + private void updateSelectedView(View view) { + if (view == null) { + return; + } + int childCount = getChildCount(); + for (int i = 0; i < childCount; ++i) { + TextView child = (TextView) getChildAt(i); + if (child == null) { + continue; + } + if (child == view) { + child.setBackgroundColor(Color.WHITE); + child.setTextColor(Color.BLACK); + mSelectIndex = i; + } else { + child.setTextColor(mTextColor); + child.setBackgroundColor(Color.TRANSPARENT); + } + } + invalidate(); + } + @Override + public void onClick(View view) { + if (! isEnabled()) { + return; + } + int oldIndex = mSelectIndex; + updateSelectedView(view); + if (mOnTabChangeListener != null) { + mOnTabChangeListener.onTabChanged(oldIndex, mSelectIndex); + } + } + + protected class TabBuilder { + String tabName; + int textSize; + int textColor; + int background; + + public TabBuilder setTabName(String tabName) { + this.tabName = tabName; + return this; + } + + public TabBuilder setTextSize(int textSize) { + this.textSize = textSize; + return this; + } + + public TabBuilder setTextColor(int textColor) { + this.textColor = textColor; + return this; + } + + public TabBuilder setBackground(int background) { + this.background = background; + return this; + } + + public TextView build() { + TextView tab = (TextView) LayoutInflater.from(getContext()).inflate(R.layout.uxsdk_widget_tab_item, null); + tab.setText(tabName); + tab.setTextColor(textColor); + tab.setBackgroundColor(background); + return tab; + } + } + + public interface OnTabChangeListener { + void onTabChanged(int oldIndex, int newIndex); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/TabSelectCell.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/TabSelectCell.java new file mode 100644 index 00000000..316444a1 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/TabSelectCell.java @@ -0,0 +1,130 @@ +package dji.v5.ux.core.base; +/* + * Copyright (c) 2014, DJI All Rights Reserved. + */ + +import android.content.Context; +import android.content.res.TypedArray; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.widget.TextView; + + + +import java.util.ArrayList; +import java.util.List; + +import dji.v5.utils.common.AndUtil; +import dji.v5.utils.common.ContextUtil; +import dji.v5.ux.R; + +/** + *

Created by luca on 2017/1/19.

+ */ + +public class TabSelectCell extends DividerConstraintLayout { + + TabModeWidget mTabWidget; + TextView mSummary; + TextView mTitle; + TextView mDesc; + private OnTabChangeListener mChangeListener; + + public TabSelectCell(Context context) { + this(context, null); + } + + public TabSelectCell(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public TabSelectCell(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(context, attrs, defStyleAttr); + } + + private void initialize(Context context, AttributeSet attrs, int defStyleAttr) { + LayoutInflater.from(context).inflate(R.layout.uxsdk_cell_tab_select_layout, this, true); + TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.TabSelectCell, defStyleAttr, 0); + + mTabWidget = (TabModeWidget) findViewById(R.id.tab_switcher); + mSummary = (TextView) findViewById(R.id.summary); + mTitle = (TextView) findViewById(R.id.title); + mDesc = findViewById(R.id.desc); + + if (ta.hasValue(R.styleable.TabSelectCell_uxsdk_title)) { + mTitle.setText(ta.getString(R.styleable.TabSelectCell_uxsdk_title)); + } else { + mTitle.setVisibility(GONE); + } + + if (ta.hasValue(R.styleable.TabSelectCell_uxsdk_summary)) { + mSummary.setText(ta.getString(R.styleable.TabSelectCell_uxsdk_summary)); + } else { + mSummary.setVisibility(GONE); + } + + if (ta.hasValue(R.styleable.TabSelectCell_uxsdk_desc)) { + mDesc.setText(ta.getString(R.styleable.TabSelectCell_uxsdk_desc)); + } else { + mDesc.setVisibility(GONE); + } + + int selectIndex = ta.getInt(R.styleable.TabSelectCell_uxsdk_select, 0); + + // 可以设置自定义背景色 + List tabs = new ArrayList(); + if (ta.hasValue(R.styleable.TabSelectCell_uxsdk_tabs)) { + CharSequence[] entries = ta.getTextArray(R.styleable.TabSelectCell_uxsdk_tabs); + if (entries != null && entries.length > 0) { + for (CharSequence s: entries) { + tabs.add(s.toString()); + } + mTabWidget.setTabs(selectIndex, tabs); + } + } + ta.recycle(); + + mTabWidget.setCurrentTab(selectIndex); + mTabWidget.setOnTabChangeListener((oldIndex, newIndex) -> { + if (mChangeListener != null) { + mChangeListener.onTabChanged(TabSelectCell.this, oldIndex, newIndex); + } + }); + + setMinHeight((int) AndUtil.getItemHeight(ContextUtil.getContext())); + setClickable(true); + } + + @Override + public void setEnabled(boolean enabled) { + super.setEnabled(enabled); + mTabWidget.setEnabled(enabled); + } + + public void addTabs(int select, List tabs) { + mTabWidget.setTabs(select, tabs); + } + + public void setCurrentTab(int tab) { + mTabWidget.setCurrentTab(tab); + } + public void setCurrentDes(int resId) { + mDesc.setText(resId); + } + public int getTabSize(){ + return mTabWidget.getTabSize(); + } + + public int getCurrentTab() { + return mTabWidget.getCurrentTab(); + } + + public void setOnTabChangeListener(OnTabChangeListener listener) { + mChangeListener = listener; + } + + public interface OnTabChangeListener { + void onTabChanged(TabSelectCell cell, int oldIndex, int newIndex); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/TestSchedulerProvider.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/TestSchedulerProvider.java new file mode 100644 index 00000000..ff3a06e3 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/TestSchedulerProvider.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base; + + +import androidx.annotation.NonNull; + +import io.reactivex.rxjava3.core.Scheduler; +import io.reactivex.rxjava3.schedulers.TestScheduler; + +/** + * Class to create schedulers for unit tests + */ +public class TestSchedulerProvider implements SchedulerProviderInterface { + + private TestScheduler testScheduler; + + public TestSchedulerProvider() { + testScheduler = new TestScheduler(); + } + + @Override + @NonNull + public Scheduler io() { + return testScheduler; + } + + @Override + @NonNull + public Scheduler computation() { + return testScheduler; + } + + @Override + @NonNull + public Scheduler ui() { + return testScheduler; + } + + public TestScheduler getTestScheduler() { + return testScheduler; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/TextCell.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/TextCell.java new file mode 100644 index 00000000..299517be --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/TextCell.java @@ -0,0 +1,294 @@ +package dji.v5.ux.core.base; + +import android.content.Context; +import android.content.res.Resources; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.Log; +import android.util.TypedValue; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.ColorInt; +import androidx.annotation.DrawableRes; +import androidx.core.content.ContextCompat; + +import com.mikepenz.iconics.IconicsDrawable; +import com.mikepenz.iconics.view.IconicsImageView; + +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.R; + +public class TextCell extends DividerConstraintLayout { + + protected TextView mTitle; + protected ImageView mInfoIV; + protected TextView mContent; + protected TextView mSubhead; + protected IconicsImageView mArrow; + protected ImageView mIcon; + protected TextView mSummary; + + public enum ArrowDirection { + LEFT(1), + TOP(2), + RIGHT(3), + BOTTOM(4), + UNKNOWN(0); + + private int value; + + ArrowDirection(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + public static ArrowDirection find(int index) { + ArrowDirection[] values = ArrowDirection.values(); + for (int i = 0; i < values.length; i++) { + if (values[i].getValue() == index) { + return values[i]; + } + } + return UNKNOWN; + } + } + + public TextCell(Context context) { + this(context, null, 0); + } + + public TextCell(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public TextCell(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initialize(context, attrs, defStyleAttr); + } + + private void initialize(Context context, AttributeSet attrs, int defStyleAttr) { + inflate(context, getLayoutId(), this); + TypedArray ta = context.getTheme().obtainStyledAttributes(attrs, R.styleable.TextCell, defStyleAttr, 0); + + mTitle = findViewById(R.id.title); + mInfoIV = findViewById(R.id.info_iv); + mContent = findViewById(R.id.content); + mSubhead = findViewById(R.id.subhead); + mArrow = findViewById(R.id.arrow); + mIcon = findViewById(R.id.icon); + mSummary = findViewById(R.id.summary); + + initTitleAndContent(ta); + + if (ta.hasValue(R.styleable.TextCell_uxsdk_text_cell_infoImageView)) { + mInfoIV.setBackground(ta.getDrawable(R.styleable.TextCell_uxsdk_text_cell_infoImageView)); + mInfoIV.setVisibility(VISIBLE); + } else { + mInfoIV.setVisibility(GONE); + } + + if (ta.hasValue(R.styleable.TextCell_uxsdk_text_cell_contentColor)) { + mContent.setTextColor(ta.getColor(R.styleable.TextCell_uxsdk_text_cell_contentColor, ContextCompat.getColor(getContext(), R.color.uxsdk_dic_color_c24_white_Transparent6))); + } + + if (ta.hasValue(R.styleable.TextCell_uxsdk_text_cell_contentTextSize)) { + mContent.setTextSize(TypedValue.COMPLEX_UNIT_PX, ta.getDimension(R.styleable.TextCell_uxsdk_text_cell_contentTextSize, 14)); + } + + if (ta.hasValue(R.styleable.TextCell_uxsdk_text_cell_arrow)) { + int direction = ta.getInt(R.styleable.TextCell_uxsdk_text_cell_arrow, 0); + setRightImageDirection(ArrowDirection.find(direction)); + } + + initSummary(ta); + + if (ta.hasValue(R.styleable.TextCell_uxsdk_text_cell_subhead)) { + String str = ta.getString(R.styleable.TextCell_uxsdk_text_cell_subhead); + mSubhead.setVisibility(VISIBLE); + mSubhead.setText(str); + } else { + mSubhead.setVisibility(GONE); + } + + if (ta.hasValue(R.styleable.TextCell_uxsdk_text_cell_drawable)) { + String drawableStr = ta.getString(R.styleable.TextCell_uxsdk_text_cell_drawable); + if (!TextUtils.isEmpty(drawableStr)) { + IconicsDrawable drawable = new IconicsDrawable(getContext(), drawableStr); + setRightImage(drawable); + } + } + + if (ta.hasValue(R.styleable.TextCell_uxsdk_text_cell_arrowRes)) { + mArrow.setVisibility(VISIBLE); + mArrow.setImageDrawable(ta.getDrawable(R.styleable.TextCell_uxsdk_text_cell_arrowRes)); + } + ta.recycle(); + + setMinHeight((int) AndUtil.getItemHeight(getContext())); + + } + + void initTitleAndContent(TypedArray ta) { + mTitle.setText(ta.getString(R.styleable.TextCell_uxsdk_text_cell_title)); + if (ta.hasValue(R.styleable.TextCell_uxsdk_text_cell_content)) { + mContent.setText(ta.getString(R.styleable.TextCell_uxsdk_text_cell_content)); + } else { + mContent.setVisibility(INVISIBLE); + } + + if (ta.hasValue(R.styleable.TextCell_uxsdk_text_cell_titleColor)) { + mTitle.setTextColor(ta.getColor(R.styleable.TextCell_uxsdk_text_cell_titleColor, ContextCompat.getColor(getContext(), R.color.uxsdk_dic_color_c8_white))); + } + + if (ta.hasValue(R.styleable.TextCell_uxsdk_text_cell_titleTextSize)) { + Log.w("test", "" + ta.getDimension(R.styleable.TextCell_uxsdk_text_cell_titleTextSize, 16)); + mTitle.setTextSize(TypedValue.COMPLEX_UNIT_PX, ta.getDimension(R.styleable.TextCell_uxsdk_text_cell_titleTextSize, 16)); + } + } + + void initSummary(TypedArray ta) { + if (ta.hasValue(R.styleable.TextCell_uxsdk_text_cell_summary)) { + mSummary.setVisibility(VISIBLE); + mSummary.setText(ta.getString(R.styleable.TextCell_uxsdk_text_cell_summary)); + } else { + mSummary.setVisibility(GONE); + } + + if (ta.hasValue(R.styleable.TextCell_uxsdk_text_cell_summaryColor)) { + mSummary.setTextColor(ta.getColor(R.styleable.TextCell_uxsdk_text_cell_summaryColor, ContextCompat.getColor(getContext(), R.color.uxsdk_dic_color_c24_white_Transparent6))); + } + + if (ta.hasValue(R.styleable.TextCell_uxsdk_text_cell_summaryTextSize)) { + mSummary.setTextSize(TypedValue.COMPLEX_UNIT_PX, ta.getDimension(R.styleable.TextCell_uxsdk_text_cell_summaryTextSize, 12)); + } + } + + /** + * 用于修改布局,当前 TextCell 布局改动影响范围太大 + */ + protected int getLayoutId() { + return R.layout.uxsdk_cell_text_layout; + } + + public void setArrowResVisible(boolean visibility) { + mArrow.setVisibility(visibility ? View.VISIBLE : View.GONE); + } + + public void setTitle(String title) { + mTitle.setText(title); + } + + public void setTitleColor(@ColorInt int titleColor) { + mTitle.setTextColor(titleColor); + } + + public void setInfoImageVisibility(int visibility) { + mInfoIV.setVisibility(visibility); + } + + public void setContent(String content) { + if (!TextUtils.isEmpty(content)) { + mContent.setText(content); + mContent.setVisibility(VISIBLE); + } else { + mContent.setVisibility(INVISIBLE); + } + } + + public void setContentColor(@ColorInt int contentColor) { + mContent.setTextColor(contentColor); + } + + public void setRightImage(IconicsDrawable icon) { + if (icon != null) { + mArrow.setIcon(icon); + mArrow.setVisibility(VISIBLE); + } else { + mArrow.setVisibility(GONE); + } + } + + public void setRightImageVisibility(int visibility) { + mArrow.setVisibility(visibility); + } + + public void setRightImageDirection(ArrowDirection direction) { + if (direction == null) { + mArrow.setVisibility(GONE); + return; + } + int imgRes = -1; + switch (direction) { + case BOTTOM: { + imgRes = R.drawable.uxsdk_arrow_down; + break; + } + case TOP: { + imgRes = R.drawable.uxsdk_arrow_up; + break; + } + case LEFT: { + imgRes = R.drawable.uxsdk_arrow_left; + break; + } + case RIGHT: { + imgRes = R.drawable.uxsdk_arrow_right; + break; + } + default: { + break; + } + } + if (imgRes != -1) { + mArrow.setVisibility(VISIBLE); + mArrow.setImageResource(imgRes); + } else { + mArrow.setVisibility(GONE); + } + } + + public void setIcon(@DrawableRes int resId) { + if (resId == Resources.ID_NULL) { + mIcon.setVisibility(GONE); + } else { + mIcon.setVisibility(VISIBLE); + mIcon.setImageResource(resId); + } + } + + public void setIconBackground(Drawable background) { + mIcon.setBackground(background); + } + + public void setSummary(String summary) { + if (TextUtils.isEmpty(summary)) { + mSummary.setVisibility(GONE); + } else { + mSummary.setVisibility(VISIBLE); + mSummary.setText(summary); + } + } + + public void setSummaryColor(@ColorInt int summaryColor) { + if (summaryColor != 0) { + mSummary.setTextColor(summaryColor); + } + } + + public void setInfoOnClickListener(OnClickListener listener) { + if (mInfoIV != null) { + mInfoIV.setOnClickListener(listener); + } + } + + public void setRightImageBackground(Drawable drawable) { + mArrow.setBackground(drawable); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/UXSDKError.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/UXSDKError.kt new file mode 100644 index 00000000..1a23d420 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/UXSDKError.kt @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base + +import dji.v5.common.error.IDJIError + +/** + * Exposes a DJIError as a Throwable + * @property djiError DJIError for the given UXSDKError + */ +data class UXSDKError( + @get:JvmName("getDJIError") + val djiError: IDJIError +) : Throwable(djiError.toString()) { + + override fun toString(): String { + return djiError.toString() + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/UXSDKErrorDescription.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/UXSDKErrorDescription.java new file mode 100644 index 00000000..ad22d719 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/UXSDKErrorDescription.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base; + +import dji.v5.common.error.DJICommonError; + +/** + * Class containing UXSDKErrors with their descriptions + */ +public final class UXSDKErrorDescription extends DJICommonError { + /** + * The value type of the object does not match the value type of the key. + */ + public static final String VALUE_TYPE_MISMATCH = "The value type of the object does not match the value type of the key."; + + /** + * Simulator not running. Wind simulation can only be achieved while the simulator is active. + */ + public static final String SIMULATOR_WIND_ERROR = "Simulator not running. Wind simulation can only be achieved while the simulator is active."; + + /** + * Fly zone error + */ + public static final String FLYZONE_ERROR = "FlyZoneManager not available."; + + /** + * User account manager error + */ + public static final String USER_ACCOUNT_MANAGER_ERROR = "UserAccountManager not available."; + +// private UXSDKErrorDescription(String description) { +// DJICommonError.FACTORY.build("", "", description); +// } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/WidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/WidgetModel.java new file mode 100644 index 00000000..56df6e5d --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/WidgetModel.java @@ -0,0 +1,292 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base; + +import java.util.ArrayList; +import java.util.List; + +import androidx.annotation.NonNull; + +import dji.sdk.keyvalue.key.DJIKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.key.ProductKey; +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.communication.UXKey; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.disposables.CompositeDisposable; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.functions.Consumer; + +/** + * Base WidgetModel class to be extended by all the individual + * widget models + */ +public abstract class WidgetModel { + + //region Constants + public final String tag = LogUtils.getTag(this); + //endregion + //region Fields + /** + * Allows communication with the SDK KeyManager using the DJIKey keyed interface. + */ + protected final DJISDKModel djiSdkModel; + /** + * Allows communication using the UXKeys keyed interface. + */ + protected final ObservableInMemoryKeyedStore uxKeyManager; + protected DataProcessor productConnectionProcessor; + private CompositeDisposable keyDisposables; + private CompositeDisposable compositeDisposable; + private final List moduleList = new ArrayList<>(); + private StatesChangeListener statesChangedListener; + //endregion + + //region Default Constructor + protected WidgetModel(@NonNull DJISDKModel djiSdkModel, + @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + this.djiSdkModel = djiSdkModel; + this.uxKeyManager = uxKeyManager; + productConnectionProcessor = DataProcessor.create(false); + } + //endregion + + //region Lifecycle + + protected void addModule(@NonNull BaseModule baseModule) { + if (isStarted()) { + throw new IllegalStateException("WidgetModel is already setup. Modules should" + + " be added during initialization."); + } + if (!moduleList.contains(baseModule)) { + moduleList.add(baseModule); + } + } + + /** + * Set up the widget model by initializing all the required resources + */ + public synchronized void setup() { + if (isStarted()) { + throw new IllegalStateException("WidgetModel is already setup. Call cleanup first."); + } + keyDisposables = new CompositeDisposable(); + compositeDisposable = new CompositeDisposable(); + initializeConnection(); + inSetup(); + for (BaseModule module : moduleList) { + module.setup(this); + } + } + + /** + * Clean up the widget model by destroying all the resources used + */ + public synchronized void cleanup() { + if (keyDisposables != null) { + keyDisposables.dispose(); + keyDisposables = null; + } + + if (compositeDisposable != null) { + compositeDisposable.dispose(); + compositeDisposable = null; + } + + djiSdkModel.removeListener(this); + + for (BaseModule module : moduleList) { + module.cleanup(); + } + + statesChangedListener = null; + inCleanup(); + } + + /** + * Restart the widget model by cleaning up and then setting up the widget model again + */ + protected void restart() { + if (isStarted()) { + cleanup(); + setup(); + } + } + + /** + * Setup method for initialization that must be implemented + */ + protected abstract void inSetup(); + + /** + * Cleanup method for post-usage destruction that must be implemented + */ + protected abstract void inCleanup(); + + /** + * Method to update states for the required processors in the child classes as required + */ + protected void updateStates() { + StatesChangeListener listener = statesChangedListener; + if (listener != null) { + listener.onStatesChanged(); + } + } + + private boolean isStarted() { + return keyDisposables != null; + } + + /** + * Add a disposable to the composite disposable list to ensure cleanup after completion + * + * @param disposable Disposable to be added + */ + protected void addDisposable(@NonNull Disposable disposable) { + if (compositeDisposable != null) { + compositeDisposable.add(disposable); + } + } + + protected void removeDisposable(@NonNull Disposable disposable) { + if (compositeDisposable != null) { + compositeDisposable.remove(disposable); + } + } + + private void initializeConnection() { + DJIKey productConnectionKey = KeyTools.createKey(ProductKey.KeyConnection); + bindDataProcessor(productConnectionKey, productConnectionProcessor, newValue -> onProductConnectionChanged((boolean) newValue)); + } + + protected void onProductConnectionChanged(boolean isConnected) { + // do nothing + } + //endregion + + /** + * Bind the given DJIKey to the given data processor. This data processor will be + * invoked with every update to the key. + * + * @param key DJIKey to be bound + * @param dataProcessor DataProcessor to be bound + */ + protected void bindDataProcessor(@NonNull DJIKey key, @NonNull DataProcessor dataProcessor) { + bindDataProcessor(key, dataProcessor, o -> { + }); + } + + /** + * Bind the given DJIKey to the given data processor and attach the given consumer to it. + * The data processor and side effect consumer will be invoked with every update to the key. + * The side effect consumer will be called before the data processor is updated. + * + * @param key DJIKey to be bound + * @param dataProcessor DataProcessor to be bound + * @param sideEffectConsumer Consumer to be called along with data processor + */ + protected void bindDataProcessor(@NonNull DJIKey key, + @NonNull DataProcessor dataProcessor, + @NonNull Consumer sideEffectConsumer) { + registerKey(key, dataProcessor::onNext, sideEffectConsumer); + } + + /** + * Bind the given UXKey to the given data processor. This data processor will be + * invoked with every update to the key. + * + * @param key UXKey to be bound + * @param dataProcessor DataProcessor to be bound + */ + protected void bindDataProcessor(@NonNull UXKey key, @NonNull DataProcessor dataProcessor) { + bindDataProcessor(key, dataProcessor, o -> { + }); + } + + /** + * Bind the given UXKey to the given data processor and attach the given consumer to it. + * The data processor and side effect consumer will be invoked with every update to the key. + * The side effect consumer will be called before the data processor is updated. + * + * @param key UXKey to be bound + * @param dataProcessor DataProcessor to be bound + * @param sideEffectConsumer Consumer to be called along with data processor + */ + protected void bindDataProcessor(@NonNull UXKey key, + @NonNull DataProcessor dataProcessor, + @NonNull Consumer sideEffectConsumer) { + registerKey(key, dataProcessor::onNext, sideEffectConsumer); + } + + private void registerKey(@NonNull DJIKey djiKey, + @NonNull Consumer bindConsumer, + @NonNull Consumer sideEffectConsumer) { + if (keyDisposables == null) { + throw new IllegalStateException("Call this method only when in inSetup"); + } + + keyDisposables.add(djiSdkModel.addListener(djiKey, this) + .doOnNext(sideEffectConsumer) + .doOnNext(bindConsumer) + .subscribe(o -> updateStates(), logError(djiKey))); + } + + private void registerKey(@NonNull UXKey uxKey, + @NonNull Consumer bindConsumer, + @NonNull Consumer sideEffectConsumer) { + if (keyDisposables == null) { + throw new IllegalStateException("Call this method only when in inSetup"); + } + keyDisposables.add( + uxKeyManager.addObserver(uxKey) + .filter(broadcastValues -> broadcastValues.getCurrentValue().getData() != null) + .map(broadcastValues -> broadcastValues.getCurrentValue().getData()) + .doOnNext(o -> sideEffectConsumer.accept((T) o)) + .doOnNext(o -> bindConsumer.accept((T) o)) + .subscribe(o -> updateStates(), logError(uxKey))); + } + + private Consumer logError(@NonNull DJIKey djiKey) { + return throwable -> LogUtils.e(tag, "Error registering " + djiKey.toString() + ": " + throwable.getMessage()); + } + + private Consumer logError(@NonNull UXKey uxKey) { + return throwable -> LogUtils.e(tag, "Error registering " + uxKey.toString() + ": " + throwable.getMessage()); + } + + /** + * Get the product connection status - true if connected, false otherwise. + * + * @return Flowable of boolean type + */ + public Flowable getProductConnection() { + return productConnectionProcessor.toFlowable(); + } + + public interface StatesChangeListener { + void onStatesChanged(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/WidgetSize.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/WidgetSize.kt new file mode 100644 index 00000000..c4b53627 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/WidgetSize.kt @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base + + +/** + * Describe how the widget should be sized. + * @param sizeType Type of size for the widget + * @param widthDimension The type of dimension of a widget's width + * @param heightDimension The type of dimension of a widget's width + */ +data class WidgetSizeDescription( + val sizeType: SizeType, + val widthDimension: Dimension = Dimension.EXPAND, + val heightDimension: Dimension = Dimension.EXPAND +) { + /** + * The size type, whether is a ratio or any other type. + */ + enum class SizeType { + /** + * The size of widget can be dynamic but should follow a ratio + */ + RATIO, + + /** + * The size of the widget is anything other than a ratio + */ + OTHER + } + + /** + * The dimension of the widget, whether it should expand or wrap. + */ + enum class Dimension { + /** + * Indicates that the dimension can be expanded. + * Similar to use 0dp in ConstraintLayout, or match parent in other layouts. + */ + EXPAND, + + /** + * Indicates that the widget should be wrapped, that is, the widget decides its own size. + */ + WRAP + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartAnimationListener.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartAnimationListener.java new file mode 100644 index 00000000..a0fc66e9 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartAnimationListener.java @@ -0,0 +1,9 @@ +package dji.v5.ux.core.base.charts.animation; + +import java.util.EventListener; + +public interface ChartAnimationListener extends EventListener { + void onAnimationStarted(); + + void onAnimationFinished(); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartDataAnimator.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartDataAnimator.java new file mode 100644 index 00000000..024a954a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartDataAnimator.java @@ -0,0 +1,13 @@ +package dji.v5.ux.core.base.charts.animation; + +public interface ChartDataAnimator { + long DEFAULT_ANIMATION_DURATION = 500L; + + void startAnimation(long var1); + + void cancelAnimation(); + + boolean isAnimationStarted(); + + void setChartAnimationListener(ChartAnimationListener var1); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartDataAnimatorV14.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartDataAnimatorV14.java new file mode 100644 index 00000000..52eb4151 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartDataAnimatorV14.java @@ -0,0 +1,70 @@ +package dji.v5.ux.core.base.charts.animation; + +import android.animation.Animator; +import android.animation.ValueAnimator; +import android.annotation.SuppressLint; + +import dji.v5.ux.core.base.charts.view.Chart; + +@SuppressLint({"NewApi"}) +public class ChartDataAnimatorV14 implements ChartDataAnimator, Animator.AnimatorListener, ValueAnimator.AnimatorUpdateListener { + private final Chart chart; + private ValueAnimator animator; + private ChartAnimationListener animationListener = new DummyChartAnimationListener(); + + public ChartDataAnimatorV14(Chart chart) { + this.chart = chart; + this.animator = ValueAnimator.ofFloat(0.0F, 1.0F); + this.animator.addListener(this); + this.animator.addUpdateListener(this); + } + + public void startAnimation(long duration) { + if (duration >= 0L) { + this.animator.setDuration(duration); + } else { + this.animator.setDuration(500L); + } + + this.animator.start(); + } + + public void cancelAnimation() { + this.animator.cancel(); + } + + public void onAnimationUpdate(ValueAnimator animation) { + this.chart.animationDataUpdate(animation.getAnimatedFraction()); + } + + public void onAnimationCancel(Animator animation) { + //do nothing + } + + public void onAnimationEnd(Animator animation) { + this.chart.animationDataFinished(); + this.animationListener.onAnimationFinished(); + } + + public void onAnimationRepeat(Animator animation) { + //do nothing + } + + public void onAnimationStart(Animator animation) { + this.animationListener.onAnimationStarted(); + } + + public boolean isAnimationStarted() { + return this.animator.isStarted(); + } + + public void setChartAnimationListener(ChartAnimationListener animationListener) { + if (null == animationListener) { + this.animationListener = new DummyChartAnimationListener(); + } else { + this.animationListener = animationListener; + } + + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartDataAnimatorV8.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartDataAnimatorV8.java new file mode 100644 index 00000000..05645f66 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartDataAnimatorV8.java @@ -0,0 +1,70 @@ +package dji.v5.ux.core.base.charts.animation; + +import android.os.Handler; +import android.os.SystemClock; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.Interpolator; + +import dji.v5.ux.core.base.charts.view.Chart; + +public class ChartDataAnimatorV8 implements ChartDataAnimator{ + final Chart chart; + final Handler handler; + final Interpolator interpolator = new AccelerateDecelerateInterpolator(); + long start; + boolean isAnimationStarted = false; + long duration; + private final Runnable runnable = new Runnable() { + public void run() { + long elapsed = SystemClock.uptimeMillis() - ChartDataAnimatorV8.this.start; + if (elapsed > ChartDataAnimatorV8.this.duration) { + ChartDataAnimatorV8.this.isAnimationStarted = false; + ChartDataAnimatorV8.this.handler.removeCallbacks(ChartDataAnimatorV8.this.runnable); + ChartDataAnimatorV8.this.chart.animationDataFinished(); + } else { + float scale = Math.min(ChartDataAnimatorV8.this.interpolator.getInterpolation((float)elapsed / (float)ChartDataAnimatorV8.this.duration), 1.0F); + ChartDataAnimatorV8.this.chart.animationDataUpdate(scale); + ChartDataAnimatorV8.this.handler.postDelayed(this, 16L); + } + } + }; + private ChartAnimationListener animationListener = new DummyChartAnimationListener(); + + public ChartDataAnimatorV8(Chart chart) { + this.chart = chart; + this.handler = new Handler(); + } + + public void startAnimation(long duration) { + if (duration >= 0L) { + this.duration = duration; + } else { + this.duration = 500L; + } + + this.isAnimationStarted = true; + this.animationListener.onAnimationStarted(); + this.start = SystemClock.uptimeMillis(); + this.handler.post(this.runnable); + } + + public void cancelAnimation() { + this.isAnimationStarted = false; + this.handler.removeCallbacks(this.runnable); + this.chart.animationDataFinished(); + this.animationListener.onAnimationFinished(); + } + + public boolean isAnimationStarted() { + return this.isAnimationStarted; + } + + public void setChartAnimationListener(ChartAnimationListener animationListener) { + if (null == animationListener) { + this.animationListener = new DummyChartAnimationListener(); + } else { + this.animationListener = animationListener; + } + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartViewportAnimator.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartViewportAnimator.java new file mode 100644 index 00000000..f34f3196 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartViewportAnimator.java @@ -0,0 +1,18 @@ +package dji.v5.ux.core.base.charts.animation; + +import dji.v5.ux.core.base.charts.model.Viewport; + +public interface ChartViewportAnimator { + int FAST_ANIMATION_DURATION = 300; + + void startAnimation(Viewport var1, Viewport var2); + + void startAnimation(Viewport var1, Viewport var2, long var3); + + void cancelAnimation(); + + boolean isAnimationStarted(); + + void setChartAnimationListener(ChartAnimationListener var1); +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartViewportAnimatorV14.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartViewportAnimatorV14.java new file mode 100644 index 00000000..ed8eef53 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartViewportAnimatorV14.java @@ -0,0 +1,84 @@ +package dji.v5.ux.core.base.charts.animation; + +import android.animation.Animator; +import android.animation.ValueAnimator; +import android.annotation.SuppressLint; + +import dji.v5.ux.core.base.charts.model.Viewport; +import dji.v5.ux.core.base.charts.view.Chart; + +@SuppressLint({"NewApi"}) +public class ChartViewportAnimatorV14 implements ChartViewportAnimator, Animator.AnimatorListener, ValueAnimator.AnimatorUpdateListener { + private final Chart chart; + private ValueAnimator animator; + private Viewport startViewport = new Viewport(); + private Viewport targetViewport = new Viewport(); + private Viewport newViewport = new Viewport(); + private ChartAnimationListener animationListener = new DummyChartAnimationListener(); + + public ChartViewportAnimatorV14(Chart chart) { + this.chart = chart; + this.animator = ValueAnimator.ofFloat(0.0F, 1.0F); + this.animator.addListener(this); + this.animator.addUpdateListener(this); + this.animator.setDuration(300L); + } + + public void startAnimation(Viewport startViewport, Viewport targetViewport) { + this.startViewport.set(startViewport); + this.targetViewport.set(targetViewport); + this.animator.setDuration(300L); + this.animator.start(); + } + + public void startAnimation(Viewport startViewport, Viewport targetViewport, long duration) { + this.startViewport.set(startViewport); + this.targetViewport.set(targetViewport); + this.animator.setDuration(duration); + this.animator.start(); + } + + public void cancelAnimation() { + this.animator.cancel(); + } + + public void onAnimationUpdate(ValueAnimator animation) { + float scale = animation.getAnimatedFraction(); + float diffLeft = (this.targetViewport.left - this.startViewport.left) * scale; + float diffTop = (this.targetViewport.top - this.startViewport.top) * scale; + float diffRight = (this.targetViewport.right - this.startViewport.right) * scale; + float diffBottom = (this.targetViewport.bottom - this.startViewport.bottom) * scale; + this.newViewport.set(this.startViewport.left + diffLeft, this.startViewport.top + diffTop, this.startViewport.right + diffRight, this.startViewport.bottom + diffBottom); + this.chart.setCurrentViewport(this.newViewport); + } + + public void onAnimationCancel(Animator animation) { + //do nothing + } + + public void onAnimationEnd(Animator animation) { + this.chart.setCurrentViewport(this.targetViewport); + this.animationListener.onAnimationFinished(); + } + + public void onAnimationRepeat(Animator animation) { + //do nothing + } + + public void onAnimationStart(Animator animation) { + this.animationListener.onAnimationStarted(); + } + + public boolean isAnimationStarted() { + return this.animator.isStarted(); + } + + public void setChartAnimationListener(ChartAnimationListener animationListener) { + if (null == animationListener) { + this.animationListener = new DummyChartAnimationListener(); + } else { + this.animationListener = animationListener; + } + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartViewportAnimatorV8.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartViewportAnimatorV8.java new file mode 100644 index 00000000..eda97ef0 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/ChartViewportAnimatorV8.java @@ -0,0 +1,89 @@ +package dji.v5.ux.core.base.charts.animation; + +import android.os.Handler; +import android.os.SystemClock; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.Interpolator; + +import dji.v5.ux.core.base.charts.model.Viewport; +import dji.v5.ux.core.base.charts.view.Chart; + +public class ChartViewportAnimatorV8 implements ChartViewportAnimator { + final Chart chart; + final Handler handler; + final Interpolator interpolator = new AccelerateDecelerateInterpolator(); + long start; + boolean isAnimationStarted = false; + private Viewport startViewport = new Viewport(); + private Viewport targetViewport = new Viewport(); + private Viewport newViewport = new Viewport(); + private long duration; + private ChartAnimationListener animationListener = new DummyChartAnimationListener(); + private final Runnable runnable = new Runnable() { + public void run() { + long elapsed = SystemClock.uptimeMillis() - ChartViewportAnimatorV8.this.start; + if (elapsed > ChartViewportAnimatorV8.this.duration) { + ChartViewportAnimatorV8.this.isAnimationStarted = false; + ChartViewportAnimatorV8.this.handler.removeCallbacks(ChartViewportAnimatorV8.this.runnable); + ChartViewportAnimatorV8.this.chart.setCurrentViewport(ChartViewportAnimatorV8.this.targetViewport); + ChartViewportAnimatorV8.this.animationListener.onAnimationFinished(); + } else { + float scale = Math.min(ChartViewportAnimatorV8.this.interpolator.getInterpolation((float)elapsed / (float)ChartViewportAnimatorV8.this.duration), 1.0F); + float diffLeft = (ChartViewportAnimatorV8.this.targetViewport.left - ChartViewportAnimatorV8.this.startViewport.left) * scale; + float diffTop = (ChartViewportAnimatorV8.this.targetViewport.top - ChartViewportAnimatorV8.this.startViewport.top) * scale; + float diffRight = (ChartViewportAnimatorV8.this.targetViewport.right - ChartViewportAnimatorV8.this.startViewport.right) * scale; + float diffBottom = (ChartViewportAnimatorV8.this.targetViewport.bottom - ChartViewportAnimatorV8.this.startViewport.bottom) * scale; + ChartViewportAnimatorV8.this.newViewport.set(ChartViewportAnimatorV8.this.startViewport.left + diffLeft, ChartViewportAnimatorV8.this.startViewport.top + diffTop, ChartViewportAnimatorV8.this.startViewport.right + diffRight, ChartViewportAnimatorV8.this.startViewport.bottom + diffBottom); + ChartViewportAnimatorV8.this.chart.setCurrentViewport(ChartViewportAnimatorV8.this.newViewport); + ChartViewportAnimatorV8.this.handler.postDelayed(this, 16L); + } + } + }; + + public ChartViewportAnimatorV8(Chart chart) { + this.chart = chart; + this.duration = 300L; + this.handler = new Handler(); + } + + public void startAnimation(Viewport startViewport, Viewport targetViewport) { + this.startViewport.set(startViewport); + this.targetViewport.set(targetViewport); + this.duration = 300L; + this.isAnimationStarted = true; + this.animationListener.onAnimationStarted(); + this.start = SystemClock.uptimeMillis(); + this.handler.post(this.runnable); + } + + public void startAnimation(Viewport startViewport, Viewport targetViewport, long duration) { + this.startViewport.set(startViewport); + this.targetViewport.set(targetViewport); + this.duration = duration; + this.isAnimationStarted = true; + this.animationListener.onAnimationStarted(); + this.start = SystemClock.uptimeMillis(); + this.handler.post(this.runnable); + } + + public void cancelAnimation() { + this.isAnimationStarted = false; + this.handler.removeCallbacks(this.runnable); + this.chart.setCurrentViewport(this.targetViewport); + this.animationListener.onAnimationFinished(); + } + + public boolean isAnimationStarted() { + return this.isAnimationStarted; + } + + public void setChartAnimationListener(ChartAnimationListener animationListener) { + if (null == animationListener) { + this.animationListener = new DummyChartAnimationListener(); + } else { + this.animationListener = animationListener; + } + + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/DummyChartAnimationListener.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/DummyChartAnimationListener.java new file mode 100644 index 00000000..429311cd --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/DummyChartAnimationListener.java @@ -0,0 +1,15 @@ +package dji.v5.ux.core.base.charts.animation; + +public class DummyChartAnimationListener implements ChartAnimationListener { + public DummyChartAnimationListener() { + //do nothing + } + + public void onAnimationStarted() { + //do nothing + } + + public void onAnimationFinished() { + //do nothing + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/PieChartRotationAnimator.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/PieChartRotationAnimator.java new file mode 100644 index 00000000..59812451 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/PieChartRotationAnimator.java @@ -0,0 +1,13 @@ +package dji.v5.ux.core.base.charts.animation; + +public interface PieChartRotationAnimator { + int FAST_ANIMATION_DURATION = 200; + + void startAnimation(float var1, float var2); + + void cancelAnimation(); + + boolean isAnimationStarted(); + + void setChartAnimationListener(ChartAnimationListener var1); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/PieChartRotationAnimatorV14.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/PieChartRotationAnimatorV14.java new file mode 100644 index 00000000..ce9d50e2 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/PieChartRotationAnimatorV14.java @@ -0,0 +1,79 @@ +package dji.v5.ux.core.base.charts.animation; + +import android.animation.Animator; +import android.animation.ValueAnimator; +import android.annotation.SuppressLint; + +import dji.v5.ux.core.base.charts.view.PieChartView; + +@SuppressLint({"NewApi"}) +public class PieChartRotationAnimatorV14 implements PieChartRotationAnimator, Animator.AnimatorListener, ValueAnimator.AnimatorUpdateListener { + private final PieChartView chart; + private ValueAnimator animator; + private float startRotation; + private float targetRotation; + private ChartAnimationListener animationListener; + + public PieChartRotationAnimatorV14(PieChartView chart) { + this(chart, 200L); + } + + public PieChartRotationAnimatorV14(PieChartView chart, long duration) { + this.startRotation = 0.0F; + this.targetRotation = 0.0F; + this.animationListener = new DummyChartAnimationListener(); + this.chart = chart; + this.animator = ValueAnimator.ofFloat(0.0F, 1.0F); + this.animator.setDuration(duration); + this.animator.addListener(this); + this.animator.addUpdateListener(this); + } + + public void startAnimation(float startRotation, float targetRotation) { + this.startRotation = (startRotation % 360.0F + 360.0F) % 360.0F; + this.targetRotation = (targetRotation % 360.0F + 360.0F) % 360.0F; + this.animator.start(); + } + + public void cancelAnimation() { + this.animator.cancel(); + } + + public void onAnimationUpdate(ValueAnimator animation) { + float scale = animation.getAnimatedFraction(); + float rotation = this.startRotation + (this.targetRotation - this.startRotation) * scale; + rotation = (rotation % 360.0F + 360.0F) % 360.0F; + this.chart.setChartRotation((int)rotation, false); + } + + public void onAnimationCancel(Animator animation) { + //do nothing + } + + public void onAnimationEnd(Animator animation) { + this.chart.setChartRotation((int)this.targetRotation, false); + this.animationListener.onAnimationFinished(); + } + + public void onAnimationRepeat(Animator animation) { + //do nothing + } + + public void onAnimationStart(Animator animation) { + this.animationListener.onAnimationStarted(); + } + + public boolean isAnimationStarted() { + return this.animator.isStarted(); + } + + public void setChartAnimationListener(ChartAnimationListener animationListener) { + if (null == animationListener) { + this.animationListener = new DummyChartAnimationListener(); + } else { + this.animationListener = animationListener; + } + + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/PieChartRotationAnimatorV8.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/PieChartRotationAnimatorV8.java new file mode 100644 index 00000000..ddf5ac1b --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/animation/PieChartRotationAnimatorV8.java @@ -0,0 +1,83 @@ +package dji.v5.ux.core.base.charts.animation; + +import android.os.Handler; +import android.os.SystemClock; +import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.Interpolator; + +import dji.v5.ux.core.base.charts.view.PieChartView; + +public class PieChartRotationAnimatorV8 implements PieChartRotationAnimator { + final PieChartView chart; + final long duration; + final Handler handler; + final Interpolator interpolator; + long start; + boolean isAnimationStarted; + private float startRotation; + private float targetRotation; + private ChartAnimationListener animationListener; + private final Runnable runnable; + + public PieChartRotationAnimatorV8(PieChartView chart) { + this(chart, 200L); + } + + public PieChartRotationAnimatorV8(PieChartView chart, long duration) { + this.interpolator = new AccelerateDecelerateInterpolator(); + this.isAnimationStarted = false; + this.startRotation = 0.0F; + this.targetRotation = 0.0F; + this.animationListener = new DummyChartAnimationListener(); + this.runnable = new Runnable() { + public void run() { + long elapsed = SystemClock.uptimeMillis() - PieChartRotationAnimatorV8.this.start; + if (elapsed > PieChartRotationAnimatorV8.this.duration) { + PieChartRotationAnimatorV8.this.isAnimationStarted = false; + PieChartRotationAnimatorV8.this.handler.removeCallbacks(PieChartRotationAnimatorV8.this.runnable); + PieChartRotationAnimatorV8.this.chart.setChartRotation((int)PieChartRotationAnimatorV8.this.targetRotation, false); + PieChartRotationAnimatorV8.this.animationListener.onAnimationFinished(); + } else { + float scale = Math.min(PieChartRotationAnimatorV8.this.interpolator.getInterpolation((float)elapsed / (float)PieChartRotationAnimatorV8.this.duration), 1.0F); + float rotation = PieChartRotationAnimatorV8.this.startRotation + (PieChartRotationAnimatorV8.this.targetRotation - PieChartRotationAnimatorV8.this.startRotation) * scale; + rotation = (rotation % 360.0F + 360.0F) % 360.0F; + PieChartRotationAnimatorV8.this.chart.setChartRotation((int)rotation, false); + PieChartRotationAnimatorV8.this.handler.postDelayed(this, 16L); + } + } + }; + this.chart = chart; + this.duration = duration; + this.handler = new Handler(); + } + + public void startAnimation(float startRotation, float targetRotation) { + this.startRotation = (startRotation % 360.0F + 360.0F) % 360.0F; + this.targetRotation = (targetRotation % 360.0F + 360.0F) % 360.0F; + this.isAnimationStarted = true; + this.animationListener.onAnimationStarted(); + this.start = SystemClock.uptimeMillis(); + this.handler.post(this.runnable); + } + + public void cancelAnimation() { + this.isAnimationStarted = false; + this.handler.removeCallbacks(this.runnable); + this.chart.setChartRotation((int)this.targetRotation, false); + this.animationListener.onAnimationFinished(); + } + + public boolean isAnimationStarted() { + return this.isAnimationStarted; + } + + public void setChartAnimationListener(ChartAnimationListener animationListener) { + if (null == animationListener) { + this.animationListener = new DummyChartAnimationListener(); + } else { + this.animationListener = animationListener; + } + + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/computator/ChartComputator.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/computator/ChartComputator.java new file mode 100644 index 00000000..e0ff8536 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/computator/ChartComputator.java @@ -0,0 +1,214 @@ +package dji.v5.ux.core.base.charts.computator; + +import android.graphics.Point; +import android.graphics.PointF; +import android.graphics.Rect; + +import dji.v5.ux.core.base.charts.listener.DummyVieportChangeListener; +import dji.v5.ux.core.base.charts.listener.ViewportChangeListener; +import dji.v5.ux.core.base.charts.model.Viewport; + +public class ChartComputator { + protected static final float DEFAULT_MAXIMUM_ZOOM = 20.0F; + protected float maxZoom = 20.0F; + protected int chartWidth; + protected int chartHeight; + protected Rect contentRectMinusAllMargins = new Rect(); + protected Rect contentRectMinusAxesMargins = new Rect(); + protected Rect maxContentRect = new Rect(); + protected Viewport currentViewport = new Viewport(); + protected Viewport maxViewport = new Viewport(); + protected float minViewportWidth; + protected float minViewportHeight; + protected ViewportChangeListener viewportChangeListener = new DummyVieportChangeListener(); + + public ChartComputator() { + //do nothing + } + + public void setContentRect(int width, int height, int paddingLeft, int paddingTop, int paddingRight, int paddingBottom) { + this.chartWidth = width; + this.chartHeight = height; + this.maxContentRect.set(paddingLeft, paddingTop, width - paddingRight, height - paddingBottom); + this.contentRectMinusAxesMargins.set(this.maxContentRect); + this.contentRectMinusAllMargins.set(this.maxContentRect); + } + + public void resetContentRect() { + this.contentRectMinusAxesMargins.set(this.maxContentRect); + this.contentRectMinusAllMargins.set(this.maxContentRect); + } + + public void insetContentRect(int deltaLeft, int deltaTop, int deltaRight, int deltaBottom) { + this.contentRectMinusAxesMargins.left += deltaLeft; + this.contentRectMinusAxesMargins.top += deltaTop; + this.contentRectMinusAxesMargins.right -= deltaRight; + this.contentRectMinusAxesMargins.bottom -= deltaBottom; + this.insetContentRectByInternalMargins(deltaLeft, deltaTop, deltaRight, deltaBottom); + } + + public void insetContentRectByInternalMargins(int deltaLeft, int deltaTop, int deltaRight, int deltaBottom) { + this.contentRectMinusAllMargins.left += deltaLeft; + this.contentRectMinusAllMargins.top += deltaTop; + this.contentRectMinusAllMargins.right -= deltaRight; + this.contentRectMinusAllMargins.bottom -= deltaBottom; + } + + public void constrainViewport(float left, float top, float right, float bottom) { + if (right - left < this.minViewportWidth) { + right = left + this.minViewportWidth; + if (left < this.maxViewport.left) { + left = this.maxViewport.left; + right = left + this.minViewportWidth; + } else if (right > this.maxViewport.right) { + right = this.maxViewport.right; + left = right - this.minViewportWidth; + } + } + + if (top - bottom < this.minViewportHeight) { + bottom = top - this.minViewportHeight; + if (top > this.maxViewport.top) { + top = this.maxViewport.top; + bottom = top - this.minViewportHeight; + } else if (bottom < this.maxViewport.bottom) { + bottom = this.maxViewport.bottom; + top = bottom + this.minViewportHeight; + } + } + + this.currentViewport.left = Math.max(this.maxViewport.left, left); + this.currentViewport.top = Math.min(this.maxViewport.top, top); + this.currentViewport.right = Math.min(this.maxViewport.right, right); + this.currentViewport.bottom = Math.max(this.maxViewport.bottom, bottom); + this.viewportChangeListener.onViewportChanged(this.currentViewport); + } + + public void setViewportTopLeft(float left, float top) { + float curWidth = this.currentViewport.width(); + float curHeight = this.currentViewport.height(); + left = Math.max(this.maxViewport.left, Math.min(left, this.maxViewport.right - curWidth)); + top = Math.max(this.maxViewport.bottom + curHeight, Math.min(top, this.maxViewport.top)); + this.constrainViewport(left, top, left + curWidth, top - curHeight); + } + + public float computeRawX(float valueX) { + float pixelOffset = (valueX - this.currentViewport.left) * (this.contentRectMinusAllMargins.width() / this.currentViewport.width()); + return (float)this.contentRectMinusAllMargins.left + pixelOffset; + } + + public float computeRawY(float valueY) { + float pixelOffset = (valueY - this.currentViewport.bottom) * (this.contentRectMinusAllMargins.height() / this.currentViewport.height()); + return (float)this.contentRectMinusAllMargins.bottom - pixelOffset; + } + + public float computeRawDistanceX(float distance) { + return distance * (this.contentRectMinusAllMargins.width() / this.currentViewport.width()); + } + + public float computeRawDistanceY(float distance) { + return distance * (this.contentRectMinusAllMargins.height() / this.currentViewport.height()); + } + + public boolean rawPixelsToDataPoint(float x, float y, PointF dest) { + if (!this.contentRectMinusAllMargins.contains((int)x, (int)y)) { + return false; + } else { + dest.set(this.currentViewport.left + (x - this.contentRectMinusAllMargins.left) * this.currentViewport.width() / this.contentRectMinusAllMargins.width(), this.currentViewport.bottom + (y - this.contentRectMinusAllMargins.bottom) * this.currentViewport.height() / (-this.contentRectMinusAllMargins.height())); + return true; + } + } + + public void computeScrollSurfaceSize(Point out) { + out.set((int)(this.maxViewport.width() * this.contentRectMinusAllMargins.width() / this.currentViewport.width()), (int)(this.maxViewport.height() * this.contentRectMinusAllMargins.height() / this.currentViewport.height())); + } + + public boolean isWithinContentRect(float x, float y, float precision) { + return x >= this.contentRectMinusAllMargins.left - precision && x <= this.contentRectMinusAllMargins.right + precision && y <= this.contentRectMinusAllMargins.bottom + precision && y >= this.contentRectMinusAllMargins.top - precision; + } + + public Rect getContentRectMinusAllMargins() { + return this.contentRectMinusAllMargins; + } + + public Rect getContentRectMinusAxesMargins() { + return this.contentRectMinusAxesMargins; + } + + public Viewport getCurrentViewport() { + return this.currentViewport; + } + + public void setCurrentViewport(Viewport viewport) { + this.constrainViewport(viewport.left, viewport.top, viewport.right, viewport.bottom); + } + + public void setCurrentViewport(float left, float top, float right, float bottom) { + this.constrainViewport(left, top, right, bottom); + } + + public Viewport getMaximumViewport() { + return this.maxViewport; + } + + public void setMaxViewport(Viewport maxViewport) { + this.setMaxViewport(maxViewport.left, maxViewport.top, maxViewport.right, maxViewport.bottom); + } + + public void setMaxViewport(float left, float top, float right, float bottom) { + this.maxViewport.set(left, top, right, bottom); + this.computeMinimumWidthAndHeight(); + } + + public Viewport getVisibleViewport() { + return this.currentViewport; + } + + public void setVisibleViewport(Viewport visibleViewport) { + this.setCurrentViewport(visibleViewport); + } + + public float getMinimumViewportWidth() { + return this.minViewportWidth; + } + + public float getMinimumViewportHeight() { + return this.minViewportHeight; + } + + public void setViewportChangeListener(ViewportChangeListener viewportChangeListener) { + if (null == viewportChangeListener) { + this.viewportChangeListener = new DummyVieportChangeListener(); + } else { + this.viewportChangeListener = viewportChangeListener; + } + + } + + public int getChartWidth() { + return this.chartWidth; + } + + public int getChartHeight() { + return this.chartHeight; + } + + public float getMaxZoom() { + return this.maxZoom; + } + + public void setMaxZoom(float maxZoom) { + if (maxZoom < 1.0F) { + maxZoom = 1.0F; + } + + this.maxZoom = maxZoom; + this.computeMinimumWidthAndHeight(); + this.setCurrentViewport(this.currentViewport); + } + + private void computeMinimumWidthAndHeight() { + this.minViewportWidth = this.maxViewport.width() / this.maxZoom; + this.minViewportHeight = this.maxViewport.height() / this.maxZoom; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/computator/PreviewChartComputator.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/computator/PreviewChartComputator.java new file mode 100644 index 00000000..66cf0a50 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/computator/PreviewChartComputator.java @@ -0,0 +1,37 @@ +package dji.v5.ux.core.base.charts.computator; + +import dji.v5.ux.core.base.charts.model.Viewport; + +public class PreviewChartComputator extends ChartComputator { + public PreviewChartComputator() { + //do nothing + } + + @Override + public float computeRawX(float valueX) { + float pixelOffset = (valueX - this.maxViewport.left) * (this.contentRectMinusAllMargins.width() / this.maxViewport.width()); + return this.contentRectMinusAllMargins.left + pixelOffset; + } + + @Override + public float computeRawY(float valueY) { + float pixelOffset = (valueY - this.maxViewport.bottom) * (this.contentRectMinusAllMargins.height() / this.maxViewport.height()); + return this.contentRectMinusAllMargins.bottom - pixelOffset; + } + + @Override + public Viewport getVisibleViewport() { + return this.maxViewport; + } + + @Override + public void setVisibleViewport(Viewport visibleViewport) { + this.setMaxViewport(visibleViewport); + } + + @Override + public void constrainViewport(float left, float top, float right, float bottom) { + super.constrainViewport(left, top, right, bottom); + this.viewportChangeListener.onViewportChanged(this.currentViewport); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/AxisValueFormatter.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/AxisValueFormatter.java new file mode 100644 index 00000000..861d16fe --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/AxisValueFormatter.java @@ -0,0 +1,9 @@ +package dji.v5.ux.core.base.charts.formatter; + +import dji.v5.ux.core.base.charts.model.AxisValue; + +public interface AxisValueFormatter { + int formatValueForManualAxis(char[] var1, AxisValue var2); + + int formatValueForAutoGeneratedAxis(char[] var1, float var2, int var3); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/BubbleChartValueFormatter.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/BubbleChartValueFormatter.java new file mode 100644 index 00000000..12d0c380 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/BubbleChartValueFormatter.java @@ -0,0 +1,7 @@ +package dji.v5.ux.core.base.charts.formatter; + +import dji.v5.ux.core.base.charts.model.BubbleValue; + +public interface BubbleChartValueFormatter { + int formatChartValue(char[] var1, BubbleValue var2); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/ColumnChartValueFormatter.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/ColumnChartValueFormatter.java new file mode 100644 index 00000000..87f07df8 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/ColumnChartValueFormatter.java @@ -0,0 +1,7 @@ +package dji.v5.ux.core.base.charts.formatter; + +import dji.v5.ux.core.base.charts.model.SubcolumnValue; + +public interface ColumnChartValueFormatter { + int formatChartValue(char[] var1, SubcolumnValue var2); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/LineChartValueFormatter.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/LineChartValueFormatter.java new file mode 100644 index 00000000..31b20837 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/LineChartValueFormatter.java @@ -0,0 +1,7 @@ +package dji.v5.ux.core.base.charts.formatter; + +import dji.v5.ux.core.base.charts.model.PointValue; + +public interface LineChartValueFormatter { + int formatChartValue(char[] var1, PointValue var2); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/PieChartValueFormatter.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/PieChartValueFormatter.java new file mode 100644 index 00000000..df763446 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/PieChartValueFormatter.java @@ -0,0 +1,8 @@ +package dji.v5.ux.core.base.charts.formatter; + +import dji.v5.ux.core.base.charts.model.SliceValue; + +public interface PieChartValueFormatter { + int formatChartValue(char[] var1, SliceValue var2); +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/SimpleAxisValueFormatter.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/SimpleAxisValueFormatter.java new file mode 100644 index 00000000..41b3a573 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/SimpleAxisValueFormatter.java @@ -0,0 +1,62 @@ +package dji.v5.ux.core.base.charts.formatter; + +import dji.v5.ux.core.base.charts.model.AxisValue; + +public class SimpleAxisValueFormatter implements AxisValueFormatter { + private ValueFormatterHelper valueFormatterHelper; + + public SimpleAxisValueFormatter() { + this.valueFormatterHelper = new ValueFormatterHelper(); + this.valueFormatterHelper.determineDecimalSeparator(); + } + + public SimpleAxisValueFormatter(int decimalDigitsNumber) { + this(); + this.valueFormatterHelper.setDecimalDigitsNumber(decimalDigitsNumber); + } + + public int formatValueForManualAxis(char[] formattedValue, AxisValue axisValue) { + return this.valueFormatterHelper.formatFloatValueWithPrependedAndAppendedText(formattedValue, axisValue.getValue(), axisValue.getLabelAsChars()); + } + + public int formatValueForAutoGeneratedAxis(char[] formattedValue, float value, int autoDecimalDigits) { + return this.valueFormatterHelper.formatFloatValueWithPrependedAndAppendedText(formattedValue, value, autoDecimalDigits); + } + + public int getDecimalDigitsNumber() { + return this.valueFormatterHelper.getDecimalDigitsNumber(); + } + + public SimpleAxisValueFormatter setDecimalDigitsNumber(int decimalDigitsNumber) { + this.valueFormatterHelper.setDecimalDigitsNumber(decimalDigitsNumber); + return this; + } + + public char[] getAppendedText() { + return this.valueFormatterHelper.getAppendedText(); + } + + public SimpleAxisValueFormatter setAppendedText(char[] appendedText) { + this.valueFormatterHelper.setAppendedText(appendedText); + return this; + } + + public char[] getPrependedText() { + return this.valueFormatterHelper.getPrependedText(); + } + + public SimpleAxisValueFormatter setPrependedText(char[] prependedText) { + this.valueFormatterHelper.setPrependedText(prependedText); + return this; + } + + public char getDecimalSeparator() { + return this.valueFormatterHelper.getDecimalSeparator(); + } + + public SimpleAxisValueFormatter setDecimalSeparator(char decimalSeparator) { + this.valueFormatterHelper.setDecimalSeparator(decimalSeparator); + return this; + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/SimpleBubbleChartValueFormatter.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/SimpleBubbleChartValueFormatter.java new file mode 100644 index 00000000..5c774d23 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/SimpleBubbleChartValueFormatter.java @@ -0,0 +1,58 @@ +package dji.v5.ux.core.base.charts.formatter; + +import dji.v5.ux.core.base.charts.model.BubbleValue; + +public class SimpleBubbleChartValueFormatter implements BubbleChartValueFormatter { + private ValueFormatterHelper valueFormatterHelper; + + public SimpleBubbleChartValueFormatter() { + this.valueFormatterHelper = new ValueFormatterHelper(); + this.valueFormatterHelper.determineDecimalSeparator(); + } + + public SimpleBubbleChartValueFormatter(int decimalDigitsNumber) { + this(); + this.valueFormatterHelper.setDecimalDigitsNumber(decimalDigitsNumber); + } + + public int formatChartValue(char[] formattedValue, BubbleValue value) { + return this.valueFormatterHelper.formatFloatValueWithPrependedAndAppendedText(formattedValue, value.getZ(), value.getLabelAsChars()); + } + + public int getDecimalDigitsNumber() { + return this.valueFormatterHelper.getDecimalDigitsNumber(); + } + + public SimpleBubbleChartValueFormatter setDecimalDigitsNumber(int decimalDigitsNumber) { + this.valueFormatterHelper.setDecimalDigitsNumber(decimalDigitsNumber); + return this; + } + + public char[] getAppendedText() { + return this.valueFormatterHelper.getAppendedText(); + } + + public SimpleBubbleChartValueFormatter setAppendedText(char[] appendedText) { + this.valueFormatterHelper.setAppendedText(appendedText); + return this; + } + + public char[] getPrependedText() { + return this.valueFormatterHelper.getPrependedText(); + } + + public SimpleBubbleChartValueFormatter setPrependedText(char[] prependedText) { + this.valueFormatterHelper.setPrependedText(prependedText); + return this; + } + + public char getDecimalSeparator() { + return this.valueFormatterHelper.getDecimalSeparator(); + } + + public SimpleBubbleChartValueFormatter setDecimalSeparator(char decimalSeparator) { + this.valueFormatterHelper.setDecimalSeparator(decimalSeparator); + return this; + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/SimpleColumnChartValueFormatter.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/SimpleColumnChartValueFormatter.java new file mode 100644 index 00000000..380c486a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/SimpleColumnChartValueFormatter.java @@ -0,0 +1,58 @@ +package dji.v5.ux.core.base.charts.formatter; + +import dji.v5.ux.core.base.charts.model.SubcolumnValue; + +public class SimpleColumnChartValueFormatter implements ColumnChartValueFormatter { + private ValueFormatterHelper valueFormatterHelper; + + public SimpleColumnChartValueFormatter() { + this.valueFormatterHelper = new ValueFormatterHelper(); + this.valueFormatterHelper.determineDecimalSeparator(); + } + + public SimpleColumnChartValueFormatter(int decimalDigitsNumber) { + this(); + this.valueFormatterHelper.setDecimalDigitsNumber(decimalDigitsNumber); + } + + public int formatChartValue(char[] formattedValue, SubcolumnValue value) { + return this.valueFormatterHelper.formatFloatValueWithPrependedAndAppendedText(formattedValue, value.getValue(), value.getLabelAsChars()); + } + + public int getDecimalDigitsNumber() { + return this.valueFormatterHelper.getDecimalDigitsNumber(); + } + + public SimpleColumnChartValueFormatter setDecimalDigitsNumber(int decimalDigitsNumber) { + this.valueFormatterHelper.setDecimalDigitsNumber(decimalDigitsNumber); + return this; + } + + public char[] getAppendedText() { + return this.valueFormatterHelper.getAppendedText(); + } + + public SimpleColumnChartValueFormatter setAppendedText(char[] appendedText) { + this.valueFormatterHelper.setAppendedText(appendedText); + return this; + } + + public char[] getPrependedText() { + return this.valueFormatterHelper.getPrependedText(); + } + + public SimpleColumnChartValueFormatter setPrependedText(char[] prependedText) { + this.valueFormatterHelper.setPrependedText(prependedText); + return this; + } + + public char getDecimalSeparator() { + return this.valueFormatterHelper.getDecimalSeparator(); + } + + public SimpleColumnChartValueFormatter setDecimalSeparator(char decimalSeparator) { + this.valueFormatterHelper.setDecimalSeparator(decimalSeparator); + return this; + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/SimpleLineChartValueFormatter.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/SimpleLineChartValueFormatter.java new file mode 100644 index 00000000..8e87c61f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/SimpleLineChartValueFormatter.java @@ -0,0 +1,58 @@ +package dji.v5.ux.core.base.charts.formatter; + +import dji.v5.ux.core.base.charts.model.PointValue; + +public class SimpleLineChartValueFormatter implements LineChartValueFormatter { + private ValueFormatterHelper valueFormatterHelper; + + public SimpleLineChartValueFormatter() { + this.valueFormatterHelper = new ValueFormatterHelper(); + this.valueFormatterHelper.determineDecimalSeparator(); + } + + public SimpleLineChartValueFormatter(int decimalDigitsNumber) { + this(); + this.valueFormatterHelper.setDecimalDigitsNumber(decimalDigitsNumber); + } + + public int formatChartValue(char[] formattedValue, PointValue value) { + return this.valueFormatterHelper.formatFloatValueWithPrependedAndAppendedText(formattedValue, value.getY(), value.getLabelAsChars()); + } + + public int getDecimalDigitsNumber() { + return this.valueFormatterHelper.getDecimalDigitsNumber(); + } + + public SimpleLineChartValueFormatter setDecimalDigitsNumber(int decimalDigitsNumber) { + this.valueFormatterHelper.setDecimalDigitsNumber(decimalDigitsNumber); + return this; + } + + public char[] getAppendedText() { + return this.valueFormatterHelper.getAppendedText(); + } + + public SimpleLineChartValueFormatter setAppendedText(char[] appendedText) { + this.valueFormatterHelper.setAppendedText(appendedText); + return this; + } + + public char[] getPrependedText() { + return this.valueFormatterHelper.getPrependedText(); + } + + public SimpleLineChartValueFormatter setPrependedText(char[] prependedText) { + this.valueFormatterHelper.setPrependedText(prependedText); + return this; + } + + public char getDecimalSeparator() { + return this.valueFormatterHelper.getDecimalSeparator(); + } + + public SimpleLineChartValueFormatter setDecimalSeparator(char decimalSeparator) { + this.valueFormatterHelper.setDecimalSeparator(decimalSeparator); + return this; + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/SimplePieChartValueFormatter.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/SimplePieChartValueFormatter.java new file mode 100644 index 00000000..16e0cf61 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/SimplePieChartValueFormatter.java @@ -0,0 +1,57 @@ +package dji.v5.ux.core.base.charts.formatter; + +import dji.v5.ux.core.base.charts.model.SliceValue; + +public class SimplePieChartValueFormatter implements PieChartValueFormatter { + private ValueFormatterHelper valueFormatterHelper; + + public SimplePieChartValueFormatter() { + this.valueFormatterHelper = new ValueFormatterHelper(); + this.valueFormatterHelper.determineDecimalSeparator(); + } + + public SimplePieChartValueFormatter(int decimalDigitsNumber) { + this(); + this.valueFormatterHelper.setDecimalDigitsNumber(decimalDigitsNumber); + } + + public int formatChartValue(char[] formattedValue, SliceValue value) { + return this.valueFormatterHelper.formatFloatValueWithPrependedAndAppendedText(formattedValue, value.getValue(), value.getLabelAsChars()); + } + + public int getDecimalDigitsNumber() { + return this.valueFormatterHelper.getDecimalDigitsNumber(); + } + + public SimplePieChartValueFormatter setDecimalDigitsNumber(int decimalDigitsNumber) { + this.valueFormatterHelper.setDecimalDigitsNumber(decimalDigitsNumber); + return this; + } + + public char[] getAppendedText() { + return this.valueFormatterHelper.getAppendedText(); + } + + public SimplePieChartValueFormatter setAppendedText(char[] appendedText) { + this.valueFormatterHelper.setAppendedText(appendedText); + return this; + } + + public char[] getPrependedText() { + return this.valueFormatterHelper.getPrependedText(); + } + + public SimplePieChartValueFormatter setPrependedText(char[] prependedText) { + this.valueFormatterHelper.setPrependedText(prependedText); + return this; + } + + public char getDecimalSeparator() { + return this.valueFormatterHelper.getDecimalSeparator(); + } + + public SimplePieChartValueFormatter setDecimalSeparator(char decimalSeparator) { + this.valueFormatterHelper.setDecimalSeparator(decimalSeparator); + return this; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/ValueFormatterHelper.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/ValueFormatterHelper.java new file mode 100644 index 00000000..8fcf4c85 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/formatter/ValueFormatterHelper.java @@ -0,0 +1,131 @@ +package dji.v5.ux.core.base.charts.formatter; + +import android.util.Log; + +import java.text.DecimalFormat; +import java.text.NumberFormat; + +import dji.v5.ux.core.base.charts.util.FloatUtils; + +public class ValueFormatterHelper { + private int decimalDigitsNumber = Integer.MIN_VALUE; + private char[] appendedText = new char[0]; + private char[] prependedText = new char[0]; + private char decimalSeparator = '.'; + + public ValueFormatterHelper() { + //do nothing + } + + public void determineDecimalSeparator() { + NumberFormat numberFormat = NumberFormat.getInstance(); + if (numberFormat instanceof DecimalFormat) { + this.decimalSeparator = ((DecimalFormat)numberFormat).getDecimalFormatSymbols().getDecimalSeparator(); + } + + } + + public int getDecimalDigitsNumber() { + return this.decimalDigitsNumber; + } + + public ValueFormatterHelper setDecimalDigitsNumber(int decimalDigitsNumber) { + this.decimalDigitsNumber = decimalDigitsNumber; + return this; + } + + public char[] getAppendedText() { + return this.appendedText; + } + + public ValueFormatterHelper setAppendedText(char[] appendedText) { + if (null != appendedText) { + this.appendedText = appendedText; + } + + return this; + } + + public char[] getPrependedText() { + return this.prependedText; + } + + public ValueFormatterHelper setPrependedText(char[] prependedText) { + if (null != prependedText) { + this.prependedText = prependedText; + } + + return this; + } + + public char getDecimalSeparator() { + return this.decimalSeparator; + } + + public ValueFormatterHelper setDecimalSeparator(char decimalSeparator) { + char nullChar = 0; + if (nullChar != decimalSeparator) { + this.decimalSeparator = decimalSeparator; + } + + return this; + } + + public int formatFloatValueWithPrependedAndAppendedText(char[] formattedValue, float value, int defaultDigitsNumber, char[] label) { + int labelLength; + if (null != label) { + labelLength = label.length; + if (labelLength > formattedValue.length) { + Log.w("ValueFormatterHelper", "Label length is larger than buffer size(64chars), some chars will be skipped!"); + labelLength = formattedValue.length; + } + + System.arraycopy(label, 0, formattedValue, formattedValue.length - labelLength, labelLength); + return labelLength; + } else { + labelLength = this.getAppliedDecimalDigitsNumber(defaultDigitsNumber); + int charsNumber = this.formatFloatValue(formattedValue, value, labelLength); + this.appendText(formattedValue); + this.prependText(formattedValue, charsNumber); + return charsNumber + this.getPrependedText().length + this.getAppendedText().length; + } + } + + public int formatFloatValueWithPrependedAndAppendedText(char[] formattedValue, float value, char[] label) { + return this.formatFloatValueWithPrependedAndAppendedText(formattedValue, value, 0, label); + } + + public int formatFloatValueWithPrependedAndAppendedText(char[] formattedValue, float value, int defaultDigitsNumber) { + return this.formatFloatValueWithPrependedAndAppendedText(formattedValue, value, defaultDigitsNumber, (char[])null); + } + + public int formatFloatValue(char[] formattedValue, float value, int decimalDigitsNumber) { + return FloatUtils.formatFloat(formattedValue, value, formattedValue.length - this.appendedText.length, decimalDigitsNumber, this.decimalSeparator); + } + + public void appendText(char[] formattedValue) { + if (this.appendedText.length > 0) { + System.arraycopy(this.appendedText, 0, formattedValue, formattedValue.length - this.appendedText.length, this.appendedText.length); + } + + } + + public void prependText(char[] formattedValue, int charsNumber) { + if (this.prependedText.length > 0) { + System.arraycopy(this.prependedText, 0, formattedValue, formattedValue.length - charsNumber - this.appendedText.length - this.prependedText.length, this.prependedText.length); + } + + } + + public int getAppliedDecimalDigitsNumber(int defaultDigitsNumber) { + int appliedDecimalDigitsNumber; + if (this.decimalDigitsNumber < 0) { + appliedDecimalDigitsNumber = defaultDigitsNumber; + } else { + appliedDecimalDigitsNumber = this.decimalDigitsNumber; + } + + return appliedDecimalDigitsNumber; + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/ChartScroller.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/ChartScroller.java new file mode 100644 index 00000000..aa4008af --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/ChartScroller.java @@ -0,0 +1,91 @@ +package dji.v5.ux.core.base.charts.gesture; + +import android.content.Context; +import android.graphics.Point; +import android.graphics.Rect; + +import androidx.core.widget.ScrollerCompat; + +import dji.v5.ux.core.base.charts.computator.ChartComputator; +import dji.v5.ux.core.base.charts.model.Viewport; + +public class ChartScroller { + private Viewport scrollerStartViewport = new Viewport(); + private Point surfaceSizeBuffer = new Point(); + private ScrollerCompat scroller; + + public ChartScroller(Context context) { + this.scroller = ScrollerCompat.create(context); + } + + public boolean startScroll(ChartComputator computator) { + this.scroller.abortAnimation(); + this.scrollerStartViewport.set(computator.getCurrentViewport()); + return true; + } + + public boolean scroll(ChartComputator computator, float distanceX, float distanceY, ScrollResult scrollResult) { + Viewport maxViewport = computator.getMaximumViewport(); + Viewport visibleViewport = computator.getVisibleViewport(); + Viewport currentViewport = computator.getCurrentViewport(); + Rect contentRect = computator.getContentRectMinusAllMargins(); + boolean canScrollLeft = currentViewport.left > maxViewport.left; + boolean canScrollRight = currentViewport.right < maxViewport.right; + boolean canScrollTop = currentViewport.top < maxViewport.top; + boolean canScrollBottom = currentViewport.bottom > maxViewport.bottom; + boolean canScrollX = false; + boolean canScrollY = false; + if ((canScrollLeft && distanceX <= 0.0F) || (canScrollRight && distanceX >= 0.0F)) { + canScrollX = true; + } + + if ((canScrollTop && distanceY <= 0.0F) || (canScrollBottom && distanceY >= 0.0)) { + canScrollY = true; + } + if (canScrollX || canScrollY) { + computator.computeScrollSurfaceSize(this.surfaceSizeBuffer); + float viewportOffsetX = distanceX * visibleViewport.width() / contentRect.width(); + float viewportOffsetY = -distanceY * visibleViewport.height() / contentRect.height(); + computator.setViewportTopLeft(currentViewport.left + viewportOffsetX, currentViewport.top + viewportOffsetY); + } + + scrollResult.canScrollX = canScrollX; + scrollResult.canScrollY = canScrollY; + return canScrollX || canScrollY; + } + + public boolean computeScrollOffset(ChartComputator computator) { + if (this.scroller.computeScrollOffset()) { + Viewport maxViewport = computator.getMaximumViewport(); + computator.computeScrollSurfaceSize(this.surfaceSizeBuffer); + float currXRange = maxViewport.left + maxViewport.width() * this.scroller.getCurrX() / this.surfaceSizeBuffer.x; + float currYRange = maxViewport.top - maxViewport.height() * this.scroller.getCurrY() / this.surfaceSizeBuffer.y; + computator.setViewportTopLeft(currXRange, currYRange); + return true; + } else { + return false; + } + } + + public boolean fling(int velocityX, int velocityY, ChartComputator computator) { + computator.computeScrollSurfaceSize(this.surfaceSizeBuffer); + this.scrollerStartViewport.set(computator.getCurrentViewport()); + int startX = (int)(this.surfaceSizeBuffer.x * (this.scrollerStartViewport.left - computator.getMaximumViewport().left) / computator.getMaximumViewport().width()); + int startY = (int)(this.surfaceSizeBuffer.y * (computator.getMaximumViewport().top - this.scrollerStartViewport.top) / computator.getMaximumViewport().height()); + this.scroller.abortAnimation(); + int width = computator.getContentRectMinusAllMargins().width(); + int height = computator.getContentRectMinusAllMargins().height(); + this.scroller.fling(startX, startY, velocityX, velocityY, 0, this.surfaceSizeBuffer.x - width + 1, 0, this.surfaceSizeBuffer.y - height + 1); + return true; + } + + public static class ScrollResult { + public boolean canScrollX; + public boolean canScrollY; + + public ScrollResult() { + //do nothing + } + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/ChartTouchHandler.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/ChartTouchHandler.java new file mode 100644 index 00000000..c0247245 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/ChartTouchHandler.java @@ -0,0 +1,260 @@ +package dji.v5.ux.core.base.charts.gesture; + +import android.content.Context; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.ScaleGestureDetector; +import android.view.ViewParent; + +import dji.v5.ux.core.base.charts.computator.ChartComputator; +import dji.v5.ux.core.base.charts.model.SelectedValue; +import dji.v5.ux.core.base.charts.renderer.ChartRenderer; +import dji.v5.ux.core.base.charts.view.Chart; + +public class ChartTouchHandler { + protected GestureDetector gestureDetector; + protected ScaleGestureDetector scaleGestureDetector; + protected ChartScroller chartScroller; + protected ChartZoomer chartZoomer; + protected Chart chart; + protected ChartComputator computator; + protected ChartRenderer renderer; + protected boolean isZoomEnabled = true; + protected boolean isScrollEnabled = true; + protected boolean isValueTouchEnabled = true; + protected boolean isValueSelectionEnabled = false; + protected SelectedValue selectionModeOldValue = new SelectedValue(); + protected SelectedValue selectedValue = new SelectedValue(); + protected SelectedValue oldSelectedValue = new SelectedValue(); + protected ViewParent viewParent; + protected ContainerScrollType containerScrollType; + + public ChartTouchHandler(Context context, Chart chart) { + this.chart = chart; + this.computator = chart.getChartComputator(); + this.renderer = chart.getChartRenderer(); + this.gestureDetector = new GestureDetector(context, new ChartGestureListener()); + this.scaleGestureDetector = new ScaleGestureDetector(context, new ChartScaleGestureListener()); + this.chartScroller = new ChartScroller(context); + this.chartZoomer = new ChartZoomer(context, ZoomType.HORIZONTAL_AND_VERTICAL); + } + + public void resetTouchHandler() { + this.computator = this.chart.getChartComputator(); + this.renderer = this.chart.getChartRenderer(); + } + + public boolean computeScroll() { + boolean needInvalidate = false; + if (this.isScrollEnabled && this.chartScroller.computeScrollOffset(this.computator)) { + needInvalidate = true; + } + + if (this.isZoomEnabled && this.chartZoomer.computeZoom(this.computator)) { + needInvalidate = true; + } + + return needInvalidate; + } + + public boolean handleTouchEvent(MotionEvent event) { + boolean needInvalidate = false; + needInvalidate = this.gestureDetector.onTouchEvent(event); + needInvalidate = this.scaleGestureDetector.onTouchEvent(event) || needInvalidate; + if (this.isZoomEnabled && this.scaleGestureDetector.isInProgress()) { + this.disallowParentInterceptTouchEvent(); + } + + if (this.isValueTouchEnabled) { + needInvalidate = this.computeTouch(event) || needInvalidate; + } + + return needInvalidate; + } + + public boolean handleTouchEvent(MotionEvent event, ViewParent viewParent, ContainerScrollType containerScrollType) { + this.viewParent = viewParent; + this.containerScrollType = containerScrollType; + return this.handleTouchEvent(event); + } + + private void disallowParentInterceptTouchEvent() { + if (null != this.viewParent) { + this.viewParent.requestDisallowInterceptTouchEvent(true); + } + + } + + private void allowParentInterceptTouchEvent(ChartScroller.ScrollResult scrollResult) { + if (this.viewParent == null) { + return; + } + + if ((ContainerScrollType.HORIZONTAL == this.containerScrollType && !scrollResult.canScrollX && !this.scaleGestureDetector.isInProgress()) || (ContainerScrollType.VERTICAL == this.containerScrollType && !scrollResult.canScrollY && !this.scaleGestureDetector.isInProgress())) { + this.viewParent.requestDisallowInterceptTouchEvent(false); + } + } + + private boolean computeTouch(MotionEvent event) { + boolean needInvalidate = false; + switch (event.getAction()) { + case 0: + boolean wasTouched = this.renderer.isTouched(); + boolean isTouched = this.checkTouch(event.getX(), event.getY()); + if (wasTouched != isTouched) { + needInvalidate = true; + if (this.isValueSelectionEnabled) { + this.selectionModeOldValue.clear(); + if (wasTouched && !this.renderer.isTouched()) { + this.chart.callTouchListener(); + } + } + } + break; + case 1: + if (this.renderer.isTouched()) { + if (this.checkTouch(event.getX(), event.getY())) { + if (this.isValueSelectionEnabled) { + if (!this.selectionModeOldValue.equals(this.selectedValue)) { + this.selectionModeOldValue.set(this.selectedValue); + this.chart.callTouchListener(); + } + } else { + this.chart.callTouchListener(); + this.renderer.clearTouch(); + } + } else { + this.renderer.clearTouch(); + } + + needInvalidate = true; + } + break; + case 2: + if (this.renderer.isTouched() && !this.checkTouch(event.getX(), event.getY())) { + this.renderer.clearTouch(); + needInvalidate = true; + } + break; + case 3: + if (this.renderer.isTouched()) { + this.renderer.clearTouch(); + needInvalidate = true; + } + break; + default: + break; + } + + return needInvalidate; + } + + private boolean checkTouch(float touchX, float touchY) { + this.oldSelectedValue.set(this.selectedValue); + this.selectedValue.clear(); + if (this.renderer.checkTouch(touchX, touchY)) { + this.selectedValue.set(this.renderer.getSelectedValue()); + } + + return this.oldSelectedValue.isSet() && this.selectedValue.isSet() && !this.oldSelectedValue.equals(this.selectedValue) ? false : this.renderer.isTouched(); + } + + public boolean isZoomEnabled() { + return this.isZoomEnabled; + } + + public void setZoomEnabled(boolean isZoomEnabled) { + this.isZoomEnabled = isZoomEnabled; + } + + public boolean isScrollEnabled() { + return this.isScrollEnabled; + } + + public void setScrollEnabled(boolean isScrollEnabled) { + this.isScrollEnabled = isScrollEnabled; + } + + public ZoomType getZoomType() { + return this.chartZoomer.getZoomType(); + } + + public void setZoomType(ZoomType zoomType) { + this.chartZoomer.setZoomType(zoomType); + } + + public boolean isValueTouchEnabled() { + return this.isValueTouchEnabled; + } + + public void setValueTouchEnabled(boolean isValueTouchEnabled) { + this.isValueTouchEnabled = isValueTouchEnabled; + } + + public boolean isValueSelectionEnabled() { + return this.isValueSelectionEnabled; + } + + public void setValueSelectionEnabled(boolean isValueSelectionEnabled) { + this.isValueSelectionEnabled = isValueSelectionEnabled; + } + + protected class ChartGestureListener extends GestureDetector.SimpleOnGestureListener { + protected ChartScroller.ScrollResult scrollResult = new ChartScroller.ScrollResult(); + + protected ChartGestureListener() { + } + + @Override + public boolean onDown(MotionEvent e) { + if (ChartTouchHandler.this.isScrollEnabled) { + ChartTouchHandler.this.disallowParentInterceptTouchEvent(); + return ChartTouchHandler.this.chartScroller.startScroll(ChartTouchHandler.this.computator); + } else { + return false; + } + } + + @Override + public boolean onDoubleTap(MotionEvent e) { + return ChartTouchHandler.this.isZoomEnabled ? ChartTouchHandler.this.chartZoomer.startZoom(e, ChartTouchHandler.this.computator) : false; + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + if (ChartTouchHandler.this.isScrollEnabled) { + boolean canScroll = ChartTouchHandler.this.chartScroller.scroll(ChartTouchHandler.this.computator, distanceX, distanceY, this.scrollResult); + ChartTouchHandler.this.allowParentInterceptTouchEvent(this.scrollResult); + return canScroll; + } else { + return false; + } + } + + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + return ChartTouchHandler.this.isScrollEnabled ? ChartTouchHandler.this.chartScroller.fling((int)(-velocityX), (int)(-velocityY), ChartTouchHandler.this.computator) : false; + } + } + + protected class ChartScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { + protected ChartScaleGestureListener() { + //do nothing + } + + @Override + public boolean onScale(ScaleGestureDetector detector) { + if (ChartTouchHandler.this.isZoomEnabled) { + float scale = 2.0F - detector.getScaleFactor(); + if (Float.isInfinite(scale)) { + scale = 1.0F; + } + + return ChartTouchHandler.this.chartZoomer.scale(ChartTouchHandler.this.computator, detector.getFocusX(), detector.getFocusY(), scale); + } else { + return false; + } + } + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/ChartZoomer.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/ChartZoomer.java new file mode 100644 index 00000000..762bc760 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/ChartZoomer.java @@ -0,0 +1,86 @@ +package dji.v5.ux.core.base.charts.gesture; + +import android.content.Context; +import android.graphics.PointF; +import android.view.MotionEvent; + +import dji.v5.ux.core.base.charts.computator.ChartComputator; +import dji.v5.ux.core.base.charts.model.Viewport; + +public class ChartZoomer { + public static final float ZOOM_AMOUNT = 0.25F; + private ZoomerCompat zoomer; + private ZoomType zoomType; + private PointF zoomFocalPoint = new PointF(); + private PointF viewportFocus = new PointF(); + private Viewport scrollerStartViewport = new Viewport(); + + public ChartZoomer(Context context, ZoomType zoomType) { + this.zoomer = new ZoomerCompat(context); + this.zoomType = zoomType; + } + + public boolean startZoom(MotionEvent e, ChartComputator computator) { + this.zoomer.forceFinished(true); + this.scrollerStartViewport.set(computator.getCurrentViewport()); + if (!computator.rawPixelsToDataPoint(e.getX(), e.getY(), this.zoomFocalPoint)) { + return false; + } else { + this.zoomer.startZoom(0.25F); + return true; + } + } + + public boolean computeZoom(ChartComputator computator) { + if (this.zoomer.computeZoom()) { + float newWidth = (1.0F - this.zoomer.getCurrZoom()) * this.scrollerStartViewport.width(); + float newHeight = (1.0F - this.zoomer.getCurrZoom()) * this.scrollerStartViewport.height(); + float pointWithinViewportX = (this.zoomFocalPoint.x - this.scrollerStartViewport.left) / this.scrollerStartViewport.width(); + float pointWithinViewportY = (this.zoomFocalPoint.y - this.scrollerStartViewport.bottom) / this.scrollerStartViewport.height(); + float left = this.zoomFocalPoint.x - newWidth * pointWithinViewportX; + float top = this.zoomFocalPoint.y + newHeight * (1.0F - pointWithinViewportY); + float right = this.zoomFocalPoint.x + newWidth * (1.0F - pointWithinViewportX); + float bottom = this.zoomFocalPoint.y - newHeight * pointWithinViewportY; + this.setCurrentViewport(computator, left, top, right, bottom); + return true; + } else { + return false; + } + } + + public boolean scale(ChartComputator computator, float focusX, float focusY, float scale) { + float newWidth = scale * computator.getCurrentViewport().width(); + float newHeight = scale * computator.getCurrentViewport().height(); + if (!computator.rawPixelsToDataPoint(focusX, focusY, this.viewportFocus)) { + return false; + } else { + float left = this.viewportFocus.x - (focusX - (float)computator.getContentRectMinusAllMargins().left) * (newWidth / (float)computator.getContentRectMinusAllMargins().width()); + float top = this.viewportFocus.y + (focusY - (float)computator.getContentRectMinusAllMargins().top) * (newHeight / (float)computator.getContentRectMinusAllMargins().height()); + float right = left + newWidth; + float bottom = top - newHeight; + this.setCurrentViewport(computator, left, top, right, bottom); + return true; + } + } + + private void setCurrentViewport(ChartComputator computator, float left, float top, float right, float bottom) { + Viewport currentViewport = computator.getCurrentViewport(); + if (ZoomType.HORIZONTAL_AND_VERTICAL == this.zoomType) { + computator.setCurrentViewport(left, top, right, bottom); + } else if (ZoomType.HORIZONTAL == this.zoomType) { + computator.setCurrentViewport(left, currentViewport.top, right, currentViewport.bottom); + } else if (ZoomType.VERTICAL == this.zoomType) { + computator.setCurrentViewport(currentViewport.left, top, currentViewport.right, bottom); + } + + } + + public ZoomType getZoomType() { + return this.zoomType; + } + + public void setZoomType(ZoomType zoomType) { + this.zoomType = zoomType; + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/ContainerScrollType.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/ContainerScrollType.java new file mode 100644 index 00000000..5108f111 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/ContainerScrollType.java @@ -0,0 +1,9 @@ +package dji.v5.ux.core.base.charts.gesture; + +public enum ContainerScrollType { + HORIZONTAL, + VERTICAL; + + private ContainerScrollType() { + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/PieChartTouchHandler.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/PieChartTouchHandler.java new file mode 100644 index 00000000..7f8f3e46 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/PieChartTouchHandler.java @@ -0,0 +1,123 @@ +package dji.v5.ux.core.base.charts.gesture; + +import android.content.Context; +import android.graphics.RectF; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.ScaleGestureDetector; + +import androidx.core.widget.ScrollerCompat; + +import dji.v5.ux.core.base.charts.view.PieChartView; + +public class PieChartTouchHandler extends ChartTouchHandler { + protected ScrollerCompat scroller; + protected PieChartView pieChart; + private boolean isRotationEnabled = true; + + public PieChartTouchHandler(Context context, PieChartView chart) { + super(context, chart); + this.pieChart = chart; + this.scroller = ScrollerCompat.create(context); + this.gestureDetector = new GestureDetector(context, new ChartGestureListener()); + this.scaleGestureDetector = new ScaleGestureDetector(context, new ChartScaleGestureListener()); + this.isZoomEnabled = false; + } + + @Override + public boolean computeScroll() { + if (!this.isRotationEnabled) { + return false; + } + if (this.scroller.computeScrollOffset()) { + this.pieChart.setChartRotation(this.scroller.getCurrY(), false); + } + return true; + } + + @Override + public boolean handleTouchEvent(MotionEvent event) { + boolean needInvalidate = super.handleTouchEvent(event); + if (this.isRotationEnabled) { + needInvalidate = this.gestureDetector.onTouchEvent(event) || needInvalidate; + } + + return needInvalidate; + } + + public boolean isRotationEnabled() { + return this.isRotationEnabled; + } + + public void setRotationEnabled(boolean isRotationEnabled) { + this.isRotationEnabled = isRotationEnabled; + } + + private class ChartGestureListener extends GestureDetector.SimpleOnGestureListener { + private ChartGestureListener() { + } + + @Override + public boolean onDown(MotionEvent e) { + if (PieChartTouchHandler.this.isRotationEnabled) { + PieChartTouchHandler.this.scroller.abortAnimation(); + return true; + } else { + return false; + } + } + + @Override + public boolean onDoubleTap(MotionEvent e) { + return false; + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + if (PieChartTouchHandler.this.isRotationEnabled) { + RectF circleOval = PieChartTouchHandler.this.pieChart.getCircleOval(); + float centerX = circleOval.centerX(); + float centerY = circleOval.centerY(); + float scrollTheta = this.vectorToScalarScroll(distanceX, distanceY, e2.getX() - centerX, e2.getY() - centerY); + PieChartTouchHandler.this.pieChart.setChartRotation(PieChartTouchHandler.this.pieChart.getChartRotation() - (int)scrollTheta / 4, false); + return true; + } else { + return false; + } + } + + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + if (PieChartTouchHandler.this.isRotationEnabled) { + RectF circleOval = PieChartTouchHandler.this.pieChart.getCircleOval(); + float centerX = circleOval.centerX(); + float centerY = circleOval.centerY(); + float scrollTheta = this.vectorToScalarScroll(velocityX, velocityY, e2.getX() - centerX, e2.getY() - centerY); + PieChartTouchHandler.this.scroller.abortAnimation(); + PieChartTouchHandler.this.scroller.fling(0, PieChartTouchHandler.this.pieChart.getChartRotation(), 0, (int)scrollTheta / 4, 0, 0, Integer.MIN_VALUE, Integer.MAX_VALUE); + return true; + } else { + return false; + } + } + + private float vectorToScalarScroll(float dx, float dy, float x, float y) { + float l = (float)Math.sqrt((double)(dx * dx + dy * dy)); + float crossX = -y; + float dot = crossX * dx + x * dy; + float sign = Math.signum(dot); + return l * sign; + } + } + + private class ChartScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { + private ChartScaleGestureListener() { + } + + @Override + public boolean onScale(ScaleGestureDetector detector) { + return false; + } + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/PreviewChartTouchHandler.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/PreviewChartTouchHandler.java new file mode 100644 index 00000000..c262549a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/PreviewChartTouchHandler.java @@ -0,0 +1,54 @@ +package dji.v5.ux.core.base.charts.gesture; + +import android.content.Context; +import android.view.GestureDetector; +import android.view.MotionEvent; +import android.view.ScaleGestureDetector; + +import dji.v5.ux.core.base.charts.view.Chart; + +public class PreviewChartTouchHandler extends ChartTouchHandler { + public PreviewChartTouchHandler(Context context, Chart chart) { + super(context, chart); + this.gestureDetector = new GestureDetector(context, new PreviewChartGestureListener()); + this.scaleGestureDetector = new ScaleGestureDetector(context, new ChartScaleGestureListener()); + this.isValueTouchEnabled = false; + this.isValueSelectionEnabled = false; + } + + protected class PreviewChartGestureListener extends ChartGestureListener { + protected PreviewChartGestureListener() { + super(); + } + + @Override + public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) { + return super.onScroll(e1, e2, -distanceX, -distanceY); + } + + @Override + public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { + return super.onFling(e1, e2, -velocityX, -velocityY); + } + } + + protected class ChartScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { + protected ChartScaleGestureListener() { + } + + @Override + public boolean onScale(ScaleGestureDetector detector) { + if (PreviewChartTouchHandler.this.isZoomEnabled) { + float scale = detector.getCurrentSpan() / detector.getPreviousSpan(); + if (Float.isInfinite(scale)) { + scale = 1.0F; + } + + return PreviewChartTouchHandler.this.chartZoomer.scale(PreviewChartTouchHandler.this.computator, detector.getFocusX(), detector.getFocusY(), scale); + } else { + return false; + } + } + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/ZoomType.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/ZoomType.java new file mode 100644 index 00000000..f18e2d1f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/ZoomType.java @@ -0,0 +1,10 @@ +package dji.v5.ux.core.base.charts.gesture; + +public enum ZoomType { + HORIZONTAL, + VERTICAL, + HORIZONTAL_AND_VERTICAL; + + private ZoomType() { + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/ZoomerCompat.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/ZoomerCompat.java new file mode 100644 index 00000000..a93924c7 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/gesture/ZoomerCompat.java @@ -0,0 +1,57 @@ +package dji.v5.ux.core.base.charts.gesture; + +import android.content.Context; +import android.os.SystemClock; +import android.view.animation.DecelerateInterpolator; +import android.view.animation.Interpolator; + +public class ZoomerCompat { + private Interpolator mInterpolator = new DecelerateInterpolator(); + private long mAnimationDurationMillis = 200L; + private boolean mFinished = true; + private float mCurrentZoom; + private long mStartRTC; + private float mEndZoom; + + public ZoomerCompat(Context context) { + //do nothing + } + + public void forceFinished(boolean finished) { + this.mFinished = finished; + } + + public void abortAnimation() { + this.mFinished = true; + this.mCurrentZoom = this.mEndZoom; + } + + public void startZoom(float endZoom) { + this.mStartRTC = SystemClock.elapsedRealtime(); + this.mEndZoom = endZoom; + this.mFinished = false; + this.mCurrentZoom = 1.0F; + } + + public boolean computeZoom() { + if (this.mFinished) { + return false; + } else { + long tRTC = SystemClock.elapsedRealtime() - this.mStartRTC; + if (tRTC >= this.mAnimationDurationMillis) { + this.mFinished = true; + this.mCurrentZoom = this.mEndZoom; + return false; + } else { + float t = (float)tRTC * 1.0F / (float)this.mAnimationDurationMillis; + this.mCurrentZoom = this.mEndZoom * this.mInterpolator.getInterpolation(t); + return true; + } + } + } + + public float getCurrZoom() { + return this.mCurrentZoom; + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/BubbleChartOnValueSelectListener.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/BubbleChartOnValueSelectListener.java new file mode 100644 index 00000000..130386be --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/BubbleChartOnValueSelectListener.java @@ -0,0 +1,7 @@ +package dji.v5.ux.core.base.charts.listener; + +import dji.v5.ux.core.base.charts.model.BubbleValue; + +public interface BubbleChartOnValueSelectListener extends OnValueDeselectListener { + void onValueSelected(int var1, BubbleValue var2); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/ColumnChartOnValueSelectListener.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/ColumnChartOnValueSelectListener.java new file mode 100644 index 00000000..5f452461 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/ColumnChartOnValueSelectListener.java @@ -0,0 +1,7 @@ +package dji.v5.ux.core.base.charts.listener; + +import dji.v5.ux.core.base.charts.model.SubcolumnValue; + +public interface ColumnChartOnValueSelectListener extends OnValueDeselectListener { + void onValueSelected(int var1, int var2, SubcolumnValue var3); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/ComboLineColumnChartOnValueSelectListener.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/ComboLineColumnChartOnValueSelectListener.java new file mode 100644 index 00000000..26188bd9 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/ComboLineColumnChartOnValueSelectListener.java @@ -0,0 +1,10 @@ +package dji.v5.ux.core.base.charts.listener; + +import dji.v5.ux.core.base.charts.model.PointValue; +import dji.v5.ux.core.base.charts.model.SubcolumnValue; + +public interface ComboLineColumnChartOnValueSelectListener extends OnValueDeselectListener { + void onColumnValueSelected(int var1, int var2, SubcolumnValue var3); + + void onPointValueSelected(int var1, int var2, PointValue var3); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/DummyBubbleChartOnValueSelectListener.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/DummyBubbleChartOnValueSelectListener.java new file mode 100644 index 00000000..3f52ae4b --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/DummyBubbleChartOnValueSelectListener.java @@ -0,0 +1,17 @@ +package dji.v5.ux.core.base.charts.listener; + +import dji.v5.ux.core.base.charts.model.BubbleValue; + +public class DummyBubbleChartOnValueSelectListener implements BubbleChartOnValueSelectListener { + public DummyBubbleChartOnValueSelectListener() { + //do nothing + } + + public void onValueSelected(int bubbleIndex, BubbleValue value) { + //do nothing + } + + public void onValueDeselected() { + //do nothing + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/DummyColumnChartOnValueSelectListener.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/DummyColumnChartOnValueSelectListener.java new file mode 100644 index 00000000..4661482c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/DummyColumnChartOnValueSelectListener.java @@ -0,0 +1,17 @@ +package dji.v5.ux.core.base.charts.listener; + +import dji.v5.ux.core.base.charts.model.SubcolumnValue; + +public class DummyColumnChartOnValueSelectListener implements ColumnChartOnValueSelectListener { + public DummyColumnChartOnValueSelectListener() { + //do nothing + } + + public void onValueSelected(int columnIndex, int subcolumnIndex, SubcolumnValue value) { + //do nothing + } + + public void onValueDeselected() { + //do nothing + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/DummyCompoLineColumnChartOnValueSelectListener.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/DummyCompoLineColumnChartOnValueSelectListener.java new file mode 100644 index 00000000..89035be7 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/DummyCompoLineColumnChartOnValueSelectListener.java @@ -0,0 +1,22 @@ +package dji.v5.ux.core.base.charts.listener; + +import dji.v5.ux.core.base.charts.model.PointValue; +import dji.v5.ux.core.base.charts.model.SubcolumnValue; + +public class DummyCompoLineColumnChartOnValueSelectListener implements ComboLineColumnChartOnValueSelectListener { + public DummyCompoLineColumnChartOnValueSelectListener() { + //do nothing + } + + public void onColumnValueSelected(int columnIndex, int subcolumnIndex, SubcolumnValue value) { + //do nothing + } + + public void onPointValueSelected(int lineIndex, int pointIndex, PointValue value) { + //do nothing + } + + public void onValueDeselected() { + //do nothing + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/DummyLineChartOnValueSelectListener.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/DummyLineChartOnValueSelectListener.java new file mode 100644 index 00000000..709397f3 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/DummyLineChartOnValueSelectListener.java @@ -0,0 +1,17 @@ +package dji.v5.ux.core.base.charts.listener; + +import dji.v5.ux.core.base.charts.model.PointValue; + +public class DummyLineChartOnValueSelectListener implements LineChartOnValueSelectListener { + public DummyLineChartOnValueSelectListener() { + //do nothing + } + + public void onValueSelected(int lineIndex, int pointIndex, PointValue value) { + //do nothing + } + + public void onValueDeselected() { + //do nothing + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/DummyPieChartOnValueSelectListener.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/DummyPieChartOnValueSelectListener.java new file mode 100644 index 00000000..24b9022a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/DummyPieChartOnValueSelectListener.java @@ -0,0 +1,17 @@ +package dji.v5.ux.core.base.charts.listener; + +import dji.v5.ux.core.base.charts.model.SliceValue; + +public class DummyPieChartOnValueSelectListener implements PieChartOnValueSelectListener { + public DummyPieChartOnValueSelectListener() { + //do nothing + } + + public void onValueSelected(int arcIndex, SliceValue value) { + //do nothing + } + + public void onValueDeselected() { + //do nothing + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/DummyVieportChangeListener.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/DummyVieportChangeListener.java new file mode 100644 index 00000000..91ac660e --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/DummyVieportChangeListener.java @@ -0,0 +1,13 @@ +package dji.v5.ux.core.base.charts.listener; + +import dji.v5.ux.core.base.charts.model.Viewport; + +public class DummyVieportChangeListener implements ViewportChangeListener { + public DummyVieportChangeListener() { + //do nothing + } + + public void onViewportChanged(Viewport viewport) { + //do nothing + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/LineChartOnValueSelectListener.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/LineChartOnValueSelectListener.java new file mode 100644 index 00000000..a301346a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/LineChartOnValueSelectListener.java @@ -0,0 +1,7 @@ +package dji.v5.ux.core.base.charts.listener; + +import dji.v5.ux.core.base.charts.model.PointValue; + +public interface LineChartOnValueSelectListener extends OnValueDeselectListener { + void onValueSelected(int var1, int var2, PointValue var3); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/OnValueDeselectListener.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/OnValueDeselectListener.java new file mode 100644 index 00000000..ed29a478 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/OnValueDeselectListener.java @@ -0,0 +1,5 @@ +package dji.v5.ux.core.base.charts.listener; + +public interface OnValueDeselectListener { + void onValueDeselected(); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/PieChartOnValueSelectListener.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/PieChartOnValueSelectListener.java new file mode 100644 index 00000000..166af55d --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/PieChartOnValueSelectListener.java @@ -0,0 +1,7 @@ +package dji.v5.ux.core.base.charts.listener; + +import dji.v5.ux.core.base.charts.model.SliceValue; + +public interface PieChartOnValueSelectListener extends OnValueDeselectListener { + void onValueSelected(int var1, SliceValue var2); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/ViewportChangeListener.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/ViewportChangeListener.java new file mode 100644 index 00000000..b48e3105 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/listener/ViewportChangeListener.java @@ -0,0 +1,7 @@ +package dji.v5.ux.core.base.charts.listener; + +import dji.v5.ux.core.base.charts.model.Viewport; + +public interface ViewportChangeListener { + void onViewportChanged(Viewport var1); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/AbstractChartData.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/AbstractChartData.java new file mode 100644 index 00000000..0a7106dd --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/AbstractChartData.java @@ -0,0 +1,126 @@ +package dji.v5.ux.core.base.charts.model; + +import android.graphics.Typeface; + +import dji.v5.ux.core.base.charts.util.ChartUtils; + +public abstract class AbstractChartData implements ChartData { + protected Axis axisXBottom; + protected Axis axisYLeft; + protected Axis axisXTop; + protected Axis axisYRight; + protected int valueLabelTextColor = -1; + protected int valueLabelTextSize = 12; + protected Typeface valueLabelTypeface; + protected boolean isValueLabelBackgroundEnabled = true; + protected boolean isValueLabelBackgrountAuto = true; + protected int valueLabelBackgroundColor; + + protected AbstractChartData() { + this.valueLabelBackgroundColor = ChartUtils.darkenColor(ChartUtils.DEFAULT_DARKEN_COLOR); + } + + protected AbstractChartData(AbstractChartData data) { + this.valueLabelBackgroundColor = ChartUtils.darkenColor(ChartUtils.DEFAULT_DARKEN_COLOR); + if (null != data.axisXBottom) { + this.axisXBottom = new Axis(data.axisXBottom); + } + + if (null != data.axisXTop) { + this.axisXTop = new Axis(data.axisXTop); + } + + if (null != data.axisYLeft) { + this.axisYLeft = new Axis(data.axisYLeft); + } + + if (null != data.axisYRight) { + this.axisYRight = new Axis(data.axisYRight); + } + + this.valueLabelTextColor = data.valueLabelTextColor; + this.valueLabelTextSize = data.valueLabelTextSize; + this.valueLabelTypeface = data.valueLabelTypeface; + } + + public Axis getAxisXBottom() { + return this.axisXBottom; + } + + public void setAxisXBottom(Axis axisX) { + this.axisXBottom = axisX; + } + + public Axis getAxisYLeft() { + return this.axisYLeft; + } + + public void setAxisYLeft(Axis axisY) { + this.axisYLeft = axisY; + } + + public Axis getAxisXTop() { + return this.axisXTop; + } + + public void setAxisXTop(Axis axisX) { + this.axisXTop = axisX; + } + + public Axis getAxisYRight() { + return this.axisYRight; + } + + public void setAxisYRight(Axis axisY) { + this.axisYRight = axisY; + } + + public int getValueLabelTextColor() { + return this.valueLabelTextColor; + } + + public void setValueLabelsTextColor(int valueLabelTextColor) { + this.valueLabelTextColor = valueLabelTextColor; + } + + public int getValueLabelTextSize() { + return this.valueLabelTextSize; + } + + public void setValueLabelTextSize(int valueLabelTextSize) { + this.valueLabelTextSize = valueLabelTextSize; + } + + public Typeface getValueLabelTypeface() { + return this.valueLabelTypeface; + } + + public void setValueLabelTypeface(Typeface typeface) { + this.valueLabelTypeface = typeface; + } + + public boolean isValueLabelBackgroundEnabled() { + return this.isValueLabelBackgroundEnabled; + } + + public void setValueLabelBackgroundEnabled(boolean isValueLabelBackgroundEnabled) { + this.isValueLabelBackgroundEnabled = isValueLabelBackgroundEnabled; + } + + public boolean isValueLabelBackgroundAuto() { + return this.isValueLabelBackgrountAuto; + } + + public void setValueLabelBackgroundAuto(boolean isValueLabelBackgrountAuto) { + this.isValueLabelBackgrountAuto = isValueLabelBackgrountAuto; + } + + public int getValueLabelBackgroundColor() { + return this.valueLabelBackgroundColor; + } + + public void setValueLabelBackgroundColor(int valueLabelBackgroundColor) { + this.valueLabelBackgroundColor = valueLabelBackgroundColor; + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/Axis.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/Axis.java new file mode 100644 index 00000000..0b6e66f4 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/Axis.java @@ -0,0 +1,243 @@ +package dji.v5.ux.core.base.charts.model; + +import android.graphics.Typeface; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import dji.v5.ux.core.base.charts.formatter.AxisValueFormatter; +import dji.v5.ux.core.base.charts.formatter.SimpleAxisValueFormatter; +import dji.v5.ux.core.base.charts.util.ChartUtils; + +public class Axis { + private int textSize = 12; + private int maxLabelChars = 3; + private List values = new ArrayList<>(); + private String name; + private boolean isAutoGenerated = true; + private boolean hasLines = false; + private boolean isInside = false; + private int textColor = -3355444; + private int lineColor; + private Typeface typeface; + private AxisValueFormatter formatter; + private boolean hasSeparationLine; + private boolean hasTiltedLabels; + + public Axis() { + this.lineColor = ChartUtils.DEFAULT_DARKEN_COLOR; + this.formatter = new SimpleAxisValueFormatter(); + this.hasSeparationLine = true; + this.hasTiltedLabels = false; + } + + public Axis(List values) { + this.lineColor = ChartUtils.DEFAULT_DARKEN_COLOR; + this.formatter = new SimpleAxisValueFormatter(); + this.hasSeparationLine = true; + this.hasTiltedLabels = false; + this.setValues(values); + } + + public Axis(Axis axis) { + this.lineColor = ChartUtils.DEFAULT_DARKEN_COLOR; + this.formatter = new SimpleAxisValueFormatter(); + this.hasSeparationLine = true; + this.hasTiltedLabels = false; + this.name = axis.name; + this.isAutoGenerated = axis.isAutoGenerated; + this.hasLines = axis.hasLines; + this.isInside = axis.isInside; + this.textColor = axis.textColor; + this.lineColor = axis.lineColor; + this.textSize = axis.textSize; + this.maxLabelChars = axis.maxLabelChars; + this.typeface = axis.typeface; + this.formatter = axis.formatter; + this.hasSeparationLine = axis.hasSeparationLine; + Iterator var2 = axis.values.iterator(); + + while(var2.hasNext()) { + AxisValue axisValue = (AxisValue)var2.next(); + this.values.add(new AxisValue(axisValue)); + } + + } + + public static Axis generateAxisFromRange(float start, float stop, float step) { + List values = new ArrayList<>(); + + for(float value = start; value <= stop; value += step) { + AxisValue axisValue = new AxisValue(value); + values.add(axisValue); + } + + return new Axis(values); + } + + public static Axis generateAxisFromCollection(List axisValues) { + List values = new ArrayList<>(); + int index = 0; + + for(Iterator var3 = axisValues.iterator(); var3.hasNext(); ++index) { + float value = (Float)var3.next(); + AxisValue axisValue = new AxisValue(value); + values.add(axisValue); + } + + return new Axis(values); + } + + public static Axis generateAxisFromCollection(List axisValues, List axisValuesLabels) { + if (axisValues.size() != axisValuesLabels.size()) { + throw new IllegalArgumentException("Values and labels lists must have the same size!"); + } else { + List values = new ArrayList<>(); + int index = 0; + + for(Iterator var4 = axisValues.iterator(); var4.hasNext(); ++index) { + float value = (Float)var4.next(); + AxisValue axisValue = (new AxisValue(value)).setLabel((String)axisValuesLabels.get(index)); + values.add(axisValue); + } + + return new Axis(values); + } + } + + public List getValues() { + return this.values; + } + + public Axis setValues(List values) { + if (null == values) { + this.values = new ArrayList<>(); + } else { + this.values = values; + } + + this.isAutoGenerated = false; + return this; + } + + public String getName() { + return this.name; + } + + public Axis setName(String name) { + this.name = name; + return this; + } + + public boolean isAutoGenerated() { + return this.isAutoGenerated; + } + + public Axis setAutoGenerated(boolean isAutoGenerated) { + this.isAutoGenerated = isAutoGenerated; + return this; + } + + public boolean hasLines() { + return this.hasLines; + } + + public Axis setHasLines(boolean hasLines) { + this.hasLines = hasLines; + return this; + } + + public int getTextColor() { + return this.textColor; + } + + public Axis setTextColor(int color) { + this.textColor = color; + return this; + } + + public boolean isInside() { + return this.isInside; + } + + public Axis setInside(boolean isInside) { + this.isInside = isInside; + return this; + } + + public int getLineColor() { + return this.lineColor; + } + + public Axis setLineColor(int lineColor) { + this.lineColor = lineColor; + return this; + } + + public int getTextSize() { + return this.textSize; + } + + public Axis setTextSize(int textSize) { + this.textSize = textSize; + return this; + } + + public int getMaxLabelChars() { + return this.maxLabelChars; + } + + public Axis setMaxLabelChars(int maxLabelChars) { + if (maxLabelChars < 0) { + maxLabelChars = 0; + } else if (maxLabelChars > 32) { + maxLabelChars = 32; + } + + this.maxLabelChars = maxLabelChars; + return this; + } + + public Typeface getTypeface() { + return this.typeface; + } + + public Axis setTypeface(Typeface typeface) { + this.typeface = typeface; + return this; + } + + public AxisValueFormatter getFormatter() { + return this.formatter; + } + + public Axis setFormatter(AxisValueFormatter formatter) { + if (null == formatter) { + this.formatter = new SimpleAxisValueFormatter(); + } else { + this.formatter = formatter; + } + + return this; + } + + public Axis setHasSeparationLine(boolean hasSeparationLine) { + this.hasSeparationLine = hasSeparationLine; + return this; + } + + public boolean hasSeparationLine() { + return this.hasSeparationLine; + } + + public boolean hasTiltedLabels() { + return this.hasTiltedLabels; + } + + public Axis setHasTiltedLabels(boolean hasTiltedLabels) { + this.hasTiltedLabels = hasTiltedLabels; + return this; + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/AxisValue.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/AxisValue.java new file mode 100644 index 00000000..0e9e1a00 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/AxisValue.java @@ -0,0 +1,77 @@ +package dji.v5.ux.core.base.charts.model; + +import java.util.Arrays; + +public class AxisValue { + private float value; + private char[] label; + + public AxisValue(float value) { + this.setValue(value); + } + + /** @deprecated */ + @Deprecated + public AxisValue(float value, char[] label) { + this.value = value; + this.label = label; + } + + public AxisValue(AxisValue axisValue) { + this.value = axisValue.value; + this.label = axisValue.label; + } + + public float getValue() { + return this.value; + } + + public AxisValue setValue(float value) { + this.value = value; + return this; + } + + /** @deprecated */ + @Deprecated + public char[] getLabel() { + return this.label; + } + + public AxisValue setLabel(String label) { + this.label = label.toCharArray(); + return this; + } + + public char[] getLabelAsChars() { + return this.label; + } + + /** @deprecated */ + @Deprecated + public AxisValue setLabel(char[] label) { + this.label = label; + return this; + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } else if (o != null && this.getClass() == o.getClass()) { + AxisValue axisValue = (AxisValue)o; + if (Float.compare(axisValue.value, this.value) != 0) { + return false; + } else { + return Arrays.equals(this.label, axisValue.label); + } + } else { + return false; + } + } + + public int hashCode() { + int result = this.value != 0.0F ? Float.floatToIntBits(this.value) : 0; + result = 31 * result + (this.label != null ? Arrays.hashCode(this.label) : 0); + return result; + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/BubbleChartData.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/BubbleChartData.java new file mode 100644 index 00000000..21d31a0b --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/BubbleChartData.java @@ -0,0 +1,140 @@ +package dji.v5.ux.core.base.charts.model; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import dji.v5.ux.core.base.charts.formatter.BubbleChartValueFormatter; +import dji.v5.ux.core.base.charts.formatter.SimpleBubbleChartValueFormatter; + +public class BubbleChartData extends AbstractChartData { + private BubbleChartValueFormatter formatter = new SimpleBubbleChartValueFormatter(); + private boolean hasLabels = false; + private boolean hasLabelsOnlyForSelected = false; + private int minBubbleRadius = 6; + private float bubbleScale = 1.0F; + private List values = new ArrayList<>(); + + public BubbleChartData() { + } + + public BubbleChartData(List values) { + this.setValues(values); + } + + public BubbleChartData(BubbleChartData data) { + super(data); + this.formatter = data.formatter; + this.hasLabels = data.hasLabels; + this.hasLabelsOnlyForSelected = data.hasLabelsOnlyForSelected; + this.minBubbleRadius = data.minBubbleRadius; + this.bubbleScale = data.bubbleScale; + Iterator var2 = data.getValues().iterator(); + + while(var2.hasNext()) { + BubbleValue bubbleValue = (BubbleValue)var2.next(); + this.values.add(new BubbleValue(bubbleValue)); + } + + } + + public static BubbleChartData generateDummyData() { + BubbleChartData data = new BubbleChartData(); + List values = new ArrayList<>(4); + values.add(new BubbleValue(0.0F, 20.0F, 15000.0F)); + values.add(new BubbleValue(3.0F, 22.0F, 20000.0F)); + values.add(new BubbleValue(5.0F, 25.0F, 5000.0F)); + values.add(new BubbleValue(7.0F, 30.0F, 30000.0F)); + values.add(new BubbleValue(11.0F, 22.0F, 10.0F)); + data.setValues(values); + return data; + } + + public void update(float scale) { + Iterator var2 = this.values.iterator(); + + while(var2.hasNext()) { + BubbleValue value = (BubbleValue)var2.next(); + value.update(scale); + } + + } + + public void finish() { + Iterator var1 = this.values.iterator(); + + while(var1.hasNext()) { + BubbleValue value = (BubbleValue)var1.next(); + value.finish(); + } + + } + + public List getValues() { + return this.values; + } + + public BubbleChartData setValues(List values) { + if (null == values) { + this.values = new ArrayList<>(); + } else { + this.values = values; + } + + return this; + } + + public boolean hasLabels() { + return this.hasLabels; + } + + public BubbleChartData setHasLabels(boolean hasLabels) { + this.hasLabels = hasLabels; + if (hasLabels) { + this.hasLabelsOnlyForSelected = false; + } + + return this; + } + + public boolean hasLabelsOnlyForSelected() { + return this.hasLabelsOnlyForSelected; + } + + public BubbleChartData setHasLabelsOnlyForSelected(boolean hasLabelsOnlyForSelected) { + this.hasLabelsOnlyForSelected = hasLabelsOnlyForSelected; + if (hasLabelsOnlyForSelected) { + this.hasLabels = false; + } + + return this; + } + + public int getMinBubbleRadius() { + return this.minBubbleRadius; + } + + public void setMinBubbleRadius(int minBubbleRadius) { + this.minBubbleRadius = minBubbleRadius; + } + + public float getBubbleScale() { + return this.bubbleScale; + } + + public void setBubbleScale(float bubbleScale) { + this.bubbleScale = bubbleScale; + } + + public BubbleChartValueFormatter getFormatter() { + return this.formatter; + } + + public BubbleChartData setFormatter(BubbleChartValueFormatter formatter) { + if (null != formatter) { + this.formatter = formatter; + } + + return this; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/BubbleValue.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/BubbleValue.java new file mode 100644 index 00000000..ea1a774e --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/BubbleValue.java @@ -0,0 +1,199 @@ +package dji.v5.ux.core.base.charts.model; + +import java.util.Arrays; + +import dji.v5.ux.core.base.charts.util.ChartUtils; + +public class BubbleValue { + private float x; + private float y; + private float z; + private float originX; + private float originY; + private float originZ; + private float diffX; + private float diffY; + private float diffZ; + private int color; + private int darkenColor; + private ValueShape shape; + private char[] label; + + public BubbleValue() { + this.color = ChartUtils.DEFAULT_COLOR; + this.darkenColor = ChartUtils.DEFAULT_DARKEN_COLOR; + this.shape = ValueShape.CIRCLE; + this.set(0.0F, 0.0F, 0.0F); + } + + public BubbleValue(float x, float y, float z) { + this.color = ChartUtils.DEFAULT_COLOR; + this.darkenColor = ChartUtils.DEFAULT_DARKEN_COLOR; + this.shape = ValueShape.CIRCLE; + this.set(x, y, z); + } + + public BubbleValue(float x, float y, float z, int color) { + this.color = ChartUtils.DEFAULT_COLOR; + this.darkenColor = ChartUtils.DEFAULT_DARKEN_COLOR; + this.shape = ValueShape.CIRCLE; + this.set(x, y, z); + this.setColor(color); + } + + public BubbleValue(BubbleValue bubbleValue) { + this.color = ChartUtils.DEFAULT_COLOR; + this.darkenColor = ChartUtils.DEFAULT_DARKEN_COLOR; + this.shape = ValueShape.CIRCLE; + this.set(bubbleValue.x, bubbleValue.y, bubbleValue.z); + this.setColor(bubbleValue.color); + this.label = bubbleValue.label; + } + + public void update(float scale) { + this.x = this.originX + this.diffX * scale; + this.y = this.originY + this.diffY * scale; + this.z = this.originZ + this.diffZ * scale; + } + + public void finish() { + this.set(this.originX + this.diffX, this.originY + this.diffY, this.originZ + this.diffZ); + } + + public BubbleValue set(float x, float y, float z) { + this.x = x; + this.y = y; + this.z = z; + this.originX = x; + this.originY = y; + this.originZ = z; + this.diffX = 0.0F; + this.diffY = 0.0F; + this.diffZ = 0.0F; + return this; + } + + public BubbleValue setTarget(float targetX, float targetY, float targetZ) { + this.set(this.x, this.y, this.z); + this.diffX = targetX - this.originX; + this.diffY = targetY - this.originY; + this.diffZ = targetZ - this.originZ; + return this; + } + + public float getX() { + return this.x; + } + + public float getY() { + return this.y; + } + + public float getZ() { + return this.z; + } + + public int getColor() { + return this.color; + } + + public BubbleValue setColor(int color) { + this.color = color; + this.darkenColor = ChartUtils.darkenColor(color); + return this; + } + + public int getDarkenColor() { + return this.darkenColor; + } + + public ValueShape getShape() { + return this.shape; + } + + public BubbleValue setShape(ValueShape shape) { + this.shape = shape; + return this; + } + + /** @deprecated */ + @Deprecated + public char[] getLabel() { + return this.label; + } + + public BubbleValue setLabel(String label) { + this.label = label.toCharArray(); + return this; + } + + public char[] getLabelAsChars() { + return this.label; + } + + /** @deprecated */ + @Deprecated + public BubbleValue setLabel(char[] label) { + this.label = label; + return this; + } + + public String toString() { + return "BubbleValue [x=" + this.x + ", y=" + this.y + ", z=" + this.z + "]"; + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } else if (o != null && this.getClass() == o.getClass()) { + BubbleValue that = (BubbleValue)o; + if (this.color != that.color) { + return false; + } else if (this.darkenColor != that.darkenColor) { + return false; + } else if (Float.compare(that.diffX, this.diffX) != 0) { + return false; + } else if (Float.compare(that.diffY, this.diffY) != 0) { + return false; + } else if (Float.compare(that.diffZ, this.diffZ) != 0) { + return false; + } else if (Float.compare(that.originX, this.originX) != 0) { + return false; + } else if (Float.compare(that.originY, this.originY) != 0) { + return false; + } else if (Float.compare(that.originZ, this.originZ) != 0) { + return false; + } else if (Float.compare(that.x, this.x) != 0) { + return false; + } else if (Float.compare(that.y, this.y) != 0) { + return false; + } else if (Float.compare(that.z, this.z) != 0) { + return false; + } else if (!Arrays.equals(this.label, that.label)) { + return false; + } else { + return this.shape == that.shape; + } + } else { + return false; + } + } + + public int hashCode() { + int result = this.x != 0.0F ? Float.floatToIntBits(this.x) : 0; + result = 31 * result + (this.y != 0.0F ? Float.floatToIntBits(this.y) : 0); + result = 31 * result + (this.z != 0.0F ? Float.floatToIntBits(this.z) : 0); + result = 31 * result + (this.originX != 0.0F ? Float.floatToIntBits(this.originX) : 0); + result = 31 * result + (this.originY != 0.0F ? Float.floatToIntBits(this.originY) : 0); + result = 31 * result + (this.originZ != 0.0F ? Float.floatToIntBits(this.originZ) : 0); + result = 31 * result + (this.diffX != 0.0F ? Float.floatToIntBits(this.diffX) : 0); + result = 31 * result + (this.diffY != 0.0F ? Float.floatToIntBits(this.diffY) : 0); + result = 31 * result + (this.diffZ != 0.0F ? Float.floatToIntBits(this.diffZ) : 0); + result = 31 * result + this.color; + result = 31 * result + this.darkenColor; + result = 31 * result + (this.shape != null ? this.shape.hashCode() : 0); + result = 31 * result + (this.label != null ? Arrays.hashCode(this.label) : 0); + return result; + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/ChartData.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/ChartData.java new file mode 100644 index 00000000..a214c6ab --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/ChartData.java @@ -0,0 +1,50 @@ +package dji.v5.ux.core.base.charts.model; + +import android.graphics.Typeface; + +public interface ChartData { + void update(float var1); + + void finish(); + + Axis getAxisXBottom(); + + void setAxisXBottom(Axis var1); + + Axis getAxisYLeft(); + + void setAxisYLeft(Axis var1); + + Axis getAxisXTop(); + + void setAxisXTop(Axis var1); + + Axis getAxisYRight(); + + void setAxisYRight(Axis var1); + + int getValueLabelTextColor(); + + void setValueLabelsTextColor(int var1); + + int getValueLabelTextSize(); + + void setValueLabelTextSize(int var1); + + Typeface getValueLabelTypeface(); + + void setValueLabelTypeface(Typeface var1); + + boolean isValueLabelBackgroundEnabled(); + + void setValueLabelBackgroundEnabled(boolean var1); + + boolean isValueLabelBackgroundAuto(); + + void setValueLabelBackgroundAuto(boolean var1); + + int getValueLabelBackgroundColor(); + + void setValueLabelBackgroundColor(int var1); +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/Column.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/Column.java new file mode 100644 index 00000000..e7097755 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/Column.java @@ -0,0 +1,107 @@ +package dji.v5.ux.core.base.charts.model; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import dji.v5.ux.core.base.charts.formatter.ColumnChartValueFormatter; +import dji.v5.ux.core.base.charts.formatter.SimpleColumnChartValueFormatter; + +public class Column { + private boolean hasLabels = false; + private boolean hasLabelsOnlyForSelected = false; + private ColumnChartValueFormatter formatter = new SimpleColumnChartValueFormatter(); + private List values = new ArrayList<>(); + + public Column() { + } + + public Column(List values) { + this.setValues(values); + } + + public Column(Column column) { + this.hasLabels = column.hasLabels; + this.hasLabelsOnlyForSelected = column.hasLabelsOnlyForSelected; + this.formatter = column.formatter; + Iterator var2 = column.values.iterator(); + + while(var2.hasNext()) { + SubcolumnValue columnValue = (SubcolumnValue)var2.next(); + this.values.add(new SubcolumnValue(columnValue)); + } + + } + + public void update(float scale) { + Iterator var2 = this.values.iterator(); + + while(var2.hasNext()) { + SubcolumnValue value = (SubcolumnValue)var2.next(); + value.update(scale); + } + + } + + public void finish() { + Iterator var1 = this.values.iterator(); + + while(var1.hasNext()) { + SubcolumnValue value = (SubcolumnValue)var1.next(); + value.finish(); + } + + } + + public List getValues() { + return this.values; + } + + public Column setValues(List values) { + if (null == values) { + this.values = new ArrayList<>(); + } else { + this.values = values; + } + + return this; + } + + public boolean hasLabels() { + return this.hasLabels; + } + + public Column setHasLabels(boolean hasLabels) { + this.hasLabels = hasLabels; + if (hasLabels) { + this.hasLabelsOnlyForSelected = false; + } + + return this; + } + + public boolean hasLabelsOnlyForSelected() { + return this.hasLabelsOnlyForSelected; + } + + public Column setHasLabelsOnlyForSelected(boolean hasLabelsOnlyForSelected) { + this.hasLabelsOnlyForSelected = hasLabelsOnlyForSelected; + if (hasLabelsOnlyForSelected) { + this.hasLabels = false; + } + + return this; + } + + public ColumnChartValueFormatter getFormatter() { + return this.formatter; + } + + public Column setFormatter(ColumnChartValueFormatter formatter) { + if (null != formatter) { + this.formatter = formatter; + } + + return this; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/ColumnChartData.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/ColumnChartData.java new file mode 100644 index 00000000..1247f970 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/ColumnChartData.java @@ -0,0 +1,117 @@ +package dji.v5.ux.core.base.charts.model; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class ColumnChartData extends AbstractChartData { + private float fillRatio = 0.75F; + private float baseValue = 0.0F; + private List columns = new ArrayList<>(); + private boolean isStacked = false; + + public ColumnChartData() { + } + + public ColumnChartData(List columns) { + this.setColumns(columns); + } + + public ColumnChartData(ColumnChartData data) { + super(data); + this.isStacked = data.isStacked; + this.fillRatio = data.fillRatio; + Iterator var2 = data.columns.iterator(); + + while(var2.hasNext()) { + Column column = (Column)var2.next(); + this.columns.add(new Column(column)); + } + + } + + public static ColumnChartData generateDummyData() { + ColumnChartData data = new ColumnChartData(); + List columns = new ArrayList<>(4); + + for(int i = 1; i <= 4; ++i) { + List values = new ArrayList<>(4); + values.add(new SubcolumnValue(i)); + Column column = new Column(values); + columns.add(column); + } + + data.setColumns(columns); + return data; + } + + public void update(float scale) { + Iterator var2 = this.columns.iterator(); + + while(var2.hasNext()) { + Column column = (Column)var2.next(); + column.update(scale); + } + + } + + public void finish() { + Iterator var1 = this.columns.iterator(); + + while(var1.hasNext()) { + Column column = (Column)var1.next(); + column.finish(); + } + + } + + public List getColumns() { + return this.columns; + } + + public ColumnChartData setColumns(List columns) { + if (null == columns) { + this.columns = new ArrayList<>(); + } else { + this.columns = columns; + } + + return this; + } + + public boolean isStacked() { + return this.isStacked; + } + + public ColumnChartData setStacked(boolean isStacked) { + this.isStacked = isStacked; + return this; + } + + public float getFillRatio() { + return this.fillRatio; + } + + public ColumnChartData setFillRatio(float fillRatio) { + if (fillRatio < 0.0F) { + fillRatio = 0.0F; + } + + if (fillRatio > 1.0F) { + fillRatio = 1.0F; + } + + this.fillRatio = fillRatio; + return this; + } + + public float getBaseValue() { + return this.baseValue; + } + + public ColumnChartData setBaseValue(float baseValue) { + this.baseValue = baseValue; + return this; + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/ComboLineColumnChartData.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/ComboLineColumnChartData.java new file mode 100644 index 00000000..72500f1f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/ComboLineColumnChartData.java @@ -0,0 +1,65 @@ +package dji.v5.ux.core.base.charts.model; + +public class ComboLineColumnChartData extends AbstractChartData { + private ColumnChartData columnChartData; + private LineChartData lineChartData; + + public ComboLineColumnChartData() { + this.columnChartData = new ColumnChartData(); + this.lineChartData = new LineChartData(); + } + + public ComboLineColumnChartData(ColumnChartData columnChartData, LineChartData lineChartData) { + this.setColumnChartData(columnChartData); + this.setLineChartData(lineChartData); + } + + public ComboLineColumnChartData(ComboLineColumnChartData data) { + super(data); + this.setColumnChartData(new ColumnChartData(data.getColumnChartData())); + this.setLineChartData(new LineChartData(data.getLineChartData())); + } + + public static ComboLineColumnChartData generateDummyData() { + ComboLineColumnChartData data = new ComboLineColumnChartData(); + data.setColumnChartData(ColumnChartData.generateDummyData()); + data.setLineChartData(LineChartData.generateDummyData()); + return data; + } + + public void update(float scale) { + this.columnChartData.update(scale); + this.lineChartData.update(scale); + } + + public void finish() { + this.columnChartData.finish(); + this.lineChartData.finish(); + } + + public ColumnChartData getColumnChartData() { + return this.columnChartData; + } + + public void setColumnChartData(ColumnChartData columnChartData) { + if (null == columnChartData) { + this.columnChartData = new ColumnChartData(); + } else { + this.columnChartData = columnChartData; + } + + } + + public LineChartData getLineChartData() { + return this.lineChartData; + } + + public void setLineChartData(LineChartData lineChartData) { + if (null == lineChartData) { + this.lineChartData = new LineChartData(); + } else { + this.lineChartData = lineChartData; + } + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/Line.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/Line.java new file mode 100644 index 00000000..50839560 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/Line.java @@ -0,0 +1,313 @@ +package dji.v5.ux.core.base.charts.model; + +import android.graphics.PathEffect; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import dji.v5.ux.core.base.charts.formatter.LineChartValueFormatter; +import dji.v5.ux.core.base.charts.formatter.SimpleLineChartValueFormatter; +import dji.v5.ux.core.base.charts.util.ChartUtils; + +public class Line { + private int color; + private int pointColor; + private int darkenColor; + private int areaTransparency; + private int strokeWidth; + private int pointRadius; + private boolean hasPoints; + private boolean hasLines; + private boolean hasLabels; + private boolean hasLabelsOnlyForSelected; + private boolean isCubic; + private boolean isSquare; + private boolean isFilled; + private ValueShape shape; + private PathEffect pathEffect; + private LineChartValueFormatter formatter; + private List values; + + public Line() { + this.color = ChartUtils.DEFAULT_COLOR; + this.pointColor = 0; + this.darkenColor = ChartUtils.DEFAULT_DARKEN_COLOR; + this.areaTransparency = 64; + this.strokeWidth = 3; + this.pointRadius = 6; + this.hasPoints = true; + this.hasLines = true; + this.hasLabels = false; + this.hasLabelsOnlyForSelected = false; + this.isCubic = false; + this.isSquare = false; + this.isFilled = false; + this.shape = ValueShape.CIRCLE; + this.formatter = new SimpleLineChartValueFormatter(); + this.values = new ArrayList<>(); + } + + public Line(List values) { + this.color = ChartUtils.DEFAULT_COLOR; + this.pointColor = 0; + this.darkenColor = ChartUtils.DEFAULT_DARKEN_COLOR; + this.areaTransparency = 64; + this.strokeWidth = 3; + this.pointRadius = 6; + this.hasPoints = true; + this.hasLines = true; + this.hasLabels = false; + this.hasLabelsOnlyForSelected = false; + this.isCubic = false; + this.isSquare = false; + this.isFilled = false; + this.shape = ValueShape.CIRCLE; + this.formatter = new SimpleLineChartValueFormatter(); + this.values = new ArrayList<>(); + this.setValues(values); + } + + public Line(Line line) { + this.color = ChartUtils.DEFAULT_COLOR; + this.pointColor = 0; + this.darkenColor = ChartUtils.DEFAULT_DARKEN_COLOR; + this.areaTransparency = 64; + this.strokeWidth = 3; + this.pointRadius = 6; + this.hasPoints = true; + this.hasLines = true; + this.hasLabels = false; + this.hasLabelsOnlyForSelected = false; + this.isCubic = false; + this.isSquare = false; + this.isFilled = false; + this.shape = ValueShape.CIRCLE; + this.formatter = new SimpleLineChartValueFormatter(); + this.values = new ArrayList<>(); + this.color = line.color; + this.pointColor = line.pointColor; + this.darkenColor = line.darkenColor; + this.areaTransparency = line.areaTransparency; + this.strokeWidth = line.strokeWidth; + this.pointRadius = line.pointRadius; + this.hasPoints = line.hasPoints; + this.hasLines = line.hasLines; + this.hasLabels = line.hasLabels; + this.hasLabelsOnlyForSelected = line.hasLabelsOnlyForSelected; + this.isSquare = line.isSquare; + this.isCubic = line.isCubic; + this.isFilled = line.isFilled; + this.shape = line.shape; + this.pathEffect = line.pathEffect; + this.formatter = line.formatter; + Iterator var2 = line.values.iterator(); + + while(var2.hasNext()) { + PointValue pointValue = (PointValue)var2.next(); + this.values.add(new PointValue(pointValue)); + } + + } + + public void update(float scale) { + Iterator var2 = this.values.iterator(); + + while(var2.hasNext()) { + PointValue value = (PointValue)var2.next(); + value.update(scale); + } + + } + + public void finish() { + Iterator var1 = this.values.iterator(); + + while(var1.hasNext()) { + PointValue value = (PointValue)var1.next(); + value.finish(); + } + + } + + public List getValues() { + return this.values; + } + + public void setValues(List values) { + if (null == values) { + this.values = new ArrayList<>(); + } else { + this.values = values; + } + + } + + public int getColor() { + return this.color; + } + + public Line setColor(int color) { + this.color = color; + if (this.pointColor == 0) { + this.darkenColor = ChartUtils.darkenColor(color); + } + + return this; + } + + public int getPointColor() { + return this.pointColor == 0 ? this.color : this.pointColor; + } + + public Line setPointColor(int pointColor) { + this.pointColor = pointColor; + if (pointColor == 0) { + this.darkenColor = ChartUtils.darkenColor(this.color); + } else { + this.darkenColor = ChartUtils.darkenColor(pointColor); + } + + return this; + } + + public int getDarkenColor() { + return this.darkenColor; + } + + public int getAreaTransparency() { + return this.areaTransparency; + } + + public Line setAreaTransparency(int areaTransparency) { + this.areaTransparency = areaTransparency; + return this; + } + + public int getStrokeWidth() { + return this.strokeWidth; + } + + public Line setStrokeWidth(int strokeWidth) { + this.strokeWidth = strokeWidth; + return this; + } + + public boolean hasPoints() { + return this.hasPoints; + } + + public Line setHasPoints(boolean hasPoints) { + this.hasPoints = hasPoints; + return this; + } + + public boolean hasLines() { + return this.hasLines; + } + + public Line setHasLines(boolean hasLines) { + this.hasLines = hasLines; + return this; + } + + public boolean hasLabels() { + return this.hasLabels; + } + + public Line setHasLabels(boolean hasLabels) { + this.hasLabels = hasLabels; + if (hasLabels) { + this.hasLabelsOnlyForSelected = false; + } + + return this; + } + + public boolean hasLabelsOnlyForSelected() { + return this.hasLabelsOnlyForSelected; + } + + public Line setHasLabelsOnlyForSelected(boolean hasLabelsOnlyForSelected) { + this.hasLabelsOnlyForSelected = hasLabelsOnlyForSelected; + if (hasLabelsOnlyForSelected) { + this.hasLabels = false; + } + + return this; + } + + public int getPointRadius() { + return this.pointRadius; + } + + public Line setPointRadius(int pointRadius) { + this.pointRadius = pointRadius; + return this; + } + + public boolean isCubic() { + return this.isCubic; + } + + public Line setCubic(boolean isCubic) { + this.isCubic = isCubic; + if (this.isSquare) { + this.setSquare(false); + } + + return this; + } + + public boolean isSquare() { + return this.isSquare; + } + + public Line setSquare(boolean isSquare) { + this.isSquare = isSquare; + if (this.isCubic) { + this.setCubic(false); + } + + return this; + } + + public boolean isFilled() { + return this.isFilled; + } + + public Line setFilled(boolean isFilled) { + this.isFilled = isFilled; + return this; + } + + public ValueShape getShape() { + return this.shape; + } + + public Line setShape(ValueShape shape) { + this.shape = shape; + return this; + } + + public PathEffect getPathEffect() { + return this.pathEffect; + } + + public void setPathEffect(PathEffect pathEffect) { + this.pathEffect = pathEffect; + } + + public LineChartValueFormatter getFormatter() { + return this.formatter; + } + + public Line setFormatter(LineChartValueFormatter formatter) { + if (null != formatter) { + this.formatter = formatter; + } + + return this; + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/LineChartData.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/LineChartData.java new file mode 100644 index 00000000..aa0dcb12 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/LineChartData.java @@ -0,0 +1,87 @@ +package dji.v5.ux.core.base.charts.model; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class LineChartData extends AbstractChartData { + private List lines = new ArrayList<>(); + private float baseValue = 0.0F; + + public LineChartData() { + } + + public LineChartData(List lines) { + this.setLines(lines); + } + + public LineChartData(LineChartData data) { + super(data); + this.baseValue = data.baseValue; + Iterator var2 = data.lines.iterator(); + + while(var2.hasNext()) { + Line line = (Line)var2.next(); + this.lines.add(new Line(line)); + } + + } + + public static LineChartData generateDummyData() { + LineChartData data = new LineChartData(); + List values = new ArrayList<>(4); + values.add(new PointValue(0.0F, 2.0F)); + values.add(new PointValue(1.0F, 4.0F)); + values.add(new PointValue(2.0F, 3.0F)); + values.add(new PointValue(3.0F, 4.0F)); + Line line = new Line(values); + List lines = new ArrayList<>(1); + lines.add(line); + data.setLines(lines); + return data; + } + + public void update(float scale) { + Iterator var2 = this.lines.iterator(); + + while(var2.hasNext()) { + Line line = (Line)var2.next(); + line.update(scale); + } + + } + + public void finish() { + Iterator var1 = this.lines.iterator(); + + while(var1.hasNext()) { + Line line = (Line)var1.next(); + line.finish(); + } + + } + + public List getLines() { + return this.lines; + } + + public LineChartData setLines(List lines) { + if (null == lines) { + this.lines = new ArrayList<>(); + } else { + this.lines = lines; + } + + return this; + } + + public float getBaseValue() { + return this.baseValue; + } + + public LineChartData setBaseValue(float baseValue) { + this.baseValue = baseValue; + return this; + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/PieChartData.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/PieChartData.java new file mode 100644 index 00000000..b2f582c9 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/PieChartData.java @@ -0,0 +1,278 @@ +package dji.v5.ux.core.base.charts.model; + +import android.graphics.Typeface; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import dji.v5.ux.core.base.charts.formatter.PieChartValueFormatter; +import dji.v5.ux.core.base.charts.formatter.SimplePieChartValueFormatter; + +public class PieChartData extends AbstractChartData { + private int centerText1FontSize = 42; + private int centerText2FontSize = 16; + private float centerCircleScale = 0.6F; + private int slicesSpacing = 2; + private PieChartValueFormatter formatter = new SimplePieChartValueFormatter(); + private boolean hasLabels = false; + private boolean hasLabelsOnlyForSelected = false; + private boolean hasLabelsOutside = false; + private boolean hasCenterCircle = false; + private int centerCircleColor = 0; + private int centerText1Color = -16777216; + private Typeface centerText1Typeface; + private String centerText1; + private int centerText2Color = -16777216; + private Typeface centerText2Typeface; + private String centerText2; + private List values = new ArrayList<>(); + + public PieChartData() { + this.setAxisXBottom((Axis)null); + this.setAxisYLeft((Axis)null); + } + + public PieChartData(List values) { + this.setValues(values); + this.setAxisXBottom((Axis)null); + this.setAxisYLeft((Axis)null); + } + + public PieChartData(PieChartData data) { + super(data); + this.formatter = data.formatter; + this.hasLabels = data.hasLabels; + this.hasLabelsOnlyForSelected = data.hasLabelsOnlyForSelected; + this.hasLabelsOutside = data.hasLabelsOutside; + this.hasCenterCircle = data.hasCenterCircle; + this.centerCircleColor = data.centerCircleColor; + this.centerCircleScale = data.centerCircleScale; + this.centerText1Color = data.centerText1Color; + this.centerText1FontSize = data.centerText1FontSize; + this.centerText1Typeface = data.centerText1Typeface; + this.centerText1 = data.centerText1; + this.centerText2Color = data.centerText2Color; + this.centerText2FontSize = data.centerText2FontSize; + this.centerText2Typeface = data.centerText2Typeface; + this.centerText2 = data.centerText2; + Iterator var2 = data.values.iterator(); + + while(var2.hasNext()) { + SliceValue sliceValue = (SliceValue)var2.next(); + this.values.add(new SliceValue(sliceValue)); + } + + } + + public static PieChartData generateDummyData() { + PieChartData data = new PieChartData(); + List values = new ArrayList<>(4); + values.add(new SliceValue(40.0F)); + values.add(new SliceValue(20.0F)); + values.add(new SliceValue(30.0F)); + values.add(new SliceValue(50.0F)); + data.setValues(values); + return data; + } + + public void update(float scale) { + Iterator var2 = this.values.iterator(); + + while(var2.hasNext()) { + SliceValue value = (SliceValue)var2.next(); + value.update(scale); + } + + } + + public void finish() { + Iterator var1 = this.values.iterator(); + + while(var1.hasNext()) { + SliceValue value = (SliceValue)var1.next(); + value.finish(); + } + + } + + @Override + public void setAxisXBottom(Axis axisX) { + super.setAxisXBottom((Axis)null); + } + + @Override + public void setAxisYLeft(Axis axisY) { + super.setAxisYLeft((Axis)null); + } + + public List getValues() { + return this.values; + } + + public PieChartData setValues(List values) { + if (null == values) { + this.values = new ArrayList<>(); + } else { + this.values = values; + } + + return this; + } + + public boolean hasLabels() { + return this.hasLabels; + } + + public PieChartData setHasLabels(boolean hasLabels) { + this.hasLabels = hasLabels; + if (hasLabels) { + this.hasLabelsOnlyForSelected = false; + } + + return this; + } + + public boolean hasLabelsOnlyForSelected() { + return this.hasLabelsOnlyForSelected; + } + + public PieChartData setHasLabelsOnlyForSelected(boolean hasLabelsOnlyForSelected) { + this.hasLabelsOnlyForSelected = hasLabelsOnlyForSelected; + if (hasLabelsOnlyForSelected) { + this.hasLabels = false; + } + + return this; + } + + public boolean hasLabelsOutside() { + return this.hasLabelsOutside; + } + + public PieChartData setHasLabelsOutside(boolean hasLabelsOutside) { + this.hasLabelsOutside = hasLabelsOutside; + return this; + } + + public boolean hasCenterCircle() { + return this.hasCenterCircle; + } + + public PieChartData setHasCenterCircle(boolean hasCenterCircle) { + this.hasCenterCircle = hasCenterCircle; + return this; + } + + public int getCenterCircleColor() { + return this.centerCircleColor; + } + + public PieChartData setCenterCircleColor(int centerCircleColor) { + this.centerCircleColor = centerCircleColor; + return this; + } + + public float getCenterCircleScale() { + return this.centerCircleScale; + } + + public PieChartData setCenterCircleScale(float centerCircleScale) { + this.centerCircleScale = centerCircleScale; + return this; + } + + public int getCenterText1Color() { + return this.centerText1Color; + } + + public PieChartData setCenterText1Color(int centerText1Color) { + this.centerText1Color = centerText1Color; + return this; + } + + public int getCenterText1FontSize() { + return this.centerText1FontSize; + } + + public PieChartData setCenterText1FontSize(int centerText1FontSize) { + this.centerText1FontSize = centerText1FontSize; + return this; + } + + public Typeface getCenterText1Typeface() { + return this.centerText1Typeface; + } + + public PieChartData setCenterText1Typeface(Typeface text1Typeface) { + this.centerText1Typeface = text1Typeface; + return this; + } + + public String getCenterText1() { + return this.centerText1; + } + + public PieChartData setCenterText1(String centerText1) { + this.centerText1 = centerText1; + return this; + } + + public String getCenterText2() { + return this.centerText2; + } + + public PieChartData setCenterText2(String centerText2) { + this.centerText2 = centerText2; + return this; + } + + public int getCenterText2Color() { + return this.centerText2Color; + } + + public PieChartData setCenterText2Color(int centerText2Color) { + this.centerText2Color = centerText2Color; + return this; + } + + public int getCenterText2FontSize() { + return this.centerText2FontSize; + } + + public PieChartData setCenterText2FontSize(int centerText2FontSize) { + this.centerText2FontSize = centerText2FontSize; + return this; + } + + public Typeface getCenterText2Typeface() { + return this.centerText2Typeface; + } + + public PieChartData setCenterText2Typeface(Typeface text2Typeface) { + this.centerText2Typeface = text2Typeface; + return this; + } + + public int getSlicesSpacing() { + return this.slicesSpacing; + } + + public PieChartData setSlicesSpacing(int sliceSpacing) { + this.slicesSpacing = sliceSpacing; + return this; + } + + public PieChartValueFormatter getFormatter() { + return this.formatter; + } + + public PieChartData setFormatter(PieChartValueFormatter formatter) { + if (null != formatter) { + this.formatter = formatter; + } + + return this; + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/PointValue.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/PointValue.java new file mode 100644 index 00000000..619840a9 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/PointValue.java @@ -0,0 +1,122 @@ +package dji.v5.ux.core.base.charts.model; + +import java.util.Arrays; + +public class PointValue { + private float x; + private float y; + private float originX; + private float originY; + private float diffX; + private float diffY; + private char[] label; + + public PointValue() { + this.set(0.0F, 0.0F); + } + + public PointValue(float x, float y) { + this.set(x, y); + } + + public PointValue(PointValue pointValue) { + this.set(pointValue.x, pointValue.y); + this.label = pointValue.label; + } + + public void update(float scale) { + this.x = this.originX + this.diffX * scale; + this.y = this.originY + this.diffY * scale; + } + + public void finish() { + this.set(this.originX + this.diffX, this.originY + this.diffY); + } + + public PointValue set(float x, float y) { + this.x = x; + this.y = y; + this.originX = x; + this.originY = y; + this.diffX = 0.0F; + this.diffY = 0.0F; + return this; + } + + public PointValue setTarget(float targetX, float targetY) { + this.set(this.x, this.y); + this.diffX = targetX - this.originX; + this.diffY = targetY - this.originY; + return this; + } + + public float getX() { + return this.x; + } + + public float getY() { + return this.y; + } + + /** @deprecated */ + @Deprecated + public char[] getLabel() { + return this.label; + } + + public PointValue setLabel(String label) { + this.label = label.toCharArray(); + return this; + } + + public char[] getLabelAsChars() { + return this.label; + } + + /** @deprecated */ + @Deprecated + public PointValue setLabel(char[] label) { + this.label = label; + return this; + } + + public String toString() { + return "PointValue [x=" + this.x + ", y=" + this.y + "]"; + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } else if (o != null && this.getClass() == o.getClass()) { + PointValue that = (PointValue)o; + if (Float.compare(that.diffX, this.diffX) != 0) { + return false; + } else if (Float.compare(that.diffY, this.diffY) != 0) { + return false; + } else if (Float.compare(that.originX, this.originX) != 0) { + return false; + } else if (Float.compare(that.originY, this.originY) != 0) { + return false; + } else if (Float.compare(that.x, this.x) != 0) { + return false; + } else if (Float.compare(that.y, this.y) != 0) { + return false; + } else { + return Arrays.equals(this.label, that.label); + } + } else { + return false; + } + } + + public int hashCode() { + int result = this.x != 0.0F ? Float.floatToIntBits(this.x) : 0; + result = 31 * result + (this.y != 0.0F ? Float.floatToIntBits(this.y) : 0); + result = 31 * result + (this.originX != 0.0F ? Float.floatToIntBits(this.originX) : 0); + result = 31 * result + (this.originY != 0.0F ? Float.floatToIntBits(this.originY) : 0); + result = 31 * result + (this.diffX != 0.0F ? Float.floatToIntBits(this.diffX) : 0); + result = 31 * result + (this.diffY != 0.0F ? Float.floatToIntBits(this.diffY) : 0); + result = 31 * result + (this.label != null ? Arrays.hashCode(this.label) : 0); + return result; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/SelectedValue.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/SelectedValue.java new file mode 100644 index 00000000..95a4e185 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/SelectedValue.java @@ -0,0 +1,108 @@ +package dji.v5.ux.core.base.charts.model; + +public class SelectedValue { + private int firstIndex; + private int secondIndex; + private SelectedValueType type; + + public SelectedValue() { + this.type = SelectedValueType.NONE; + this.clear(); + } + + public SelectedValue(int firstIndex, int secondIndex, SelectedValueType type) { + this.type = SelectedValueType.NONE; + this.set(firstIndex, secondIndex, type); + } + + public void set(int firstIndex, int secondIndex, SelectedValueType type) { + this.firstIndex = firstIndex; + this.secondIndex = secondIndex; + if (null != type) { + this.type = type; + } else { + this.type = SelectedValueType.NONE; + } + + } + + public void set(SelectedValue selectedValue) { + this.firstIndex = selectedValue.firstIndex; + this.secondIndex = selectedValue.secondIndex; + this.type = selectedValue.type; + } + + public void clear() { + this.set(Integer.MIN_VALUE, Integer.MIN_VALUE, SelectedValueType.NONE); + } + + public boolean isSet() { + return this.firstIndex >= 0 && this.secondIndex >= 0; + } + + public int getFirstIndex() { + return this.firstIndex; + } + + public void setFirstIndex(int firstIndex) { + this.firstIndex = firstIndex; + } + + public int getSecondIndex() { + return this.secondIndex; + } + + public void setSecondIndex(int secondIndex) { + this.secondIndex = secondIndex; + } + + public SelectedValueType getType() { + return this.type; + } + + public void setType(SelectedValueType type) { + this.type = type; + } + + public int hashCode() { + int prime = 1; + int result = 1; + result = 31 * result + this.firstIndex; + result = 31 * result + this.secondIndex; + result = 31 * result + (this.type == null ? 0 : this.type.hashCode()); + return result; + } + + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (obj == null) { + return false; + } else if (this.getClass() != obj.getClass()) { + return false; + } else { + SelectedValue other = (SelectedValue)obj; + if (this.firstIndex != other.firstIndex) { + return false; + } else if (this.secondIndex != other.secondIndex) { + return false; + } else { + return this.type == other.type; + } + } + } + + public String toString() { + return "SelectedValue [firstIndex=" + this.firstIndex + ", secondIndex=" + this.secondIndex + ", type=" + this.type + "]"; + } + + public static enum SelectedValueType { + NONE, + LINE, + COLUMN; + + private SelectedValueType() { + } + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/SliceValue.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/SliceValue.java new file mode 100644 index 00000000..7f0755e0 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/SliceValue.java @@ -0,0 +1,168 @@ +package dji.v5.ux.core.base.charts.model; + +import java.util.Arrays; + +import dji.v5.ux.core.base.charts.util.ChartUtils; + +public class SliceValue { + /** @deprecated */ + @Deprecated + private int sliceSpacing = 2; + private float value; + private float originValue; + private float diff; + private int color; + private int darkenColor; + private char[] label; + + public SliceValue() { + this.color = ChartUtils.DEFAULT_COLOR; + this.darkenColor = ChartUtils.DEFAULT_DARKEN_COLOR; + this.setValue(0.0F); + } + + public SliceValue(float value) { + this.color = ChartUtils.DEFAULT_COLOR; + this.darkenColor = ChartUtils.DEFAULT_DARKEN_COLOR; + this.setValue(value); + } + + public SliceValue(float value, int color) { + this.color = ChartUtils.DEFAULT_COLOR; + this.darkenColor = ChartUtils.DEFAULT_DARKEN_COLOR; + this.setValue(value); + this.setColor(color); + } + + public SliceValue(float value, int color, int sliceSpacing) { + this.color = ChartUtils.DEFAULT_COLOR; + this.darkenColor = ChartUtils.DEFAULT_DARKEN_COLOR; + this.setValue(value); + this.setColor(color); + this.sliceSpacing = sliceSpacing; + } + + public SliceValue(SliceValue sliceValue) { + this.color = ChartUtils.DEFAULT_COLOR; + this.darkenColor = ChartUtils.DEFAULT_DARKEN_COLOR; + this.setValue(sliceValue.value); + this.setColor(sliceValue.color); + this.sliceSpacing = sliceValue.sliceSpacing; + this.label = sliceValue.label; + } + + public void update(float scale) { + this.value = this.originValue + this.diff * scale; + } + + public void finish() { + this.setValue(this.originValue + this.diff); + } + + public float getValue() { + return this.value; + } + + public SliceValue setValue(float value) { + this.value = value; + this.originValue = value; + this.diff = 0.0F; + return this; + } + + public SliceValue setTarget(float target) { + this.setValue(this.value); + this.diff = target - this.originValue; + return this; + } + + public int getColor() { + return this.color; + } + + public SliceValue setColor(int color) { + this.color = color; + this.darkenColor = ChartUtils.darkenColor(color); + return this; + } + + public int getDarkenColor() { + return this.darkenColor; + } + + /** @deprecated */ + @Deprecated + public int getSliceSpacing() { + return this.sliceSpacing; + } + + /** @deprecated */ + @Deprecated + public SliceValue setSliceSpacing(int sliceSpacing) { + this.sliceSpacing = sliceSpacing; + return this; + } + + /** @deprecated */ + @Deprecated + public char[] getLabel() { + return this.label; + } + + /** @deprecated */ + @Deprecated + public SliceValue setLabel(char[] label) { + this.label = label; + return this; + } + + public SliceValue setLabel(String label) { + this.label = label.toCharArray(); + return this; + } + + public char[] getLabelAsChars() { + return this.label; + } + + public String toString() { + return "SliceValue [value=" + this.value + "]"; + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } else if (o != null && this.getClass() == o.getClass()) { + SliceValue that = (SliceValue)o; + if (this.color != that.color) { + return false; + } else if (this.darkenColor != that.darkenColor) { + return false; + } else if (Float.compare(that.diff, this.diff) != 0) { + return false; + } else if (Float.compare(that.originValue, this.originValue) != 0) { + return false; + } else if (this.sliceSpacing != that.sliceSpacing) { + return false; + } else if (Float.compare(that.value, this.value) != 0) { + return false; + } else { + return Arrays.equals(this.label, that.label); + } + } else { + return false; + } + } + + public int hashCode() { + int result = this.value != 0.0F ? Float.floatToIntBits(this.value) : 0; + result = 31 * result + (this.originValue != 0.0F ? Float.floatToIntBits(this.originValue) : 0); + result = 31 * result + (this.diff != 0.0F ? Float.floatToIntBits(this.diff) : 0); + result = 31 * result + this.color; + result = 31 * result + this.darkenColor; + result = 31 * result + this.sliceSpacing; + result = 31 * result + (this.label != null ? Arrays.hashCode(this.label) : 0); + return result; + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/SubcolumnValue.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/SubcolumnValue.java new file mode 100644 index 00000000..77ac2b56 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/SubcolumnValue.java @@ -0,0 +1,140 @@ +package dji.v5.ux.core.base.charts.model; + +import java.util.Arrays; + +import dji.v5.ux.core.base.charts.util.ChartUtils; + +public class SubcolumnValue { + private float value; + private float originValue; + private float diff; + private int color; + private int darkenColor; + private char[] label; + + public SubcolumnValue() { + this.color = ChartUtils.DEFAULT_COLOR; + this.darkenColor = ChartUtils.DEFAULT_DARKEN_COLOR; + this.setValue(0.0F); + } + + public SubcolumnValue(float value) { + this.color = ChartUtils.DEFAULT_COLOR; + this.darkenColor = ChartUtils.DEFAULT_DARKEN_COLOR; + this.setValue(value); + } + + public SubcolumnValue(float value, int color) { + this.color = ChartUtils.DEFAULT_COLOR; + this.darkenColor = ChartUtils.DEFAULT_DARKEN_COLOR; + this.setValue(value); + this.setColor(color); + } + + public SubcolumnValue(SubcolumnValue columnValue) { + this.color = ChartUtils.DEFAULT_COLOR; + this.darkenColor = ChartUtils.DEFAULT_DARKEN_COLOR; + this.setValue(columnValue.value); + this.setColor(columnValue.color); + this.label = columnValue.label; + } + + public void update(float scale) { + this.value = this.originValue + this.diff * scale; + } + + public void finish() { + this.setValue(this.originValue + this.diff); + } + + public float getValue() { + return this.value; + } + + public SubcolumnValue setValue(float value) { + this.value = value; + this.originValue = value; + this.diff = 0.0F; + return this; + } + + public SubcolumnValue setTarget(float target) { + this.setValue(this.value); + this.diff = target - this.originValue; + return this; + } + + public int getColor() { + return this.color; + } + + public SubcolumnValue setColor(int color) { + this.color = color; + this.darkenColor = ChartUtils.darkenColor(color); + return this; + } + + public int getDarkenColor() { + return this.darkenColor; + } + + /** @deprecated */ + @Deprecated + public char[] getLabel() { + return this.label; + } + + public SubcolumnValue setLabel(String label) { + this.label = label.toCharArray(); + return this; + } + + public char[] getLabelAsChars() { + return this.label; + } + + /** @deprecated */ + @Deprecated + public SubcolumnValue setLabel(char[] label) { + this.label = label; + return this; + } + + public String toString() { + return "ColumnValue [value=" + this.value + "]"; + } + + public boolean equals(Object o) { + if (this == o) { + return true; + } else if (o != null && this.getClass() == o.getClass()) { + SubcolumnValue that = (SubcolumnValue)o; + if (this.color != that.color) { + return false; + } else if (this.darkenColor != that.darkenColor) { + return false; + } else if (Float.compare(that.diff, this.diff) != 0) { + return false; + } else if (Float.compare(that.originValue, this.originValue) != 0) { + return false; + } else if (Float.compare(that.value, this.value) != 0) { + return false; + } else { + return Arrays.equals(this.label, that.label); + } + } else { + return false; + } + } + + public int hashCode() { + int result = this.value != 0.0F ? Float.floatToIntBits(this.value) : 0; + result = 31 * result + (this.originValue != 0.0F ? Float.floatToIntBits(this.originValue) : 0); + result = 31 * result + (this.diff != 0.0F ? Float.floatToIntBits(this.diff) : 0); + result = 31 * result + this.color; + result = 31 * result + this.darkenColor; + result = 31 * result + (this.label != null ? Arrays.hashCode(this.label) : 0); + return result; + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/ValueShape.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/ValueShape.java new file mode 100644 index 00000000..36dbced3 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/ValueShape.java @@ -0,0 +1,10 @@ +package dji.v5.ux.core.base.charts.model; + +public enum ValueShape { + CIRCLE, + SQUARE, + DIAMOND; + + private ValueShape() { + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/Viewport.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/Viewport.java new file mode 100644 index 00000000..332ff552 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/model/Viewport.java @@ -0,0 +1,229 @@ +package dji.v5.ux.core.base.charts.model; + +import android.os.Parcel; +import android.os.Parcelable; + +public class Viewport implements Parcelable { + public float left; + public float top; + public float right; + public float bottom; + public static final Creator CREATOR = new Creator() { + public Viewport createFromParcel(Parcel in) { + Viewport v = new Viewport(); + v.readFromParcel(in); + return v; + } + + public Viewport[] newArray(int size) { + return new Viewport[size]; + } + }; + + public Viewport() { + } + + public Viewport(float left, float top, float right, float bottom) { + this.left = left; + this.top = top; + this.right = right; + this.bottom = bottom; + } + + public Viewport(Viewport v) { + if (v == null) { + this.left = this.top = this.right = this.bottom = 0.0F; + } else { + this.left = v.left; + this.top = v.top; + this.right = v.right; + this.bottom = v.bottom; + } + + } + + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (obj == null) { + return false; + } else if (this.getClass() != obj.getClass()) { + return false; + } else { + Viewport other = (Viewport)obj; + if (Float.floatToIntBits(this.bottom) != Float.floatToIntBits(other.bottom)) { + return false; + } else if (Float.floatToIntBits(this.left) != Float.floatToIntBits(other.left)) { + return false; + } else if (Float.floatToIntBits(this.right) != Float.floatToIntBits(other.right)) { + return false; + } else { + return Float.floatToIntBits(this.top) == Float.floatToIntBits(other.top); + } + } + } + + public final boolean isEmpty() { + return this.left >= this.right || this.bottom >= this.top; + } + + public void setEmpty() { + this.left = this.right = this.top = this.bottom = 0.0F; + } + + public final float width() { + return this.right - this.left; + } + + public final float height() { + return this.top - this.bottom; + } + + public final float centerX() { + return (this.left + this.right) * 0.5F; + } + + public final float centerY() { + return (this.top + this.bottom) * 0.5F; + } + + public void set(float left, float top, float right, float bottom) { + this.left = left; + this.top = top; + this.right = right; + this.bottom = bottom; + } + + public void set(Viewport src) { + this.left = src.left; + this.top = src.top; + this.right = src.right; + this.bottom = src.bottom; + } + + public void offset(float dx, float dy) { + this.left += dx; + this.top += dy; + this.right += dx; + this.bottom += dy; + } + + public void offsetTo(float newLeft, float newTop) { + this.right += newLeft - this.left; + this.bottom += newTop - this.top; + this.left = newLeft; + this.top = newTop; + } + + public void inset(float dx, float dy) { + this.left += dx; + this.top -= dy; + this.right -= dx; + this.bottom += dy; + } + + public boolean contains(float x, float y) { + return this.left < this.right && this.bottom < this.top && x >= this.left && x < this.right && y >= this.bottom && y < this.top; + } + + public boolean contains(float left, float top, float right, float bottom) { + return this.left < this.right && this.bottom < this.top && this.left <= left && this.top >= top && this.right >= right && this.bottom <= bottom; + } + + public boolean contains(Viewport v) { + return this.left < this.right && this.bottom < this.top && this.left <= v.left && this.top >= v.top && this.right >= v.right && this.bottom <= v.bottom; + } + + public void union(float left, float top, float right, float bottom) { + if (left < right && bottom < top) { + if (this.left < this.right && this.bottom < this.top) { + if (this.left > left) { + this.left = left; + } + + if (this.top < top) { + this.top = top; + } + + if (this.right < right) { + this.right = right; + } + + if (this.bottom > bottom) { + this.bottom = bottom; + } + } else { + this.left = left; + this.top = top; + this.right = right; + this.bottom = bottom; + } + } + + } + + public void union(Viewport v) { + this.union(v.left, v.top, v.right, v.bottom); + } + + public boolean intersect(float left, float top, float right, float bottom) { + if (this.left < right && left < this.right && this.bottom < top && bottom < this.top) { + if (this.left < left) { + this.left = left; + } + + if (this.top > top) { + this.top = top; + } + + if (this.right > right) { + this.right = right; + } + + if (this.bottom < bottom) { + this.bottom = bottom; + } + + return true; + } else { + return false; + } + } + + public boolean intersect(Viewport v) { + return this.intersect(v.left, v.top, v.right, v.bottom); + } + + public String toString() { + return "Viewport [left=" + this.left + ", top=" + this.top + ", right=" + this.right + ", bottom=" + this.bottom + "]"; + } + + public int hashCode() { + int prime = 1; + int result = 1; + result = 31 * result + Float.floatToIntBits(this.bottom); + result = 31 * result + Float.floatToIntBits(this.left); + result = 31 * result + Float.floatToIntBits(this.right); + result = 31 * result + Float.floatToIntBits(this.top); + return result; + } + + public int describeContents() { + return 0; + } + + public void writeToParcel(Parcel out, int flags) { + out.writeFloat(this.left); + out.writeFloat(this.top); + out.writeFloat(this.right); + out.writeFloat(this.bottom); + } + + public void readFromParcel(Parcel in) { + this.left = in.readFloat(); + this.top = in.readFloat(); + this.right = in.readFloat(); + this.bottom = in.readFloat(); + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/provider/BubbleChartDataProvider.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/provider/BubbleChartDataProvider.java new file mode 100644 index 00000000..c50607da --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/provider/BubbleChartDataProvider.java @@ -0,0 +1,10 @@ +package dji.v5.ux.core.base.charts.provider; + +import dji.v5.ux.core.base.charts.model.BubbleChartData; + +public interface BubbleChartDataProvider { + BubbleChartData getBubbleChartData(); + + void setBubbleChartData(BubbleChartData var1); +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/provider/ColumnChartDataProvider.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/provider/ColumnChartDataProvider.java new file mode 100644 index 00000000..c8d22270 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/provider/ColumnChartDataProvider.java @@ -0,0 +1,9 @@ +package dji.v5.ux.core.base.charts.provider; + +import dji.v5.ux.core.base.charts.model.ColumnChartData; + +public interface ColumnChartDataProvider { + ColumnChartData getColumnChartData(); + + void setColumnChartData(ColumnChartData var1); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/provider/ComboLineColumnChartDataProvider.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/provider/ComboLineColumnChartDataProvider.java new file mode 100644 index 00000000..c39eae8c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/provider/ComboLineColumnChartDataProvider.java @@ -0,0 +1,9 @@ +package dji.v5.ux.core.base.charts.provider; + +import dji.v5.ux.core.base.charts.model.ComboLineColumnChartData; + +public interface ComboLineColumnChartDataProvider { + ComboLineColumnChartData getComboLineColumnChartData(); + + void setComboLineColumnChartData(ComboLineColumnChartData var1); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/provider/LineChartDataProvider.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/provider/LineChartDataProvider.java new file mode 100644 index 00000000..f753bb3a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/provider/LineChartDataProvider.java @@ -0,0 +1,9 @@ +package dji.v5.ux.core.base.charts.provider; + +import dji.v5.ux.core.base.charts.model.LineChartData; + +public interface LineChartDataProvider { + LineChartData getLineChartData(); + + void setLineChartData(LineChartData var1); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/provider/PieChartDataProvider.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/provider/PieChartDataProvider.java new file mode 100644 index 00000000..17246a33 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/provider/PieChartDataProvider.java @@ -0,0 +1,9 @@ +package dji.v5.ux.core.base.charts.provider; + +import dji.v5.ux.core.base.charts.model.PieChartData; + +public interface PieChartDataProvider { + PieChartData getPieChartData(); + + void setPieChartData(PieChartData var1); +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/AbstractChartRenderer.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/AbstractChartRenderer.java new file mode 100644 index 00000000..0236051f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/AbstractChartRenderer.java @@ -0,0 +1,135 @@ +package dji.v5.ux.core.base.charts.renderer; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Typeface; + +import dji.v5.ux.core.base.charts.computator.ChartComputator; +import dji.v5.ux.core.base.charts.model.ChartData; +import dji.v5.ux.core.base.charts.model.SelectedValue; +import dji.v5.ux.core.base.charts.model.Viewport; +import dji.v5.ux.core.base.charts.util.ChartUtils; +import dji.v5.ux.core.base.charts.view.Chart; + +public abstract class AbstractChartRenderer implements ChartRenderer { + public int DEFAULT_LABEL_MARGIN_DP = 4; + protected Chart chart; + protected ChartComputator computator; + protected Paint labelPaint = new Paint(); + protected Paint labelBackgroundPaint = new Paint(); + protected RectF labelBackgroundRect = new RectF(); + protected Paint.FontMetricsInt fontMetrics = new Paint.FontMetricsInt(); + protected boolean isViewportCalculationEnabled = true; + protected float density; + protected float scaledDensity; + protected SelectedValue selectedValue = new SelectedValue(); + protected char[] labelBuffer = new char[64]; + protected int labelOffset; + protected int labelMargin; + protected boolean isValueLabelBackgroundEnabled; + protected boolean isValueLabelBackgroundAuto; + + protected AbstractChartRenderer(Context context, Chart chart) { + this.density = context.getResources().getDisplayMetrics().density; + this.scaledDensity = context.getResources().getDisplayMetrics().scaledDensity; + this.chart = chart; + this.computator = chart.getChartComputator(); + this.labelMargin = ChartUtils.dp2px(this.density, this.DEFAULT_LABEL_MARGIN_DP); + this.labelOffset = this.labelMargin; + this.labelPaint.setAntiAlias(true); + this.labelPaint.setStyle(Paint.Style.FILL); + this.labelPaint.setTextAlign(Paint.Align.LEFT); + this.labelPaint.setTypeface(Typeface.defaultFromStyle(Typeface.BOLD)); + this.labelPaint.setColor(-1); + this.labelBackgroundPaint.setAntiAlias(true); + this.labelBackgroundPaint.setStyle(Paint.Style.FILL); + } + + public void resetRenderer() { + this.computator = this.chart.getChartComputator(); + } + + public void onChartDataChanged() { + ChartData data = this.chart.getChartData(); + Typeface typeface = this.chart.getChartData().getValueLabelTypeface(); + if (null != typeface) { + this.labelPaint.setTypeface(typeface); + } + + this.labelPaint.setColor(data.getValueLabelTextColor()); + this.labelPaint.setTextSize((float)ChartUtils.sp2px(this.scaledDensity, data.getValueLabelTextSize())); + this.labelPaint.getFontMetricsInt(this.fontMetrics); + this.isValueLabelBackgroundEnabled = data.isValueLabelBackgroundEnabled(); + this.isValueLabelBackgroundAuto = data.isValueLabelBackgroundAuto(); + this.labelBackgroundPaint.setColor(data.getValueLabelBackgroundColor()); + this.selectedValue.clear(); + } + + protected void drawLabelTextAndBackground(Canvas canvas, char[] labelBuffer, int startIndex, int numChars, int autoBackgroundColor) { + float textX; + float textY; + if (this.isValueLabelBackgroundEnabled) { + if (this.isValueLabelBackgroundAuto) { + this.labelBackgroundPaint.setColor(autoBackgroundColor); + } + + canvas.drawRect(this.labelBackgroundRect, this.labelBackgroundPaint); + textX = this.labelBackgroundRect.left + (float)this.labelMargin; + textY = this.labelBackgroundRect.bottom - (float)this.labelMargin; + } else { + textX = this.labelBackgroundRect.left; + textY = this.labelBackgroundRect.bottom; + } + + canvas.drawText(labelBuffer, startIndex, numChars, textX, textY, this.labelPaint); + } + + public boolean isTouched() { + return this.selectedValue.isSet(); + } + + public void clearTouch() { + this.selectedValue.clear(); + } + + public Viewport getMaximumViewport() { + return this.computator.getMaximumViewport(); + } + + public void setMaximumViewport(Viewport maxViewport) { + if (null != maxViewport) { + this.computator.setMaxViewport(maxViewport); + } + + } + + public Viewport getCurrentViewport() { + return this.computator.getCurrentViewport(); + } + + public void setCurrentViewport(Viewport viewport) { + if (null != viewport) { + this.computator.setCurrentViewport(viewport); + } + + } + + public boolean isViewportCalculationEnabled() { + return this.isViewportCalculationEnabled; + } + + public void setViewportCalculationEnabled(boolean isEnabled) { + this.isViewportCalculationEnabled = isEnabled; + } + + public void selectValue(SelectedValue selectedValue) { + this.selectedValue.set(selectedValue); + } + + public SelectedValue getSelectedValue() { + return this.selectedValue; + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/AxesRenderer.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/AxesRenderer.java new file mode 100644 index 00000000..07c1650c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/AxesRenderer.java @@ -0,0 +1,591 @@ +package dji.v5.ux.core.base.charts.renderer; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.Typeface; +import android.text.TextUtils; + +import java.util.Iterator; + +import dji.v5.ux.core.base.charts.computator.ChartComputator; +import dji.v5.ux.core.base.charts.model.Axis; +import dji.v5.ux.core.base.charts.model.AxisValue; +import dji.v5.ux.core.base.charts.model.Viewport; +import dji.v5.ux.core.base.charts.util.AxisAutoValues; +import dji.v5.ux.core.base.charts.util.ChartUtils; +import dji.v5.ux.core.base.charts.util.FloatUtils; +import dji.v5.ux.core.base.charts.view.Chart; + +public class AxesRenderer { + private static final char[] labelWidthChars = new char[]{'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0'}; + private Chart chart; + private ChartComputator computator; + private int axisMargin; + private float density; + private float scaledDensity; + private Paint[] labelPaintTab = new Paint[]{new Paint(), new Paint(), new Paint(), new Paint()}; + private Paint[] namePaintTab = new Paint[]{new Paint(), new Paint(), new Paint(), new Paint()}; + private Paint[] linePaintTab = new Paint[]{new Paint(), new Paint(), new Paint(), new Paint()}; + private float[] nameBaselineTab = new float[4]; + private float[] labelBaselineTab = new float[4]; + private float[] separationLineTab = new float[4]; + private int[] labelWidthTab = new int[4]; + private int[] labelTextAscentTab = new int[4]; + private int[] labelTextDescentTab = new int[4]; + private int[] labelDimensionForMarginsTab = new int[4]; + private int[] labelDimensionForStepsTab = new int[4]; + private int[] tiltedLabelXTranslation = new int[4]; + private int[] tiltedLabelYTranslation = new int[4]; + private Paint.FontMetricsInt[] fontMetricsTab = new Paint.FontMetricsInt[]{new Paint.FontMetricsInt(), new Paint.FontMetricsInt(), new Paint.FontMetricsInt(), new Paint.FontMetricsInt()}; + private char[] labelBuffer = new char[64]; + private int[] valuesToDrawNumTab = new int[4]; + private float[][] rawValuesTab = new float[4][0]; + private float[][] autoValuesToDrawTab = new float[4][0]; + private AxisValue[][] valuesToDrawTab = new AxisValue[4][0]; + private float[][] linesDrawBufferTab = new float[4][0]; + private AxisAutoValues[] autoValuesBufferTab = new AxisAutoValues[]{new AxisAutoValues(), new AxisAutoValues(), new AxisAutoValues(), new AxisAutoValues()}; + + public AxesRenderer(Context context, Chart chart) { + this.chart = chart; + this.computator = chart.getChartComputator(); + this.density = context.getResources().getDisplayMetrics().density; + this.scaledDensity = context.getResources().getDisplayMetrics().scaledDensity; + this.axisMargin = ChartUtils.dp2px(this.density, 2); + + for(int position = 0; position < 4; ++position) { + this.labelPaintTab[position].setStyle(Paint.Style.FILL); + this.labelPaintTab[position].setAntiAlias(true); + this.namePaintTab[position].setStyle(Paint.Style.FILL); + this.namePaintTab[position].setAntiAlias(true); + this.linePaintTab[position].setStyle(Paint.Style.STROKE); + this.linePaintTab[position].setAntiAlias(true); + } + + } + + public void onChartSizeChanged() { + this.onChartDataOrSizeChanged(); + } + + public void onChartDataChanged() { + this.onChartDataOrSizeChanged(); + } + + private void onChartDataOrSizeChanged() { + this.initAxis(this.chart.getChartData().getAxisXTop(), 0); + this.initAxis(this.chart.getChartData().getAxisXBottom(), 3); + this.initAxis(this.chart.getChartData().getAxisYLeft(), 1); + this.initAxis(this.chart.getChartData().getAxisYRight(), 2); + } + + public void resetRenderer() { + this.computator = this.chart.getChartComputator(); + } + + private void initAxis(Axis axis, int position) { + if (null != axis) { + this.initAxisAttributes(axis, position); + this.initAxisMargin(axis, position); + this.initAxisMeasurements(axis, position); + } + } + + private void initAxisAttributes(Axis axis, int position) { + this.initAxisPaints(axis, position); + this.initAxisTextAlignment(axis, position); + if (axis.hasTiltedLabels()) { + this.initAxisDimensionForTiltedLabels(position); + this.intiTiltedLabelsTranslation(axis, position); + } else { + this.initAxisDimension(position); + } + + } + + private void initAxisPaints(Axis axis, int position) { + Typeface typeface = axis.getTypeface(); + if (null != typeface) { + this.labelPaintTab[position].setTypeface(typeface); + this.namePaintTab[position].setTypeface(typeface); + } + + this.labelPaintTab[position].setColor(axis.getTextColor()); + this.labelPaintTab[position].setTextSize((float)ChartUtils.sp2px(this.scaledDensity, axis.getTextSize())); + this.labelPaintTab[position].getFontMetricsInt(this.fontMetricsTab[position]); + this.namePaintTab[position].setColor(axis.getTextColor()); + this.namePaintTab[position].setTextSize((float)ChartUtils.sp2px(this.scaledDensity, axis.getTextSize())); + this.linePaintTab[position].setColor(axis.getLineColor()); + this.labelTextAscentTab[position] = Math.abs(this.fontMetricsTab[position].ascent); + this.labelTextDescentTab[position] = Math.abs(this.fontMetricsTab[position].descent); + this.labelWidthTab[position] = (int)this.labelPaintTab[position].measureText(labelWidthChars, 0, axis.getMaxLabelChars()); + } + + private void initAxisTextAlignment(Axis axis, int position) { + this.namePaintTab[position].setTextAlign(Paint.Align.CENTER); + if (0 != position && 3 != position) { + if (1 == position) { + if (axis.isInside()) { + this.labelPaintTab[position].setTextAlign(Paint.Align.LEFT); + } else { + this.labelPaintTab[position].setTextAlign(Paint.Align.RIGHT); + } + } else if (2 == position) { + if (axis.isInside()) { + this.labelPaintTab[position].setTextAlign(Paint.Align.RIGHT); + } else { + this.labelPaintTab[position].setTextAlign(Paint.Align.LEFT); + } + } + } else { + this.labelPaintTab[position].setTextAlign(Paint.Align.CENTER); + } + + } + + private void initAxisDimensionForTiltedLabels(int position) { + int pythagoreanFromLabelWidth = (int)Math.sqrt(Math.pow((double)this.labelWidthTab[position], 2.0) / 2.0); + int pythagoreanFromAscent = (int)Math.sqrt(Math.pow((double)this.labelTextAscentTab[position], 2.0) / 2.0); + this.labelDimensionForMarginsTab[position] = pythagoreanFromAscent + pythagoreanFromLabelWidth; + this.labelDimensionForStepsTab[position] = Math.round((float)this.labelDimensionForMarginsTab[position] * 0.75F); + } + + private void initAxisDimension(int position) { + if (1 != position && 2 != position) { + if (0 == position || 3 == position) { + this.labelDimensionForMarginsTab[position] = this.labelTextAscentTab[position] + this.labelTextDescentTab[position]; + this.labelDimensionForStepsTab[position] = this.labelWidthTab[position]; + } + } else { + this.labelDimensionForMarginsTab[position] = this.labelWidthTab[position]; + this.labelDimensionForStepsTab[position] = this.labelTextAscentTab[position]; + } + + } + + private void intiTiltedLabelsTranslation(Axis axis, int position) { + int pythagoreanFromLabelWidth = (int)Math.sqrt(Math.pow((double)this.labelWidthTab[position], 2.0) / 2.0); + int pythagoreanFromAscent = (int)Math.sqrt(Math.pow((double)this.labelTextAscentTab[position], 2.0) / 2.0); + int dx = 0; + int dy = 0; + if (axis.isInside()) { + if (1 == position) { + dx = pythagoreanFromAscent; + } else if (2 == position) { + dy = -pythagoreanFromLabelWidth / 2; + } else if (0 == position) { + dy = pythagoreanFromAscent + pythagoreanFromLabelWidth / 2 - this.labelTextAscentTab[position]; + } else if (3 == position) { + dy = -pythagoreanFromLabelWidth / 2; + } + } else if (1 == position) { + dy = -pythagoreanFromLabelWidth / 2; + } else if (2 == position) { + dx = pythagoreanFromAscent; + } else if (0 == position) { + dy = -pythagoreanFromLabelWidth / 2; + } else if (3 == position) { + dy = pythagoreanFromAscent + pythagoreanFromLabelWidth / 2 - this.labelTextAscentTab[position]; + } + + this.tiltedLabelXTranslation[position] = dx; + this.tiltedLabelYTranslation[position] = dy; + } + + private void initAxisMargin(Axis axis, int position) { + int margin = 0; + if (!axis.isInside() && (axis.isAutoGenerated() || !axis.getValues().isEmpty())) { + margin += this.axisMargin + this.labelDimensionForMarginsTab[position]; + } + + margin += this.getAxisNameMargin(axis, position); + this.insetContentRectWithAxesMargins(margin, position); + } + + private int getAxisNameMargin(Axis axis, int position) { + int margin = 0; + if (!TextUtils.isEmpty(axis.getName())) { + margin += this.labelTextAscentTab[position]; + margin += this.labelTextDescentTab[position]; + margin += this.axisMargin; + } + + return margin; + } + + private void insetContentRectWithAxesMargins(int axisMargin, int position) { + if (1 == position) { + this.chart.getChartComputator().insetContentRect(axisMargin, 0, 0, 0); + } else if (2 == position) { + this.chart.getChartComputator().insetContentRect(0, 0, axisMargin, 0); + } else if (0 == position) { + this.chart.getChartComputator().insetContentRect(0, axisMargin, 0, 0); + } else if (3 == position) { + this.chart.getChartComputator().insetContentRect(0, 0, 0, axisMargin); + } + + } + + private void initAxisMeasurements(Axis axis, int position) { + if (1 == position) { + if (axis.isInside()) { + this.labelBaselineTab[position] = (float)(this.computator.getContentRectMinusAllMargins().left + this.axisMargin); + this.nameBaselineTab[position] = (float)(this.computator.getContentRectMinusAxesMargins().left - this.axisMargin - this.labelTextDescentTab[position]); + } else { + this.labelBaselineTab[position] = (float)(this.computator.getContentRectMinusAxesMargins().left - this.axisMargin); + this.nameBaselineTab[position] = this.labelBaselineTab[position] - (float)this.axisMargin - (float)this.labelTextDescentTab[position] - (float)this.labelDimensionForMarginsTab[position]; + } + + this.separationLineTab[position] = (float)this.computator.getContentRectMinusAllMargins().left; + } else if (2 == position) { + if (axis.isInside()) { + this.labelBaselineTab[position] = (float)(this.computator.getContentRectMinusAllMargins().right - this.axisMargin); + this.nameBaselineTab[position] = (float)(this.computator.getContentRectMinusAxesMargins().right + this.axisMargin + this.labelTextAscentTab[position]); + } else { + this.labelBaselineTab[position] = (float)(this.computator.getContentRectMinusAxesMargins().right + this.axisMargin); + this.nameBaselineTab[position] = this.labelBaselineTab[position] + (float)this.axisMargin + (float)this.labelTextAscentTab[position] + (float)this.labelDimensionForMarginsTab[position]; + } + + this.separationLineTab[position] = (float)this.computator.getContentRectMinusAllMargins().right; + } else if (3 == position) { + if (axis.isInside()) { + this.labelBaselineTab[position] = (float)(this.computator.getContentRectMinusAllMargins().bottom - this.axisMargin - this.labelTextDescentTab[position]); + this.nameBaselineTab[position] = (float)(this.computator.getContentRectMinusAxesMargins().bottom + this.axisMargin + this.labelTextAscentTab[position]); + } else { + this.labelBaselineTab[position] = (float)(this.computator.getContentRectMinusAxesMargins().bottom + this.axisMargin + this.labelTextAscentTab[position]); + this.nameBaselineTab[position] = this.labelBaselineTab[position] + (float)this.axisMargin + (float)this.labelDimensionForMarginsTab[position]; + } + + this.separationLineTab[position] = (float)this.computator.getContentRectMinusAllMargins().bottom; + } else { + if (0 != position) { + throw new IllegalArgumentException("Invalid axis position: " + position); + } + + if (axis.isInside()) { + this.labelBaselineTab[position] = (float)(this.computator.getContentRectMinusAllMargins().top + this.axisMargin + this.labelTextAscentTab[position]); + this.nameBaselineTab[position] = (float)(this.computator.getContentRectMinusAxesMargins().top - this.axisMargin - this.labelTextDescentTab[position]); + } else { + this.labelBaselineTab[position] = (float)(this.computator.getContentRectMinusAxesMargins().top - this.axisMargin - this.labelTextDescentTab[position]); + this.nameBaselineTab[position] = this.labelBaselineTab[position] - (float)this.axisMargin - (float)this.labelDimensionForMarginsTab[position]; + } + + this.separationLineTab[position] = (float)this.computator.getContentRectMinusAllMargins().top; + } + + } + + public void drawInBackground(Canvas canvas) { + Axis axis = this.chart.getChartData().getAxisYLeft(); + if (null != axis) { + this.prepareAxisToDraw(axis, 1); + this.drawAxisLines(canvas, axis, 1); + } + + axis = this.chart.getChartData().getAxisYRight(); + if (null != axis) { + this.prepareAxisToDraw(axis, 2); + this.drawAxisLines(canvas, axis, 2); + } + + axis = this.chart.getChartData().getAxisXBottom(); + if (null != axis) { + this.prepareAxisToDraw(axis, 3); + this.drawAxisLines(canvas, axis, 3); + } + + axis = this.chart.getChartData().getAxisXTop(); + if (null != axis) { + this.prepareAxisToDraw(axis, 0); + this.drawAxisLines(canvas, axis, 0); + } + + } + + private void prepareAxisToDraw(Axis axis, int position) { + if (axis.isAutoGenerated()) { + this.prepareAutoGeneratedAxis(axis, position); + } else { + this.prepareCustomAxis(axis, position); + } + + } + + public void drawInForeground(Canvas canvas) { + Axis axis = this.chart.getChartData().getAxisYLeft(); + if (null != axis) { + this.drawAxisLabelsAndName(canvas, axis, 1); + } + + axis = this.chart.getChartData().getAxisYRight(); + if (null != axis) { + this.drawAxisLabelsAndName(canvas, axis, 2); + } + + axis = this.chart.getChartData().getAxisXBottom(); + if (null != axis) { + this.drawAxisLabelsAndName(canvas, axis, 3); + } + + axis = this.chart.getChartData().getAxisXTop(); + if (null != axis) { + this.drawAxisLabelsAndName(canvas, axis, 0); + } + + } + + private void prepareCustomAxis(Axis axis, int position) { + Viewport maxViewport = this.computator.getMaximumViewport(); + Viewport visibleViewport = this.computator.getVisibleViewport(); + Rect contentRect = this.computator.getContentRectMinusAllMargins(); + boolean isAxisVertical = this.isAxisVertical(position); + float scale = 1.0F; + float viewportMin; + float viewportMax; + if (isAxisVertical) { + if (maxViewport.height() > 0.0F && visibleViewport.height() > 0.0F) { + scale = (float)contentRect.height() * (maxViewport.height() / visibleViewport.height()); + } + + viewportMin = visibleViewport.bottom; + viewportMax = visibleViewport.top; + } else { + if (maxViewport.width() > 0.0F && visibleViewport.width() > 0.0F) { + scale = (float)contentRect.width() * (maxViewport.width() / visibleViewport.width()); + } + + viewportMin = visibleViewport.left; + viewportMax = visibleViewport.right; + } + + if (scale == 0.0F) { + scale = 1.0F; + } + + int module = (int)Math.max(1.0, Math.ceil((double)(axis.getValues().size() * this.labelDimensionForStepsTab[position]) * 1.5 / (double)scale)); + if (axis.hasLines() && this.linesDrawBufferTab[position].length < axis.getValues().size() * 4) { + this.linesDrawBufferTab[position] = new float[axis.getValues().size() * 4]; + } + + if (this.rawValuesTab[position].length < axis.getValues().size()) { + this.rawValuesTab[position] = new float[axis.getValues().size()]; + } + + if (this.valuesToDrawTab[position].length < axis.getValues().size()) { + this.valuesToDrawTab[position] = new AxisValue[axis.getValues().size()]; + } + + int valueIndex = 0; + int valueToDrawIndex = 0; + Iterator var14 = axis.getValues().iterator(); + + while(var14.hasNext()) { + AxisValue axisValue = (AxisValue)var14.next(); + float value = axisValue.getValue(); + if (value >= viewportMin && value <= viewportMax) { + if (0 == valueIndex % module) { + float rawValue; + if (isAxisVertical) { + rawValue = this.computator.computeRawY(value); + } else { + rawValue = this.computator.computeRawX(value); + } + + if (this.checkRawValue(contentRect, rawValue, axis.isInside(), position, isAxisVertical)) { + this.rawValuesTab[position][valueToDrawIndex] = rawValue; + this.valuesToDrawTab[position][valueToDrawIndex] = axisValue; + ++valueToDrawIndex; + } + } + + ++valueIndex; + } + } + + this.valuesToDrawNumTab[position] = valueToDrawIndex; + } + + private void prepareAutoGeneratedAxis(Axis axis, int position) { + Viewport visibleViewport = this.computator.getVisibleViewport(); + Rect contentRect = this.computator.getContentRectMinusAllMargins(); + boolean isAxisVertical = this.isAxisVertical(position); + float start; + float stop; + int contentRectDimension; + if (isAxisVertical) { + start = visibleViewport.bottom; + stop = visibleViewport.top; + contentRectDimension = contentRect.height(); + } else { + start = visibleViewport.left; + stop = visibleViewport.right; + contentRectDimension = contentRect.width(); + } + + FloatUtils.computeAutoGeneratedAxisValues(start, stop, Math.abs(contentRectDimension) / this.labelDimensionForStepsTab[position] / 2, this.autoValuesBufferTab[position]); + if (axis.hasLines() && this.linesDrawBufferTab[position].length < this.autoValuesBufferTab[position].valuesNumber * 4) { + this.linesDrawBufferTab[position] = new float[this.autoValuesBufferTab[position].valuesNumber * 4]; + } + + if (this.rawValuesTab[position].length < this.autoValuesBufferTab[position].valuesNumber) { + this.rawValuesTab[position] = new float[this.autoValuesBufferTab[position].valuesNumber]; + } + + if (this.autoValuesToDrawTab[position].length < this.autoValuesBufferTab[position].valuesNumber) { + this.autoValuesToDrawTab[position] = new float[this.autoValuesBufferTab[position].valuesNumber]; + } + + int valueToDrawIndex = 0; + + for(int i = 0; i < this.autoValuesBufferTab[position].valuesNumber; ++i) { + float rawValue; + if (isAxisVertical) { + rawValue = this.computator.computeRawY(this.autoValuesBufferTab[position].values[i]); + } else { + rawValue = this.computator.computeRawX(this.autoValuesBufferTab[position].values[i]); + } + + if (this.checkRawValue(contentRect, rawValue, axis.isInside(), position, isAxisVertical)) { + this.rawValuesTab[position][valueToDrawIndex] = rawValue; + this.autoValuesToDrawTab[position][valueToDrawIndex] = this.autoValuesBufferTab[position].values[i]; + ++valueToDrawIndex; + } + } + + this.valuesToDrawNumTab[position] = valueToDrawIndex; + } + + private boolean checkRawValue(Rect rect, float rawValue, boolean axisInside, int position, boolean isVertical) { + if (axisInside) { + float margin; + if (isVertical) { + margin = (float)(this.labelTextAscentTab[3] + this.axisMargin); + float marginTop = (float)(this.labelTextAscentTab[0] + this.axisMargin); + return rawValue <= (float)rect.bottom - margin && rawValue >= (float)rect.top + marginTop; + } else { + margin = (float)((double)this.labelWidthTab[position] / 2); + return rawValue >= (float)rect.left + margin && rawValue <= (float)rect.right - margin; + } + } else { + return true; + } + } + + private void drawAxisLines(Canvas canvas, Axis axis, int position) { + Rect contentRectMargins = this.computator.getContentRectMinusAxesMargins(); + float separationY2 = 0.0F; + float separationX2 = 0.0F; + float separationY1 = 0.0F; + float separationX1 = 0.0F; + float lineY2 = 0.0F; + float lineX2 = 0.0F; + float lineY1 = 0.0F; + float lineX1 = 0.0F; + boolean isAxisVertical = this.isAxisVertical(position); + if (1 != position && 2 != position) { + if (0 == position || 3 == position) { + separationX1 = (float)contentRectMargins.left; + separationX2 = (float)contentRectMargins.right; + separationY1 = separationY2 = this.separationLineTab[position]; + lineY1 = (float)contentRectMargins.top; + lineY2 = (float)contentRectMargins.bottom; + } + } else { + separationX1 = separationX2 = this.separationLineTab[position]; + separationY1 = (float)contentRectMargins.bottom; + separationY2 = (float)contentRectMargins.top; + lineX1 = (float)contentRectMargins.left; + lineX2 = (float)contentRectMargins.right; + } + + if (axis.hasSeparationLine()) { + canvas.drawLine(separationX1, separationY1, separationX2, separationY2, this.labelPaintTab[position]); + } + + if (axis.hasLines()) { + int valueToDrawIndex; + for(valueToDrawIndex = 0; valueToDrawIndex < this.valuesToDrawNumTab[position]; ++valueToDrawIndex) { + if (isAxisVertical) { + lineY1 = lineY2 = this.rawValuesTab[position][valueToDrawIndex]; + } else { + lineX1 = lineX2 = this.rawValuesTab[position][valueToDrawIndex]; + } + + this.linesDrawBufferTab[position][valueToDrawIndex * 4 + 0] = lineX1; + this.linesDrawBufferTab[position][valueToDrawIndex * 4 + 1] = lineY1; + this.linesDrawBufferTab[position][valueToDrawIndex * 4 + 2] = lineX2; + this.linesDrawBufferTab[position][valueToDrawIndex * 4 + 3] = lineY2; + } + + canvas.drawLines(this.linesDrawBufferTab[position], 0, valueToDrawIndex * 4, this.linePaintTab[position]); + } + + } + + private void drawAxisLabelsAndName(Canvas canvas, Axis axis, int position) { + float labelY = 0.0F; + float labelX = 0.0F; + boolean isAxisVertical = this.isAxisVertical(position); + if (1 != position && 2 != position) { + if (0 == position || 3 == position) { + labelY = this.labelBaselineTab[position]; + } + } else { + labelX = this.labelBaselineTab[position]; + } + + for(int valueToDrawIndex = 0; valueToDrawIndex < this.valuesToDrawNumTab[position]; ++valueToDrawIndex) { + int charsNumber = 0; + if (axis.isAutoGenerated()) { + float value = this.autoValuesToDrawTab[position][valueToDrawIndex]; + charsNumber = axis.getFormatter().formatValueForAutoGeneratedAxis(this.labelBuffer, value, this.autoValuesBufferTab[position].decimals); + } else { + AxisValue axisValue = this.valuesToDrawTab[position][valueToDrawIndex]; + charsNumber = axis.getFormatter().formatValueForManualAxis(this.labelBuffer, axisValue); + } + + if (isAxisVertical) { + labelY = this.rawValuesTab[position][valueToDrawIndex]; + } else { + labelX = this.rawValuesTab[position][valueToDrawIndex]; + } + + if (axis.hasTiltedLabels()) { + canvas.save(); + canvas.translate((float)this.tiltedLabelXTranslation[position], (float)this.tiltedLabelYTranslation[position]); + canvas.rotate(-45.0F, labelX, labelY); + canvas.drawText(this.labelBuffer, this.labelBuffer.length - charsNumber, charsNumber, labelX, labelY, this.labelPaintTab[position]); + canvas.restore(); + } else { + canvas.drawText(this.labelBuffer, this.labelBuffer.length - charsNumber, charsNumber, labelX, labelY, this.labelPaintTab[position]); + } + } + + Rect contentRectMargins = this.computator.getContentRectMinusAxesMargins(); + if (!TextUtils.isEmpty(axis.getName())) { + if (isAxisVertical) { + canvas.save(); + canvas.rotate(-90.0F, (float)contentRectMargins.centerY(), (float)contentRectMargins.centerY()); + canvas.drawText(axis.getName(), (float)contentRectMargins.centerY(), this.nameBaselineTab[position], this.namePaintTab[position]); + canvas.restore(); + } else { + canvas.drawText(axis.getName(), (float)contentRectMargins.centerX(), this.nameBaselineTab[position], this.namePaintTab[position]); + } + } + + } + + private boolean isAxisVertical(int position) { + if (1 != position && 2 != position) { + if (0 != position && 3 != position) { + throw new IllegalArgumentException("Invalid axis position " + position); + } else { + return false; + } + } else { + return true; + } + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/BubbleChartRenderer.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/BubbleChartRenderer.java new file mode 100644 index 00000000..d9ea5a95 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/BubbleChartRenderer.java @@ -0,0 +1,306 @@ +package dji.v5.ux.core.base.charts.renderer; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PointF; +import android.graphics.Rect; +import android.graphics.RectF; + +import java.util.Iterator; + +import dji.v5.ux.core.base.charts.computator.ChartComputator; +import dji.v5.ux.core.base.charts.formatter.BubbleChartValueFormatter; +import dji.v5.ux.core.base.charts.model.BubbleChartData; +import dji.v5.ux.core.base.charts.model.BubbleValue; +import dji.v5.ux.core.base.charts.model.SelectedValue; +import dji.v5.ux.core.base.charts.model.ValueShape; +import dji.v5.ux.core.base.charts.model.Viewport; +import dji.v5.ux.core.base.charts.provider.BubbleChartDataProvider; +import dji.v5.ux.core.base.charts.util.ChartUtils; +import dji.v5.ux.core.base.charts.view.Chart; + +public class BubbleChartRenderer extends AbstractChartRenderer { + private BubbleChartDataProvider dataProvider; + private int touchAdditional; + private float bubbleScaleX; + private float bubbleScaleY; + private boolean isBubbleScaledByX = true; + private float maxRadius; + private float minRawRadius; + private PointF bubbleCenter = new PointF(); + private Paint bubblePaint = new Paint(); + private RectF bubbleRect = new RectF(); + private boolean hasLabels; + private boolean hasLabelsOnlyForSelected; + private BubbleChartValueFormatter valueFormatter; + private Viewport tempMaximumViewport = new Viewport(); + + public BubbleChartRenderer(Context context, Chart chart, BubbleChartDataProvider dataProvider) { + super(context, chart); + this.dataProvider = dataProvider; + this.touchAdditional = ChartUtils.dp2px(this.density, 4); + this.bubblePaint.setAntiAlias(true); + this.bubblePaint.setStyle(Paint.Style.FILL); + } + + public void onChartSizeChanged() { + ChartComputator computator = this.chart.getChartComputator(); + Rect contentRect = computator.getContentRectMinusAllMargins(); + if (contentRect.width() < contentRect.height()) { + this.isBubbleScaledByX = true; + } else { + this.isBubbleScaledByX = false; + } + + } + + @Override + public void onChartDataChanged() { + super.onChartDataChanged(); + BubbleChartData data = this.dataProvider.getBubbleChartData(); + this.hasLabels = data.hasLabels(); + this.hasLabelsOnlyForSelected = data.hasLabelsOnlyForSelected(); + this.valueFormatter = data.getFormatter(); + this.onChartViewportChanged(); + } + + public void onChartViewportChanged() { + if (this.isViewportCalculationEnabled) { + this.calculateMaxViewport(); + this.computator.setMaxViewport(this.tempMaximumViewport); + this.computator.setCurrentViewport(this.computator.getMaximumViewport()); + } + + } + + public void draw(Canvas canvas) { + this.drawBubbles(canvas); + if (this.isTouched()) { + this.highlightBubbles(canvas); + } + + } + + public void drawUnclipped(Canvas canvas) { + //do nothing + } + + public boolean checkTouch(float touchX, float touchY) { + this.selectedValue.clear(); + BubbleChartData data = this.dataProvider.getBubbleChartData(); + int valueIndex = 0; + + for(Iterator var5 = data.getValues().iterator(); var5.hasNext(); ++valueIndex) { + BubbleValue bubbleValue = (BubbleValue)var5.next(); + float rawRadius = this.processBubble(bubbleValue); + if (ValueShape.SQUARE.equals(bubbleValue.getShape())) { + if (this.bubbleRect.contains(touchX, touchY)) { + this.selectedValue.set(valueIndex, valueIndex, SelectedValue.SelectedValueType.NONE); + } + } else { + if (!ValueShape.CIRCLE.equals(bubbleValue.getShape())) { + throw new IllegalArgumentException("Invalid bubble shape: " + bubbleValue.getShape()); + } + + float diffX = touchX - this.bubbleCenter.x; + float diffY = touchY - this.bubbleCenter.y; + float touchDistance = (float)Math.sqrt((diffX * diffX + diffY * diffY)); + if (touchDistance <= rawRadius) { + this.selectedValue.set(valueIndex, valueIndex, SelectedValue.SelectedValueType.NONE); + } + } + } + + return this.isTouched(); + } + + public void removeMargins() { + Rect contentRect = this.computator.getContentRectMinusAllMargins(); + if (contentRect.height() != 0 && contentRect.width() != 0) { + float pxX = this.computator.computeRawDistanceX(this.maxRadius * this.bubbleScaleX); + float pxY = this.computator.computeRawDistanceY(this.maxRadius * this.bubbleScaleY); + float scaleX = this.computator.getMaximumViewport().width() / (float)contentRect.width(); + float scaleY = this.computator.getMaximumViewport().height() / (float)contentRect.height(); + float dx = 0.0F; + float dy = 0.0F; + if (this.isBubbleScaledByX) { + dy = (pxY - pxX) * scaleY * 0.75F; + } else { + dx = (pxX - pxY) * scaleX * 0.75F; + } + + Viewport maxViewport = this.computator.getMaximumViewport(); + maxViewport.inset(dx, dy); + Viewport currentViewport = this.computator.getCurrentViewport(); + currentViewport.inset(dx, dy); + this.computator.setMaxViewport(maxViewport); + this.computator.setCurrentViewport(currentViewport); + } + } + + private void drawBubbles(Canvas canvas) { + BubbleChartData data = this.dataProvider.getBubbleChartData(); + Iterator var3 = data.getValues().iterator(); + + while(var3.hasNext()) { + BubbleValue bubbleValue = (BubbleValue)var3.next(); + this.drawBubble(canvas, bubbleValue); + } + + } + + private void drawBubble(Canvas canvas, BubbleValue bubbleValue) { + float rawRadius = this.processBubble(bubbleValue); + rawRadius -= (float)this.touchAdditional; + this.bubbleRect.inset((float)this.touchAdditional, (float)this.touchAdditional); + this.bubblePaint.setColor(bubbleValue.getColor()); + this.drawBubbleShapeAndLabel(canvas, bubbleValue, rawRadius, 0); + } + + private void drawBubbleShapeAndLabel(Canvas canvas, BubbleValue bubbleValue, float rawRadius, int mode) { + if (ValueShape.SQUARE.equals(bubbleValue.getShape())) { + canvas.drawRect(this.bubbleRect, this.bubblePaint); + } else { + if (!ValueShape.CIRCLE.equals(bubbleValue.getShape())) { + throw new IllegalArgumentException("Invalid bubble shape: " + bubbleValue.getShape()); + } + + canvas.drawCircle(this.bubbleCenter.x, this.bubbleCenter.y, rawRadius, this.bubblePaint); + } + + if (1 == mode) { + if (this.hasLabels || this.hasLabelsOnlyForSelected) { + this.drawLabel(canvas, bubbleValue, this.bubbleCenter.x, this.bubbleCenter.y); + } + } else { + if (0 != mode) { + throw new IllegalStateException("Cannot process bubble in mode: " + mode); + } + + if (this.hasLabels) { + this.drawLabel(canvas, bubbleValue, this.bubbleCenter.x, this.bubbleCenter.y); + } + } + + } + + private void highlightBubbles(Canvas canvas) { + BubbleChartData data = this.dataProvider.getBubbleChartData(); + BubbleValue bubbleValue = (BubbleValue)data.getValues().get(this.selectedValue.getFirstIndex()); + this.highlightBubble(canvas, bubbleValue); + } + + private void highlightBubble(Canvas canvas, BubbleValue bubbleValue) { + float rawRadius = this.processBubble(bubbleValue); + this.bubblePaint.setColor(bubbleValue.getDarkenColor()); + this.drawBubbleShapeAndLabel(canvas, bubbleValue, rawRadius, 1); + } + + private float processBubble(BubbleValue bubbleValue) { + float rawX = this.computator.computeRawX(bubbleValue.getX()); + float rawY = this.computator.computeRawY(bubbleValue.getY()); + float radius = (float)Math.sqrt((double)Math.abs(bubbleValue.getZ()) / Math.PI); + float rawRadius; + if (this.isBubbleScaledByX) { + radius *= this.bubbleScaleX; + rawRadius = this.computator.computeRawDistanceX(radius); + } else { + radius *= this.bubbleScaleY; + rawRadius = this.computator.computeRawDistanceY(radius); + } + + if (rawRadius < this.minRawRadius + (float)this.touchAdditional) { + rawRadius = this.minRawRadius + (float)this.touchAdditional; + } + + this.bubbleCenter.set(rawX, rawY); + if (ValueShape.SQUARE.equals(bubbleValue.getShape())) { + this.bubbleRect.set(rawX - rawRadius, rawY - rawRadius, rawX + rawRadius, rawY + rawRadius); + } + + return rawRadius; + } + + private void drawLabel(Canvas canvas, BubbleValue bubbleValue, float rawX, float rawY) { + Rect contentRect = this.computator.getContentRectMinusAllMargins(); + int numChars = this.valueFormatter.formatChartValue(this.labelBuffer, bubbleValue); + if (numChars != 0) { + float labelWidth = this.labelPaint.measureText(this.labelBuffer, this.labelBuffer.length - numChars, numChars); + int labelHeight = Math.abs(this.fontMetrics.ascent); + float left = rawX - labelWidth / 2.0F - (float)this.labelMargin; + float right = rawX + labelWidth / 2.0F + (float)this.labelMargin; + float top = rawY - (float)((double)labelHeight / 2) - (float)this.labelMargin; + float bottom = rawY + (float)((double)labelHeight / 2) + (float)this.labelMargin; + if (top < (float)contentRect.top) { + top = rawY; + bottom = rawY + (float)labelHeight + (float)(this.labelMargin * 2); + } + + if (bottom > (float)contentRect.bottom) { + top = rawY - (float)labelHeight - (float)(this.labelMargin * 2); + bottom = rawY; + } + + if (left < (float)contentRect.left) { + left = rawX; + right = rawX + labelWidth + (float)(this.labelMargin * 2); + } + + if (right > (float)contentRect.right) { + left = rawX - labelWidth - (float)(this.labelMargin * 2); + right = rawX; + } + + this.labelBackgroundRect.set(left, top, right, bottom); + this.drawLabelTextAndBackground(canvas, this.labelBuffer, this.labelBuffer.length - numChars, numChars, bubbleValue.getDarkenColor()); + } + } + + private void calculateMaxViewport() { + float maxZ = Float.MIN_VALUE; + this.tempMaximumViewport.set(Float.MAX_VALUE, Float.MIN_VALUE, Float.MIN_VALUE, Float.MAX_VALUE); + BubbleChartData data = this.dataProvider.getBubbleChartData(); + Iterator var3 = data.getValues().iterator(); + + while(var3.hasNext()) { + BubbleValue bubbleValue = (BubbleValue)var3.next(); + if (Math.abs(bubbleValue.getZ()) > maxZ) { + maxZ = Math.abs(bubbleValue.getZ()); + } + + if (bubbleValue.getX() < this.tempMaximumViewport.left) { + this.tempMaximumViewport.left = bubbleValue.getX(); + } + + if (bubbleValue.getX() > this.tempMaximumViewport.right) { + this.tempMaximumViewport.right = bubbleValue.getX(); + } + + if (bubbleValue.getY() < this.tempMaximumViewport.bottom) { + this.tempMaximumViewport.bottom = bubbleValue.getY(); + } + + if (bubbleValue.getY() > this.tempMaximumViewport.top) { + this.tempMaximumViewport.top = bubbleValue.getY(); + } + } + + this.maxRadius = (float)Math.sqrt((double)maxZ / Math.PI); + this.bubbleScaleX = this.tempMaximumViewport.width() / (this.maxRadius * 4.0F); + if (this.bubbleScaleX == 0.0F) { + this.bubbleScaleX = 1.0F; + } + + this.bubbleScaleY = this.tempMaximumViewport.height() / (this.maxRadius * 4.0F); + if (this.bubbleScaleY == 0.0F) { + this.bubbleScaleY = 1.0F; + } + + this.bubbleScaleX *= data.getBubbleScale(); + this.bubbleScaleY *= data.getBubbleScale(); + this.tempMaximumViewport.inset(-this.maxRadius * this.bubbleScaleX, -this.maxRadius * this.bubbleScaleY); + this.minRawRadius = (float)ChartUtils.dp2px(this.density, this.dataProvider.getBubbleChartData().getMinBubbleRadius()); + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/ChartRenderer.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/ChartRenderer.java new file mode 100644 index 00000000..0f633295 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/ChartRenderer.java @@ -0,0 +1,43 @@ +package dji.v5.ux.core.base.charts.renderer; + +import android.graphics.Canvas; + +import dji.v5.ux.core.base.charts.model.SelectedValue; +import dji.v5.ux.core.base.charts.model.Viewport; + +public interface ChartRenderer { + void onChartSizeChanged(); + + void onChartDataChanged(); + + void onChartViewportChanged(); + + void resetRenderer(); + + void draw(Canvas var1); + + void drawUnclipped(Canvas var1); + + boolean checkTouch(float var1, float var2); + + boolean isTouched(); + + void clearTouch(); + + Viewport getMaximumViewport(); + + void setMaximumViewport(Viewport var1); + + Viewport getCurrentViewport(); + + void setCurrentViewport(Viewport var1); + + boolean isViewportCalculationEnabled(); + + void setViewportCalculationEnabled(boolean var1); + + void selectValue(SelectedValue var1); + + SelectedValue getSelectedValue(); +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/ColumnChartRenderer.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/ColumnChartRenderer.java new file mode 100644 index 00000000..f9776a02 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/ColumnChartRenderer.java @@ -0,0 +1,394 @@ +package dji.v5.ux.core.base.charts.renderer; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PointF; +import android.graphics.RectF; + +import java.util.Iterator; + +import dji.v5.ux.core.base.charts.model.Column; +import dji.v5.ux.core.base.charts.model.ColumnChartData; +import dji.v5.ux.core.base.charts.model.SelectedValue; +import dji.v5.ux.core.base.charts.model.SubcolumnValue; +import dji.v5.ux.core.base.charts.model.Viewport; +import dji.v5.ux.core.base.charts.provider.ColumnChartDataProvider; +import dji.v5.ux.core.base.charts.util.ChartUtils; +import dji.v5.ux.core.base.charts.view.Chart; + +public class ColumnChartRenderer extends AbstractChartRenderer { + private ColumnChartDataProvider dataProvider; + private int touchAdditionalWidth; + private int subcolumnSpacing; + private Paint columnPaint = new Paint(); + private RectF drawRect = new RectF(); + private PointF touchedPoint = new PointF(); + private float fillRatio; + private float baseValue; + private Viewport tempMaximumViewport = new Viewport(); + + public ColumnChartRenderer(Context context, Chart chart, ColumnChartDataProvider dataProvider) { + super(context, chart); + this.dataProvider = dataProvider; + this.subcolumnSpacing = ChartUtils.dp2px(this.density, 1); + this.touchAdditionalWidth = ChartUtils.dp2px(this.density, 4); + this.columnPaint.setAntiAlias(true); + this.columnPaint.setStyle(Paint.Style.FILL); + this.columnPaint.setStrokeCap(Paint.Cap.SQUARE); + } + + public void onChartSizeChanged() { + //do nothing + } + + @Override + public void onChartDataChanged() { + super.onChartDataChanged(); + ColumnChartData data = this.dataProvider.getColumnChartData(); + this.fillRatio = data.getFillRatio(); + this.baseValue = data.getBaseValue(); + this.onChartViewportChanged(); + } + + public void onChartViewportChanged() { + if (this.isViewportCalculationEnabled) { + this.calculateMaxViewport(); + this.computator.setMaxViewport(this.tempMaximumViewport); + this.computator.setCurrentViewport(this.computator.getMaximumViewport()); + } + + } + + public void draw(Canvas canvas) { + ColumnChartData data = this.dataProvider.getColumnChartData(); + if (data.isStacked()) { + this.drawColumnForStacked(canvas); + if (this.isTouched()) { + this.highlightColumnForStacked(canvas); + } + } else { + this.drawColumnsForSubcolumns(canvas); + if (this.isTouched()) { + this.highlightColumnsForSubcolumns(canvas); + } + } + + } + + public void drawUnclipped(Canvas canvas) { + //do nothing + } + + public boolean checkTouch(float touchX, float touchY) { + this.selectedValue.clear(); + ColumnChartData data = this.dataProvider.getColumnChartData(); + if (data.isStacked()) { + this.checkTouchForStacked(touchX, touchY); + } else { + this.checkTouchForSubcolumns(touchX, touchY); + } + + return this.isTouched(); + } + + private void calculateMaxViewport() { + ColumnChartData data = this.dataProvider.getColumnChartData(); + this.tempMaximumViewport.set(-0.5F, this.baseValue, (float)data.getColumns().size() - 0.5F, this.baseValue); + if (data.isStacked()) { + this.calculateMaxViewportForStacked(data); + } else { + this.calculateMaxViewportForSubcolumns(data); + } + + } + + private void calculateMaxViewportForSubcolumns(ColumnChartData data) { + Iterator var2 = data.getColumns().iterator(); + + while(var2.hasNext()) { + Column column = (Column)var2.next(); + Iterator var4 = column.getValues().iterator(); + + while(var4.hasNext()) { + SubcolumnValue columnValue = (SubcolumnValue)var4.next(); + if (columnValue.getValue() >= this.baseValue && columnValue.getValue() > this.tempMaximumViewport.top) { + this.tempMaximumViewport.top = columnValue.getValue(); + } + + if (columnValue.getValue() < this.baseValue && columnValue.getValue() < this.tempMaximumViewport.bottom) { + this.tempMaximumViewport.bottom = columnValue.getValue(); + } + } + } + + } + + private void calculateMaxViewportForStacked(ColumnChartData data) { + Iterator var2 = data.getColumns().iterator(); + + while(var2.hasNext()) { + Column column = (Column)var2.next(); + float sumPositive = this.baseValue; + float sumNegative = this.baseValue; + Iterator var6 = column.getValues().iterator(); + + while(var6.hasNext()) { + SubcolumnValue columnValue = (SubcolumnValue)var6.next(); + if (columnValue.getValue() >= this.baseValue) { + sumPositive += columnValue.getValue(); + } else { + sumNegative += columnValue.getValue(); + } + } + + if (sumPositive > this.tempMaximumViewport.top) { + this.tempMaximumViewport.top = sumPositive; + } + + if (sumNegative < this.tempMaximumViewport.bottom) { + this.tempMaximumViewport.bottom = sumNegative; + } + } + + } + + private void drawColumnsForSubcolumns(Canvas canvas) { + ColumnChartData data = this.dataProvider.getColumnChartData(); + float columnWidth = this.calculateColumnWidth(); + int columnIndex = 0; + + for(Iterator var5 = data.getColumns().iterator(); var5.hasNext(); ++columnIndex) { + Column column = (Column)var5.next(); + this.processColumnForSubcolumns(canvas, column, columnWidth, columnIndex, 0); + } + + } + + private void highlightColumnsForSubcolumns(Canvas canvas) { + ColumnChartData data = this.dataProvider.getColumnChartData(); + float columnWidth = this.calculateColumnWidth(); + Column column = (Column)data.getColumns().get(this.selectedValue.getFirstIndex()); + this.processColumnForSubcolumns(canvas, column, columnWidth, this.selectedValue.getFirstIndex(), 2); + } + + private void checkTouchForSubcolumns(float touchX, float touchY) { + this.touchedPoint.x = touchX; + this.touchedPoint.y = touchY; + ColumnChartData data = this.dataProvider.getColumnChartData(); + float columnWidth = this.calculateColumnWidth(); + int columnIndex = 0; + + for(Iterator var6 = data.getColumns().iterator(); var6.hasNext(); ++columnIndex) { + Column column = (Column)var6.next(); + this.processColumnForSubcolumns((Canvas)null, column, columnWidth, columnIndex, 1); + } + + } + + private void processColumnForSubcolumns(Canvas canvas, Column column, float columnWidth, int columnIndex, int mode) { + float subcolumnWidth = (columnWidth - (float)(this.subcolumnSpacing * (column.getValues().size() - 1))) / (float)column.getValues().size(); + if (subcolumnWidth < 1.0F) { + subcolumnWidth = 1.0F; + } + + float rawX = this.computator.computeRawX((float)columnIndex); + float halfColumnWidth = columnWidth / 2.0F; + float baseRawY = this.computator.computeRawY(this.baseValue); + float subcolumnRawX = rawX - halfColumnWidth; + int valueIndex = 0; + + for(Iterator var12 = column.getValues().iterator(); var12.hasNext(); ++valueIndex) { + SubcolumnValue columnValue = (SubcolumnValue)var12.next(); + this.columnPaint.setColor(columnValue.getColor()); + if (subcolumnRawX > rawX + halfColumnWidth) { + break; + } + + float rawY = this.computator.computeRawY(columnValue.getValue()); + this.calculateRectToDraw(columnValue, subcolumnRawX, subcolumnRawX + subcolumnWidth, baseRawY, rawY); + switch (mode) { + case 0: + this.drawSubcolumn(canvas, column, columnValue, false); + break; + case 1: + this.checkRectToDraw(columnIndex, valueIndex); + break; + case 2: + this.highlightSubcolumn(canvas, column, columnValue, valueIndex, false); + break; + default: + throw new IllegalStateException("Cannot process column in mode: " + mode); + } + + subcolumnRawX += subcolumnWidth + (float)this.subcolumnSpacing; + } + + } + + private void drawColumnForStacked(Canvas canvas) { + ColumnChartData data = this.dataProvider.getColumnChartData(); + float columnWidth = this.calculateColumnWidth(); + int columnIndex = 0; + + for(Iterator var5 = data.getColumns().iterator(); var5.hasNext(); ++columnIndex) { + Column column = (Column)var5.next(); + this.processColumnForStacked(canvas, column, columnWidth, columnIndex, 0); + } + + } + + private void highlightColumnForStacked(Canvas canvas) { + ColumnChartData data = this.dataProvider.getColumnChartData(); + float columnWidth = this.calculateColumnWidth(); + Column column = (Column)data.getColumns().get(this.selectedValue.getFirstIndex()); + this.processColumnForStacked(canvas, column, columnWidth, this.selectedValue.getFirstIndex(), 2); + } + + private void checkTouchForStacked(float touchX, float touchY) { + this.touchedPoint.x = touchX; + this.touchedPoint.y = touchY; + ColumnChartData data = this.dataProvider.getColumnChartData(); + float columnWidth = this.calculateColumnWidth(); + int columnIndex = 0; + + for(Iterator var6 = data.getColumns().iterator(); var6.hasNext(); ++columnIndex) { + Column column = (Column)var6.next(); + this.processColumnForStacked((Canvas)null, column, columnWidth, columnIndex, 1); + } + + } + + private void processColumnForStacked(Canvas canvas, Column column, float columnWidth, int columnIndex, int mode) { + float rawX = this.computator.computeRawX(columnIndex); + float halfColumnWidth = columnWidth / 2.0F; + float mostPositiveValue = this.baseValue; + float mostNegativeValue = this.baseValue; + float subcolumnBaseValue; + int valueIndex = 0; + + for(Iterator var12 = column.getValues().iterator(); var12.hasNext(); ++valueIndex) { + SubcolumnValue columnValue = (SubcolumnValue)var12.next(); + this.columnPaint.setColor(columnValue.getColor()); + if (columnValue.getValue() >= this.baseValue) { + subcolumnBaseValue = mostPositiveValue; + mostPositiveValue += columnValue.getValue(); + } else { + subcolumnBaseValue = mostNegativeValue; + mostNegativeValue += columnValue.getValue(); + } + + float rawBaseY = this.computator.computeRawY(subcolumnBaseValue); + float rawY = this.computator.computeRawY(subcolumnBaseValue + columnValue.getValue()); + this.calculateRectToDraw(columnValue, rawX - halfColumnWidth, rawX + halfColumnWidth, rawBaseY, rawY); + switch (mode) { + case 0: + this.drawSubcolumn(canvas, column, columnValue, true); + break; + case 1: + this.checkRectToDraw(columnIndex, valueIndex); + break; + case 2: + this.highlightSubcolumn(canvas, column, columnValue, valueIndex, true); + break; + default: + throw new IllegalStateException("Cannot process column in mode: " + mode); + } + } + + } + + private void drawSubcolumn(Canvas canvas, Column column, SubcolumnValue columnValue, boolean isStacked) { + canvas.drawRect(this.drawRect, this.columnPaint); + if (column.hasLabels()) { + this.drawLabel(canvas, column, columnValue, isStacked, (float)this.labelOffset); + } + + } + + private void highlightSubcolumn(Canvas canvas, Column column, SubcolumnValue columnValue, int valueIndex, boolean isStacked) { + if (this.selectedValue.getSecondIndex() == valueIndex) { + this.columnPaint.setColor(columnValue.getDarkenColor()); + canvas.drawRect(this.drawRect.left - (float)this.touchAdditionalWidth, this.drawRect.top, this.drawRect.right + (float)this.touchAdditionalWidth, this.drawRect.bottom, this.columnPaint); + if (column.hasLabels() || column.hasLabelsOnlyForSelected()) { + this.drawLabel(canvas, column, columnValue, isStacked, (float)this.labelOffset); + } + } + + } + + private void checkRectToDraw(int columnIndex, int valueIndex) { + if (this.drawRect.contains(this.touchedPoint.x, this.touchedPoint.y)) { + this.selectedValue.set(columnIndex, valueIndex, SelectedValue.SelectedValueType.COLUMN); + } + + } + + private float calculateColumnWidth() { + float columnWidth = this.fillRatio * (float)this.computator.getContentRectMinusAllMargins().width() / this.computator.getVisibleViewport().width(); + if (columnWidth < 2.0F) { + columnWidth = 2.0F; + } + + return columnWidth; + } + + private void calculateRectToDraw(SubcolumnValue columnValue, float left, float right, float rawBaseY, float rawY) { + this.drawRect.left = left; + this.drawRect.right = right; + if (columnValue.getValue() >= this.baseValue) { + this.drawRect.top = rawY; + this.drawRect.bottom = rawBaseY - (float)this.subcolumnSpacing; + } else { + this.drawRect.bottom = rawY; + this.drawRect.top = rawBaseY + (float)this.subcolumnSpacing; + } + + } + + private void drawLabel(Canvas canvas, Column column, SubcolumnValue columnValue, boolean isStacked, float offset) { + int numChars = column.getFormatter().formatChartValue(this.labelBuffer, columnValue); + if (numChars != 0) { + float labelWidth = this.labelPaint.measureText(this.labelBuffer, this.labelBuffer.length - numChars, numChars); + int labelHeight = Math.abs(this.fontMetrics.ascent); + float left = this.drawRect.centerX() - labelWidth / 2.0F - (float)this.labelMargin; + float right = this.drawRect.centerX() + labelWidth / 2.0F + (float)this.labelMargin; + float top; + float bottom; + if (isStacked && (float)labelHeight < this.drawRect.height() - (float)(2 * this.labelMargin)) { + if (columnValue.getValue() >= this.baseValue) { + top = this.drawRect.top; + bottom = this.drawRect.top + (float)labelHeight + (float)(this.labelMargin * 2); + } else { + top = this.drawRect.bottom - (float)labelHeight - (float)(this.labelMargin * 2); + bottom = this.drawRect.bottom; + } + } else { + if (isStacked) { + return; + } + + if (columnValue.getValue() >= this.baseValue) { + top = this.drawRect.top - offset - (float)labelHeight - (float)(this.labelMargin * 2); + if (top < (float)this.computator.getContentRectMinusAllMargins().top) { + top = this.drawRect.top + offset; + bottom = this.drawRect.top + offset + (float)labelHeight + (float)(this.labelMargin * 2); + } else { + bottom = this.drawRect.top - offset; + } + } else { + bottom = this.drawRect.bottom + offset + (float)labelHeight + (float)(this.labelMargin * 2); + if (bottom > (float)this.computator.getContentRectMinusAllMargins().bottom) { + top = this.drawRect.bottom - offset - (float)labelHeight - (float)(this.labelMargin * 2); + bottom = this.drawRect.bottom - offset; + } else { + top = this.drawRect.bottom + offset; + } + } + } + + this.labelBackgroundRect.set(left, top, right, bottom); + this.drawLabelTextAndBackground(canvas, this.labelBuffer, this.labelBuffer.length - numChars, numChars, columnValue.getDarkenColor()); + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/ComboChartRenderer.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/ComboChartRenderer.java new file mode 100644 index 00000000..092a8259 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/ComboChartRenderer.java @@ -0,0 +1,120 @@ +package dji.v5.ux.core.base.charts.renderer; + +import android.content.Context; +import android.graphics.Canvas; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import dji.v5.ux.core.base.charts.model.Viewport; +import dji.v5.ux.core.base.charts.view.Chart; + +public class ComboChartRenderer extends AbstractChartRenderer { + protected List renderers = new ArrayList<>(); + protected Viewport unionViewport = new Viewport(); + + public ComboChartRenderer(Context context, Chart chart) { + super(context, chart); + } + + public void onChartSizeChanged() { + Iterator var1 = this.renderers.iterator(); + + while(var1.hasNext()) { + ChartRenderer renderer = (ChartRenderer)var1.next(); + renderer.onChartSizeChanged(); + } + + } + + @Override + public void onChartDataChanged() { + super.onChartDataChanged(); + Iterator var1 = this.renderers.iterator(); + + while(var1.hasNext()) { + ChartRenderer renderer = (ChartRenderer)var1.next(); + renderer.onChartDataChanged(); + } + + this.onChartViewportChanged(); + } + + public void onChartViewportChanged() { + if (this.isViewportCalculationEnabled) { + int rendererIndex = 0; + + for(Iterator var2 = this.renderers.iterator(); var2.hasNext(); ++rendererIndex) { + ChartRenderer renderer = (ChartRenderer)var2.next(); + renderer.onChartViewportChanged(); + if (rendererIndex == 0) { + this.unionViewport.set(renderer.getMaximumViewport()); + } else { + this.unionViewport.union(renderer.getMaximumViewport()); + } + } + + this.computator.setMaxViewport(this.unionViewport); + this.computator.setCurrentViewport(this.unionViewport); + } + + } + + public void draw(Canvas canvas) { + Iterator var2 = this.renderers.iterator(); + + while(var2.hasNext()) { + ChartRenderer renderer = (ChartRenderer)var2.next(); + renderer.draw(canvas); + } + + } + + public void drawUnclipped(Canvas canvas) { + Iterator var2 = this.renderers.iterator(); + + while(var2.hasNext()) { + ChartRenderer renderer = (ChartRenderer)var2.next(); + renderer.drawUnclipped(canvas); + } + + } + + public boolean checkTouch(float touchX, float touchY) { + this.selectedValue.clear(); + + int rendererIndex; + ChartRenderer renderer; + for(rendererIndex = this.renderers.size() - 1; rendererIndex >= 0; --rendererIndex) { + renderer = (ChartRenderer)this.renderers.get(rendererIndex); + if (renderer.checkTouch(touchX, touchY)) { + this.selectedValue.set(renderer.getSelectedValue()); + break; + } + } + + --rendererIndex; + + while(rendererIndex >= 0) { + renderer = (ChartRenderer)this.renderers.get(rendererIndex); + renderer.clearTouch(); + --rendererIndex; + } + + return this.isTouched(); + } + + @Override + public void clearTouch() { + Iterator var1 = this.renderers.iterator(); + + while(var1.hasNext()) { + ChartRenderer renderer = (ChartRenderer)var1.next(); + renderer.clearTouch(); + } + + this.selectedValue.clear(); + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/ComboLineColumnChartRenderer.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/ComboLineColumnChartRenderer.java new file mode 100644 index 00000000..368d86de --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/ComboLineColumnChartRenderer.java @@ -0,0 +1,32 @@ +package dji.v5.ux.core.base.charts.renderer; + +import android.content.Context; + +import dji.v5.ux.core.base.charts.provider.ColumnChartDataProvider; +import dji.v5.ux.core.base.charts.provider.LineChartDataProvider; +import dji.v5.ux.core.base.charts.view.Chart; + +public class ComboLineColumnChartRenderer extends ComboChartRenderer { + private ColumnChartRenderer columnChartRenderer; + private LineChartRenderer lineChartRenderer; + + public ComboLineColumnChartRenderer(Context context, Chart chart, ColumnChartDataProvider columnChartDataProvider, LineChartDataProvider lineChartDataProvider) { + this(context, chart, new ColumnChartRenderer(context, chart, columnChartDataProvider), new LineChartRenderer(context, chart, lineChartDataProvider)); + } + + public ComboLineColumnChartRenderer(Context context, Chart chart, ColumnChartRenderer columnChartRenderer, LineChartDataProvider lineChartDataProvider) { + this(context, chart, columnChartRenderer, new LineChartRenderer(context, chart, lineChartDataProvider)); + } + + public ComboLineColumnChartRenderer(Context context, Chart chart, ColumnChartDataProvider columnChartDataProvider, LineChartRenderer lineChartRenderer) { + this(context, chart, new ColumnChartRenderer(context, chart, columnChartDataProvider), lineChartRenderer); + } + + public ComboLineColumnChartRenderer(Context context, Chart chart, ColumnChartRenderer columnChartRenderer, LineChartRenderer lineChartRenderer) { + super(context, chart); + this.columnChartRenderer = columnChartRenderer; + this.lineChartRenderer = lineChartRenderer; + this.renderers.add(this.columnChartRenderer); + this.renderers.add(this.lineChartRenderer); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/LineChartRenderer.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/LineChartRenderer.java new file mode 100644 index 00000000..78cec82f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/LineChartRenderer.java @@ -0,0 +1,473 @@ +package dji.v5.ux.core.base.charts.renderer; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.PorterDuff; +import android.graphics.Rect; +import android.graphics.Shader; + +import java.util.Iterator; + +import dji.v5.ux.core.base.charts.model.Line; +import dji.v5.ux.core.base.charts.model.LineChartData; +import dji.v5.ux.core.base.charts.model.PointValue; +import dji.v5.ux.core.base.charts.model.SelectedValue; +import dji.v5.ux.core.base.charts.model.ValueShape; +import dji.v5.ux.core.base.charts.model.Viewport; +import dji.v5.ux.core.base.charts.provider.LineChartDataProvider; +import dji.v5.ux.core.base.charts.util.ChartUtils; +import dji.v5.ux.core.base.charts.view.Chart; + +public class LineChartRenderer extends AbstractChartRenderer { + private LineChartDataProvider dataProvider; + private int checkPrecision; + private float baseValue; + private int touchToleranceMargin; + private Path path = new Path(); + private Paint linePaint = new Paint(); + private Paint pointPaint = new Paint(); + private Bitmap softwareBitmap; + private Canvas softwareCanvas = new Canvas(); + private Viewport tempMaximumViewport = new Viewport(); + + public LineChartRenderer(Context context, Chart chart, LineChartDataProvider dataProvider) { + super(context, chart); + this.dataProvider = dataProvider; + this.touchToleranceMargin = ChartUtils.dp2px(this.density, 4); + this.linePaint.setAntiAlias(true); + this.linePaint.setStyle(Paint.Style.STROKE); + this.linePaint.setStrokeCap(Paint.Cap.ROUND); + this.linePaint.setStrokeWidth((float)ChartUtils.dp2px(this.density, 3)); + this.pointPaint.setAntiAlias(true); + this.pointPaint.setStyle(Paint.Style.FILL); + this.checkPrecision = ChartUtils.dp2px(this.density, 2); + } + + public void setShader(Shader shader) { + this.linePaint.setShader(shader); + } + + public void onChartSizeChanged() { + int internalMargin = this.calculateContentRectInternalMargin(); + this.computator.insetContentRectByInternalMargins(internalMargin, internalMargin, internalMargin, internalMargin); + if (this.computator.getChartWidth() > 0 && this.computator.getChartHeight() > 0) { + this.softwareBitmap = Bitmap.createBitmap(this.computator.getChartWidth(), this.computator.getChartHeight(), Bitmap.Config.ARGB_8888); + this.softwareCanvas.setBitmap(this.softwareBitmap); + } + + } + + @Override + public void onChartDataChanged() { + super.onChartDataChanged(); + int internalMargin = this.calculateContentRectInternalMargin(); + this.computator.insetContentRectByInternalMargins(internalMargin, internalMargin, internalMargin, internalMargin); + this.baseValue = this.dataProvider.getLineChartData().getBaseValue(); + this.onChartViewportChanged(); + } + + public void onChartViewportChanged() { + if (this.isViewportCalculationEnabled) { + this.calculateMaxViewport(); + this.computator.setMaxViewport(this.tempMaximumViewport); + this.computator.setCurrentViewport(this.computator.getMaximumViewport()); + } + + } + + public void draw(Canvas canvas) { + LineChartData data = this.dataProvider.getLineChartData(); + Canvas drawCanvas; + if (null != this.softwareBitmap) { + drawCanvas = this.softwareCanvas; + drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR); + } else { + drawCanvas = canvas; + } + + Iterator var4 = data.getLines().iterator(); + + while(var4.hasNext()) { + Line line = (Line)var4.next(); + if (line.hasLines()) { + if (line.isCubic()) { + this.drawSmoothPath(drawCanvas, line); + } else if (line.isSquare()) { + this.drawSquarePath(drawCanvas, line); + } else { + this.drawPath(drawCanvas, line); + } + } + } + + if (null != this.softwareBitmap) { + canvas.drawBitmap(this.softwareBitmap, 0.0F, 0.0F, (Paint)null); + } + + } + + public void drawUnclipped(Canvas canvas) { + LineChartData data = this.dataProvider.getLineChartData(); + int lineIndex = 0; + + for(Iterator var4 = data.getLines().iterator(); var4.hasNext(); ++lineIndex) { + Line line = (Line)var4.next(); + if (this.checkIfShouldDrawPoints(line)) { + this.drawPoints(canvas, line, lineIndex, 0); + } + } + + if (this.isTouched()) { + this.highlightPoints(canvas); + } + + } + + private boolean checkIfShouldDrawPoints(Line line) { + return line.hasPoints() || line.getValues().size() == 1; + } + + public boolean checkTouch(float touchX, float touchY) { + this.selectedValue.clear(); + LineChartData data = this.dataProvider.getLineChartData(); + int lineIndex = 0; + + for(Iterator var5 = data.getLines().iterator(); var5.hasNext(); ++lineIndex) { + Line line = (Line)var5.next(); + if (this.checkIfShouldDrawPoints(line)) { + int pointRadius = ChartUtils.dp2px(this.density, line.getPointRadius()); + int valueIndex = 0; + + for(Iterator var9 = line.getValues().iterator(); var9.hasNext(); ++valueIndex) { + PointValue pointValue = (PointValue)var9.next(); + float rawValueX = this.computator.computeRawX(pointValue.getX()); + float rawValueY = this.computator.computeRawY(pointValue.getY()); + if (this.isInArea(rawValueX, rawValueY, touchX, touchY, (float)(pointRadius + this.touchToleranceMargin))) { + this.selectedValue.set(lineIndex, valueIndex, SelectedValue.SelectedValueType.LINE); + } + } + } + } + + return this.isTouched(); + } + + private void calculateMaxViewport() { + this.tempMaximumViewport.set(Float.MAX_VALUE, Float.MIN_VALUE, Float.MIN_VALUE, Float.MAX_VALUE); + LineChartData data = this.dataProvider.getLineChartData(); + Iterator var2 = data.getLines().iterator(); + + while(var2.hasNext()) { + Line line = (Line)var2.next(); + Iterator var4 = line.getValues().iterator(); + + while(var4.hasNext()) { + PointValue pointValue = (PointValue)var4.next(); + if (pointValue.getX() < this.tempMaximumViewport.left) { + this.tempMaximumViewport.left = pointValue.getX(); + } + + if (pointValue.getX() > this.tempMaximumViewport.right) { + this.tempMaximumViewport.right = pointValue.getX(); + } + + if (pointValue.getY() < this.tempMaximumViewport.bottom) { + this.tempMaximumViewport.bottom = pointValue.getY(); + } + + if (pointValue.getY() > this.tempMaximumViewport.top) { + this.tempMaximumViewport.top = pointValue.getY(); + } + } + } + + } + + private int calculateContentRectInternalMargin() { + int contentAreaMargin = 0; + LineChartData data = this.dataProvider.getLineChartData(); + Iterator var3 = data.getLines().iterator(); + + while(var3.hasNext()) { + Line line = (Line)var3.next(); + if (this.checkIfShouldDrawPoints(line)) { + int margin = line.getPointRadius() + 4; + if (margin > contentAreaMargin) { + contentAreaMargin = margin; + } + } + } + + return ChartUtils.dp2px(this.density, contentAreaMargin); + } + + private void drawPath(Canvas canvas, Line line) { + this.prepareLinePaint(line); + int valueIndex = 0; + + for(Iterator var4 = line.getValues().iterator(); var4.hasNext(); ++valueIndex) { + PointValue pointValue = (PointValue)var4.next(); + float rawX = this.computator.computeRawX(pointValue.getX()); + float rawY = this.computator.computeRawY(pointValue.getY()); + if (valueIndex == 0) { + this.path.moveTo(rawX, rawY); + } else { + this.path.lineTo(rawX, rawY); + } + } + + canvas.drawPath(this.path, this.linePaint); + if (line.isFilled()) { + this.drawArea(canvas, line); + } + + this.path.reset(); + } + + private void drawSquarePath(Canvas canvas, Line line) { + this.prepareLinePaint(line); + int valueIndex = 0; + float previousRawY = 0.0F; + + for(Iterator var5 = line.getValues().iterator(); var5.hasNext(); ++valueIndex) { + PointValue pointValue = (PointValue)var5.next(); + float rawX = this.computator.computeRawX(pointValue.getX()); + float rawY = this.computator.computeRawY(pointValue.getY()); + if (valueIndex == 0) { + this.path.moveTo(rawX, rawY); + } else { + this.path.lineTo(rawX, previousRawY); + this.path.lineTo(rawX, rawY); + } + + previousRawY = rawY; + } + + canvas.drawPath(this.path, this.linePaint); + if (line.isFilled()) { + this.drawArea(canvas, line); + } + + this.path.reset(); + } + + private void drawSmoothPath(Canvas canvas, Line line) { + this.prepareLinePaint(line); + int lineSize = line.getValues().size(); + float prePreviousPointX = Float.NaN; + float prePreviousPointY = Float.NaN; + float previousPointX = Float.NaN; + float previousPointY = Float.NaN; + float currentPointX = Float.NaN; + float currentPointY = Float.NaN; + float nextPointX; + float nextPointY; + + for(int valueIndex = 0; valueIndex < lineSize; ++valueIndex) { + PointValue linePoint; + if (Float.isNaN(currentPointX)) { + linePoint = (PointValue)line.getValues().get(valueIndex); + currentPointX = this.computator.computeRawX(linePoint.getX()); + currentPointY = this.computator.computeRawY(linePoint.getY()); + } + + if (Float.isNaN(previousPointX)) { + if (valueIndex > 0) { + linePoint = (PointValue)line.getValues().get(valueIndex - 1); + previousPointX = this.computator.computeRawX(linePoint.getX()); + previousPointY = this.computator.computeRawY(linePoint.getY()); + } else { + previousPointX = currentPointX; + previousPointY = currentPointY; + } + } + + if (Float.isNaN(prePreviousPointX)) { + if (valueIndex > 1) { + linePoint = (PointValue)line.getValues().get(valueIndex - 2); + prePreviousPointX = this.computator.computeRawX(linePoint.getX()); + prePreviousPointY = this.computator.computeRawY(linePoint.getY()); + } else { + prePreviousPointX = previousPointX; + prePreviousPointY = previousPointY; + } + } + + if (valueIndex < lineSize - 1) { + linePoint = (PointValue)line.getValues().get(valueIndex + 1); + nextPointX = this.computator.computeRawX(linePoint.getX()); + nextPointY = this.computator.computeRawY(linePoint.getY()); + } else { + nextPointX = currentPointX; + nextPointY = currentPointY; + } + + if (valueIndex == 0) { + this.path.moveTo(currentPointX, currentPointY); + } else { + float firstDiffX = currentPointX - prePreviousPointX; + float firstDiffY = currentPointY - prePreviousPointY; + float secondDiffX = nextPointX - previousPointX; + float secondDiffY = nextPointY - previousPointY; + float firstControlPointX = previousPointX + 0.16F * firstDiffX; + float firstControlPointY = previousPointY + 0.16F * firstDiffY; + float secondControlPointX = currentPointX - 0.16F * secondDiffX; + float secondControlPointY = currentPointY - 0.16F * secondDiffY; + this.path.cubicTo(firstControlPointX, firstControlPointY, secondControlPointX, secondControlPointY, currentPointX, currentPointY); + } + + prePreviousPointX = previousPointX; + prePreviousPointY = previousPointY; + previousPointX = currentPointX; + previousPointY = currentPointY; + currentPointX = nextPointX; + currentPointY = nextPointY; + } + + canvas.drawPath(this.path, this.linePaint); + if (line.isFilled()) { + this.drawArea(canvas, line); + } + + this.path.reset(); + } + + private void prepareLinePaint(Line line) { + this.linePaint.setStrokeWidth((float)ChartUtils.dp2px(this.density, line.getStrokeWidth())); + this.linePaint.setColor(line.getColor()); + this.linePaint.setPathEffect(line.getPathEffect()); + } + + private void drawPoints(Canvas canvas, Line line, int lineIndex, int mode) { + this.pointPaint.setColor(line.getPointColor()); + int valueIndex = 0; + + for(Iterator var6 = line.getValues().iterator(); var6.hasNext(); ++valueIndex) { + PointValue pointValue = (PointValue)var6.next(); + int pointRadius = ChartUtils.dp2px(this.density, line.getPointRadius()); + float rawX = this.computator.computeRawX(pointValue.getX()); + float rawY = this.computator.computeRawY(pointValue.getY()); + if (this.computator.isWithinContentRect(rawX, rawY, (float)this.checkPrecision)) { + if (0 == mode) { + this.drawPoint(canvas, line, rawX, rawY, (float)pointRadius); + if (line.hasLabels()) { + this.drawLabel(canvas, line, pointValue, rawX, rawY, (float)(pointRadius + this.labelOffset)); + } + } else { + if (1 != mode) { + throw new IllegalStateException("Cannot process points in mode: " + mode); + } + + this.highlightPoint(canvas, line, pointValue, rawX, rawY, lineIndex, valueIndex); + } + } + } + + } + + private void drawPoint(Canvas canvas, Line line, float rawX, float rawY, float pointRadius) { + if (ValueShape.SQUARE.equals(line.getShape())) { + canvas.drawRect(rawX - pointRadius, rawY - pointRadius, rawX + pointRadius, rawY + pointRadius, this.pointPaint); + } else if (ValueShape.CIRCLE.equals(line.getShape())) { + canvas.drawCircle(rawX, rawY, pointRadius, this.pointPaint); + } else { + if (!ValueShape.DIAMOND.equals(line.getShape())) { + throw new IllegalArgumentException("Invalid point shape: " + line.getShape()); + } + + canvas.save(); + canvas.rotate(45.0F, rawX, rawY); + canvas.drawRect(rawX - pointRadius, rawY - pointRadius, rawX + pointRadius, rawY + pointRadius, this.pointPaint); + canvas.restore(); + } + + } + + private void highlightPoints(Canvas canvas) { + int lineIndex = this.selectedValue.getFirstIndex(); + Line line = (Line)this.dataProvider.getLineChartData().getLines().get(lineIndex); + this.drawPoints(canvas, line, lineIndex, 1); + } + + private void highlightPoint(Canvas canvas, Line line, PointValue pointValue, float rawX, float rawY, int lineIndex, int valueIndex) { + if (this.selectedValue.getFirstIndex() == lineIndex && this.selectedValue.getSecondIndex() == valueIndex) { + int pointRadius = ChartUtils.dp2px(this.density, line.getPointRadius()); + this.pointPaint.setColor(line.getDarkenColor()); + this.drawPoint(canvas, line, rawX, rawY, (float)(pointRadius + this.touchToleranceMargin)); + if (line.hasLabels() || line.hasLabelsOnlyForSelected()) { + this.drawLabel(canvas, line, pointValue, rawX, rawY, (float)(pointRadius + this.labelOffset)); + } + } + + } + + private void drawLabel(Canvas canvas, Line line, PointValue pointValue, float rawX, float rawY, float offset) { + Rect contentRect = this.computator.getContentRectMinusAllMargins(); + int numChars = line.getFormatter().formatChartValue(this.labelBuffer, pointValue); + if (numChars != 0) { + float labelWidth = this.labelPaint.measureText(this.labelBuffer, this.labelBuffer.length - numChars, numChars); + int labelHeight = Math.abs(this.fontMetrics.ascent); + float left = rawX - labelWidth / 2.0F - (float)this.labelMargin; + float right = rawX + labelWidth / 2.0F + (float)this.labelMargin; + float top; + float bottom; + if (pointValue.getY() >= this.baseValue) { + top = rawY - offset - (float)labelHeight - (float)(this.labelMargin * 2); + bottom = rawY - offset; + } else { + top = rawY + offset; + bottom = rawY + offset + (float)labelHeight + (float)(this.labelMargin * 2); + } + + if (top < (float)contentRect.top) { + top = rawY + offset; + bottom = rawY + offset + (float)labelHeight + (float)(this.labelMargin * 2); + } + + if (bottom > (float)contentRect.bottom) { + top = rawY - offset - (float)labelHeight - (float)(this.labelMargin * 2); + bottom = rawY - offset; + } + + if (left < (float)contentRect.left) { + left = rawX; + right = rawX + labelWidth + (float)(this.labelMargin * 2); + } + + if (right > (float)contentRect.right) { + left = rawX - labelWidth - (float)(this.labelMargin * 2); + right = rawX; + } + + this.labelBackgroundRect.set(left, top, right, bottom); + this.drawLabelTextAndBackground(canvas, this.labelBuffer, this.labelBuffer.length - numChars, numChars, line.getDarkenColor()); + } + } + + private void drawArea(Canvas canvas, Line line) { + int lineSize = line.getValues().size(); + if (lineSize >= 2) { + Rect contentRect = this.computator.getContentRectMinusAllMargins(); + float baseRawValue = Math.min((float)contentRect.bottom, Math.max(this.computator.computeRawY(this.baseValue), (float)contentRect.top)); + float left = Math.max(this.computator.computeRawX(((PointValue)line.getValues().get(0)).getX()), (float)contentRect.left); + float right = Math.min(this.computator.computeRawX(((PointValue)line.getValues().get(lineSize - 1)).getX()), (float)contentRect.right); + this.path.lineTo(right, baseRawValue); + this.path.lineTo(left, baseRawValue); + this.path.close(); + this.linePaint.setStyle(Paint.Style.FILL); + this.linePaint.setAlpha(line.getAreaTransparency()); + canvas.drawPath(this.path, this.linePaint); + this.linePaint.setStyle(Paint.Style.STROKE); + } + } + + private boolean isInArea(float x, float y, float touchX, float touchY, float radius) { + float diffX = touchX - x; + float diffY = touchY - y; + return Math.pow((double)diffX, 2.0) + Math.pow((double)diffY, 2.0) <= 2.0 * Math.pow((double)radius, 2.0); + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/PieChartRenderer.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/PieChartRenderer.java new file mode 100644 index 00000000..0c25fea3 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/PieChartRenderer.java @@ -0,0 +1,419 @@ +package dji.v5.ux.core.base.charts.renderer; + +import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.PointF; +import android.graphics.PorterDuff; +import android.graphics.PorterDuffXfermode; +import android.graphics.Rect; +import android.graphics.RectF; +import android.text.TextUtils; + +import java.util.Iterator; + +import dji.v5.ux.core.base.charts.formatter.PieChartValueFormatter; +import dji.v5.ux.core.base.charts.model.PieChartData; +import dji.v5.ux.core.base.charts.model.SelectedValue; +import dji.v5.ux.core.base.charts.model.SliceValue; +import dji.v5.ux.core.base.charts.model.Viewport; +import dji.v5.ux.core.base.charts.provider.PieChartDataProvider; +import dji.v5.ux.core.base.charts.util.ChartUtils; +import dji.v5.ux.core.base.charts.view.Chart; + +public class PieChartRenderer extends AbstractChartRenderer { + private int rotation = 45; + private PieChartDataProvider dataProvider; + private Paint slicePaint = new Paint(); + private float maxSum; + private RectF originCircleOval = new RectF(); + private RectF drawCircleOval = new RectF(); + private PointF sliceVector = new PointF(); + private int touchAdditional; + private float circleFillRatio = 1.0F; + private boolean hasCenterCircle; + private float centerCircleScale; + private Paint centerCirclePaint = new Paint(); + private Paint centerCircleText1Paint = new Paint(); + private Paint.FontMetricsInt centerCircleText1FontMetrics = new Paint.FontMetricsInt(); + private Paint centerCircleText2Paint = new Paint(); + private Paint.FontMetricsInt centerCircleText2FontMetrics = new Paint.FontMetricsInt(); + private Paint separationLinesPaint = new Paint(); + private boolean hasLabelsOutside; + private boolean hasLabels; + private boolean hasLabelsOnlyForSelected; + private PieChartValueFormatter valueFormatter; + private Viewport tempMaximumViewport = new Viewport(); + private Bitmap softwareBitmap; + private Canvas softwareCanvas = new Canvas(); + + public PieChartRenderer(Context context, Chart chart, PieChartDataProvider dataProvider) { + super(context, chart); + this.dataProvider = dataProvider; + this.touchAdditional = ChartUtils.dp2px(this.density, 8); + this.slicePaint.setAntiAlias(true); + this.slicePaint.setStyle(Paint.Style.FILL); + this.centerCirclePaint.setAntiAlias(true); + this.centerCirclePaint.setStyle(Paint.Style.FILL); + this.centerCirclePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC)); + this.centerCircleText1Paint.setAntiAlias(true); + this.centerCircleText1Paint.setTextAlign(Paint.Align.CENTER); + this.centerCircleText2Paint.setAntiAlias(true); + this.centerCircleText2Paint.setTextAlign(Paint.Align.CENTER); + this.separationLinesPaint.setAntiAlias(true); + this.separationLinesPaint.setStyle(Paint.Style.STROKE); + this.separationLinesPaint.setStrokeCap(Paint.Cap.ROUND); + this.separationLinesPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR)); + this.separationLinesPaint.setColor(0); + } + + public void onChartSizeChanged() { + this.calculateCircleOval(); + if (this.computator.getChartWidth() > 0 && this.computator.getChartHeight() > 0) { + this.softwareBitmap = Bitmap.createBitmap(this.computator.getChartWidth(), this.computator.getChartHeight(), Bitmap.Config.ARGB_8888); + this.softwareCanvas.setBitmap(this.softwareBitmap); + } + + } + + @Override + public void onChartDataChanged() { + super.onChartDataChanged(); + PieChartData data = this.dataProvider.getPieChartData(); + this.hasLabelsOutside = data.hasLabelsOutside(); + this.hasLabels = data.hasLabels(); + this.hasLabelsOnlyForSelected = data.hasLabelsOnlyForSelected(); + this.valueFormatter = data.getFormatter(); + this.hasCenterCircle = data.hasCenterCircle(); + this.centerCircleScale = data.getCenterCircleScale(); + this.centerCirclePaint.setColor(data.getCenterCircleColor()); + if (null != data.getCenterText1Typeface()) { + this.centerCircleText1Paint.setTypeface(data.getCenterText1Typeface()); + } + + this.centerCircleText1Paint.setTextSize((float)ChartUtils.sp2px(this.scaledDensity, data.getCenterText1FontSize())); + this.centerCircleText1Paint.setColor(data.getCenterText1Color()); + this.centerCircleText1Paint.getFontMetricsInt(this.centerCircleText1FontMetrics); + if (null != data.getCenterText2Typeface()) { + this.centerCircleText2Paint.setTypeface(data.getCenterText2Typeface()); + } + + this.centerCircleText2Paint.setTextSize((float)ChartUtils.sp2px(this.scaledDensity, data.getCenterText2FontSize())); + this.centerCircleText2Paint.setColor(data.getCenterText2Color()); + this.centerCircleText2Paint.getFontMetricsInt(this.centerCircleText2FontMetrics); + this.onChartViewportChanged(); + } + + public void onChartViewportChanged() { + if (this.isViewportCalculationEnabled) { + this.calculateMaxViewport(); + this.computator.setMaxViewport(this.tempMaximumViewport); + this.computator.setCurrentViewport(this.computator.getMaximumViewport()); + } + + } + + public void draw(Canvas canvas) { + Canvas drawCanvas; + if (null != this.softwareBitmap) { + drawCanvas = this.softwareCanvas; + drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR); + } else { + drawCanvas = canvas; + } + + this.drawSlices(drawCanvas); + this.drawSeparationLines(drawCanvas); + if (this.hasCenterCircle) { + this.drawCenterCircle(drawCanvas); + } + + this.drawLabels(drawCanvas); + if (null != this.softwareBitmap) { + canvas.drawBitmap(this.softwareBitmap, 0.0F, 0.0F, (Paint)null); + } + + } + + public void drawUnclipped(Canvas canvas) { + //do nothing + } + + public boolean checkTouch(float touchX, float touchY) { + this.selectedValue.clear(); + PieChartData data = this.dataProvider.getPieChartData(); + float centerX = this.originCircleOval.centerX(); + float centerY = this.originCircleOval.centerY(); + float circleRadius = this.originCircleOval.width() / 2.0F; + this.sliceVector.set(touchX - centerX, touchY - centerY); + if (this.sliceVector.length() > circleRadius + (float)this.touchAdditional) { + return false; + } else if (data.hasCenterCircle() && this.sliceVector.length() < circleRadius * data.getCenterCircleScale()) { + return false; + } else { + float touchAngle = (this.pointToAngle(touchX, touchY, centerX, centerY) - (float)this.rotation + 360.0F) % 360.0F; + float sliceScale = 360.0F / this.maxSum; + float lastAngle = 0.0F; + int sliceIndex = 0; + + for(Iterator var11 = data.getValues().iterator(); var11.hasNext(); ++sliceIndex) { + SliceValue sliceValue = (SliceValue)var11.next(); + float angle = Math.abs(sliceValue.getValue()) * sliceScale; + if (touchAngle >= lastAngle) { + this.selectedValue.set(sliceIndex, sliceIndex, SelectedValue.SelectedValueType.NONE); + } + + lastAngle += angle; + } + + return this.isTouched(); + } + } + + private void drawCenterCircle(Canvas canvas) { + PieChartData data = this.dataProvider.getPieChartData(); + float circleRadius = this.originCircleOval.width() / 2.0F; + float centerRadius = circleRadius * data.getCenterCircleScale(); + float centerX = this.originCircleOval.centerX(); + float centerY = this.originCircleOval.centerY(); + canvas.drawCircle(centerX, centerY, centerRadius, this.centerCirclePaint); + if (!TextUtils.isEmpty(data.getCenterText1())) { + int text1Height = Math.abs(this.centerCircleText1FontMetrics.ascent); + if (!TextUtils.isEmpty(data.getCenterText2())) { + int text2Height = Math.abs(this.centerCircleText2FontMetrics.ascent); + canvas.drawText(data.getCenterText1(), centerX, centerY - (float)text1Height * 0.2F, this.centerCircleText1Paint); + canvas.drawText(data.getCenterText2(), centerX, centerY + (float)text2Height, this.centerCircleText2Paint); + } else { + canvas.drawText(data.getCenterText1(), centerX, centerY + (float)((double)text1Height / 4), this.centerCircleText1Paint); + } + } + + } + + private void drawSlices(Canvas canvas) { + PieChartData data = this.dataProvider.getPieChartData(); + float sliceScale = 360.0F / this.maxSum; + float lastAngle = (float)this.rotation; + int sliceIndex = 0; + + for(Iterator var6 = data.getValues().iterator(); var6.hasNext(); ++sliceIndex) { + SliceValue sliceValue = (SliceValue)var6.next(); + float angle = Math.abs(sliceValue.getValue()) * sliceScale; + if (this.isTouched() && this.selectedValue.getFirstIndex() == sliceIndex) { + this.drawSlice(canvas, sliceValue, lastAngle, angle, 1); + } else { + this.drawSlice(canvas, sliceValue, lastAngle, angle, 0); + } + + lastAngle += angle; + } + + } + + private void drawSeparationLines(Canvas canvas) { + PieChartData data = this.dataProvider.getPieChartData(); + if (data.getValues().size() >= 2) { + int sliceSpacing = ChartUtils.dp2px(this.density, data.getSlicesSpacing()); + if (sliceSpacing >= 1) { + float sliceScale = 360.0F / this.maxSum; + float lastAngle = (float)this.rotation; + float circleRadius = this.originCircleOval.width() / 2.0F; + this.separationLinesPaint.setStrokeWidth((float)sliceSpacing); + + float angle; + for(Iterator var7 = data.getValues().iterator(); var7.hasNext(); lastAngle += angle) { + SliceValue sliceValue = (SliceValue)var7.next(); + angle = Math.abs(sliceValue.getValue()) * sliceScale; + this.sliceVector.set((float)Math.cos(Math.toRadians((double)lastAngle)), (float)Math.sin(Math.toRadians((double)lastAngle))); + this.normalizeVector(this.sliceVector); + float x1 = this.sliceVector.x * (circleRadius + (float)this.touchAdditional) + this.originCircleOval.centerX(); + float y1 = this.sliceVector.y * (circleRadius + (float)this.touchAdditional) + this.originCircleOval.centerY(); + canvas.drawLine(this.originCircleOval.centerX(), this.originCircleOval.centerY(), x1, y1, this.separationLinesPaint); + } + + } + } + } + + public void drawLabels(Canvas canvas) { + PieChartData data = this.dataProvider.getPieChartData(); + float sliceScale = 360.0F / this.maxSum; + float lastAngle = (float)this.rotation; + int sliceIndex = 0; + + for(Iterator var6 = data.getValues().iterator(); var6.hasNext(); ++sliceIndex) { + SliceValue sliceValue = (SliceValue)var6.next(); + float angle = Math.abs(sliceValue.getValue()) * sliceScale; + if (this.hasLabels || (this.hasLabelsOnlyForSelected && this.selectedValue.getFirstIndex() == sliceIndex)) { + this.drawLabel(canvas, sliceValue, lastAngle, angle); + } + + lastAngle += angle; + } + + } + + private void drawSlice(Canvas canvas, SliceValue sliceValue, float lastAngle, float angle, int mode) { + this.sliceVector.set((float)Math.cos(Math.toRadians((double)(lastAngle + angle / 2.0F))), (float)Math.sin(Math.toRadians((double)(lastAngle + angle / 2.0F)))); + this.normalizeVector(this.sliceVector); + this.drawCircleOval.set(this.originCircleOval); + if (1 == mode) { + this.drawCircleOval.inset((float)(-this.touchAdditional), (float)(-this.touchAdditional)); + this.slicePaint.setColor(sliceValue.getDarkenColor()); + canvas.drawArc(this.drawCircleOval, lastAngle, angle, true, this.slicePaint); + } else { + this.slicePaint.setColor(sliceValue.getColor()); + canvas.drawArc(this.drawCircleOval, lastAngle, angle, true, this.slicePaint); + } + + } + + private void drawLabel(Canvas canvas, SliceValue sliceValue, float lastAngle, float angle) { + this.sliceVector.set((float)Math.cos(Math.toRadians((double)(lastAngle + angle / 2.0F))), (float)Math.sin(Math.toRadians((double)(lastAngle + angle / 2.0F)))); + this.normalizeVector(this.sliceVector); + int numChars = this.valueFormatter.formatChartValue(this.labelBuffer, sliceValue); + if (numChars != 0) { + float labelWidth = this.labelPaint.measureText(this.labelBuffer, this.labelBuffer.length - numChars, numChars); + int labelHeight = Math.abs(this.fontMetrics.ascent); + float centerX = this.originCircleOval.centerX(); + float centerY = this.originCircleOval.centerY(); + float circleRadius = this.originCircleOval.width() / 2.0F; + float labelRadius; + if (this.hasLabelsOutside) { + labelRadius = circleRadius * 1.0F; + } else if (this.hasCenterCircle) { + labelRadius = circleRadius - (circleRadius - circleRadius * this.centerCircleScale) / 2.0F; + } else { + labelRadius = circleRadius * 0.7F; + } + + float rawX = labelRadius * this.sliceVector.x + centerX; + float rawY = labelRadius * this.sliceVector.y + centerY; + float left; + float right; + float top; + float bottom; + if (this.hasLabelsOutside) { + if (rawX > centerX) { + left = rawX + (float)this.labelMargin; + right = rawX + labelWidth + (float)(this.labelMargin * 3); + } else { + left = rawX - labelWidth - (float)(this.labelMargin * 3); + right = rawX - (float)this.labelMargin; + } + + if (rawY > centerY) { + top = rawY + (float)this.labelMargin; + bottom = rawY + (float)labelHeight + (float)(this.labelMargin * 3); + } else { + top = rawY - (float)labelHeight - (float)(this.labelMargin * 3); + bottom = rawY - (float)this.labelMargin; + } + } else { + left = rawX - labelWidth / 2.0F - (float)this.labelMargin; + right = rawX + labelWidth / 2.0F + (float)this.labelMargin; + top = rawY - (float)((double)labelHeight / 2) - (float)this.labelMargin; + bottom = rawY + (float)((double)labelHeight / 2) + (float)this.labelMargin; + } + + this.labelBackgroundRect.set(left, top, right, bottom); + this.drawLabelTextAndBackground(canvas, this.labelBuffer, this.labelBuffer.length - numChars, numChars, sliceValue.getDarkenColor()); + } + } + + private void normalizeVector(PointF point) { + float abs = point.length(); + point.set(point.x / abs, point.y / abs); + } + + private float pointToAngle(float x, float y, float centerX, float centerY) { + double diffX = (double)(x - centerX); + double diffY = (double)(y - centerY); + double radian = Math.atan2(-diffX, diffY); + float angle = ((float)Math.toDegrees(radian) + 360.0F) % 360.0F; + angle += 90.0F; + return angle; + } + + private void calculateCircleOval() { + Rect contentRect = this.computator.getContentRectMinusAllMargins(); + float circleRadius = Math.min((float)contentRect.width() / 2.0F, (float)contentRect.height() / 2.0F); + float centerX = (float)contentRect.centerX(); + float centerY = (float)contentRect.centerY(); + float left = centerX - circleRadius + (float)this.touchAdditional; + float top = centerY - circleRadius + (float)this.touchAdditional; + float right = centerX + circleRadius - (float)this.touchAdditional; + float bottom = centerY + circleRadius - (float)this.touchAdditional; + this.originCircleOval.set(left, top, right, bottom); + float inest = 0.5F * this.originCircleOval.width() * (1.0F - this.circleFillRatio); + this.originCircleOval.inset(inest, inest); + } + + private void calculateMaxViewport() { + this.tempMaximumViewport.set(0.0F, 100.0F, 100.0F, 0.0F); + this.maxSum = 0.0F; + + SliceValue sliceValue; + for(Iterator var1 = this.dataProvider.getPieChartData().getValues().iterator(); var1.hasNext(); this.maxSum += Math.abs(sliceValue.getValue())) { + sliceValue = (SliceValue)var1.next(); + } + + } + + public RectF getCircleOval() { + return this.originCircleOval; + } + + public void setCircleOval(RectF orginCircleOval) { + this.originCircleOval = orginCircleOval; + } + + public int getChartRotation() { + return this.rotation; + } + + public void setChartRotation(int rotation) { + rotation = (rotation % 360 + 360) % 360; + this.rotation = rotation; + } + + public SliceValue getValueForAngle(int angle, SelectedValue selectedValue) { + PieChartData data = this.dataProvider.getPieChartData(); + float touchAngle = ((float)(angle - this.rotation) + 360.0F) % 360.0F; + float sliceScale = 360.0F / this.maxSum; + float lastAngle = 0.0F; + int sliceIndex = 0; + + for(Iterator var8 = data.getValues().iterator(); var8.hasNext(); ++sliceIndex) { + SliceValue sliceValue = (SliceValue)var8.next(); + float tempAngle = Math.abs(sliceValue.getValue()) * sliceScale; + if (touchAngle >= lastAngle) { + if (null != selectedValue) { + selectedValue.set(sliceIndex, sliceIndex, SelectedValue.SelectedValueType.NONE); + } + + return sliceValue; + } + + lastAngle += tempAngle; + } + + return null; + } + + public float getCircleFillRatio() { + return this.circleFillRatio; + } + + public void setCircleFillRatio(float fillRatio) { + if (fillRatio < 0.0F) { + fillRatio = 0.0F; + } else if (fillRatio > 1.0F) { + fillRatio = 1.0F; + } + + this.circleFillRatio = fillRatio; + this.calculateCircleOval(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/PreviewColumnChartRenderer.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/PreviewColumnChartRenderer.java new file mode 100644 index 00000000..b879a90a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/PreviewColumnChartRenderer.java @@ -0,0 +1,46 @@ +package dji.v5.ux.core.base.charts.renderer; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; + +import dji.v5.ux.core.base.charts.model.Viewport; +import dji.v5.ux.core.base.charts.provider.ColumnChartDataProvider; +import dji.v5.ux.core.base.charts.util.ChartUtils; +import dji.v5.ux.core.base.charts.view.Chart; + +public class PreviewColumnChartRenderer extends ColumnChartRenderer { + private Paint previewPaint = new Paint(); + + public PreviewColumnChartRenderer(Context context, Chart chart, ColumnChartDataProvider dataProvider) { + super(context, chart, dataProvider); + this.previewPaint.setAntiAlias(true); + this.previewPaint.setColor(-3355444); + this.previewPaint.setStrokeWidth((float) ChartUtils.dp2px(this.density, 2)); + } + + @Override + public void drawUnclipped(Canvas canvas) { + super.drawUnclipped(canvas); + Viewport currentViewport = this.computator.getCurrentViewport(); + float left = this.computator.computeRawX(currentViewport.left); + float top = this.computator.computeRawY(currentViewport.top); + float right = this.computator.computeRawX(currentViewport.right); + float bottom = this.computator.computeRawY(currentViewport.bottom); + this.previewPaint.setAlpha(64); + this.previewPaint.setStyle(Paint.Style.FILL); + canvas.drawRect(left, top, right, bottom, this.previewPaint); + this.previewPaint.setStyle(Paint.Style.STROKE); + this.previewPaint.setAlpha(255); + canvas.drawRect(left, top, right, bottom, this.previewPaint); + } + + public int getPreviewColor() { + return this.previewPaint.getColor(); + } + + public void setPreviewColor(int color) { + this.previewPaint.setColor(color); + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/PreviewLineChartRenderer.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/PreviewLineChartRenderer.java new file mode 100644 index 00000000..d319177f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/renderer/PreviewLineChartRenderer.java @@ -0,0 +1,46 @@ +package dji.v5.ux.core.base.charts.renderer; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; + +import dji.v5.ux.core.base.charts.model.Viewport; +import dji.v5.ux.core.base.charts.provider.LineChartDataProvider; +import dji.v5.ux.core.base.charts.util.ChartUtils; +import dji.v5.ux.core.base.charts.view.Chart; + +public class PreviewLineChartRenderer extends LineChartRenderer { + private Paint previewPaint = new Paint(); + + public PreviewLineChartRenderer(Context context, Chart chart, LineChartDataProvider dataProvider) { + super(context, chart, dataProvider); + this.previewPaint.setAntiAlias(true); + this.previewPaint.setColor(-3355444); + this.previewPaint.setStrokeWidth((float) ChartUtils.dp2px(this.density, 2)); + } + + @Override + public void drawUnclipped(Canvas canvas) { + super.drawUnclipped(canvas); + Viewport currentViewport = this.computator.getCurrentViewport(); + float left = this.computator.computeRawX(currentViewport.left); + float top = this.computator.computeRawY(currentViewport.top); + float right = this.computator.computeRawX(currentViewport.right); + float bottom = this.computator.computeRawY(currentViewport.bottom); + this.previewPaint.setAlpha(64); + this.previewPaint.setStyle(Paint.Style.FILL); + canvas.drawRect(left, top, right, bottom, this.previewPaint); + this.previewPaint.setStyle(Paint.Style.STROKE); + this.previewPaint.setAlpha(255); + canvas.drawRect(left, top, right, bottom, this.previewPaint); + } + + public int getPreviewColor() { + return this.previewPaint.getColor(); + } + + public void setPreviewColor(int color) { + this.previewPaint.setColor(color); + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/util/AxisAutoValues.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/util/AxisAutoValues.java new file mode 100644 index 00000000..e6bf9578 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/util/AxisAutoValues.java @@ -0,0 +1,11 @@ +package dji.v5.ux.core.base.charts.util; + +public class AxisAutoValues { + public float[] values = new float[0]; + public int valuesNumber; + public int decimals; + + public AxisAutoValues() { + //do nothing + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/util/ChartUtils.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/util/ChartUtils.java new file mode 100644 index 00000000..21b2aae5 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/util/ChartUtils.java @@ -0,0 +1,64 @@ +package dji.v5.ux.core.base.charts.util; + +import android.content.Context; +import android.graphics.Color; +import android.util.TypedValue; + +public abstract class ChartUtils { + public static final int DEFAULT_COLOR = Color.parseColor("#DFDFDF"); + public static final int DEFAULT_DARKEN_COLOR = Color.parseColor("#DDDDDD"); + public static final int COLOR_BLUE = Color.parseColor("#33B5E5"); + public static final int COLOR_VIOLET = Color.parseColor("#AA66CC"); + public static final int COLOR_GREEN = Color.parseColor("#99CC00"); + public static final int COLOR_ORANGE = Color.parseColor("#FFBB33"); + public static final int COLOR_RED = Color.parseColor("#FF4444"); + public static final int[] COLORS; + private static int COLOR_INDEX; + + private ChartUtils() { + //do nothing + } + + public static final int nextColor() { + if (COLOR_INDEX >= COLORS.length) { + COLOR_INDEX = 0; + } + + return COLORS[COLOR_INDEX++]; + } + + public static int dp2px(float density, int dp) { + return dp == 0 ? 0 : (int)((float)dp * density + 0.5F); + } + + public static int px2dp(float density, int px) { + return (int)Math.ceil((double)((float)px / density)); + } + + public static int sp2px(float scaledDensity, int sp) { + return sp == 0 ? 0 : (int)((float)sp * scaledDensity + 0.5F); + } + + public static int px2sp(float scaledDensity, int px) { + return (int)Math.ceil((double)((float)px / scaledDensity)); + } + + public static int mm2px(Context context, int mm) { + return (int)(TypedValue.applyDimension(5, (float)mm, context.getResources().getDisplayMetrics()) + 0.5F); + } + + public static int darkenColor(int color) { + float[] hsv = new float[3]; + int alpha = Color.alpha(color); + Color.colorToHSV(color, hsv); + hsv[1] = Math.min(hsv[1] * 1.1F, 1.0F); + hsv[2] *= 0.9F; + int tempColor = Color.HSVToColor(hsv); + return Color.argb(alpha, Color.red(tempColor), Color.green(tempColor), Color.blue(tempColor)); + } + + static { + COLORS = new int[]{COLOR_BLUE, COLOR_VIOLET, COLOR_GREEN, COLOR_ORANGE, COLOR_RED}; + COLOR_INDEX = 0; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/util/FloatUtils.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/util/FloatUtils.java new file mode 100644 index 00000000..5f8cc634 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/util/FloatUtils.java @@ -0,0 +1,165 @@ +package dji.v5.ux.core.base.charts.util; + +public class FloatUtils { + public static final int[] POW10 = new int[]{1, 10, 100, 1000, 10000, 100000, 1000000}; + + private FloatUtils() { + //do nothing + } + + public static float nextUpF(float f) { + if (!Float.isNaN(f) && f != Float.POSITIVE_INFINITY) { + f += 0.0F; + return Float.intBitsToFloat(Float.floatToRawIntBits(f) + (f >= 0.0F ? 1 : -1)); + } else { + return f; + } + } + + public static float nextDownF(float f) { + if (!Float.isNaN(f) && f != Float.NEGATIVE_INFINITY) { + if (f == 0.0F) { + return -1.4E-45F; + } else { + return Float.intBitsToFloat(Float.floatToRawIntBits(f) + (f > 0.0F ? -1 : 1)); + } + } else { + return f; + } + } + + public static double nextUp(double d) { + if (!Double.isNaN(d) && d != Double.POSITIVE_INFINITY) { + d += 0.0; + return Double.longBitsToDouble(Double.doubleToRawLongBits(d) + (long)(d >= 0.0 ? 1 : -1)); + } else { + return d; + } + } + + public static double nextDown(double d) { + if (!Double.isNaN(d) && d != Double.NEGATIVE_INFINITY) { + if (d == 0.0) { + return -1.401298464324817E-45; + } else { + return Double.longBitsToDouble(Double.doubleToRawLongBits(d) + (long) (d > 0.0 ? -1 : 1)); + } + } else { + return d; + } + } + + public static boolean almostEqual(float a, float b, float absoluteDiff, float relativeDiff) { + float diff = Math.abs(a - b); + if (diff <= absoluteDiff) { + return true; + } else { + a = Math.abs(a); + b = Math.abs(b); + float largest = a > b ? a : b; + return diff <= largest * relativeDiff; + } + } + + public static float roundToOneSignificantFigure(double num) { + float d = (float)Math.ceil((double)((float)Math.log10(num < 0.0 ? -num : num))); + int power = 1 - (int)d; + float magnitude = (float)Math.pow(10.0, (double)power); + long shifted = Math.round(num * (double)magnitude); + return (float)shifted / magnitude; + } + + public static int formatFloat(char[] formattedValue, float value, int endIndex, int digits, char separator) { + if (digits >= POW10.length) { + formattedValue[endIndex - 1] = '.'; + return 1; + } else { + boolean negative = false; + if (value == 0.0F) { + formattedValue[endIndex - 1] = '0'; + return 1; + } else { + if (value < 0.0F) { + negative = true; + value = -value; + } + + if (digits > POW10.length) { + digits = POW10.length - 1; + } + + value *= (float)POW10[digits]; + long lval = (long)Math.round(value); + int index = endIndex - 1; + int charsNumber = 0; + + while(lval != 0L || charsNumber < digits + 1) { + int digit = (int)(lval % 10L); + lval /= 10L; + formattedValue[index--] = (char)(digit + 48); + ++charsNumber; + if (charsNumber == digits) { + formattedValue[index--] = separator; + ++charsNumber; + } + } + + if (formattedValue[index + 1] == separator) { + formattedValue[index--] = '0'; + ++charsNumber; + } + + if (negative) { + formattedValue[index] = '-'; + ++charsNumber; + } + + return charsNumber; + } + } + } + + public static void computeAutoGeneratedAxisValues(float start, float stop, int steps, AxisAutoValues outValues) { + double range = (double)(stop - start); + if (steps != 0 && !(range <= 0.0)) { + double rawInterval = range / (double)steps; + double interval = (double)roundToOneSignificantFigure(rawInterval); + double intervalMagnitude = Math.pow(10.0, (double)((int)Math.log10(interval))); + int intervalSigDigit = (int)(interval / intervalMagnitude); + if (intervalSigDigit > 5) { + interval = Math.floor(10.0 * intervalMagnitude); + } + + double first = Math.ceil((double)start / interval) * interval; + double last = nextUp(Math.floor((double)stop / interval) * interval); + int valuesNum = 0; + + double intervalValue; + for(intervalValue = first; intervalValue <= last; intervalValue += interval) { + ++valuesNum; + } + + outValues.valuesNumber = valuesNum; + if (outValues.values.length < valuesNum) { + outValues.values = new float[valuesNum]; + } + + intervalValue = first; + + for(int valueIndex = 0; valueIndex < valuesNum; ++valueIndex) { + outValues.values[valueIndex] = (float)intervalValue; + intervalValue += interval; + } + + if (interval < 1.0) { + outValues.decimals = (int)Math.ceil(-Math.log10(interval)); + } else { + outValues.decimals = 0; + } + + } else { + outValues.values = new float[0]; + outValues.valuesNumber = 0; + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/AbstractChartView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/AbstractChartView.java new file mode 100644 index 00000000..7192f35d --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/AbstractChartView.java @@ -0,0 +1,433 @@ +package dji.v5.ux.core.base.charts.view; + +import android.content.Context; +import android.graphics.Canvas; +import android.os.Build; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; + +import androidx.core.view.ViewCompat; + +import dji.v5.ux.core.base.charts.animation.ChartAnimationListener; +import dji.v5.ux.core.base.charts.animation.ChartDataAnimator; +import dji.v5.ux.core.base.charts.animation.ChartDataAnimatorV14; +import dji.v5.ux.core.base.charts.animation.ChartDataAnimatorV8; +import dji.v5.ux.core.base.charts.animation.ChartViewportAnimator; +import dji.v5.ux.core.base.charts.animation.ChartViewportAnimatorV14; +import dji.v5.ux.core.base.charts.animation.ChartViewportAnimatorV8; +import dji.v5.ux.core.base.charts.computator.ChartComputator; +import dji.v5.ux.core.base.charts.gesture.ChartTouchHandler; +import dji.v5.ux.core.base.charts.gesture.ContainerScrollType; +import dji.v5.ux.core.base.charts.gesture.ZoomType; +import dji.v5.ux.core.base.charts.listener.ViewportChangeListener; +import dji.v5.ux.core.base.charts.model.SelectedValue; +import dji.v5.ux.core.base.charts.model.Viewport; +import dji.v5.ux.core.base.charts.renderer.AxesRenderer; +import dji.v5.ux.core.base.charts.renderer.ChartRenderer; +import dji.v5.ux.core.base.charts.util.ChartUtils; + +public abstract class AbstractChartView extends View implements Chart { + protected ChartComputator chartComputator; + protected AxesRenderer axesRenderer; + protected ChartTouchHandler touchHandler; + protected ChartRenderer chartRenderer; + protected ChartDataAnimator dataAnimator; + protected ChartViewportAnimator viewportAnimator; + protected boolean isInteractive; + protected boolean isContainerScrollEnabled; + protected ContainerScrollType containerScrollType; + + protected AbstractChartView(Context context) { + this(context, (AttributeSet)null, 0); + } + + protected AbstractChartView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + protected AbstractChartView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + this.isInteractive = true; + this.isContainerScrollEnabled = false; + this.chartComputator = new ChartComputator(); + this.touchHandler = new ChartTouchHandler(context, this); + this.axesRenderer = new AxesRenderer(context, this); + if (Build.VERSION.SDK_INT < 14) { + this.dataAnimator = new ChartDataAnimatorV8(this); + this.viewportAnimator = new ChartViewportAnimatorV8(this); + } else { + this.viewportAnimator = new ChartViewportAnimatorV14(this); + this.dataAnimator = new ChartDataAnimatorV14(this); + } + + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight) { + super.onSizeChanged(width, height, oldWidth, oldHeight); + this.chartComputator.setContentRect(this.getWidth(), this.getHeight(), this.getPaddingLeft(), this.getPaddingTop(), this.getPaddingRight(), this.getPaddingBottom()); + this.chartRenderer.onChartSizeChanged(); + this.axesRenderer.onChartSizeChanged(); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (this.isEnabled()) { + this.axesRenderer.drawInBackground(canvas); + int clipRestoreCount = canvas.save(); + canvas.clipRect(this.chartComputator.getContentRectMinusAllMargins()); + this.chartRenderer.draw(canvas); + canvas.restoreToCount(clipRestoreCount); + this.chartRenderer.drawUnclipped(canvas); + this.axesRenderer.drawInForeground(canvas); + } else { + canvas.drawColor(ChartUtils.DEFAULT_COLOR); + } + + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + super.onTouchEvent(event); + if (this.isInteractive) { + boolean needInvalidate; + if (this.isContainerScrollEnabled) { + needInvalidate = this.touchHandler.handleTouchEvent(event, this.getParent(), this.containerScrollType); + } else { + needInvalidate = this.touchHandler.handleTouchEvent(event); + } + + if (needInvalidate) { + ViewCompat.postInvalidateOnAnimation(this); + } + + return true; + } else { + return false; + } + } + + @Override + public void computeScroll() { + super.computeScroll(); + if (this.isInteractive && this.touchHandler.computeScroll()) { + ViewCompat.postInvalidateOnAnimation(this); + } + + } + + public void startDataAnimation() { + this.dataAnimator.startAnimation(Long.MIN_VALUE); + } + + public void startDataAnimation(long duration) { + this.dataAnimator.startAnimation(duration); + } + + public void cancelDataAnimation() { + this.dataAnimator.cancelAnimation(); + } + + public void animationDataUpdate(float scale) { + this.getChartData().update(scale); + this.chartRenderer.onChartViewportChanged(); + ViewCompat.postInvalidateOnAnimation(this); + } + + public void animationDataFinished() { + this.getChartData().finish(); + this.chartRenderer.onChartViewportChanged(); + ViewCompat.postInvalidateOnAnimation(this); + } + + public void setDataAnimationListener(ChartAnimationListener animationListener) { + this.dataAnimator.setChartAnimationListener(animationListener); + } + + public void setViewportAnimationListener(ChartAnimationListener animationListener) { + this.viewportAnimator.setChartAnimationListener(animationListener); + } + + public void setViewportChangeListener(ViewportChangeListener viewportChangeListener) { + this.chartComputator.setViewportChangeListener(viewportChangeListener); + } + + public ChartRenderer getChartRenderer() { + return this.chartRenderer; + } + + public void setChartRenderer(ChartRenderer renderer) { + this.chartRenderer = renderer; + this.resetRendererAndTouchHandler(); + ViewCompat.postInvalidateOnAnimation(this); + } + + public AxesRenderer getAxesRenderer() { + return this.axesRenderer; + } + + public ChartComputator getChartComputator() { + return this.chartComputator; + } + + public ChartTouchHandler getTouchHandler() { + return this.touchHandler; + } + + public boolean isInteractive() { + return this.isInteractive; + } + + public void setInteractive(boolean isInteractive) { + this.isInteractive = isInteractive; + } + + public boolean isZoomEnabled() { + return this.touchHandler.isZoomEnabled(); + } + + public void setZoomEnabled(boolean isZoomEnabled) { + this.touchHandler.setZoomEnabled(isZoomEnabled); + } + + public boolean isScrollEnabled() { + return this.touchHandler.isScrollEnabled(); + } + + public void setScrollEnabled(boolean isScrollEnabled) { + this.touchHandler.setScrollEnabled(isScrollEnabled); + } + + public void moveTo(float x, float y) { + Viewport scrollViewport = this.computeScrollViewport(x, y); + this.setCurrentViewport(scrollViewport); + } + + public void moveToWithAnimation(float x, float y) { + Viewport scrollViewport = this.computeScrollViewport(x, y); + this.setCurrentViewportWithAnimation(scrollViewport); + } + + private Viewport computeScrollViewport(float x, float y) { + Viewport maxViewport = this.getMaximumViewport(); + Viewport currentViewport = this.getCurrentViewport(); + Viewport scrollViewport = new Viewport(currentViewport); + if (maxViewport.contains(x, y)) { + float width = currentViewport.width(); + float height = currentViewport.height(); + float halfWidth = width / 2.0F; + float halfHeight = height / 2.0F; + float left = x - halfWidth; + float top = y + halfHeight; + left = Math.max(maxViewport.left, Math.min(left, maxViewport.right - width)); + top = Math.max(maxViewport.bottom + height, Math.min(top, maxViewport.top)); + scrollViewport.set(left, top, left + width, top - height); + } + + return scrollViewport; + } + + public boolean isValueTouchEnabled() { + return this.touchHandler.isValueTouchEnabled(); + } + + public void setValueTouchEnabled(boolean isValueTouchEnabled) { + this.touchHandler.setValueTouchEnabled(isValueTouchEnabled); + } + + public ZoomType getZoomType() { + return this.touchHandler.getZoomType(); + } + + public void setZoomType(ZoomType zoomType) { + this.touchHandler.setZoomType(zoomType); + } + + public float getMaxZoom() { + return this.chartComputator.getMaxZoom(); + } + + public void setMaxZoom(float maxZoom) { + this.chartComputator.setMaxZoom(maxZoom); + ViewCompat.postInvalidateOnAnimation(this); + } + + public float getZoomLevel() { + Viewport maxViewport = this.getMaximumViewport(); + Viewport currentViewport = this.getCurrentViewport(); + return Math.max(maxViewport.width() / currentViewport.width(), maxViewport.height() / currentViewport.height()); + } + + public void setZoomLevel(float x, float y, float zoomLevel) { + Viewport zoomViewport = this.computeZoomViewport(x, y, zoomLevel); + this.setCurrentViewport(zoomViewport); + } + + public void setZoomLevelWithAnimation(float x, float y, float zoomLevel) { + Viewport zoomViewport = this.computeZoomViewport(x, y, zoomLevel); + this.setCurrentViewportWithAnimation(zoomViewport); + } + + private Viewport computeZoomViewport(float x, float y, float zoomLevel) { + Viewport maxViewport = this.getMaximumViewport(); + Viewport zoomViewport = new Viewport(this.getMaximumViewport()); + if (maxViewport.contains(x, y)) { + if (zoomLevel < 1.0F) { + zoomLevel = 1.0F; + } else if (zoomLevel > this.getMaxZoom()) { + zoomLevel = this.getMaxZoom(); + } + + float newWidth = zoomViewport.width() / zoomLevel; + float newHeight = zoomViewport.height() / zoomLevel; + float halfWidth = newWidth / 2.0F; + float halfHeight = newHeight / 2.0F; + float left = x - halfWidth; + float right = x + halfWidth; + float top = y + halfHeight; + float bottom = y - halfHeight; + if (left < maxViewport.left) { + left = maxViewport.left; + right = left + newWidth; + } else if (right > maxViewport.right) { + right = maxViewport.right; + left = right - newWidth; + } + + if (top > maxViewport.top) { + top = maxViewport.top; + bottom = top - newHeight; + } else if (bottom < maxViewport.bottom) { + bottom = maxViewport.bottom; + top = bottom + newHeight; + } + + ZoomType zoomType = this.getZoomType(); + if (ZoomType.HORIZONTAL_AND_VERTICAL == zoomType) { + zoomViewport.set(left, top, right, bottom); + } else if (ZoomType.HORIZONTAL == zoomType) { + zoomViewport.left = left; + zoomViewport.right = right; + } else if (ZoomType.VERTICAL == zoomType) { + zoomViewport.top = top; + zoomViewport.bottom = bottom; + } + } + + return zoomViewport; + } + + public Viewport getMaximumViewport() { + return this.chartRenderer.getMaximumViewport(); + } + + public void setMaximumViewport(Viewport maxViewport) { + this.chartRenderer.setMaximumViewport(maxViewport); + ViewCompat.postInvalidateOnAnimation(this); + } + + public void setCurrentViewportWithAnimation(Viewport targetViewport) { + if (null != targetViewport) { + this.viewportAnimator.cancelAnimation(); + this.viewportAnimator.startAnimation(this.getCurrentViewport(), targetViewport); + } + + ViewCompat.postInvalidateOnAnimation(this); + } + + public void setCurrentViewportWithAnimation(Viewport targetViewport, long duration) { + if (null != targetViewport) { + this.viewportAnimator.cancelAnimation(); + this.viewportAnimator.startAnimation(this.getCurrentViewport(), targetViewport, duration); + } + + ViewCompat.postInvalidateOnAnimation(this); + } + + public Viewport getCurrentViewport() { + return this.getChartRenderer().getCurrentViewport(); + } + + public void setCurrentViewport(Viewport targetViewport) { + if (null != targetViewport) { + this.chartRenderer.setCurrentViewport(targetViewport); + } + + ViewCompat.postInvalidateOnAnimation(this); + } + + public void resetViewports() { + this.chartRenderer.setMaximumViewport((Viewport)null); + this.chartRenderer.setCurrentViewport((Viewport)null); + } + + public boolean isViewportCalculationEnabled() { + return this.chartRenderer.isViewportCalculationEnabled(); + } + + public void setViewportCalculationEnabled(boolean isEnabled) { + this.chartRenderer.setViewportCalculationEnabled(isEnabled); + } + + public boolean isValueSelectionEnabled() { + return this.touchHandler.isValueSelectionEnabled(); + } + + public void setValueSelectionEnabled(boolean isValueSelectionEnabled) { + this.touchHandler.setValueSelectionEnabled(isValueSelectionEnabled); + } + + public void selectValue(SelectedValue selectedValue) { + this.chartRenderer.selectValue(selectedValue); + this.callTouchListener(); + ViewCompat.postInvalidateOnAnimation(this); + } + + public SelectedValue getSelectedValue() { + return this.chartRenderer.getSelectedValue(); + } + + public boolean isContainerScrollEnabled() { + return this.isContainerScrollEnabled; + } + + public void setContainerScrollEnabled(boolean isContainerScrollEnabled, ContainerScrollType containerScrollType) { + this.isContainerScrollEnabled = isContainerScrollEnabled; + this.containerScrollType = containerScrollType; + } + + protected void onChartDataChange() { + this.chartComputator.resetContentRect(); + this.chartRenderer.onChartDataChanged(); + this.axesRenderer.onChartDataChanged(); + ViewCompat.postInvalidateOnAnimation(this); + } + + protected void resetRendererAndTouchHandler() { + this.chartRenderer.resetRenderer(); + this.axesRenderer.resetRenderer(); + this.touchHandler.resetTouchHandler(); + } + + @Override + public boolean canScrollHorizontally(int direction) { + if ((double)this.getZoomLevel() <= 1.0) { + return false; + } else { + Viewport currentViewport = this.getCurrentViewport(); + Viewport maximumViewport = this.getMaximumViewport(); + if (direction < 0) { + return currentViewport.left > maximumViewport.left; + } else { + return currentViewport.right < maximumViewport.right; + } + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/BubbleChartView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/BubbleChartView.java new file mode 100644 index 00000000..6ffb84a4 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/BubbleChartView.java @@ -0,0 +1,89 @@ +package dji.v5.ux.core.base.charts.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; + +import androidx.core.view.ViewCompat; + +import dji.v5.ux.BuildConfig; +import dji.v5.ux.core.base.charts.listener.BubbleChartOnValueSelectListener; +import dji.v5.ux.core.base.charts.listener.DummyBubbleChartOnValueSelectListener; +import dji.v5.ux.core.base.charts.model.BubbleChartData; +import dji.v5.ux.core.base.charts.model.BubbleValue; +import dji.v5.ux.core.base.charts.model.ChartData; +import dji.v5.ux.core.base.charts.model.SelectedValue; +import dji.v5.ux.core.base.charts.provider.BubbleChartDataProvider; +import dji.v5.ux.core.base.charts.renderer.BubbleChartRenderer; + +public class BubbleChartView extends AbstractChartView implements BubbleChartDataProvider { + protected BubbleChartData data; + protected BubbleChartOnValueSelectListener onValueTouchListener; + protected BubbleChartRenderer bubbleChartRenderer; + + public BubbleChartView(Context context) { + this(context, (AttributeSet)null, 0); + } + + public BubbleChartView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public BubbleChartView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + this.onValueTouchListener = new DummyBubbleChartOnValueSelectListener(); + this.bubbleChartRenderer = new BubbleChartRenderer(context, this, this); + this.setChartRenderer(this.bubbleChartRenderer); + this.setBubbleChartData(BubbleChartData.generateDummyData()); + } + + public BubbleChartData getBubbleChartData() { + return this.data; + } + + public void setBubbleChartData(BubbleChartData data) { + if (BuildConfig.DEBUG) { + Log.d("BubbleChartView", "Setting data for BubbleChartView"); + } + + if (null == data) { + this.data = BubbleChartData.generateDummyData(); + } else { + this.data = data; + } + + super.onChartDataChange(); + } + + public ChartData getChartData() { + return this.data; + } + + public void callTouchListener() { + SelectedValue selectedValue = this.chartRenderer.getSelectedValue(); + if (selectedValue.isSet()) { + BubbleValue value = (BubbleValue)this.data.getValues().get(selectedValue.getFirstIndex()); + this.onValueTouchListener.onValueSelected(selectedValue.getFirstIndex(), value); + } else { + this.onValueTouchListener.onValueDeselected(); + } + + } + + public BubbleChartOnValueSelectListener getOnValueTouchListener() { + return this.onValueTouchListener; + } + + public void setOnValueTouchListener(BubbleChartOnValueSelectListener touchListener) { + if (null != touchListener) { + this.onValueTouchListener = touchListener; + } + + } + + public void removeMargins() { + this.bubbleChartRenderer.removeMargins(); + ViewCompat.postInvalidateOnAnimation(this); + } +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/Chart.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/Chart.java new file mode 100644 index 00000000..257d5438 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/Chart.java @@ -0,0 +1,109 @@ +package dji.v5.ux.core.base.charts.view; + +import dji.v5.ux.core.base.charts.animation.ChartAnimationListener; +import dji.v5.ux.core.base.charts.computator.ChartComputator; +import dji.v5.ux.core.base.charts.gesture.ChartTouchHandler; +import dji.v5.ux.core.base.charts.gesture.ContainerScrollType; +import dji.v5.ux.core.base.charts.gesture.ZoomType; +import dji.v5.ux.core.base.charts.listener.ViewportChangeListener; +import dji.v5.ux.core.base.charts.model.ChartData; +import dji.v5.ux.core.base.charts.model.SelectedValue; +import dji.v5.ux.core.base.charts.model.Viewport; +import dji.v5.ux.core.base.charts.renderer.AxesRenderer; +import dji.v5.ux.core.base.charts.renderer.ChartRenderer; + +public interface Chart { + ChartData getChartData(); + + ChartRenderer getChartRenderer(); + + void setChartRenderer(ChartRenderer var1); + + AxesRenderer getAxesRenderer(); + + ChartComputator getChartComputator(); + + ChartTouchHandler getTouchHandler(); + + void animationDataUpdate(float var1); + + void animationDataFinished(); + + void startDataAnimation(); + + void startDataAnimation(long var1); + + void cancelDataAnimation(); + + boolean isViewportCalculationEnabled(); + + void setViewportCalculationEnabled(boolean var1); + + void setDataAnimationListener(ChartAnimationListener var1); + + void setViewportAnimationListener(ChartAnimationListener var1); + + void setViewportChangeListener(ViewportChangeListener var1); + + void callTouchListener(); + + boolean isInteractive(); + + void setInteractive(boolean var1); + + boolean isZoomEnabled(); + + void setZoomEnabled(boolean var1); + + boolean isScrollEnabled(); + + void setScrollEnabled(boolean var1); + + void moveTo(float var1, float var2); + + void moveToWithAnimation(float var1, float var2); + + ZoomType getZoomType(); + + void setZoomType(ZoomType var1); + + float getMaxZoom(); + + void setMaxZoom(float var1); + + float getZoomLevel(); + + void setZoomLevel(float var1, float var2, float var3); + + void setZoomLevelWithAnimation(float var1, float var2, float var3); + + boolean isValueTouchEnabled(); + + void setValueTouchEnabled(boolean var1); + + Viewport getMaximumViewport(); + + void setMaximumViewport(Viewport var1); + + Viewport getCurrentViewport(); + + void setCurrentViewport(Viewport var1); + + void setCurrentViewportWithAnimation(Viewport var1); + + void setCurrentViewportWithAnimation(Viewport var1, long var2); + + void resetViewports(); + + boolean isValueSelectionEnabled(); + + void setValueSelectionEnabled(boolean var1); + + void selectValue(SelectedValue var1); + + SelectedValue getSelectedValue(); + + boolean isContainerScrollEnabled(); + + void setContainerScrollEnabled(boolean var1, ContainerScrollType var2); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/ColumnChartView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/ColumnChartView.java new file mode 100644 index 00000000..1c57e2a3 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/ColumnChartView.java @@ -0,0 +1,79 @@ +package dji.v5.ux.core.base.charts.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; + +import dji.v5.ux.BuildConfig; +import dji.v5.ux.core.base.charts.listener.ColumnChartOnValueSelectListener; +import dji.v5.ux.core.base.charts.listener.DummyColumnChartOnValueSelectListener; +import dji.v5.ux.core.base.charts.model.Column; +import dji.v5.ux.core.base.charts.model.ColumnChartData; +import dji.v5.ux.core.base.charts.model.SelectedValue; +import dji.v5.ux.core.base.charts.model.SubcolumnValue; +import dji.v5.ux.core.base.charts.provider.ColumnChartDataProvider; +import dji.v5.ux.core.base.charts.renderer.ColumnChartRenderer; + +public class ColumnChartView extends AbstractChartView implements ColumnChartDataProvider { + private ColumnChartData data; + private ColumnChartOnValueSelectListener onValueTouchListener; + + public ColumnChartView(Context context) { + this(context, (AttributeSet)null, 0); + } + + public ColumnChartView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public ColumnChartView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + this.onValueTouchListener = new DummyColumnChartOnValueSelectListener(); + this.setChartRenderer(new ColumnChartRenderer(context, this, this)); + this.setColumnChartData(ColumnChartData.generateDummyData()); + } + + public ColumnChartData getColumnChartData() { + return this.data; + } + + public void setColumnChartData(ColumnChartData data) { + if ( BuildConfig.DEBUG) { + Log.d("ColumnChartView", "Setting data for ColumnChartView"); + } + + if (null == data) { + this.data = ColumnChartData.generateDummyData(); + } else { + this.data = data; + } + + super.onChartDataChange(); + } + + public ColumnChartData getChartData() { + return this.data; + } + + public void callTouchListener() { + SelectedValue selectedValue = this.chartRenderer.getSelectedValue(); + if (selectedValue.isSet()) { + SubcolumnValue value = (SubcolumnValue)((Column)this.data.getColumns().get(selectedValue.getFirstIndex())).getValues().get(selectedValue.getSecondIndex()); + this.onValueTouchListener.onValueSelected(selectedValue.getFirstIndex(), selectedValue.getSecondIndex(), value); + } else { + this.onValueTouchListener.onValueDeselected(); + } + + } + + public ColumnChartOnValueSelectListener getOnValueTouchListener() { + return this.onValueTouchListener; + } + + public void setOnValueTouchListener(ColumnChartOnValueSelectListener touchListener) { + if (null != touchListener) { + this.onValueTouchListener = touchListener; + } + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/ComboLineColumnChartView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/ComboLineColumnChartView.java new file mode 100644 index 00000000..35b276b5 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/ComboLineColumnChartView.java @@ -0,0 +1,135 @@ +package dji.v5.ux.core.base.charts.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; + +import dji.v5.ux.BuildConfig; +import dji.v5.ux.core.base.charts.listener.ComboLineColumnChartOnValueSelectListener; +import dji.v5.ux.core.base.charts.listener.DummyCompoLineColumnChartOnValueSelectListener; +import dji.v5.ux.core.base.charts.model.ChartData; +import dji.v5.ux.core.base.charts.model.Column; +import dji.v5.ux.core.base.charts.model.ColumnChartData; +import dji.v5.ux.core.base.charts.model.ComboLineColumnChartData; +import dji.v5.ux.core.base.charts.model.Line; +import dji.v5.ux.core.base.charts.model.LineChartData; +import dji.v5.ux.core.base.charts.model.PointValue; +import dji.v5.ux.core.base.charts.model.SelectedValue; +import dji.v5.ux.core.base.charts.model.SubcolumnValue; +import dji.v5.ux.core.base.charts.provider.ColumnChartDataProvider; +import dji.v5.ux.core.base.charts.provider.ComboLineColumnChartDataProvider; +import dji.v5.ux.core.base.charts.provider.LineChartDataProvider; +import dji.v5.ux.core.base.charts.renderer.ColumnChartRenderer; +import dji.v5.ux.core.base.charts.renderer.ComboLineColumnChartRenderer; +import dji.v5.ux.core.base.charts.renderer.LineChartRenderer; + +public class ComboLineColumnChartView extends AbstractChartView implements ComboLineColumnChartDataProvider { + protected ComboLineColumnChartData data; + protected ColumnChartDataProvider columnChartDataProvider; + protected LineChartDataProvider lineChartDataProvider; + protected ComboLineColumnChartOnValueSelectListener onValueTouchListener; + + public ComboLineColumnChartView(Context context) { + this(context, (AttributeSet)null, 0); + } + + public ComboLineColumnChartView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public ComboLineColumnChartView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + this.columnChartDataProvider = new ComboColumnChartDataProvider(); + this.lineChartDataProvider = new ComboLineChartDataProvider(); + this.onValueTouchListener = new DummyCompoLineColumnChartOnValueSelectListener(); + this.setChartRenderer(new ComboLineColumnChartRenderer(context, this, this.columnChartDataProvider, this.lineChartDataProvider)); + this.setComboLineColumnChartData(ComboLineColumnChartData.generateDummyData()); + } + + public ComboLineColumnChartData getComboLineColumnChartData() { + return this.data; + } + + public void setComboLineColumnChartData(ComboLineColumnChartData data) { + if (BuildConfig.DEBUG) { + Log.d("ComboLineColumnChartView", "Setting data for ComboLineColumnChartView"); + } + + if (null == data) { + this.data = null; + } else { + this.data = data; + } + + super.onChartDataChange(); + } + + public ChartData getChartData() { + return this.data; + } + + public void callTouchListener() { + SelectedValue selectedValue = this.chartRenderer.getSelectedValue(); + if (selectedValue.isSet()) { + if (SelectedValue.SelectedValueType.COLUMN.equals(selectedValue.getType())) { + SubcolumnValue value = (SubcolumnValue)((Column)this.data.getColumnChartData().getColumns().get(selectedValue.getFirstIndex())).getValues().get(selectedValue.getSecondIndex()); + this.onValueTouchListener.onColumnValueSelected(selectedValue.getFirstIndex(), selectedValue.getSecondIndex(), value); + } else { + if (!SelectedValue.SelectedValueType.LINE.equals(selectedValue.getType())) { + throw new IllegalArgumentException("Invalid selected value type " + selectedValue.getType().name()); + } + + PointValue value = (PointValue)((Line)this.data.getLineChartData().getLines().get(selectedValue.getFirstIndex())).getValues().get(selectedValue.getSecondIndex()); + this.onValueTouchListener.onPointValueSelected(selectedValue.getFirstIndex(), selectedValue.getSecondIndex(), value); + } + } else { + this.onValueTouchListener.onValueDeselected(); + } + + } + + public ComboLineColumnChartOnValueSelectListener getOnValueTouchListener() { + return this.onValueTouchListener; + } + + public void setOnValueTouchListener(ComboLineColumnChartOnValueSelectListener touchListener) { + if (null != touchListener) { + this.onValueTouchListener = touchListener; + } + + } + + public void setColumnChartRenderer(Context context, ColumnChartRenderer columnChartRenderer) { + this.setChartRenderer(new ComboLineColumnChartRenderer(context, this, columnChartRenderer, this.lineChartDataProvider)); + } + + public void setLineChartRenderer(Context context, LineChartRenderer lineChartRenderer) { + this.setChartRenderer(new ComboLineColumnChartRenderer(context, this, this.columnChartDataProvider, lineChartRenderer)); + } + + private class ComboColumnChartDataProvider implements ColumnChartDataProvider { + private ComboColumnChartDataProvider() { + } + + public ColumnChartData getColumnChartData() { + return ComboLineColumnChartView.this.data.getColumnChartData(); + } + + public void setColumnChartData(ColumnChartData data) { + ComboLineColumnChartView.this.data.setColumnChartData(data); + } + } + + private class ComboLineChartDataProvider implements LineChartDataProvider { + private ComboLineChartDataProvider() { + } + + public LineChartData getLineChartData() { + return ComboLineColumnChartView.this.data.getLineChartData(); + } + + public void setLineChartData(LineChartData data) { + ComboLineColumnChartView.this.data.setLineChartData(data); + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/LineChartView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/LineChartView.java new file mode 100644 index 00000000..0d0c3d2f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/LineChartView.java @@ -0,0 +1,88 @@ +package dji.v5.ux.core.base.charts.view; + +import android.content.Context; +import android.graphics.Shader; +import android.util.AttributeSet; +import android.util.Log; + +import dji.v5.ux.BuildConfig; +import dji.v5.ux.core.base.charts.listener.DummyLineChartOnValueSelectListener; +import dji.v5.ux.core.base.charts.listener.LineChartOnValueSelectListener; +import dji.v5.ux.core.base.charts.model.ChartData; +import dji.v5.ux.core.base.charts.model.Line; +import dji.v5.ux.core.base.charts.model.LineChartData; +import dji.v5.ux.core.base.charts.model.PointValue; +import dji.v5.ux.core.base.charts.model.SelectedValue; +import dji.v5.ux.core.base.charts.provider.LineChartDataProvider; +import dji.v5.ux.core.base.charts.renderer.LineChartRenderer; + +public class LineChartView extends AbstractChartView implements LineChartDataProvider { + protected LineChartData data; + protected LineChartOnValueSelectListener onValueTouchListener; + + public LineChartView(Context context) { + this(context, (AttributeSet)null, 0); + } + + public LineChartView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public LineChartView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + this.onValueTouchListener = new DummyLineChartOnValueSelectListener(); + this.setChartRenderer(new LineChartRenderer(context, this, this)); + this.setLineChartData(LineChartData.generateDummyData()); + } + + public LineChartData getLineChartData() { + return this.data; + } + + public void setLineChartData(LineChartData data) { + if (BuildConfig.DEBUG) { + Log.d("LineChartView", "Setting data for LineChartView"); + } + + if (null == data) { + this.data = LineChartData.generateDummyData(); + } else { + this.data = data; + } + + super.onChartDataChange(); + } + + public ChartData getChartData() { + return this.data; + } + + public void callTouchListener() { + SelectedValue selectedValue = this.chartRenderer.getSelectedValue(); + if (selectedValue.isSet()) { + PointValue point = (PointValue)((Line)this.data.getLines().get(selectedValue.getFirstIndex())).getValues().get(selectedValue.getSecondIndex()); + this.onValueTouchListener.onValueSelected(selectedValue.getFirstIndex(), selectedValue.getSecondIndex(), point); + } else { + this.onValueTouchListener.onValueDeselected(); + } + + } + + public LineChartOnValueSelectListener getOnValueTouchListener() { + return this.onValueTouchListener; + } + + public void setOnValueTouchListener(LineChartOnValueSelectListener touchListener) { + if (null != touchListener) { + this.onValueTouchListener = touchListener; + } + + } + + public void setLineShader(Shader shader) { + if (this.chartRenderer instanceof LineChartRenderer) { + ((LineChartRenderer)this.chartRenderer).setShader(shader); + } + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/PieChartView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/PieChartView.java new file mode 100644 index 00000000..0cd2e4c5 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/PieChartView.java @@ -0,0 +1,145 @@ +package dji.v5.ux.core.base.charts.view; + +import android.content.Context; +import android.graphics.RectF; +import android.os.Build; +import android.util.AttributeSet; +import android.util.Log; + +import androidx.core.view.ViewCompat; + +import dji.v5.ux.BuildConfig; +import dji.v5.ux.core.base.charts.animation.PieChartRotationAnimator; +import dji.v5.ux.core.base.charts.animation.PieChartRotationAnimatorV14; +import dji.v5.ux.core.base.charts.animation.PieChartRotationAnimatorV8; +import dji.v5.ux.core.base.charts.gesture.PieChartTouchHandler; +import dji.v5.ux.core.base.charts.listener.DummyPieChartOnValueSelectListener; +import dji.v5.ux.core.base.charts.listener.PieChartOnValueSelectListener; +import dji.v5.ux.core.base.charts.model.ChartData; +import dji.v5.ux.core.base.charts.model.PieChartData; +import dji.v5.ux.core.base.charts.model.SelectedValue; +import dji.v5.ux.core.base.charts.model.SliceValue; +import dji.v5.ux.core.base.charts.provider.PieChartDataProvider; +import dji.v5.ux.core.base.charts.renderer.PieChartRenderer; + +public class PieChartView extends AbstractChartView implements PieChartDataProvider { + protected PieChartData data; + protected PieChartOnValueSelectListener onValueTouchListener; + protected PieChartRenderer pieChartRenderer; + protected PieChartRotationAnimator rotationAnimator; + + public PieChartView(Context context) { + this(context, (AttributeSet)null, 0); + } + + public PieChartView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public PieChartView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + this.onValueTouchListener = new DummyPieChartOnValueSelectListener(); + this.pieChartRenderer = new PieChartRenderer(context, this, this); + this.touchHandler = new PieChartTouchHandler(context, this); + this.setChartRenderer(this.pieChartRenderer); + if (Build.VERSION.SDK_INT < 14) { + this.rotationAnimator = new PieChartRotationAnimatorV8(this); + } else { + this.rotationAnimator = new PieChartRotationAnimatorV14(this); + } + + this.setPieChartData(PieChartData.generateDummyData()); + } + + public PieChartData getPieChartData() { + return this.data; + } + + public void setPieChartData(PieChartData data) { + if (BuildConfig.DEBUG) { + Log.d("PieChartView", "Setting data for ColumnChartView"); + } + + if (null == data) { + this.data = PieChartData.generateDummyData(); + } else { + this.data = data; + } + + super.onChartDataChange(); + } + + public ChartData getChartData() { + return this.data; + } + + public void callTouchListener() { + SelectedValue selectedValue = this.chartRenderer.getSelectedValue(); + if (selectedValue.isSet()) { + SliceValue sliceValue = (SliceValue)this.data.getValues().get(selectedValue.getFirstIndex()); + this.onValueTouchListener.onValueSelected(selectedValue.getFirstIndex(), sliceValue); + } else { + this.onValueTouchListener.onValueDeselected(); + } + + } + + public PieChartOnValueSelectListener getOnValueTouchListener() { + return this.onValueTouchListener; + } + + public void setOnValueTouchListener(PieChartOnValueSelectListener touchListener) { + if (null != touchListener) { + this.onValueTouchListener = touchListener; + } + + } + + public RectF getCircleOval() { + return this.pieChartRenderer.getCircleOval(); + } + + public void setCircleOval(RectF orginCircleOval) { + this.pieChartRenderer.setCircleOval(orginCircleOval); + ViewCompat.postInvalidateOnAnimation(this); + } + + public int getChartRotation() { + return this.pieChartRenderer.getChartRotation(); + } + + public void setChartRotation(int rotation, boolean isAnimated) { + if (isAnimated) { + this.rotationAnimator.cancelAnimation(); + this.rotationAnimator.startAnimation((float)this.pieChartRenderer.getChartRotation(), (float)rotation); + } else { + this.pieChartRenderer.setChartRotation(rotation); + } + + ViewCompat.postInvalidateOnAnimation(this); + } + + public boolean isChartRotationEnabled() { + return this.touchHandler instanceof PieChartTouchHandler ? ((PieChartTouchHandler)this.touchHandler).isRotationEnabled() : false; + } + + public void setChartRotationEnabled(boolean isRotationEnabled) { + if (this.touchHandler instanceof PieChartTouchHandler) { + ((PieChartTouchHandler)this.touchHandler).setRotationEnabled(isRotationEnabled); + } + + } + + public SliceValue getValueForAngle(int angle, SelectedValue selectedValue) { + return this.pieChartRenderer.getValueForAngle(angle, selectedValue); + } + + public float getCircleFillRatio() { + return this.pieChartRenderer.getCircleFillRatio(); + } + + public void setCircleFillRatio(float fillRatio) { + this.pieChartRenderer.setCircleFillRatio(fillRatio); + ViewCompat.postInvalidateOnAnimation(this); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/PreviewColumnChartView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/PreviewColumnChartView.java new file mode 100644 index 00000000..4a2ff2f4 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/PreviewColumnChartView.java @@ -0,0 +1,60 @@ +package dji.v5.ux.core.base.charts.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; + +import androidx.core.view.ViewCompat; + +import dji.v5.ux.BuildConfig; +import dji.v5.ux.core.base.charts.computator.PreviewChartComputator; +import dji.v5.ux.core.base.charts.gesture.PreviewChartTouchHandler; +import dji.v5.ux.core.base.charts.model.ColumnChartData; +import dji.v5.ux.core.base.charts.renderer.PreviewColumnChartRenderer; + +public class PreviewColumnChartView extends ColumnChartView { + protected PreviewColumnChartRenderer previewChartRenderer; + + public PreviewColumnChartView(Context context) { + this(context, (AttributeSet)null, 0); + } + + public PreviewColumnChartView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public PreviewColumnChartView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + this.chartComputator = new PreviewChartComputator(); + this.previewChartRenderer = new PreviewColumnChartRenderer(context, this, this); + this.touchHandler = new PreviewChartTouchHandler(context, this); + this.setChartRenderer(this.previewChartRenderer); + this.setColumnChartData(ColumnChartData.generateDummyData()); + } + + public int getPreviewColor() { + return this.previewChartRenderer.getPreviewColor(); + } + + public void setPreviewColor(int color) { + if (BuildConfig.DEBUG) { + Log.d("ColumnChartView", "Changing preview area color"); + } + + this.previewChartRenderer.setPreviewColor(color); + ViewCompat.postInvalidateOnAnimation(this); + } + + @Override + public boolean canScrollHorizontally(int direction) { + int offset = this.computeHorizontalScrollOffset(); + int range = this.computeHorizontalScrollRange() - this.computeHorizontalScrollExtent(); + if (range == 0) { + return false; + } else if (direction < 0) { + return offset > 0; + } else { + return offset < range - 1; + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/PreviewLineChartView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/PreviewLineChartView.java new file mode 100644 index 00000000..004144dd --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/charts/view/PreviewLineChartView.java @@ -0,0 +1,60 @@ +package dji.v5.ux.core.base.charts.view; + +import android.content.Context; +import android.util.AttributeSet; +import android.util.Log; + +import androidx.core.view.ViewCompat; + +import dji.v5.ux.BuildConfig; +import dji.v5.ux.core.base.charts.computator.PreviewChartComputator; +import dji.v5.ux.core.base.charts.gesture.PreviewChartTouchHandler; +import dji.v5.ux.core.base.charts.model.LineChartData; +import dji.v5.ux.core.base.charts.renderer.PreviewLineChartRenderer; + +public class PreviewLineChartView extends LineChartView { + protected PreviewLineChartRenderer previewChartRenderer; + + public PreviewLineChartView(Context context) { + this(context, (AttributeSet)null, 0); + } + + public PreviewLineChartView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public PreviewLineChartView(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + this.chartComputator = new PreviewChartComputator(); + this.previewChartRenderer = new PreviewLineChartRenderer(context, this, this); + this.touchHandler = new PreviewChartTouchHandler(context, this); + this.setChartRenderer(this.previewChartRenderer); + this.setLineChartData(LineChartData.generateDummyData()); + } + + public int getPreviewColor() { + return this.previewChartRenderer.getPreviewColor(); + } + + public void setPreviewColor(int color) { + if (BuildConfig.DEBUG) { + Log.d("PreviewLineChartView", "Changing preview area color"); + } + + this.previewChartRenderer.setPreviewColor(color); + ViewCompat.postInvalidateOnAnimation(this); + } + + @Override + public boolean canScrollHorizontally(int direction) { + int offset = this.computeHorizontalScrollOffset(); + int range = this.computeHorizontalScrollRange() - this.computeHorizontalScrollExtent(); + if (range == 0) { + return false; + } else if (direction < 0) { + return offset > 0; + } else { + return offset < range - 1; + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/BarPanelWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/BarPanelWidget.kt new file mode 100644 index 00000000..18308e0b --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/BarPanelWidget.kt @@ -0,0 +1,641 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base.panel + +import android.annotation.SuppressLint +import android.content.Context +import android.util.AttributeSet +import android.view.ViewGroup +import androidx.annotation.FloatRange +import androidx.annotation.IntRange +import androidx.constraintlayout.widget.ConstraintSet +import androidx.constraintlayout.widget.Guideline +import androidx.core.content.res.use +import dji.v5.ux.R +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.panel.BarPanelWidget.BarPanelWidgetOrientation +import dji.v5.ux.core.extension.getDimensionAndUse +import dji.v5.ux.core.extension.getFloatAndUse +import dji.v5.ux.core.extension.getIntAndUse +import dji.v5.ux.core.util.ViewIDGenerator + +/** + * Base class for [BarPanelWidget]s. A BarPanelWidget is a collection of simple widgets that + * can be grouped together in two orientations: + * [BarPanelWidgetOrientation.VERTICAL] or [BarPanelWidgetOrientation.HORIZONTAL]. + * This type of [PanelWidget] is primarily used for the application's top bar or similarly sized + * widgets. + * The BarPanelWidget is split into two lists: left and right (in vertical orientation left is + * equivalent to top and right to bottom.) + * BarPanelWidgets don't have title bars or close bars. + * To initialize the BarPanelWidget, pass a list of [PanelItem] using [BarPanelWidget.addLeftWidgets] + * and/or [BarPanelWidget.addRightWidgets]. + * + * Note that child widgets are not created dynamically, instead they are created when the + * BarPanelWidget is created. + * + * @property orientation The current BarPanelWidget orientation. + */ +abstract class BarPanelWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + val orientation: BarPanelWidgetOrientation +) : PanelWidget( + context, + attrs, + defStyleAttr, + PanelWidgetConfiguration(context, orientation.toPanelWidgetType()) +) { + + //region Customization Properties + /** + * Margin for the left side of the BarPanelWidget. + */ + @IntRange(from = 0) + var itemsMarginLeft: Int = 0 + set(value) { + field = value + updateUI() + } + + /** + * Margin for the top side of the BarPanelWidget. + */ + @IntRange(from = 0) + var itemsMarginTop: Int = 0 + set(value) { + field = value + updateUI() + } + + /** + * Margin for the right side of the BarPanelWidget. + */ + @IntRange(from = 0) + var itemsMarginRight: Int = 0 + set(value) { + field = value + updateUI() + } + + /** + * Margin for the bottom side of the BarPanelWidget. + */ + @IntRange(from = 0) + var itemsMarginBottom: Int = 0 + set(value) { + field = value + updateUI() + } + + /** + * The spacing between the [PanelItem]s inserted. + */ + @IntRange(from = 0) + var itemSpacing: Int = 0 + set(value) { + field = value + updateUI() + } + + /** + * The bias for the left section of the BarPanelWidget. 0 aligns items to the left/top. + * Left items are aligned to the left (0) by default. + */ + @FloatRange(from = 0.0, to = 1.0) + var leftBias: Float = 0f + set(value) { + field = value + setChainBias(leftPanelItems, value) + } + + /** + * The bias for the right section of the BarPanelWidget. 0 aligns items to the left/top. + * Right items are aligned to the right (1) by default. + */ + @FloatRange(from = 0.0, to = 1.0) + var rightBias: Float = 1f + set(value) { + field = value + setChainBias(rightPanelItems, value) + } + + /** + * The chain style for the left section of the BarPanelWidget. + * [ConstraintSet.CHAIN_PACKED] is used by default. + */ + @IntRange(from = ConstraintSet.CHAIN_SPREAD.toLong(), to = ConstraintSet.CHAIN_PACKED.toLong()) + var leftChainStyle: Int = ConstraintSet.CHAIN_PACKED + set(value) { + field = value + setChainStyle(leftPanelItems, value) + } + + /** + * The chain style for the right section of the BarPanelWidget. + * [ConstraintSet.CHAIN_PACKED] is used by default. + */ + @IntRange(from = ConstraintSet.CHAIN_SPREAD.toLong(), to = ConstraintSet.CHAIN_PACKED.toLong()) + var rightChainStyle: Int = ConstraintSet.CHAIN_PACKED + set(value) { + field = value + setChainStyle(leftPanelItems, value) + } + + /** + * The percentage between the left and the right. + * 0.5 distributes both sides equally. + */ + @FloatRange(from = 0.0, to = 1.0) + var guidelinePercent: Float = 0.5f + set(value) { + field = value + val constraintSet = ConstraintSet() + constraintSet.clone(this) + constraintSet.setGuidelinePercent(midGuideline.id, field) + constraintSet.applyTo(this) + } + //endregion + + //region Private Properties + private var leftPanelItems: MutableList = arrayListOf() + private var rightPanelItems: MutableList = arrayListOf() + private val midGuideline = Guideline(context) + //endregion + + //region Constructor + init { + check(this.panelWidgetConfiguration.isBarPanelWidget()) { + "PanelWidgetConfiguration.panelWidgetType should " + + "be PanelWidgetType.BAR_VERTICAL or PanelWidgetType.BAR_HORIZONTAL" + } + setUpContainers() + attrs?.let { initAttributes(it) } + } + + private fun setUpContainers() { + val guidelineOrientation = + if (orientation == BarPanelWidgetOrientation.HORIZONTAL) { + ConstraintSet.VERTICAL_GUIDELINE + } else { + ConstraintSet.HORIZONTAL_GUIDELINE + } + midGuideline.id = ViewIDGenerator.generateViewId() + addView(midGuideline) + + val constraintSet = ConstraintSet() + constraintSet.clone(this) + + constraintSet.create(midGuideline.id, guidelineOrientation) + constraintSet.setGuidelinePercent(midGuideline.id, guidelinePercent) + + constraintSet.applyTo(this) + } + + @SuppressLint("Recycle") + protected open fun initAttributes(attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.BarPanelWidget).use { typedArray -> + typedArray.getDimensionAndUse(R.styleable.BarPanelWidget_uxsdk_itemsMarginLeft) { + itemsMarginLeft = it.toInt() + } + typedArray.getDimensionAndUse(R.styleable.BarPanelWidget_uxsdk_itemsMarginTop) { + itemsMarginTop = it.toInt() + } + typedArray.getDimensionAndUse(R.styleable.BarPanelWidget_uxsdk_itemsMarginRight) { + itemsMarginRight = it.toInt() + } + typedArray.getDimensionAndUse(R.styleable.BarPanelWidget_uxsdk_itemsMarginBottom) { + itemsMarginBottom = it.toInt() + } + typedArray.getDimensionAndUse(R.styleable.BarPanelWidget_uxsdk_itemsSpacing) { + itemSpacing = it.toInt() + } + typedArray.getFloatAndUse(R.styleable.BarPanelWidget_uxsdk_guidelinePercent) { + guidelinePercent = it + } + typedArray.getFloatAndUse(R.styleable.BarPanelWidget_uxsdk_leftBias) { + leftBias = it + } + typedArray.getFloatAndUse(R.styleable.BarPanelWidget_uxsdk_rightBias) { + rightBias = it + } + typedArray.getIntAndUse(R.styleable.BarPanelWidget_uxsdk_leftChainStyle) { + leftChainStyle = it.toChainStyle() + } + typedArray.getIntAndUse(R.styleable.BarPanelWidget_uxsdk_rightChainStyle) { + leftChainStyle = it.toChainStyle() + } + } + } + //endregion + + //region Lifecycle & Setup + override fun updateUI() { + if (leftPanelItems.isEmpty() && rightPanelItems.isEmpty()) return + + // Set the size constraints to each view + val constraintSet = ConstraintSet() + constraintSet.clone(this) + leftPanelItems.forEachIndexed { index, _ -> + connectPanelItem(constraintSet, leftPanelItems, index, isLeftSide = true) + } + rightPanelItems.forEachIndexed { index, _ -> + connectPanelItem(constraintSet, rightPanelItems, index, isLeftSide = false) + } + + // Set chain styles + setChainStyle(constraintSet, leftPanelItems, leftChainStyle) + setChainStyle(constraintSet, rightPanelItems, rightChainStyle) + setChainBias(constraintSet, leftPanelItems, leftBias) + setChainBias(constraintSet, rightPanelItems, rightBias) + + constraintSet.applyTo(this) + } + + private fun connectPanelItem(constraintSet: ConstraintSet, panelItems: MutableList, @IntRange(from = 0) index: Int, isLeftSide: Boolean) { + if (index < panelItems.size) { + val barPanelItem = panelItems[index] + val ratioString = barPanelItem.ratioString ?: defaultRatioString + val widgetSizeDescription = barPanelItem.widgetSizeDescription + ?: WidgetSizeDescription( + WidgetSizeDescription.SizeType.RATIO, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.EXPAND + ) + val currentView = barPanelItem.view + + if (widgetSizeDescription.sizeType == WidgetSizeDescription.SizeType.OTHER + && !widgetSizeDescription.widthShouldWrap() + && !(isFirstItem(index) || isLastItem(panelItems, index))) { + throw IllegalStateException("Should not add a fill view in the middle of the list") + } + + // Set size constraints + val width = + if (widgetSizeDescription.widthShouldWrap()) ViewGroup.LayoutParams.WRAP_CONTENT + else 0 + val height = + if (widgetSizeDescription.heightShouldWrap()) ViewGroup.LayoutParams.WRAP_CONTENT + else 0 + constraintSet.constrainWidth(currentView.id, width) + constraintSet.constrainHeight(currentView.id, height) + if (widgetSizeDescription.sizeType == WidgetSizeDescription.SizeType.RATIO) { + constraintSet.setDimensionRatio(currentView.id, ratioString) + } + + // Constraint top/start + if (orientation == BarPanelWidgetOrientation.HORIZONTAL) { + constraintSet.constraintToParentTop(currentView, barPanelItem.getDefaultItemMarginTop()) + constraintSet.constraintToParentBottom(currentView, barPanelItem.getDefaultItemMarginBottom()) + } else { + constraintSet.constraintToParentStart(currentView, barPanelItem.getDefaultItemMarginLeft()) + constraintSet.constraintToParentEnd(currentView, barPanelItem.getDefaultItemMarginRight()) + } + + // Chain with prev and next view (or parent/guideline) + connectToPreviousView(constraintSet, panelItems, index, isLeftSide) + connectToNextView(constraintSet, panelItems, index, isLeftSide) + } + } + + private fun connectToPreviousView(constraintSet: ConstraintSet, panelItems: MutableList, currentIndex: Int, isLeft: Boolean) { + val currentPanelItem = panelItems[currentIndex] + val panelItemSide = + if (orientation == BarPanelWidgetOrientation.HORIZONTAL) ConstraintSet.START + else ConstraintSet.TOP + val endID = + if (isFirstItem(currentIndex)) { + if (isLeft) ConstraintSet.PARENT_ID + else midGuideline.id + } else { + panelItems[currentIndex - 1].view.id + } + val endSide = + if (isFirstItem(currentIndex)) { + if (orientation == BarPanelWidgetOrientation.HORIZONTAL) ConstraintSet.START + else ConstraintSet.TOP + } else { + if (orientation == BarPanelWidgetOrientation.HORIZONTAL) ConstraintSet.END + else ConstraintSet.BOTTOM + } + constraintSet.connect( + currentPanelItem.view.id, + panelItemSide, + endID, + endSide, + getStartTopMargin(currentIndex) + ) + } + + private fun connectToNextView(constraintSet: ConstraintSet, panelItems: MutableList, currentIndex: Int, isLeft: Boolean) { + val currentPanelItem = panelItems[currentIndex] + val panelItemSide = + if (orientation == BarPanelWidgetOrientation.HORIZONTAL) ConstraintSet.END + else ConstraintSet.BOTTOM + val endID = + if (isLastItem(panelItems, currentIndex)) { + if (isLeft) midGuideline.id + else ConstraintSet.PARENT_ID + } else { + panelItems[currentIndex + 1].view.id + } + val endSide = + if (isLastItem(panelItems, currentIndex)) { + if (orientation == BarPanelWidgetOrientation.HORIZONTAL) ConstraintSet.END + else ConstraintSet.BOTTOM + } else { + if (orientation == BarPanelWidgetOrientation.HORIZONTAL) ConstraintSet.START + else ConstraintSet.TOP + } + constraintSet.connect( + currentPanelItem.view.id, + panelItemSide, + endID, + endSide, + getEndBottomMargin(panelItems, currentIndex) + ) + } + + private fun setChainStyle(panelItems: MutableList, chainStyle: Int) { + val constraintSet = ConstraintSet() + setChainStyle(constraintSet, panelItems, chainStyle) + constraintSet.applyTo(this) + } + + private fun setChainStyle(constraintSet: ConstraintSet, panelItems: MutableList, chainStyle: Int) { + if (panelItems.isNotEmpty()) { + if (orientation == BarPanelWidgetOrientation.HORIZONTAL) { + constraintSet.setHorizontalChainStyle(panelItems[0].view.id, chainStyle) + } else { + constraintSet.setVerticalChainStyle(panelItems[0].view.id, chainStyle) + } + } + } + + private fun setChainBias(panelItems: MutableList, bias: Float) { + val constraintSet = ConstraintSet() + setChainBias(constraintSet, panelItems, bias) + constraintSet.applyTo(this) + } + + private fun setChainBias(constraintSet: ConstraintSet, panelItems: MutableList, bias: Float) { + if (panelItems.isNotEmpty()) { + if (orientation == BarPanelWidgetOrientation.HORIZONTAL) { + constraintSet.setHorizontalBias(panelItems[0].view.id, bias) + } else { + constraintSet.setVerticalBias(panelItems[0].view.id, bias) + } + } + } + //endregion + + //region Populate BarPanelWidget + @Throws(UnsupportedOperationException::class) + override fun getWidget(@IntRange(from = 0) index: Int): PanelItem? = + throw UnsupportedOperationException("Try getLeftPanelItem or getRightPanelItem instead") + + @Throws(UnsupportedOperationException::class) + override fun addWidgets(panelItems: Array) { + throw UnsupportedOperationException("Try addLeftPanelItems or addRightPanelItems instead") + } + + /** + * Total number of [PanelItem]s inside this [BarPanelWidget]. Includes left and right lists. + */ + override fun size(): Int = leftPanelItems.size + rightPanelItems.size + + @Throws(UnsupportedOperationException::class) + override fun addWidget(@IntRange(from = 0) index: Int, item: PanelItem) { + throw UnsupportedOperationException("Call either") + } + + @Throws(UnsupportedOperationException::class) + override fun removeWidget(@IntRange(from = 0) index: Int): PanelItem? = + throw UnsupportedOperationException("Try removeLeftPanelItem or removeRightPanelItem instead") + + /** + * Remove all [PanelItem]s from both left and right lists of this BarPanelWidget. + */ + override fun removeAllWidgets() { + removeAllLeftWidgets() + removeAllRightWidgets() + } + + /** + * Get [PanelItem] from the left list of this BarPanelWidget. + * [index] 0, is the first position of the left list. + */ + fun getLeftWidget(@IntRange(from = 0) index: Int): PanelItem? = getLeftWidget(index, leftPanelItems) + + /** + * Append an array of [PanelItem]s to the left list of this BarPanelWidget. + * The items should be unique and not be present in this BarPanelWidget already. + */ + fun addLeftWidgets(panelItems: Array) { + addPanelItems(fromPanelItems = panelItems, toPanelItems = leftPanelItems) + } + + /** + * Total number of [PanelItem]s inside the left list of this [BarPanelWidget]. + */ + fun leftWidgetsSize(): Int = leftPanelItems.size + + /** + * Insert a [PanelItem] at the given index to the left list of this BarPanelWidget. + * [index] 0, is the first position of the left list. + */ + fun addLeftWidget(@IntRange(from = 0) index: Int, panelItem: PanelItem) { + insertPanelItem(leftPanelItems, panelItem, index) + } + + /** + * Remove a [PanelItem] at the given index from the left list of this BarPanelWidget. + * [index] 0, is the first position of the left list. + */ + fun removeLeftWidget(@IntRange(from = 0) index: Int): PanelItem? = removePanelItem(leftPanelItems, index) + + /** + * Remove all [PanelItem] from the left list of this BarPanelWidget. + */ + fun removeAllLeftWidgets() { + removeAllPanelItem(rightPanelItems) + } + + /** + * Get [PanelItem] from the right list of this BarPanelWidget. + * [index] 0, is the first position of the right list. + */ + fun getRightWidget(@IntRange(from = 0) index: Int): PanelItem? = getLeftWidget(index, rightPanelItems) + + /** + * Appends an array of [PanelItem]s to the right list of this BarPanelWidget. + * The items should be unique and not be present in this BarPanelWidget already. + */ + fun addRightWidgets(panelItems: Array) { + addPanelItems(fromPanelItems = panelItems, toPanelItems = rightPanelItems) + } + + /** + * Total number of [PanelItem]s inside the right list of this [BarPanelWidget]. + */ + fun rightWidgetsSize(): Int = rightPanelItems.size + + /** + * Insert a [PanelItem] at the given index to the right list of this BarPanelWidget. + * [index] 0, is the first position of the right list. + */ + fun addRightWidget(@IntRange(from = 0) index: Int, panelItem: PanelItem) { + insertPanelItem(rightPanelItems, panelItem, index) + } + + /** + * Remove a [PanelItem] at the given index from the right list of this BarPanelWidget. + * [index] 0, is the first position of the right list. + */ + fun removeRightWidget(@IntRange(from = 0) index: Int): PanelItem? = removePanelItem(rightPanelItems, index) + + /** + * Remove all [PanelItem] from the right list of this BarPanelWidget. + */ + fun removeAllRightWidgets() { + removeAllPanelItem(rightPanelItems) + } + + private fun getLeftWidget(@IntRange(from = 0) index: Int, panelItems: MutableList): PanelItem? = + panelItems.getOrNull(index) + + private fun addPanelItems(fromPanelItems: Array, toPanelItems: MutableList) { + toPanelItems.addAll(fromPanelItems) + addViews(fromPanelItems) + updateUI() + } + + private fun insertPanelItem(panelItems: MutableList, panelItem: PanelItem, @IntRange(from = 0) atIndex: Int) { + panelItems.add(atIndex, panelItem) + addView(panelItem.view) + updateUI() + } + + private fun removePanelItem(panelItems: MutableList, @IntRange(from = 0) atIndex: Int): PanelItem? { + if (atIndex >= panelItems.size) return null + + val removedPanelItem = panelItems.removeAt(atIndex) + removeView(removedPanelItem.view) + updateUI() + + return removedPanelItem + } + + private fun removeAllPanelItem(panelItems: MutableList) { + panelItems.forEach { + removeView(it.view) + } + panelItems.clear() + updateUI() + } + //endregion + + //region Helpers + /** + * Checks if [index] is equivalent to the first position in a list. + */ + protected fun isFirstItem(@IntRange(from = 0) index: Int): Boolean = index == 0 + + /** + * Checks if item at [index] is at the last item of the [list]. + */ + protected fun isLastItem(list: MutableList, @IntRange(from = 0) index: Int): Boolean = + index == list.size - 1 + + /** + * Add views from each [PanelItem] into the parent ConstraintLayout. + */ + protected fun addViews(panelItems: Array) { + panelItems.forEach { addView(it.view) } + } + + private fun PanelItem.getDefaultItemMarginLeft(): Int = this.itemMarginLeft ?: itemsMarginLeft + private fun PanelItem.getDefaultItemMarginTop(): Int = this.itemMarginTop ?: itemsMarginTop + private fun PanelItem.getDefaultItemMarginRight(): Int = this.itemMarginRight + ?: itemsMarginRight + + private fun PanelItem.getDefaultItemMarginBottom(): Int = this.itemMarginBottom + ?: itemsMarginBottom + + private fun WidgetSizeDescription.widthShouldWrap() = + widthDimension == WidgetSizeDescription.Dimension.WRAP + + + private fun WidgetSizeDescription.heightShouldWrap(): Boolean = + heightDimension == WidgetSizeDescription.Dimension.WRAP + + private fun getStartTopMargin(index: Int): Int { + val margin = + if (orientation == BarPanelWidgetOrientation.HORIZONTAL) itemsMarginLeft + else itemsMarginTop + return if (isFirstItem(index)) margin + else itemSpacing / 2 + } + + private fun getEndBottomMargin(panelItems: MutableList, index: Int): Int { + val margin = + if (orientation == BarPanelWidgetOrientation.HORIZONTAL) itemsMarginRight + else itemsMarginBottom + return if (isLastItem(panelItems, index)) margin + else itemSpacing / 2 + } + + @IntRange(from = ConstraintSet.CHAIN_SPREAD.toLong(), to = ConstraintSet.CHAIN_PACKED.toLong()) + private fun Int.toChainStyle(): Int { + return when (this) { + 0 -> ConstraintSet.CHAIN_SPREAD + 1 -> ConstraintSet.CHAIN_SPREAD_INSIDE + else -> ConstraintSet.CHAIN_PACKED + } + } + //endregion + + /** + * Indicates the orientation of the BarPanelWidget. + */ + enum class BarPanelWidgetOrientation { + /** + * Items are aligned from top to bottom. + */ + VERTICAL, + + /** + * Items are aligned from left to right. + */ + HORIZONTAL; + + /** + * Convert [BarPanelWidgetOrientation] into a [PanelWidgetType] + */ + fun toPanelWidgetType(): PanelWidgetType = + if (this == HORIZONTAL) PanelWidgetType.BAR_HORIZONTAL + else PanelWidgetType.BAR_VERTICAL + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/FreeFormPanelWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/FreeFormPanelWidget.kt new file mode 100644 index 00000000..643659a0 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/FreeFormPanelWidget.kt @@ -0,0 +1,727 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base.panel + +import android.content.Context +import android.graphics.Color +import android.util.AttributeSet +import android.view.View +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.constraintlayout.widget.ConstraintSet +import androidx.core.view.contains +import dji.v5.ux.R +import dji.v5.ux.core.extension.getColor +import dji.v5.ux.core.extension.hide +import dji.v5.ux.core.extension.show +import dji.v5.ux.core.util.ViewIDGenerator +import kotlin.random.Random + +/** + * Base class for [FreeFormPanelWidget]. + * A [FreeFormPanelWidget] is a panel containing splittable panes. + * Out of the box the panel contains only one pane. + * Based on the requirement, a pane can be split into rows or columns with proportion of choice. + * Each pane can hold one view or widget and can be split only once. If a pane containing a view or + * a widget is split, the view/widget will be removed permanently before splitting the pane. + * Use [FreeFormPanelWidget.splitPane] to split a pane. + * A pane which has been split can be unified by merging its children. If any child of the pane to + * be merged contains a view or a widget, the view/widget will be removed permanently. + * Use [FreeFormPanelWidget.mergeChildren] to merge the children of a pane. + * Use [FreeFormPanelWidget.mergeSiblings] to merge the siblings of a pane. + * + * The class provides helper methods to add, remove and get view/widget in a pane. + * + */ +abstract class FreeFormPanelWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + configuration: PanelWidgetConfiguration, +) : PanelWidget( + context, + attrs, + defStyleAttr, + configuration +) { + + + //region Fields + private val paneMap: HashMap = hashMapOf() + + private var isLabelAssistEnabled: Boolean = false + + private var isBackgroundAssistEnabled: Boolean = false + + /** + * Color of the text for in debug labels. + */ + var debugTextColor: Int = getColor(R.color.uxsdk_white) + + /** + * Color of the background of debug labels. + */ + var debugTextBackgroundColor = getColor(R.color.uxsdk_black) + + /** + * ID of root pane. + */ + val rootID: Int = ViewIDGenerator.generateViewId() + + /** + * List of the currently visible pane IDs. + */ + val listOfViewIds: List + get() = paneMap.filter { !it.value.isSplit }.keys.toList() + //endregion + + //region Lifecycle + init { + check(panelWidgetConfiguration.panelWidgetType == PanelWidgetType.FREE_FORM) { + "PanelWidgetConfiguration.panelWidgetType should be PanelWidgetType.FREE_FORM" + } + val defaultView = View(context) + addView(defaultView, childCount) + defaultView.id = rootID + defaultView.setBackgroundColor(getColor(R.color.uxsdk_yellow)) + val constraintSet = ConstraintSet() + constraintSet.clone(this) + constraintSet.constrainHeight(rootID, 0) + constraintSet.constrainWidth(rootID, 0) + constraintSet.constraintToParentStart(defaultView) + constraintSet.constraintToParentEnd(defaultView) + constraintSet.constraintToParentBottom(defaultView) + constraintSet.constraintToParentTop(defaultView) + constraintSet.applyTo(this) + paneMap[rootID] = Pane(id = rootID, parentId = -1, background = defaultView) + } + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + // Empty method + } + + override fun initPanelWidget(context: Context, attrs: AttributeSet?, defStyleAttr: Int, widgetConfiguration: PanelWidgetConfiguration?) { + // No implementation + } + + + @Throws(UnsupportedOperationException::class) + override fun getWidget(index: Int): PanelItem? = + throw UnsupportedOperationException("Try findViewPane instead") + + @Throws(UnsupportedOperationException::class) + override fun addWidgets(items: Array) = + throw UnsupportedOperationException(("This call is not supported.")) + + @Throws(UnsupportedOperationException::class) + override fun size(): Int = + throw UnsupportedOperationException(("This call is not supported.")) + + @Throws(UnsupportedOperationException::class) + override fun addWidget(index: Int, item: PanelItem) = + throw UnsupportedOperationException("Try addView instead") + + @Throws(UnsupportedOperationException::class) + override fun removeWidget(index: Int): PanelItem? = + throw UnsupportedOperationException("Try remove view instead") + + @Throws(UnsupportedOperationException::class) + override fun updateUI() = + throw UnsupportedOperationException(("This call is not supported.")) + + override fun removeAllWidgets() { + for ((_, pane) in paneMap) { + removeView(pane.view) + pane.view = null + } + } + //endregion + + //region Panel Customizations + /** + * Split pane into multiple panes. + * + * @param paneId - the ID of the pane that needs to be split. + * @param splitType - instance of [SplitType] representing the axis to use for the splits. + * @param proportions - float array representing the proportions in which the pane should be. + * split. The sum of the proportions should not exceed 1. If the sum is less + * than 1 the balance will be added to the last pane. + * @return List of integer IDs of the newly created panes. + */ + fun splitPane(paneId: Int, splitType: SplitType, proportions: Array): List { + // Pane has already been split or pane does not exist + val parentPane = paneMap[paneId] + if (parentPane == null || parentPane.isSplit) { + return emptyList() + } + + // Pane cannot be split into less than 2 parts + if (proportions.size < 2) { + return emptyList() + } + + val sum = proportions.sum() + + // Sum of proportions cannot exceed 1 which is the total size + if (sum > 1f) { + return emptyList() + } + + // Remove all the debug labels + removeDebugViews() + + // If a view / widget exists in the current pane, remove it + if (parentPane.view != null) { + removeView(paneId) + } + + val set = ConstraintSet() + set.clone(this) + + val childrenViewList = arrayListOf() + val childrenIdList = IntArray(proportions.size) + + val weights = proportions.toFloatArray() + + // Loop over number of proportions and create child elements + proportions.forEachIndexed { index, _ -> + val childView = View(context) + childView.id = ViewIDGenerator.generateViewId() + childrenIdList[index] = childView.id + childrenViewList.add(childView) + addView(childView, childCount) + val childPane = Pane(id = childView.id, parentId = parentPane.id, background = childView) + paneMap[childView.id] = childPane + if (splitType == SplitType.HORIZONTAL) { + // If Split type is horizontal make height 100% + set.constrainPercentHeight(childrenViewList[index].id, 1f) + set.connect(childView.id, ConstraintSet.TOP, paneId, ConstraintSet.TOP) + set.connect(childView.id, ConstraintSet.BOTTOM, paneId, ConstraintSet.BOTTOM) + } else { + // If Split type is vertical make width 100% + set.constrainPercentWidth(childrenViewList[index].id, 1f) + set.connect(childView.id, ConstraintSet.LEFT, paneId, ConstraintSet.LEFT) + set.connect(childView.id, ConstraintSet.RIGHT, paneId, ConstraintSet.RIGHT) + } + } + + // Adjust the last pane proportion to compensate for the left over space. + proportions[proportions.lastIndex] = 1.0f - sum + proportions[proportions.lastIndex] + + if (splitType == SplitType.HORIZONTAL) { + set.createHorizontalChain( + paneId, + ConstraintSet.LEFT, + paneId, + ConstraintSet.RIGHT, + childrenIdList, + weights, + ConstraintSet.CHAIN_SPREAD + ) + } else { + set.createVerticalChain( + paneId, + ConstraintSet.TOP, + paneId, + ConstraintSet.BOTTOM, + childrenIdList, + weights, + ConstraintSet.CHAIN_SPREAD + ) + } + set.applyTo(this) + + // Assign the list of children to the pane + parentPane.childrenIdList = childrenIdList.toList() + parentPane.isSplit = true + + // Assign the list of children as siblings to each other + childrenIdList.forEach { childId -> paneMap[childId]?.siblingIdList = childrenIdList.toList() } + + //Add debug labels if debugging is enabled + addDebugViews(isLabelAssistEnabled, isBackgroundAssistEnabled) + return childrenIdList.toList() + + } + + /** + * The method addView installs a descendant of [View] into the designated pane, + * removing the existing view already there. + * + * @param paneId - the ID of the pane to which view should be added. + * @param widgetView - the instance of widget or view to be added to the pane. + * @param position - instance of [ViewAlignment] representing the position of the view in the pane. + * @param leftMargin - Optional left margin for the widget or view. Defaults to 0. + * @param topMargin - Optional top margin for the widget or view. Defaults to 0. + * @param rightMargin - Optional right margin for the widget or view. Defaults to 0. + * @param bottomMargin - Optional bottom margin for the widget or view. Defaults to 0. + */ + fun addView( + paneId: Int, widgetView: View, position: ViewAlignment = ViewAlignment.CENTER, + leftMargin: Int = 0, topMargin: Int = 0, rightMargin: Int = 0, bottomMargin: Int = 0, + ) { + val pane = paneMap[paneId] ?: return + removeView(paneId) + if (widgetView.id == -1) { + widgetView.id = ViewIDGenerator.generateViewId() + } + addView(widgetView, childCount) + setViewAlignment(paneId, widgetView, position, leftMargin, topMargin, rightMargin, bottomMargin) + pane.view = widgetView + pane.position = position + } + + /** + * Remove the view in a pane. + * + * @param - ID of the pane from which the view should be removed. + */ + fun removeView(paneId: Int) { + val pane = paneMap[paneId] ?: return + val viewToRemove = pane.view ?: return + val set = ConstraintSet() + set.clone(this) + set.clear(viewToRemove.id) + set.applyTo(this) + if (contains(viewToRemove)) { + removeView(viewToRemove) + } + pane.view = null + } + + /** + * The method returns the integer ID of the pane in which the given view in + * installed or -1. + */ + fun findViewPane(view: View): Int { + val key = paneMap.filter { it.value.view == view }.keys.firstOrNull() + return key ?: -1 + } + + /** + * The method returns the view installed in the given pane ID. + */ + fun viewInPane(paneId: Int): View? { + return paneMap[paneId]?.view + } + + /** + * Get the list of siblings of a pane. + */ + fun getSiblingList(paneId: Int): List { + val list = paneMap[paneId]?.siblingIdList + return list ?: emptyList() + } + + /** + * Get the list of children of a pane. + */ + fun getChildrenList(paneId: Int): List { + val list = paneMap[paneId]?.childrenIdList + return list ?: emptyList() + } + + /** + * Get the parent id of a pane. + */ + fun getParentId(paneId: Int): Int { + val parentId = paneMap[paneId]?.parentId + return parentId ?: -1 + } + + /** + * The method enablePaneDebug activates or deactivates some visual debugging tools + * for the Freeform panel. These tools can help you quickly debug how your panes are + * appearing and where, and how large they are. + * + * + * @param enableLabelAssist - Turns debugging PaneIDs on or off in each pane. + * @param enableBackgroundAssist - This optional boolean sets the background color of panes + * using a rotating list of colors to help visualize where + * each pane displays. Defaults to off. + * @param textColor - This optional parameter sets the UIColor of the text label for each pane + * created after the assist is turned on. Defaults to white. + * @param textBackgroundColor - This optional parameter sets the UIColor to use as the + * background color of the text label. Defaults to black. + */ + fun enablePaneDebug( + enableLabelAssist: Boolean, enableBackgroundAssist: Boolean = false, + @ColorInt textColor: Int = INVALID_COLOR, @ColorInt textBackgroundColor: Int = INVALID_COLOR, + ) { + if (textColor != INVALID_COLOR) { + debugTextColor = textColor + } + if (textBackgroundColor != INVALID_COLOR) { + debugTextBackgroundColor = textBackgroundColor + } + + isLabelAssistEnabled = enableLabelAssist + isBackgroundAssistEnabled = enableBackgroundAssist + removeDebugViews() + addDebugViews(isLabelAssistEnabled, isBackgroundAssistEnabled) + } + + /** + * Call method mergeChildren to merge all the children of a pane back to form the original pane. + * This deletes all the children and re-exposes the parent pane. + * + * @param paneId - The paneID to be revealed after removing the child panes. + */ + fun mergeChildren(paneId: Int) { + removeDebugViews() + mergePaneChildren(paneId) + addDebugViews(isLabelAssistEnabled, isBackgroundAssistEnabled) + } + + /** + * Call method mergeSiblings to merge all the siblings of a pane back to form the parent pane. + * This deletes all the siblings and re-exposes the parent pane. + * + * @param paneId - The paneID to be deleted along with its siblings. + */ + fun mergeSiblings(paneId: Int) { + val pane = paneMap[paneId] ?: return + mergeChildren(pane.parentId) + } + + /** + * Get the [ViewAlignment] used by the pane to align its content. + */ + fun getPanePositioning(paneId: Int): ViewAlignment? { + return paneMap[paneId]?.position + } + + /** + * Set the [ViewAlignment] to a pane to align its content. + * + * @param paneId - the ID of the pane to which the position should be set. + * @param position - instance of [ViewAlignment] representing the position of the view in the pane. + * @param leftMargin - Optional left margin for the widget or view. Defaults to 0. + * @param topMargin - Optional top margin for the widget or view. Defaults to 0. + * @param rightMargin - Optional right margin for the widget or view. Defaults to 0. + * @param bottomMargin + */ + fun setPanePosition( + paneId: Int, position: ViewAlignment, + leftMargin: Int = 0, topMargin: Int = 0, + rightMargin: Int = 0, bottomMargin: Int = 0, + ) { + val pane = paneMap[paneId] ?: return + val widgetView = pane.view ?: return + pane.position = position + setViewAlignment(paneId, widgetView, position, leftMargin, topMargin, rightMargin, bottomMargin) + } + + /** + * Set the background color of the pane. + */ + fun setPaneBackgroundColor(paneId: Int, @ColorInt color: Int) { + val pane = paneMap[paneId] ?: return + pane.backgroundColor = color + pane.background.setBackgroundColor(color) + } + + /** + * Set the background color of the pane. + */ + fun setPaneVisibility(paneId: Int, isVisible: Boolean) { + val pane = paneMap[paneId] ?: return + if (isVisible) { + pane.background.show() + } else { + pane.background.hide() + } + val view = pane.view ?: return + if (isVisible) { + view.show() + } else { + view.hide() + } + } + + //endregion + + //region Helpers + private fun setViewAlignment( + paneId: Int, widgetView: View, position: ViewAlignment, + leftMargin: Int, topMargin: Int, rightMargin: Int, bottomMargin: Int, + ) { + val set = ConstraintSet() + set.clone(this) + set.clear(widgetView.id) + set.setMargin(widgetView.id, ConstraintSet.LEFT, leftMargin) + set.setMargin(widgetView.id, ConstraintSet.TOP, topMargin) + set.setMargin(widgetView.id, ConstraintSet.RIGHT, rightMargin) + set.setMargin(widgetView.id, ConstraintSet.BOTTOM, bottomMargin) + when (position) { + ViewAlignment.CENTER -> { + set.connect(widgetView.id, ConstraintSet.LEFT, paneId, ConstraintSet.LEFT) + set.connect(widgetView.id, ConstraintSet.RIGHT, paneId, ConstraintSet.RIGHT) + set.connect(widgetView.id, ConstraintSet.TOP, paneId, ConstraintSet.TOP) + set.connect(widgetView.id, ConstraintSet.BOTTOM, paneId, ConstraintSet.BOTTOM) + } + + ViewAlignment.TOP -> { + set.constrainHeight(widgetView.id, ConstraintSet.WRAP_CONTENT) + set.constrainWidth(widgetView.id, 0) + set.connect(widgetView.id, ConstraintSet.LEFT, paneId, ConstraintSet.LEFT) + set.connect(widgetView.id, ConstraintSet.RIGHT, paneId, ConstraintSet.RIGHT) + set.connect(widgetView.id, ConstraintSet.TOP, paneId, ConstraintSet.TOP) + } + + ViewAlignment.BOTTOM -> { + set.constrainHeight(widgetView.id, ConstraintSet.WRAP_CONTENT) + set.constrainWidth(widgetView.id, 0) + set.connect(widgetView.id, ConstraintSet.LEFT, paneId, ConstraintSet.LEFT) + set.connect(widgetView.id, ConstraintSet.RIGHT, paneId, ConstraintSet.RIGHT) + set.connect(widgetView.id, ConstraintSet.BOTTOM, paneId, ConstraintSet.BOTTOM) + } + + ViewAlignment.LEFT -> { + set.constrainHeight(widgetView.id, 0) + set.constrainWidth(widgetView.id, ConstraintSet.WRAP_CONTENT) + set.connect(widgetView.id, ConstraintSet.LEFT, paneId, ConstraintSet.LEFT) + set.connect(widgetView.id, ConstraintSet.TOP, paneId, ConstraintSet.TOP) + set.connect(widgetView.id, ConstraintSet.BOTTOM, paneId, ConstraintSet.BOTTOM) + } + + ViewAlignment.RIGHT -> { + set.constrainHeight(widgetView.id, 0) + set.constrainWidth(widgetView.id, ConstraintSet.WRAP_CONTENT) + set.connect(widgetView.id, ConstraintSet.RIGHT, paneId, ConstraintSet.RIGHT) + set.connect(widgetView.id, ConstraintSet.TOP, paneId, ConstraintSet.TOP) + set.connect(widgetView.id, ConstraintSet.BOTTOM, paneId, ConstraintSet.BOTTOM) + } + + ViewAlignment.LEFT_TOP -> { + set.constrainHeight(widgetView.id, ConstraintSet.WRAP_CONTENT) + set.constrainWidth(widgetView.id, ConstraintSet.WRAP_CONTENT) + set.connect(widgetView.id, ConstraintSet.LEFT, paneId, ConstraintSet.LEFT) + set.connect(widgetView.id, ConstraintSet.TOP, paneId, ConstraintSet.TOP) + } + + ViewAlignment.LEFT_BOTTOM -> { + set.constrainHeight(widgetView.id, ConstraintSet.WRAP_CONTENT) + set.constrainWidth(widgetView.id, ConstraintSet.WRAP_CONTENT) + set.connect(widgetView.id, ConstraintSet.LEFT, paneId, ConstraintSet.LEFT) + set.connect(widgetView.id, ConstraintSet.BOTTOM, paneId, ConstraintSet.BOTTOM) + } + + ViewAlignment.RIGHT_TOP -> { + set.constrainHeight(widgetView.id, ConstraintSet.WRAP_CONTENT) + set.constrainWidth(widgetView.id, ConstraintSet.WRAP_CONTENT) + set.connect(widgetView.id, ConstraintSet.RIGHT, paneId, ConstraintSet.RIGHT) + set.connect(widgetView.id, ConstraintSet.TOP, paneId, ConstraintSet.TOP) + } + + ViewAlignment.RIGHT_BOTTOM -> { + set.constrainHeight(widgetView.id, ConstraintSet.WRAP_CONTENT) + set.constrainWidth(widgetView.id, ConstraintSet.WRAP_CONTENT) + set.connect(widgetView.id, ConstraintSet.RIGHT, paneId, ConstraintSet.RIGHT) + set.connect(widgetView.id, ConstraintSet.BOTTOM, paneId, ConstraintSet.BOTTOM) + } + } + set.applyTo(this) + } + + private fun mergePaneChildren(paneId: Int) { + val pane = paneMap[paneId] ?: return + if (!pane.isSplit) return + + for (childId in pane.childrenIdList) { + // Call function recursively to delete all children + mergePaneChildren(childId) + val childPane = paneMap[childId] ?: continue + val set = ConstraintSet() + set.clone(this) + // Remove widget / view from the pane + val widgetView = childPane.view + if (widgetView != null) { + set.clear(widgetView.id) + removeView(widgetView) + } + // Remove debug text view from the pane + val debugTextView = childPane.debugTextView + if (debugTextView != null) { + set.clear(debugTextView.id) + removeView(debugTextView) + childPane.debugTextView = null + } + set.clear(childPane.id) + // Remove Pane + removeView(childPane.background) + childPane.siblingIdList = emptyList() + paneMap.remove(childPane.id) + set.applyTo(this) + } + pane.childrenIdList = emptyList() + pane.isSplit = false + } + + private fun addDebugViews( + isLabelAssist: Boolean = false, + isBackgroundAssist: Boolean = false, + ) { + val visiblePaneMap = paneMap.filter { !it.value.isSplit } + for ((_, pane) in visiblePaneMap) { + // If background assist is enabled apply random color to view background + if (isBackgroundAssist) { + val color: Int = Color.argb( + 255, + Random.nextInt(256), + Random.nextInt(256), + Random.nextInt(256) + ) + pane.background.setBackgroundColor(color) + } + // If label assist is enabled add debug label to text view + if (isLabelAssist && pane.debugTextView == null) { + val debugTextView = TextView(context) + debugTextView.id = ViewIDGenerator.generateViewId() + debugTextView.text = pane.id.toString() + debugTextView.setTextColor(debugTextColor) + debugTextView.setBackgroundColor(debugTextBackgroundColor) + addView(debugTextView, childCount) + val set = ConstraintSet() + set.clone(this) + set.connect(debugTextView.id, ConstraintSet.LEFT, pane.background.id, ConstraintSet.LEFT) + set.connect(debugTextView.id, ConstraintSet.TOP, pane.background.id, ConstraintSet.TOP) + set.applyTo(this) + pane.debugTextView = debugTextView + + } + } + } + + + private fun removeDebugViews() { + val visiblePaneMap = paneMap.filter { !it.value.isSplit } + for ((_, pane) in visiblePaneMap) { + // If no color was applied prior to debug make background null + if (pane.backgroundColor == INVALID_COLOR) { + pane.background.background = null + } else { + pane.background.setBackgroundColor(pane.backgroundColor) + } + val debugTextView = pane.debugTextView + // Remove debug text view if present + if (debugTextView != null) { + val set = ConstraintSet() + set.clone(this) + set.clear(debugTextView.id) + set.applyTo(this) + if (contains(debugTextView)) { + removeView(debugTextView) + } + pane.debugTextView = null + } + } + } + + //endregion + + /** + * View placement positions in a pane. + */ + enum class ViewAlignment { + /** + * Center of the pane. + */ + CENTER, + + /** + * Top edge of the pane horizontally centered. + */ + TOP, + + /** + * Bottom edge of the pane horizontally centered. + */ + BOTTOM, + + /** + * Left edge of the pane vertically centered. + */ + LEFT, + + /** + * Right edge of the pane vertically centered. + */ + RIGHT, + + /** + * Top left corner of the pane. + */ + LEFT_TOP, + + /** + * Bottom left corner of the pane. + */ + LEFT_BOTTOM, + + /** + * Top right corner of the pane. + */ + RIGHT_TOP, + + /** + * Bottom right corner of the pane. + */ + RIGHT_BOTTOM + + } + + /** + * Pane class for caching pane data. + * + */ + private data class Pane( + val id: Int, + val parentId: Int, + val background: View, + var backgroundColor: Int = INVALID_COLOR, + var isSplit: Boolean = false, + var view: View? = null, + var position: ViewAlignment? = null, + var childrenIdList: List = emptyList(), + var siblingIdList: List = emptyList(), + var debugTextView: TextView? = null, + ) + + /** + * Enum to define types of split. + */ + enum class SplitType { + /** + * Pane will be split into columns + */ + HORIZONTAL, + + /** + * Pane will be split into rows + */ + VERTICAL + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/ListPanelWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/ListPanelWidget.kt new file mode 100644 index 00000000..7d944579 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/ListPanelWidget.kt @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base.panel + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import android.view.ViewGroup +import android.widget.BaseAdapter +import android.widget.ListView +import androidx.constraintlayout.widget.ConstraintSet +import androidx.core.view.ViewCompat +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.util.ViewIDGenerator + +/** + * Base class for [ListPanelWidget]s. A [ListPanelWidget] is a vertical collection of widgets. + * The child widgets of a [ListPanelWidget], unlike those of a [BarPanelWidget], + * are created dynamically and the list can change based on changes at the MSDK level. + * + * This list is not meant to be used as an infinite list, but rather for a limited number of widgets. + * For infinite lists, prefer to use a RecyclerView. + * + * Widgets in this list are placed with the following properties: + * - Width: MATCH_PARENT + * - Height: WRAP_CONTENT + * + * The ListPanelWidget may contain a default [SmartListModel], which injects views into this + * ListPanelWidget. The [SmartListModel] can also be overwritten by setting [smartListModel], allowing + * the user to change the behavior of the list. + * + * Customization: + * The [ListPanelWidget] uses a ListView internally. To customize the dividers, user can use the + * ListView's attributes: + * android:divider="#FFCCFF" + * android:dividerHeight="4dp" + * User can also remove the dividers: + * android:divider="@null" + */ +abstract class ListPanelWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + configuration: PanelWidgetConfiguration +) : PanelWidget(context, attrs, defStyleAttr, configuration) { + + //region Properties + /** + * Optional [SmartListModel]. + * Setting a new instance refreshes the whole list. + */ + var smartListModel: SmartListModel? = null + set(value) { + field = value + field?.setListPanelWidgetHolder(listPanelWidgetBaseModel) + if (ViewCompat.isAttachedToWindow(this)) { + field?.setUp() + } + if (field != null) { + onSmartListModelCreated() + } + } + + /** + * Default [ListPanelWidgetBaseModel], can be overwritten. + */ + protected open val listPanelWidgetBaseModel: ListPanelWidgetBaseModel = ListPanelWidgetBaseModel() + private val adapter = Adapter() + //endregion + + //region Constructor + init { + check(panelWidgetConfiguration.panelWidgetType == PanelWidgetType.LIST) { + "PanelWidgetConfiguration.panelWidgetType should be PanelWidgetType.LIST" + } + + setUpListView(attrs) + // Set padding on the parent to 0, so only the listview can change padding + setPadding(0, 0, 0, 0) + } + + private fun setUpListView(attrs: AttributeSet?) { + val listView = ListView(context, attrs) + listView.id = ViewIDGenerator.generateViewId() + listView.adapter = adapter + addView(listView) + listView.visibility = View.VISIBLE + + val constraintSet = ConstraintSet() + constraintSet.clone(this) + + constraintSet.constrainWidth(listView.id, 0) + constraintSet.constrainHeight(listView.id, 0) + constraintSet.constraintToParentStart(listView) + constraintSet.constraintToParentEnd(listView) + constraintSet.constraintToParentBottom(listView) + constraintSet.constraintToParentTop(listView) + + constraintSet.applyTo(this) + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + smartListModel?.setUp() + + listPanelWidgetBaseModel.widgetList + .observeOn(SchedulerProvider.ui()) + .subscribe { updateUI() } + } + } + + override fun onDetachedFromWindow() { + smartListModel?.cleanUp() + super.onDetachedFromWindow() + } + + + /** + * Call to refresh the list. + */ + override fun updateUI() { + adapter.notifyDataSetChanged() + } + + /** + * Callback for when a new [SmartListModel] is created. + */ + protected abstract fun onSmartListModelCreated() + //endregion + + //region Populate Panel + /** + * Get the [View] at index from the current list of widgets. + */ + override fun getWidget(index: Int): View? { + smartListModel?.let { return it.getActiveWidget(index) } + return listPanelWidgetBaseModel.getWidget(index) + } + + /** + * Add a new [List] of [View]. + */ + override fun addWidgets(items: Array) { + if (smartListModel == null) { + listPanelWidgetBaseModel.addWidgets(items.toList()) + } + } + + /** + * Total size of [View] in the current list of widgets. + */ + override fun size(): Int { + smartListModel?.let { return it.activeWidgetSize } + return listPanelWidgetBaseModel.size() + } + + /** + * Add a [View] at [index] to the current list of widgets. + */ + override fun addWidget(index: Int, view: View) { + if (smartListModel == null) { + listPanelWidgetBaseModel.addWidget(index, view) + } + } + + /** + * Remove a [View] at [index] from the current list of widgets. + */ + override fun removeWidget(index: Int): View? { + if (smartListModel == null) { + return listPanelWidgetBaseModel.removeWidget(index) + } + return null + } + + /** + * Remove all [View]s. + */ + override fun removeAllWidgets() { + if (smartListModel == null) { + listPanelWidgetBaseModel.removeAllWidgets() + } + } + //endregion + + //region Customization + override fun getIdealDimensionRatioString(): String? = null + //endregion + + private inner class Adapter : BaseAdapter() { + override fun getView(position: Int, convertView: View?, parent: ViewGroup?): View { + val view = listPanelWidgetBaseModel.getWidget(position) + ?: throw IllegalAccessException("View not found at position $position") + if (view is Navigable) { + view.panelNavigator = this@ListPanelWidget.panelNavigator + } + view.setHasTransientState(true) + return view + } + + override fun getItem(position: Int): Any { + return listPanelWidgetBaseModel.getWidget(position) + ?: throw IllegalAccessException("Item not found at position $position") + } + + override fun getItemId(position: Int): Long = position.toLong() + + override fun getCount(): Int = listPanelWidgetBaseModel.size() + + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/ListPanelWidgetBaseModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/ListPanelWidgetBaseModel.kt new file mode 100644 index 00000000..b1a9233c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/ListPanelWidgetBaseModel.kt @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base.panel + +import android.view.View +import androidx.annotation.IntRange +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.util.DataProcessor + +// TODO: +// * Documentation UX-5195 + +/** + * The base model for the [ListPanelWidget] + */ +class ListPanelWidgetBaseModel { + + //region Properties + /** + * [Flowable] for the current widget list + */ + val widgetList: Flowable> + get() = widgetListProcessor.toFlowable() + + private val widgetListProcessor: DataProcessor> = DataProcessor.create(emptyList()) + //endregion + + //region List Helpers + /** + * Add a new [List] of [View]. + */ + fun addWidgets(widgetList: List) { + widgetListProcessor.onNext(widgetList) + } + + /** + * Add a [View] to the current list of widgets. + */ + fun addWidget(widget: View) { + val newList = widgetListProcessor.value + listOf(widget) + + widgetListProcessor.onNext(newList) + } + + /** + * Add a [View] at [index] to the current list of widgets. + */ + fun addWidget(@IntRange(from = 0) index: Int, widget: View) { + val prevList = widgetListProcessor.value + if (index >= prevList.size) return + + val newList = when (index) { + 0 -> listOf(widget) + prevList + prevList.size -> prevList + listOf(widget) + else -> + prevList.subList(0, index) + listOf(widget) + prevList.subList(index, prevList.size) + + } + widgetListProcessor.onNext(newList) + } + + /** + * Remove a [View] at [index] from the current list of widgets. + */ + fun removeWidget(@IntRange(from = 0) index: Int): View? { + val prevList = widgetListProcessor.value + if (index >= prevList.size) return null + val newList = prevList.minus(prevList[index]) + widgetListProcessor.onNext(newList) + return prevList[index] + } + + /** + * Remove all [View]s. + */ + fun removeAllWidgets() { + widgetListProcessor.onNext(emptyList()) + } + + /** + * Get the [View] at index from the current list of widgets. + */ + fun getWidget(@IntRange(from = 0) index: Int): View? = widgetListProcessor.value.getOrNull(index) + + /** + * Total size of the current list of widgets. + */ + fun size(): Int = widgetListProcessor.value.size + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/Navigation.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/Navigation.kt new file mode 100644 index 00000000..00f996e4 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/Navigation.kt @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base.panel + +import android.annotation.SuppressLint +import android.content.Context +import android.util.AttributeSet +import android.view.View +import android.view.animation.Animation +import android.view.animation.AnimationUtils +import android.widget.FrameLayout +import androidx.annotation.AnimRes +import androidx.core.content.res.use +import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.processors.BehaviorProcessor +import dji.v5.ux.R +import dji.v5.ux.core.extension.addListener +import dji.v5.ux.core.extension.getResourceIdAndUse +import java.util.* + +/** + * Check if the current view is the first or the root view in the [PanelNavigationView]. + */ +fun PanelNavigator.isCurrentViewRoot(): Boolean = peek() == null + +/** + * Make an object navigable. + */ +interface Navigable { + /** + * Use to navigate to another panel. + */ + var panelNavigator: PanelNavigator? +} + +/** + * Core functions to navigate in the [PanelNavigationView]. + */ +interface PanelNavigator { + /** + * Push a [View] to the top. + */ + fun push(view: View) + + /** + * Pop the current view. Will not pop if the current view is the root. + */ + fun pop() + + /** + * Get the top level [View]. + */ + fun peek(): View? +} + +/** + * View to handheld navigation between panels. + * If a panel item needs to navigate to another panel, make that view implement [Navigable]. + * The [PanelNavigationView] controls the stack of views being presented. It also provides + * customization to change the transition animations. + * + * The PanelNavigationView can be initialized with root view. The root view can also be [push] + * during Runtime. + */ +abstract class PanelNavigationView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + rootView: View? = null +) : FrameLayout(context, attrs, defStyleAttr), PanelNavigator { + + //region Properties + /** + * Enables or disables all transition animations. + */ + var isAnimationEnabled: Boolean = true + + /** + * Transition animation for when a view is added on top. + * Set to null to remove animation. + */ + var addViewToTopAnimation: Animation = loadAnimation(R.anim.uxsdk_slide_right_in) + + /** + * Transition animation for when a view is removed from the top. + * * Set to null to remove animation. + */ + var removeViewFromTopAnimation: Animation = loadAnimation(R.anim.uxsdk_slide_right_out) + + /** + * Transition animation for when a view is reappearing. + * * Set to null to remove animation. + */ + var showViewAnimation: Animation = loadAnimation(R.anim.uxsdk_fade_in) + + /** + * Transition animation for when a view is being replaced. + * * Set to null to remove animation. + */ + var hideViewAnimation: Animation = loadAnimation(R.anim.uxsdk_fade_out) + + private val viewStack: Stack = Stack() + private var currentView: View? = null + private val layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT) + private val isRootViewVisible: BehaviorProcessor = BehaviorProcessor.createDefault(true) + private val viewAdded: BehaviorProcessor = BehaviorProcessor.create() + //endregion + + //region Lifecycle + init { + attrs?.let { + initAnimationAttributes(context, it) + // Must initialize attributes before the first view is added. + initAttributes(context, it) + } + if (rootView != null) { + push(rootView) + } + } + //endregion + + //region Navigation + /** + * Push a [View] to the top. + */ + override fun push(view: View) { + val previousView = currentView + view.tag = view.id + if (view is Navigable) { + view.panelNavigator = this + } + + if (isAnimationEnabled && previousView != null) { + view.isEnabled = false + previousView.isEnabled = false + addViewToTopAnimation.addListener(onEnd = fun(_) { + post { + view.isEnabled = true + previousView.isEnabled = true + removeView(previousView) + } + }) + view.startAnimation(addViewToTopAnimation) + previousView.startAnimation(hideViewAnimation) + } + + currentView = view + previousView?.let { + viewStack.push(it) + if (!isAnimationEnabled) { + removeView(it) + } + } + + addView(currentView, layoutParams) + updateIsRootViewVisible() + onViewPushed(view) + viewAdded.onNext(view) + } + + /** + * Pop the current view. Will not pop if the current view is the root. + */ + override fun pop() { + if (!canRemoveView()) return + + val viewToAdd = viewStack.pop() + val viewToRemove = currentView as View + + if (isAnimationEnabled) { + viewToRemove.isEnabled = false + viewToAdd.isEnabled = false + removeViewFromTopAnimation.addListener(onEnd = fun(_) { + post { + viewToRemove.isEnabled = true + viewToAdd.isEnabled = true + removeView(viewToRemove) + } + }) + + viewToAdd.startAnimation(showViewAnimation) + viewToRemove.startAnimation(removeViewFromTopAnimation) + } else { + removeView(viewToRemove) + } + + currentView = viewToAdd + addView(currentView, layoutParams) + updateIsRootViewVisible() + viewAdded.onNext(viewToAdd) + } + + /** + * Get the top level [View]. + */ + override fun peek(): View? { + if (viewStack.isEmpty()) return null + return viewStack.peek() + } + + /** + * Callback for when a [View] is pushed to the top. + */ + protected abstract fun onViewPushed(view: View) + + /** + * [Flowable] to observe when a [View] is added to the top. + */ + fun viewAdded(): Flowable = viewAdded + //endregion + + //region Customizations + /** + * Set the [animRes] for when a view is added on top. + */ + fun setAddViewToTopAnimation(@AnimRes animRes: Int) { + addViewToTopAnimation = loadAnimation(animRes) + } + + /** + * Set the [animRes] for when a view is removed from the top. + */ + fun setRemoveViewFromTopAnimation(@AnimRes animRes: Int) { + removeViewFromTopAnimation = loadAnimation(animRes) + } + + /** + * Set the [animRes] for when a view is reappearing. + */ + fun setShowViewAnimation(@AnimRes animRes: Int) { + showViewAnimation = loadAnimation(animRes) + } + + /** + * Set the [animRes] for when a view is being replaced. + */ + fun setHideViewAnimation(@AnimRes animRes: Int) { + hideViewAnimation = loadAnimation(animRes) + } + + //region Customization + @SuppressLint("Recycle") + private fun initAnimationAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.PanelNavigationView).use { typedArray -> + isAnimationEnabled = typedArray.getBoolean(R.styleable.PanelNavigationView_uxsdk_animationEnabled, true) + typedArray.getResourceIdAndUse(R.styleable.PanelNavigationView_uxsdk_animationShowView) { + setShowViewAnimation(it) + } + typedArray.getResourceIdAndUse(R.styleable.PanelNavigationView_uxsdk_animationHideView) { + setHideViewAnimation(it) + } + typedArray.getResourceIdAndUse(R.styleable.PanelNavigationView_uxsdk_animationAddViewToTop) { + setAddViewToTopAnimation(it) + } + typedArray.getResourceIdAndUse(R.styleable.PanelNavigationView_uxsdk_animationRemoveViewFromTop) { + setRemoveViewFromTopAnimation(it) + } + } + } + + /** + * Initialize child attributes here. + */ + protected abstract fun initAttributes(context: Context, attrs: AttributeSet) + //endregion + + //region Helpers + private fun canRemoveView(): Boolean = viewStack.size > 0 && currentView != null + + private fun updateIsRootViewVisible() { + val isRootViewVisible = !canRemoveView() + val currentValue = this.isRootViewVisible.value + if (currentValue != isRootViewVisible) { + this.isRootViewVisible.onNext(isRootViewVisible) + } + } + + private fun loadAnimation(@AnimRes animRes: Int) = AnimationUtils.loadAnimation(context, animRes) + //endregion + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/PanelItem.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/PanelItem.kt new file mode 100644 index 00000000..11a5d7f7 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/PanelItem.kt @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base.panel + +import android.view.View +import androidx.annotation.IntRange +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.base.widget.FrameLayoutWidget + +/** + * Encapsulates a View with properties used to define how it is laid out. + * @property view The child view to add into a panel. + * @property itemMarginLeft Left margin pixel size, null by default + * @property itemMarginTop Top margin pixel size, null by default + * @property itemMarginRight Right margin pixel size, null by default + * @property itemMarginBottom Bottom margin pixel size, null by default + * @param desiredWidgetSizeDescription Widget size description, null by default + * @param desiredRatioString Desired ratio for the view of the width to height, null by default + */ +class PanelItem( + val view: View, + @IntRange(from = 0) val itemMarginLeft: Int? = null, + @IntRange(from = 0) val itemMarginTop: Int? = null, + @IntRange(from = 0) val itemMarginRight: Int? = null, + @IntRange(from = 0) val itemMarginBottom: Int? = null, + desiredWidgetSizeDescription: WidgetSizeDescription? = null, + desiredRatioString: String? = null) { + + /** + * The default [WidgetSizeDescription]. + */ + val widgetSizeDescription: WidgetSizeDescription? = desiredWidgetSizeDescription + ?: when (view) { + is FrameLayoutWidget<*> -> view.widgetSizeDescription + is ConstraintLayoutWidget<*> -> view.widgetSizeDescription + else -> null + } + + /** + * The default ratio [String] of the width to height. + */ + val ratioString: String? = desiredRatioString + ?: when (view) { + is ConstraintLayoutWidget<*> -> view.getIdealDimensionRatioString() + is FrameLayoutWidget<*> -> view.getIdealDimensionRatioString() + else -> null + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/PanelWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/PanelWidget.kt new file mode 100644 index 00000000..e4d8b14a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/PanelWidget.kt @@ -0,0 +1,607 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base.panel + +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.ColorStateList +import android.content.res.TypedArray +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.View +import android.view.View.OnClickListener +import android.widget.ImageView +import android.widget.TextView +import androidx.annotation.* +import androidx.annotation.IntRange +import androidx.constraintlayout.widget.ConstraintSet +import androidx.core.content.res.use +import dji.v5.utils.common.DisplayUtil +import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.processors.PublishProcessor +import dji.v5.ux.R +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.util.ViewIDGenerator +import dji.v5.ux.core.util.ViewUtil + +/** + * Base class for all PanelWidgets. + * [S] is the type of objects the panel holds. + * [T] is the type of Widget State Update, @see[getWidgetStateUpdate]. + * A PanelWidget is a collection of widgets that can be displayed in different ways: + * - [BarPanelWidget] + * - [ListPanelWidget] + * The PanelWidget can be configured with a [PanelWidgetConfiguration], which allows the user + * to set the [PanelWidgetType] and set up a toolbar if needed. + * It also provides helpers for the children to know the bounds of the parent: + * - [PanelWidget.getParentTopId] + * - [PanelWidget.getParentBottomId] + * - [PanelWidget.getParentStartId] + * - [PanelWidget.getParentEndId] + * + * Widgets in the BarPanelWidget can be customized in terms of how they are placed, e.g., using ratio, + * wrapping content. See [PanelItem] for configuration of individual widgets. + * + * @param panelWidgetConfiguration * The default [PanelWidgetConfiguration]. + */ +abstract class PanelWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + protected val panelWidgetConfiguration: PanelWidgetConfiguration +) : ConstraintLayoutWidget(context, attrs, defStyleAttr), Navigable { + + //region Public Properties + /** + * Background color for the title bar + */ + @get:ColorInt + var titleBarBackgroundColor: Int = 0 + set(@ColorInt value) { + field = value + titleBarContainer?.setBackgroundColor(value) + } + + /** + * The drawable for the back button icon + */ + var backButtonIcon: Drawable? + get() = backImageView?.imageDrawable + set(value) { + backImageView?.imageDrawable = value + } + + /** + * The color for the back button icon + */ + @get:ColorInt + var backButtonIconColor: Int? = null + set(@ColorInt value) { + field = value + if (backImageView != null && value != null) { + ViewUtil.tintImage(backImageView as ImageView, value) + } + } + + /** + * The color state list for the back button icon + */ + var backButtonIconColors: ColorStateList? = null + set(value) { + field = value + if (backImageView != null && value != null) { + ViewUtil.tintImage(backImageView as ImageView, value) + } + } + + /** + * The drawable for the back button icon's background + */ + var backButtonIconBackground: Drawable? = null + set(value) { + field = value + backImageView?.background = value + } + + /** + * The drawable for the close button icon + */ + var closeButtonIcon: Drawable? = null + set(value) { + field = value + closeImageView?.imageDrawable = value + } + + /** + * The drawable for the close button icon's background + */ + var closeButtonIconBackground: Drawable? = null + set(value) { + field = value + closeImageView?.background = value + } + + /** + * The color for the close button icon + */ + @get:ColorInt + var closeButtonIconColor: Int? = null + set(@ColorInt value) { + field = value + if (closeImageView != null && value != null) { + ViewUtil.tintImage(closeImageView as ImageView, value) + } + } + + /** + * The color state list for the close button icon + */ + var closeButtonIconColors: ColorStateList? = null + set(value) { + field = value + if (closeImageView != null && value != null) { + ViewUtil.tintImage(closeImageView as ImageView, value) + } + } + + /** + * Text for the title + */ + var titleText: CharSequence? + get() = titleTextView?.text + set(text) { + if (text != null) { + titleTextView?.text = text + } + } + + /** + * Text size for the title + */ + var titleTextSize: Float? + get() = titleTextView?.textSize + set(textSize) { + if (textSize != null) { + titleTextView?.textSize = textSize + } + } + + /** + * The color for the title + */ + @get:ColorInt + var titleTextColor: Int? = null + set(@ColorInt value) { + field = value + if (value != null) { + titleTextView?.textColor = value + } + } + //endregion + + //region Private Properties + /** + * Use for navigating between panels, + */ + override var panelNavigator: PanelNavigator? = null + + /** + * The default ratio [String] for panel items. + */ + protected val defaultRatioString: String = getString(R.string.uxsdk_widget_default_ratio) + private val backButtonPressedProcessor: PublishProcessor = PublishProcessor.create() + private val closeBoxPressedProcessor: PublishProcessor = PublishProcessor.create() + + private var parentTopId: Int = ConstraintSet.PARENT_ID + private val parentBottomId: Int = ConstraintSet.PARENT_ID + private val parentStartId: Int = ConstraintSet.PARENT_ID + private val parentEndId: Int = ConstraintSet.PARENT_ID + + private var titleBarContainer: View? = null + private var backImageView: ImageView? = null + private var backBackgroundView: View? = null + private var closeImageView: ImageView? = null + private var closeBackgroundView: View? = null + private var titleTextView: TextView? = null + + private val closeButtonBackgroundOnClickListener = OnClickListener { + closeImageView?.performClick() + } + private val closeButtonOnClickListener = OnClickListener { + closeBoxPressedProcessor.onNext(true) + } + //endregion + + //region Constructor + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + // Nothing to do + } + + init { + setUpTitleBar() + initPanelWidget(context, attrs, defStyleAttr, panelWidgetConfiguration) + attrs?.let { initAttributes(context, it) } + } + + /** + * Invoked during the initialization of the class. + * Inflate should be done here. For Kotlin, load attributes, findViewById should be done in + * the init block. + * + * @param context Context + * @param attrs Attribute set + * @param defStyleAttr Style attribute + */ + protected abstract fun initPanelWidget(context: Context, attrs: AttributeSet?, defStyleAttr: Int, widgetConfiguration: PanelWidgetConfiguration?) + //endregion + + //region Lifecycle & Setup + protected abstract fun updateUI() + + private fun setUpTitleBar() { + val currentBackground = background + if (panelWidgetConfiguration.showTitleBar) { + val titleBarView: View = inflate(context, R.layout.uxsdk_layout_title_bar, this) + val titleBarContainer = titleBarView.findViewById(R.id.view_title_bar_container) + val containerLayoutParams = titleBarContainer?.layoutParams + containerLayoutParams?.height = panelWidgetConfiguration.titleBarHeight.toInt() + + // Back button + backBackgroundView = titleBarView.findViewById(R.id.view_back_background) + backImageView = titleBarView.findViewById(R.id.image_view_back) as ImageView? + backBackgroundView?.setOnClickListener { backImageView?.performClick() } + backImageView?.setOnClickListener { + backButtonPressedProcessor.onNext(true) + panelNavigator?.pop() + } + hideBackButton() + + // Close box + closeBackgroundView = titleBarView.findViewById(R.id.view_close_background) + closeImageView = titleBarView.findViewById(R.id.image_view_close) as ImageView? + setCloseButtonVisible(panelWidgetConfiguration.hasCloseButton) + + // Title + titleTextView = titleBarView.findViewById(R.id.text_view_title) + titleTextView?.text = panelWidgetConfiguration.panelTitle + titleTextView?.visibility = + if (panelWidgetConfiguration.showTitleBar) View.VISIBLE + else View.GONE + + parentTopId = titleBarContainer.id + this.titleBarContainer = titleBarContainer + } + background = currentBackground + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (panelNavigator?.isCurrentViewRoot() == false) { + showBackButton() + } + } + //endregion + + //region Events + /** + * [Flowable] to observe when the back button is pressed. + */ + fun backButtonPressed(): Flowable = backButtonPressedProcessor + + /** + * [Flowable] to observe when the close button is pressed. + */ + fun closeButtonPressed(): Flowable = closeBoxPressedProcessor + //endregion + + //region Populate Panel + /** + * Get the [S] at index from to the current list of widgets. + */ + abstract fun getWidget(@IntRange(from = 0) index: Int): S? + + /** + * Add a new [List] of [S]. + */ + abstract fun addWidgets(items: Array) + + /** + * Total size of [S] in the current list of widgets. + */ + abstract fun size(): Int + + /** + * Add a [S] at [index] to the current list of widgets. + */ + abstract fun addWidget(@IntRange(from = 0) index: Int, item: S) + + /** + * Remove a [S] at [index] to the current list of widgets. + */ + abstract fun removeWidget(@IntRange(from = 0) index: Int): S? + + /** + * Remove all [S]s. + */ + abstract fun removeAllWidgets() + //endregion + + //region Customization + /** + * Enable/disable close and back button + */ + override fun setEnabled(enabled: Boolean) { + super.setEnabled(enabled) + setBackButtonEnabled(enabled) + setCloseButtonEnabled(enabled) + } + + /** + * Set the resource ID for the title background color + * + * @param colorRes Integer ID of the resource + */ + fun setTitleBarBackgroundColorRes(@ColorRes colorRes: Int) { + titleBarBackgroundColor = getColor(colorRes) + } + + /** + * Set the resource ID for the back button icon + * + * @param resourceId Integer ID of the drawable resource + */ + fun setBackButtonIcon(@DrawableRes resourceId: Int) { + backButtonIcon = getDrawable(resourceId) + } + + /** + * Set the resource ID for the back button icon's background + * + * @param resourceId Integer ID of the icon's background resource + */ + fun setBackButtonIconBackground(@DrawableRes resourceId: Int) { + backButtonIconBackground = getDrawable(resourceId) + } + + /** + * Set the resource ID for the back button icon's color + * + * @param colorRes Integer ID of the icon's background resource + */ + fun setBackButtonIconColorRes(@ColorRes colorRes: Int) { + backButtonIconColor = getColor(colorRes) + } + + /** + * Set the resource ID for the close button icon + * + * @param resourceId Integer ID of the drawable resource + */ + fun setCloseButtonIcon(@DrawableRes resourceId: Int) { + closeButtonIcon = getDrawable(resourceId) + } + + /** + * Set the resource ID for the back button icon's background + * + * @param resourceId Integer ID of the icon's background resource + */ + fun setCloseButtonIconBackground(@DrawableRes resourceId: Int) { + closeButtonIconBackground = getDrawable(resourceId) + } + + /** + * Change the visibility of the title bar's close button. + */ + fun setCloseButtonVisible(visible: Boolean) { + if (visible) { + closeImageView?.visibility = View.VISIBLE + closeImageView?.isFocusable = true + closeImageView?.isClickable = true + closeBackgroundView?.setOnClickListener(closeButtonBackgroundOnClickListener) + closeImageView?.setOnClickListener(closeButtonOnClickListener) + } else { + closeImageView?.visibility = View.INVISIBLE + closeImageView?.isFocusable = false + closeImageView?.isClickable = false + closeBackgroundView?.setOnClickListener(null) + closeImageView?.setOnClickListener(null) + } + } + + /** + * Set text appearance of the title text view + * + * @param textAppearanceResId Style resource for text appearance + */ + fun setTitleTextAppearance(@StyleRes textAppearanceResId: Int) { + titleTextView?.setTextAppearance(context, textAppearanceResId) + } + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.PanelWidget).use { typedArray -> + extractAttributes(typedArray) + } + } + + /** + * Override the style of the panel with the [styleRes]. + */ + @SuppressLint("Recycle") + fun setStyle(@StyleRes styleRes: Int) { + context.obtainStyledAttributes(styleRes, R.styleable.PanelWidget).use { typedArray -> + extractAttributes(typedArray) + } + } + + private fun extractAttributes(typedArray: TypedArray) { + typedArray.getColorAndUse(R.styleable.PanelWidget_uxsdk_titleBarBackgroundColor) { + titleBarBackgroundColor = it + } + typedArray.getDrawableAndUse(R.styleable.PanelWidget_uxsdk_backButtonIcon) { + backButtonIcon = it + } + typedArray.getDrawableAndUse(R.styleable.PanelWidget_uxsdk_backButtonIconBackground) { + backButtonIconBackground = it + } + typedArray.getColorStateListAndUse(R.styleable.PanelWidget_uxsdk_backButtonIconColor) { + backButtonIconColors = it + } + typedArray.getColorAndUse(R.styleable.PanelWidget_uxsdk_backButtonIconColor) { + backButtonIconColor = it + } + typedArray.getDrawableAndUse(R.styleable.PanelWidget_uxsdk_closeButtonIcon) { + closeButtonIcon = it + } + typedArray.getDrawableAndUse(R.styleable.PanelWidget_uxsdk_closeButtonIconBackground) { + closeButtonIconBackground = it + } + typedArray.getColorStateListAndUse(R.styleable.PanelWidget_uxsdk_closeButtonIconColor) { + closeButtonIconColors = it + } + typedArray.getColorAndUse(R.styleable.PanelWidget_uxsdk_closeButtonIconColor) { + closeButtonIconColor = it + } + typedArray.getStringAndUse(R.styleable.PanelWidget_uxsdk_titleText) { + titleText = it + } + typedArray.getResourceIdAndUse(R.styleable.PanelWidget_uxsdk_titleTextAppearance) { + setTitleTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.PanelWidget_uxsdk_titleTextSize) { + titleTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.PanelWidget_uxsdk_titleTextColor) { + titleTextColor = it + } + } + //endregion + + //region Helpers + /** + * Constrain the [view] to the top of the panel, with an optional [margin]. + */ + protected fun ConstraintSet.constraintToParentTop(view: View, margin: Int = 0) { + if (parentTopId == ConstraintSet.PARENT_ID) { + connect(view.id, ConstraintSet.TOP, parentTopId, ConstraintSet.TOP, margin) + } else { + connect(view.id, ConstraintSet.TOP, parentTopId, ConstraintSet.BOTTOM, margin) + } + } + + /** + * Constrain the [view] to the bottom of the panel, with an optional [margin]. + */ + protected fun ConstraintSet.constraintToParentBottom(view: View, margin: Int = 0) { + if (parentBottomId == ConstraintSet.PARENT_ID) { + connect(view.id, ConstraintSet.BOTTOM, ConstraintSet.PARENT_ID, ConstraintSet.BOTTOM, margin) + } else { + connect(view.id, ConstraintSet.BOTTOM, parentBottomId, ConstraintSet.TOP, margin) + } + } + + /** + * Constrain the [view] to the start of the panel, with an optional [margin]. + */ + protected fun ConstraintSet.constraintToParentStart(view: View, margin: Int = 0) { + if (parentStartId == ConstraintSet.PARENT_ID) { + connect(view.id, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.START, margin) + } else { + connect(view.id, ConstraintSet.START, ConstraintSet.PARENT_ID, ConstraintSet.END, margin) + } + } + + /** + * Constrain the [view] to the end of the panel, with an optional [margin]. + */ + protected fun ConstraintSet.constraintToParentEnd(view: View, margin: Int = 0) { + if (parentEndId == ConstraintSet.PARENT_ID) { + connect(view.id, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.END, margin) + } else { + connect(view.id, ConstraintSet.END, ConstraintSet.PARENT_ID, ConstraintSet.START, margin) + } + } + + /** + * Get the current parent top view id to use for constraints. + */ + protected fun getParentTopId(): Int = parentTopId + + /** + * Get the current parent bottom view id to use for constraints. + */ + protected fun getParentBottomId(): Int = parentBottomId + + /** + * Get the current parent start view id to use for constraints. + */ + protected fun getParentStartId(): Int = parentStartId + + /** + * Get the current parent end view id to use for constraints. + */ + protected fun getParentEndId(): Int = parentEndId + + /** + * Add view to the panel. + */ + override fun addView(view: View) { + view.id = ViewIDGenerator.generateViewId() + if (view is Navigable) { + view.panelNavigator = panelNavigator + } + super.addView(view) + } + + private fun showBackButton() { + backImageView?.visibility = View.VISIBLE + setBackButtonClickable(true) + } + + private fun hideBackButton() { + backImageView?.visibility = View.INVISIBLE + setBackButtonClickable(false) + } + + private fun setBackButtonClickable(enabled: Boolean) { + backImageView?.isClickable = enabled + backImageView?.isFocusable = enabled + backBackgroundView?.isClickable = enabled + backBackgroundView?.isFocusable = enabled + } + + private fun setBackButtonEnabled(enabled: Boolean) { + backImageView?.isEnabled = enabled + backBackgroundView?.isEnabled = enabled + } + + private fun setCloseButtonEnabled(enabled: Boolean) { + closeImageView?.isEnabled = enabled + closeBackgroundView?.isEnabled = enabled + } + //endregion +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/PanelWidgetConfiguration.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/PanelWidgetConfiguration.kt new file mode 100644 index 00000000..0841454c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/PanelWidgetConfiguration.kt @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base.panel + +import android.content.Context +import androidx.annotation.DimenRes +import androidx.annotation.Px +import dji.v5.ux.R + +/** + * Configuration properties to initialize a panel. + * @param context asd + * @property panelWidgetType The type of panel widget + * @property showTitleBar Boolean to hide or show the whole title bar + * @property hasCloseButton Boolean to hide or show the close button + * @property panelTitle Default panel title text + * @param titleBarHeightDimensionResID [DimenRes] for the height of the title bar + */ +class PanelWidgetConfiguration( + context: Context, + var panelWidgetType: PanelWidgetType, + var showTitleBar: Boolean = false, + var hasCloseButton: Boolean = false, + var panelTitle: String = "", + @DimenRes titleBarHeightDimensionResID: Int = R.dimen.uxsdk_top_bar_default_height +) { + /** + * The title bar height in pixels. + */ + @Px + var titleBarHeight: Float = context.resources.getDimension(titleBarHeightDimensionResID) + + /** + * Check if the [PanelWidget] is a [BarPanelWidget]. + */ + fun isBarPanelWidget(): Boolean = + panelWidgetType == PanelWidgetType.BAR_HORIZONTAL + || panelWidgetType == PanelWidgetType.BAR_VERTICAL +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/PanelWidgetType.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/PanelWidgetType.kt new file mode 100644 index 00000000..2fa440c0 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/PanelWidgetType.kt @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base.panel + +import androidx.annotation.IntRange + +/** + * Enum representing the type of panel widget created. + * @param value Int value + */ +enum class PanelWidgetType(val value: Int) { + /** + * Vertical type for [BarPanelWidget] + */ + BAR_VERTICAL(0), + + /** + * Horizontal type for [BarPanelWidget] + */ + BAR_HORIZONTAL(1), + + /** + * Vertical list type for [ListPanelWidget] + */ + LIST(2), + + /** + * A custom structure formed using [FreeFormPanelWidget] + */ + FREE_FORM(3), + + /** + * A custom structure formed using [ToolbarPanelWidget] + */ + TOOLBAR_LEFT(4), + + /** + * A custom structure formed using [ToolbarPanelWidget] + */ + TOOLBAR_RIGHT(5), + + /** + * A custom structure formed using [ToolbarPanelWidget] + */ + TOOLBAR_TOP(6); + + companion object { + @JvmStatic + val values = values() + + /** + * Find a [PanelWidgetType] from an int value. + */ + @JvmStatic + fun find(@IntRange(from = 0, to = 3) index: Int): PanelWidgetType = values[index] + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/SmartListModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/SmartListModel.kt new file mode 100644 index 00000000..ae71fed5 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/SmartListModel.kt @@ -0,0 +1,322 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base.panel + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import androidx.annotation.IntRange +import dji.sdk.keyvalue.value.product.ProductType +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.SchedulerProvider +import io.reactivex.rxjava3.disposables.CompositeDisposable +import io.reactivex.rxjava3.disposables.Disposable +import io.reactivex.rxjava3.functions.Consumer +import io.reactivex.rxjava3.processors.PublishProcessor +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.panel.systemstatus.SmartListInternalModel +import dji.v5.ux.core.util.UxErrorHandle + +/** + * The [String] to identify a widget. + */ +typealias WidgetID = String + +/** + * The [SmartListModel] handles the creation and order of child views for a [ListPanelWidget] by holding + * a reference to ListPanelWidget's [ListPanelWidgetBaseModel]. + * + * The [SmartListModel] controls when the child view is created and it may encapsulate a WidgetModel to + * handheld business logic for when to show/hide items. + * + * When creating a [SmartListModel], widgets are registered with [registeredWidgetIDList]. This + * list defines all the [WidgetID]s that are allowed in this panel. + * A widget is said to become active, when its [WidgetID] is passed in a set with [buildAndInstallWidgets]. + * Thus, An active widget is a widget that is currently being shown and its object has been created. + * Once a widget is active at least once, the [SmartListModel] will hold a reference until the [SmartListModel] + * is destroyed. + */ +abstract class SmartListModel @JvmOverloads constructor( + protected val context: Context, + private val attrs: AttributeSet? = null, + private val excludedItems: Set? = null) { + + //region Properties + /** + * Defines what [WidgetID]s are allowed into this [SmartListModel]. + * This list also defines the order of all the items. + * Override this to register more [WidgetID]s. + */ + abstract val registeredWidgetIDList: List + + /** + * The default active widgets that will be created and shown. + */ + abstract val defaultActiveWidgetSet: Set + + /** + * The size of the current active widgets. + */ + val activeWidgetSize: Int + get() = activeWidgetList.size + + /** + * The size of all widgets registered in this [SmartListModel]. + */ + val totalWidgetSize: Int + get() = registeredWidgetIDList.size + + /** + * [Flowable] to observe when a widget has been created. + * Emits a [Pair] of [WidgetID] and [View]. + */ + val widgetCreated: Flowable> + get() = widgetCreatedProcessor + + /** + * Widget model to detect the connected product. + */ + private var widgetModel : SmartListInternalModel? = null + private var currentOrderList: MutableList = mutableListOf() + private val createdWidgetsMap: MutableMap = mutableMapOf() + private var activeWidgetList: List = emptyList() + private var activeWidgetSet: Set = emptySet() + private var listPanelWidgetBaseModel: ListPanelWidgetBaseModel? = null + private var widgetCreatedProcessor: PublishProcessor> = PublishProcessor.create() + + private var compositeDisposable: CompositeDisposable? = null + //endregion + + //region Lifecycle + /** + * Set up the [SmartListModel] by initializing all the required resources. + */ + fun setUp() { + currentOrderList = registeredWidgetIDList.toMutableList() + buildAndInstallWidgets(defaultActiveWidgetSet) + compositeDisposable = CompositeDisposable() + widgetModel = SmartListInternalModel(djiSdkModel = DJISDKModel.getInstance(), uxKeyManager = ObservableInMemoryKeyedStore.getInstance()) + widgetModel?.setup() + addDisposable(widgetModel!!.productConnection.observeOn(SchedulerProvider.ui()) + .subscribe(Consumer { onProductConnectionChanged(it) }, + UxErrorHandle.logErrorConsumer("SmartListModel", "Error on Product changed. "))) + addDisposable(widgetModel!!.aircraftModel.observeOn(SchedulerProvider.ui()) + .subscribe(Consumer { onAircraftModelChanged(it) }, + UxErrorHandle.logErrorConsumer("SmartListModel", "Error on Aircraft Model Changed. "))) + + inSetUp() + + } + + /** + * Clean up the [SmartListModel] by destroying all the resources used. + */ + fun cleanUp() { + inCleanUp() + widgetModel?.cleanup() + disposeAll() + } + + /** + * Setup method for initialization that must be implemented + */ + protected abstract fun inSetUp() + + /** + * Cleanup method for post-usage destruction that must be implemented + */ + protected abstract fun inCleanUp() + + /** + * Setup the list based product connection + */ + protected abstract fun onProductConnectionChanged(isConnected: Boolean) + + /** + * Setup the list based on the connected aircraft + */ + protected abstract fun onAircraftModelChanged(model: ProductType) + //endregion + + //region Installing Widgets + /** + * Pass a new [Set] of active [WidgetID]. + * It will create widgets that have not been created and emit them to [ListPanelWidget]. + */ + protected fun buildAndInstallWidgets(newActiveWidgetIDs: Set) { + buildActiveWidgetList(newActiveWidgetIDs) + updateHolder() + } + + /** + * Callback for when a [View] needs to be created for the given [WidgetID]. + */ + protected abstract fun createWidget(widgetID: WidgetID): View + + /** + * Set a reference to a [ListPanelWidgetBaseModel]. + * Must be set to communicate changes to the [ListPanelWidget]. + */ + fun setListPanelWidgetHolder(listPanelWidgetBaseModel: ListPanelWidgetBaseModel) { + this.listPanelWidgetBaseModel = listPanelWidgetBaseModel + } + + /** + * Get [View] at [index] from the active widget list. + */ + fun getActiveWidget(@IntRange(from = 0) index: Int): View? = activeWidgetList.getOrNull(index) + + /** + * Get [View] with [widgetID] from the active widget list. + */ + fun getActiveWidget(widgetID: WidgetID): View? { + if (activeWidgetSet.contains(widgetID)) return createdWidgetsMap[widgetID] + return null + } + + /** + * Get the [WidgetID] at [index] from the current order list. + * This is the order of all active and inactive widgets. + */ + fun getWidgetID(@IntRange(from = 0) index: Int): WidgetID? = currentOrderList.getOrNull(index) + + /** + * Get the [View] for the [WidgetID]. Only available if the widget has become active at least once. + */ + fun getWidget(widgetID: WidgetID): View? = createdWidgetsMap[widgetID] + + /** + * Ge the index for the [WidgetID] from the current order list. + * This is the order of all active and inactive widgets. + */ + fun getWidgetIndex(widgetID: WidgetID): Int { + currentOrderList.forEachIndexed { index, currWidgetId -> + if (currWidgetId == widgetID) return index + } + + return -1 + } + + /** + * Change the [index] for a [WidgetID], effectively changing its order in + * the list of active and inactive widgets. + */ + fun setIndex(@IntRange(from = 0) index: Int, widgetID: WidgetID) { + if (index >= currentOrderList.size) return + var currentIndex = -1 + currentOrderList.forEachIndexed { i, value -> + if (value == widgetID) currentIndex = i + } + if (currentIndex != -1) { + currentOrderList.removeAt(currentIndex) + currentOrderList.add(index, widgetID) + + reorderActiveWidgets() + updateHolder() + } + } + + /** + * Change the order of a [WidgetID] from one index to another, effectively changing its order in + * the list of active and inactive widgets. + */ + fun setIndex(@IntRange(from = 0) fromIndex: Int, @IntRange(from = 0) toIndex: Int) { + if (fromIndex >= currentOrderList.size || toIndex >= currentOrderList.size) return + val widgetID = currentOrderList.removeAt(fromIndex) + currentOrderList.add(toIndex, widgetID) + + reorderActiveWidgets() + updateHolder() + } + + /** + * Remove items from the current active list. + */ + protected fun updateListMinus(vararg itemToRemove: WidgetID) { + val newOrder = activeWidgetSet.minus(itemToRemove.toSet()) + buildAndInstallWidgets(newOrder) + } + + /** + * Add items from the current active list. + */ + protected fun updateListPlus(vararg itemToAdd: WidgetID) { + val newOrder = activeWidgetSet.plus(itemToAdd.toSet()) + buildAndInstallWidgets(newOrder) + } + //endregion + + //region Helpers + /** + * Add a disposable which is automatically disposed with the [SmartListModel]'s lifecycle. + * + * @param disposable the disposable to add + */ + protected fun addDisposable(disposable: Disposable) { + compositeDisposable?.add(disposable) + } + + private fun disposeAll() { + compositeDisposable?.dispose() + compositeDisposable = null + } + + private fun updateHolder() { + listPanelWidgetBaseModel?.addWidgets(activeWidgetList) + } + + private fun WidgetID.isNotExcluded(): Boolean = excludedItems == null || !excludedItems.contains(this) + + private fun buildActiveWidgetList(newActiveWidgetIDs: Set) { + // Prevent widgetIDs that were not originally registered + activeWidgetSet = newActiveWidgetIDs.intersect(registeredWidgetIDList) + // Create views if they don't exist + activeWidgetSet + .filter { widgetID -> + widgetID.isNotExcluded() && !createdWidgetsMap.containsKey(widgetID) + } + .map { widgetID -> + val createdWidget = createWidget(widgetID) + widgetCreatedProcessor.onNext(widgetID to createdWidget) + createdWidgetsMap[widgetID] = createdWidget + createdWidget + } + + + // Create new list based on sorted items + reorderActiveWidgets() + } + + private fun reorderActiveWidgets() { + activeWidgetList = currentOrderList + .filter { widgetID -> + widgetID.isNotExcluded() + && activeWidgetSet.contains(widgetID) + && createdWidgetsMap.containsKey(widgetID) + }.map { originalIndex -> createdWidgetsMap[originalIndex] as View } + } + //endregion + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/listitem/ListItemEditTextButtonWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/listitem/ListItemEditTextButtonWidget.kt new file mode 100644 index 00000000..c85a76e3 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/listitem/ListItemEditTextButtonWidget.kt @@ -0,0 +1,680 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base.panel.listitem + +import android.annotation.SuppressLint +import android.app.Activity +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.drawable.Drawable +import android.os.Build +import android.text.Editable +import android.text.InputType +import android.text.TextWatcher +import android.util.AttributeSet +import android.view.* +import android.view.inputmethod.EditorInfo +import android.view.inputmethod.InputMethodManager +import android.widget.EditText +import android.widget.TextView +import androidx.annotation.* +import androidx.constraintlayout.widget.ConstraintSet +import androidx.core.content.res.use +import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.processors.PublishProcessor +import dji.v5.ux.R +import dji.v5.ux.core.base.panel.listitem.ListItemEditTextButtonWidget.WidgetType +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.util.ViewIDGenerator + + +/** + * This is the base class to be used for list item + * The class represents the item with icon, item name and editable fields + * @property widgetType - The [WidgetType] of the current widget. + */ +abstract class ListItemEditTextButtonWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + val widgetType: WidgetType, + @StyleRes defaultStyle: Int +) : ListItemTitleWidget(context, attrs, defStyleAttr, defaultStyle), View.OnClickListener { + + //region Fields + private val listItemButton: TextView = TextView(context) + + private val listItemHintTextView: TextView = TextView(context) + + private val listItemEditTextView: EditText = EditText(context) + + protected val uiUpdateStateProcessor: PublishProcessor = PublishProcessor.create() + + //endregion + /** + * Get the [UIState] updates + */ + open fun getUIStateUpdates(): Flowable { + return uiUpdateStateProcessor.onBackpressureBuffer() + } + + /** + * Default color of the edit text value + */ + @ColorInt + var editTextNormalColor: Int = getColor(R.color.uxsdk_status_edit_text_color) + + //region hint customizations + /** + * The list item hint string + */ + var listItemHint: String? + @Nullable get() = listItemHintTextView.text.toString() + set(@Nullable value) { + listItemHintTextView.text = value + } + + /** + * The size of the list item hint text + */ + var listItemHintTextSize: Float + @Dimension get() = listItemHintTextView.textSize + set(@Dimension value) { + listItemHintTextView.textSize = value + } + + /** + * The color of the list item hint text + */ + var listItemHintTextColor: Int + @ColorInt get() = listItemHintTextView.textColor + set(@ColorInt value) { + listItemHintTextView.textColor = value + } + + /** + * The color state list of the list item hint text + */ + var listItemHintTextColors: ColorStateList? + get() = listItemHintTextView.textColorStateList + set(value) { + listItemHintTextView.textColorStateList = value + } + + /** + * The background of the list item hint text + */ + var listItemHintBackground: Drawable? + get() = listItemHintTextView.background + set(value) { + listItemHintTextView.background = value + } + + /** + * The visibility of list item hint + */ + var listItemHintVisibility: Boolean + get() = listItemHintTextView.visibility == View.VISIBLE + set(value) { + if (value) { + listItemHintTextView.show() + } else { + listItemHintTextView.hide() + } + } + //endregion + + //region button customizations + /** + * The list item hint string + */ + var listItemButtonText: String? + @Nullable get() = listItemButton.text.toString() + set(@Nullable hint) { + listItemButton.text = hint + } + + /** + * The size of the list item hint text + */ + var listItemButtonTextSize: Float + @Dimension get() = listItemButton.textSize + set(@Dimension hint) { + listItemButton.textSize = hint + } + + /** + * The color of the list item hint text + */ + var listItemButtonTextColor: Int + @ColorInt get() = listItemButton.textColor + set(@ColorInt value) { + listItemButton.textColor = value + } + + /** + * The color state list of the list item hint text + */ + var listItemButtonTextColors: ColorStateList? + get() = listItemButton.textColorStateList + set(value) { + listItemButton.textColorStateList = value + } + + /** + * The background of the list item hint text + */ + var listItemButtonBackground: Drawable? + get() = listItemButton.background + set(value) { + listItemButton.background = value + } + + /** + * Button enabled/disabled + */ + var listItemButtonEnabled: Boolean + get() = listItemButton.isEnabled + set(value) { + listItemButton.isEnabled = value + } + + /** + * Button visibility + */ + var listItemButtonVisibility: Boolean + get() = listItemButton.visibility == View.VISIBLE + set(value) { + if (value) { + listItemButton.show() + } else { + listItemButton.hide() + } + } + //endregion + + //region Edit text + + /** + * Background of edit text + */ + var listItemEditTextBackground: Drawable? + get() = listItemEditTextView.background + set(value) { + listItemEditTextView.background = value + } + + /** + * Text color of edit text + */ + var listItemEditTextColor: Int + @ColorInt get() = listItemEditTextView.textColor + set(@ColorInt value) { + listItemEditTextView.textColor = value + } + + /** + * Text ColorStateList for edit text + */ + var listItemEditTextColors: ColorStateList? + get() = listItemEditTextView.textColorStateList + set(value) { + listItemEditTextView.textColorStateList = value + } + + /** + * Width of edit text + */ + var listItemEditTextWidth: Int + @Dimension get() = listItemEditTextView.width + set(@Dimension value) { + listItemEditTextView.width = value + } + + /** + * Input type of edit text + */ + var listItemEditTextInputType: Int + get() = listItemEditTextView.inputType + set(value) { + listItemEditTextView.inputType = value + } + + /** + * Visibility of the edit text + */ + var listItemEditTextVisibility: Boolean + get() = listItemEditTextView.visibility == View.VISIBLE + set(value) { + if (value) { + listItemEditTextView.show() + } else { + listItemEditTextView.hide() + } + } + + /** + * Edit text value + */ + var listItemEditTextValue: String? + get() = listItemEditTextView.text.toString() + set(value) = listItemEditTextView.setText(value) + + /** + * Text size of edit text + */ + var listItemEditTextSize: Float + get() = listItemEditTextView.textSize + set(value) { + listItemEditTextView.textSize = value + } + //endregion + + init { + if (widgetType == WidgetType.EDIT) { + configureEditTextWidget() + } else { + configureEditTextButtonWidget() + } + val paddingValue = resources.getDimension(R.dimen.uxsdk_pre_flight_checklist_item_padding).toInt() + setContentPadding(0, paddingValue, 0, paddingValue) + initAttributes(context, attrs) + } + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet?) { + context.obtainStyledAttributes(attrs, R.styleable.ListItemEditTextButtonWidget, 0, defaultStyle).use { typedArray -> + typedArray.getColorAndUse(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_edit_text_normal_color) { + editTextNormalColor = it + } + typedArray.getResourceIdAndUse(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_hint_appearance) { + setListItemHintTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_hint_text_size) { + listItemHintTextSize = it + } + typedArray.getColorAndUse(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_hint_text_color) { + listItemHintTextColor = it + } + typedArray.getColorStateListAndUse(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_hint_text_color) { + listItemHintTextColors = it + } + typedArray.getDrawableAndUse(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_hint_background) { + listItemHintBackground = it + } + listItemHintVisibility = typedArray.getBoolean(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_hint_visibility, + listItemHintVisibility) + listItemHint = + typedArray.getString(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_hint, + getString(R.string.uxsdk_string_default_value)) + + typedArray.getResourceIdAndUse(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_button_appearance) { + setListItemButtonTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_button_text_size) { + listItemButtonTextSize = it + } + typedArray.getColorAndUse(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_button_text_color) { + listItemButtonTextColor = it + } + typedArray.getColorStateListAndUse(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_button_text_color) { + listItemButtonTextColors = it + } + typedArray.getDrawableAndUse(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_button_background) { + listItemButtonBackground = it + } + listItemButtonVisibility = typedArray.getBoolean(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_button_visibility, + listItemButtonVisibility) + listItemButtonEnabled = typedArray.getBoolean(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_button_enabled, + listItemButtonEnabled) + listItemButtonText = + typedArray.getString(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_button_text, + getString(R.string.uxsdk_string_default_value)) + + typedArray.getResourceIdAndUse(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_edit_appearance) { + setListItemButtonTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_edit_text_size) { + listItemEditTextSize = it + } + typedArray.getColorAndUse(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_edit_text_color) { + listItemEditTextColor = it + } + typedArray.getColorStateListAndUse(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_edit_text_color) { + listItemEditTextColors = it + } + typedArray.getDrawableAndUse(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_edit_background) { + listItemEditTextBackground = it + } + listItemEditTextVisibility = typedArray.getBoolean(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_edit_visibility, + listItemEditTextVisibility) + listItemEditTextValue = + typedArray.getString(R.styleable.ListItemEditTextButtonWidget_uxsdk_list_item_edit_text, + getString(R.string.uxsdk_string_default_value)) + + } + } + + + private fun initEditText() { + listItemEditTextView.id = ViewIDGenerator.generateViewId() + listItemEditTextView.gravity = Gravity.CENTER + listItemEditTextView.width = getDimension(R.dimen.uxsdk_list_item_edit_min_width).toInt() + listItemEditTextView.inputType = InputType.TYPE_CLASS_PHONE + listItemEditTextView.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI + listItemEditTextSize = getDimension(R.dimen.uxsdk_list_item_edit_text_size) + val verticalPadding = getDimension(R.dimen.uxsdk_list_item_button_padding_vertical).toInt() + listItemEditTextView.setPadding(0, verticalPadding, 0, verticalPadding) + listItemEditTextView.background = getDrawable(R.drawable.uxsdk_system_status_edit_background_selector) + listItemEditTextView.textColorStateList = resources.getColorStateList(R.color.uxsdk_selector_edit_text_color) + listItemEditTextView.setOnClickListener(this) + listItemEditTextView.setOnEditorActionListener { _, p1, p2 -> + if (isDoneActionClicked(p1, p2)) { + uiUpdateStateProcessor.onNext(UIState.EditFinished) + listItemEditTextView.isCursorVisible = false + hideKeyboardFrom() + onKeyboardDoneAction() + } + true + } + + listItemEditTextView.addTextChangedListener(object : TextWatcher { + override fun afterTextChanged(s: Editable?) { + onEditorTextChanged(s?.toString()) + } + + override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) { + // Do nothing + } + + override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) { + // Do nothing + } + }) + + } + + private fun initHint() { + listItemHintTextView.id = ViewIDGenerator.generateViewId() + listItemHintTextSize = getDimension(R.dimen.uxsdk_list_item_hint_text_size) + listItemHintTextView.gravity = Gravity.CENTER_VERTICAL or Gravity.END + listItemHintTextColor = getColor(R.color.uxsdk_white_50_percent) + listItemHint = getString(R.string.uxsdk_string_default_value) + } + + private fun initButton() { + listItemButton.id = ViewIDGenerator.generateViewId() + listItemButtonBackground = getDrawable(R.drawable.uxsdk_system_status_button_background_selector) + listItemButtonTextColors = resources.getColorStateList(R.color.uxsdk_selector_text_color) + listItemButtonText = getString(R.string.uxsdk_string_default_value) + listItemButtonTextSize = getDimension(R.dimen.uxsdk_list_item_button_text_size) + listItemButton.setOnClickListener(this) + listItemButton.gravity = Gravity.CENTER + listItemButton.minWidth = getDimension(R.dimen.uxsdk_list_item_button_min_width).toInt() + val buttonPaddingHorizontal: Int = getDimension(R.dimen.uxsdk_list_item_button_padding_horizontal).toInt() + val buttonPaddingVertical: Int = getDimension(R.dimen.uxsdk_list_item_button_padding_vertical).toInt() + listItemButton.setPadding(buttonPaddingHorizontal, buttonPaddingVertical, buttonPaddingHorizontal, buttonPaddingVertical) + } + + private fun configureEditTextWidget() { + initEditText() + initHint() + val layoutParams = LayoutParams(getDimension(R.dimen.uxsdk_list_item_edit_min_width).toInt(), ConstraintSet.WRAP_CONTENT) + layoutParams.leftMargin = getDimension(R.dimen.uxsdk_list_item_button_padding_horizontal).toInt() + layoutParams.rightToLeft = clickIndicatorId + layoutParams.topToTop = guidelineTop.id + layoutParams.bottomToBottom = guidelineBottom.id + layoutParams.leftToRight = listItemHintTextView.id + listItemEditTextView.layoutParams = layoutParams + val hintLayoutParams = LayoutParams(0, ConstraintSet.WRAP_CONTENT) + hintLayoutParams.leftToRight = guidelineCenter.id + hintLayoutParams.rightToLeft = listItemEditTextView.id + hintLayoutParams.topToTop = guidelineTop.id + hintLayoutParams.bottomToBottom = guidelineBottom.id + hintLayoutParams.horizontalBias = 1.0f + hintLayoutParams.horizontalChainStyle = ConstraintSet.CHAIN_PACKED + listItemHintTextView.layoutParams = hintLayoutParams + addView(listItemEditTextView) + addView(listItemHintTextView) + } + + + private fun configureEditTextButtonWidget() { + initEditText() + initHint() + initButton() + val layoutParams = LayoutParams(getDimension(R.dimen.uxsdk_list_item_edit_min_width).toInt(), ConstraintSet.WRAP_CONTENT) + layoutParams.leftMargin = getDimension(R.dimen.uxsdk_list_item_button_padding_horizontal).toInt() + layoutParams.rightToLeft = clickIndicatorId + layoutParams.topToTop = guidelineTop.id + layoutParams.bottomToBottom = guidelineBottom.id + layoutParams.leftToRight = listItemHintTextView.id + listItemEditTextView.layoutParams = layoutParams + val hintLayoutParams = LayoutParams(0, ConstraintSet.WRAP_CONTENT) + hintLayoutParams.leftMargin = getDimension(R.dimen.uxsdk_list_item_button_padding_horizontal).toInt() + hintLayoutParams.leftToRight = listItemButton.id + hintLayoutParams.rightToLeft = listItemEditTextView.id + hintLayoutParams.topToTop = guidelineTop.id + hintLayoutParams.bottomToBottom = guidelineBottom.id + listItemHintTextView.layoutParams = hintLayoutParams + val buttonLayoutParams = LayoutParams(ConstraintSet.WRAP_CONTENT, ConstraintSet.WRAP_CONTENT) + buttonLayoutParams.rightToLeft = listItemHintTextView.id + buttonLayoutParams.topToTop = guidelineTop.id + buttonLayoutParams.bottomToBottom = guidelineBottom.id + buttonLayoutParams.leftToRight = guidelineCenter.id + buttonLayoutParams.horizontalBias = 1.0f + buttonLayoutParams.horizontalChainStyle = ConstraintSet.CHAIN_PACKED + listItemButton.layoutParams = buttonLayoutParams + addView(listItemEditTextView) + addView(listItemHintTextView) + addView(listItemButton) + } + + + /** + * Set the background of the item button + * + * @param resourceId Integer ID of the background resource + */ + fun setListItemButtonBackground(@DrawableRes resourceId: Int) { + listItemButtonBackground = getDrawable(resourceId) + } + + /** + * Set the background of the item hint + * + * @param resourceId Integer ID of the background resource + */ + fun setListItemHintBackground(@DrawableRes resourceId: Int) { + listItemHintBackground = getDrawable(resourceId) + } + + /** + * Set the background of the item edit text + * + * @param resourceId Integer ID of the background resource + */ + fun setListItemEditTextBackground(@DrawableRes resourceId: Int) { + listItemEditTextBackground = getDrawable(resourceId) + } + + /** + * Set the text appearance of the item hint + * + * @param textAppearanceResId Style resource for text appearance + */ + fun setListItemHintTextAppearance(@StyleRes textAppearanceResId: Int) { + listItemHintTextView.setTextAppearance(context, textAppearanceResId) + } + + /** + * Set the text appearance of the item button + * + * @param textAppearanceResId Style resource for text appearance + */ + fun setListItemButtonTextAppearance(@StyleRes textAppearanceResId: Int) { + listItemButton.setTextAppearance(context, textAppearanceResId) + } + + /** + * Set the text appearance of the item edit text + * + * @param textAppearanceResId Style resource for text appearance + */ + fun setListItemEditTextTextAppearance(@StyleRes textAppearanceResId: Int) { + listItemEditTextView.setTextAppearance(context, textAppearanceResId) + } + + override fun setEnabled(enabled: Boolean) { + super.setEnabled(enabled) + listItemButton.isEnabled = enabled + listItemHintTextView.isEnabled = enabled + listItemEditTextView.isEnabled = enabled + } + + @CallSuper + override fun onClick(view: View?) { + super.onClick(view) + if (view == listItemButton) { + uiUpdateStateProcessor.onNext(UIState.ButtonClicked) + onButtonClick() + } else if (view == listItemEditTextView) { + uiUpdateStateProcessor.onNext(UIState.EditStarted) + listItemEditTextView.isCursorVisible = true + } + } + + @CallSuper + override fun onListItemClick() { + uiUpdateStateProcessor.onNext(UIState.ListItemClicked) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + // Android 11 is calling onAttached and onDetached when keyboard is shown. + // This disposes the disposables mid action. To avoid misbehavior this is a + // temporary fix. + if (context is Activity && Build.VERSION.SDK_INT > Build.VERSION_CODES.Q) { + val window: Window = (context as Activity).window + window.setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING) + } + } + + private fun isDoneActionClicked(actionId: Int, keyEvent: KeyEvent?): Boolean { + return actionId == EditorInfo.IME_ACTION_DONE + || actionId == EditorInfo.IME_FLAG_NO_EXTRACT_UI + || actionId == EditorInfo.IME_ACTION_NEXT + || actionId == EditorInfo.IME_FLAG_NAVIGATE_NEXT + || actionId == EditorInfo.IME_ACTION_GO + || (keyEvent != null + && keyEvent.action == KeyEvent.ACTION_DOWN + && keyEvent.keyCode == KeyEvent.KEYCODE_ENTER) + } + + private fun hideKeyboardFrom() { + val imm: InputMethodManager = context.getSystemService(Activity.INPUT_METHOD_SERVICE) as InputMethodManager + imm.hideSoftInputFromWindow(windowToken, 0) + } + + /** + * Called when button click event occurs + */ + abstract fun onButtonClick() + + /** + * Called when keyboard is hidden + */ + abstract fun onKeyboardDoneAction() + + /** + * Called when user changes text + */ + abstract fun onEditorTextChanged(currentText: String?) + + + /** + * Widget UI update State + */ + sealed class UIState { + /** + * List Item click update + */ + object ListItemClicked : UIState() + + /** + * Button click update + */ + object ButtonClicked : UIState() + + /** + * Update when user clicks edit text to modify + * value + */ + object EditStarted : UIState() + + /** + * Update when user finishes edit action + */ + object EditFinished : UIState() + + /** + * Dialog shown update + */ + data class DialogDisplayed(val info: Any?) : UIState() + + /** + * Dialog action confirm + */ + data class DialogActionConfirmed(val info: Any?) : UIState() + + /** + * Dialog action cancel + */ + data class DialogActionCanceled(val info: Any?) : UIState() + + /** + * Dialog action dismiss + */ + data class DialogDismissed(val info: Any?) : UIState() + } + + /** + * Defines the type of widget + */ + enum class WidgetType { + + /** + * The type represents the item with icon, + * item name, item hint and editable value + */ + EDIT, + + /** + * The type represents the item with icon, + * item name, button and item hint and editable value + */ + EDIT_BUTTON + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/listitem/ListItemLabelButtonWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/listitem/ListItemLabelButtonWidget.kt new file mode 100644 index 00000000..a67b8c8c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/listitem/ListItemLabelButtonWidget.kt @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base.panel.listitem + +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.Gravity +import android.view.View +import android.widget.TextView +import androidx.annotation.* +import androidx.constraintlayout.widget.ConstraintSet +import androidx.core.content.res.use +import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.processors.PublishProcessor +import dji.v5.ux.R +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.util.ViewIDGenerator + +/** + * This is the base class to be used for display + * type of list item + * @property widgetType - The [WidgetType] of the current widget. + */ +abstract class ListItemLabelButtonWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + val widgetType: WidgetType, + defaultStyle: Int +) : ListItemTitleWidget(context, attrs, defStyleAttr, defaultStyle), View.OnClickListener { + + //region Fields + private val listItemButton: TextView = TextView(context) + + private val listItemLabelTextView: TextView = TextView(context) + + protected val uiUpdateStateProcessor: PublishProcessor = PublishProcessor.create() + //endregion + + //region label customizations + /** + * Get the [UIState] updates + */ + open fun getUIStateUpdates(): Flowable { + return uiUpdateStateProcessor.onBackpressureBuffer() + } + + /** + * The list item label string + */ + var listItemLabel: String? + @Nullable get() = listItemLabelTextView.text.toString() + set(@Nullable value) { + listItemLabelTextView.text = value + } + + /** + * The size of the list item label text + */ + var listItemLabelTextSize: Float + @Dimension get() = listItemLabelTextView.textSize + set(@Dimension value) { + listItemLabelTextView.textSize = value + } + + /** + * The color of the list item label text + */ + var listItemLabelTextColor: Int + @ColorInt get() = listItemLabelTextView.textColor + set(@ColorInt value) { + listItemLabelTextView.textColor = value + } + + /** + * The color state list of the list item label text + */ + var listItemLabelTextColors: ColorStateList? + get() = listItemLabelTextView.textColorStateList + set(value) { + listItemLabelTextView.textColorStateList = value + } + + /** + * The background of the list item label text + */ + var listItemLabelBackground: Drawable? + get() = listItemLabelTextView.background + set(value) { + listItemLabelTextView.background = value + } + + /** + * The visibility of the list item button + */ + var listItemLabelVisibility: Boolean + get() = listItemLabelTextView.visibility == View.VISIBLE + set(value) { + if (value) { + listItemLabelTextView.show() + } else { + listItemLabelTextView.hide() + } + } + //endregion + + //region button customizations + /** + * The list item label string + */ + var listItemButtonText: String? + @Nullable get() = listItemButton.text.toString() + set(@Nullable value) { + listItemButton.text = value + } + + /** + * The size of the list item label text + */ + var listItemButtonTextSize: Float + @Dimension get() = listItemButton.textSize + set(@Dimension value) { + listItemButton.textSize = value + } + + /** + * The color of the list item label text + */ + var listItemButtonTextColor: Int + @ColorInt get() = listItemButton.textColor + set(@ColorInt value) { + listItemButton.textColor = value + } + + /** + * The color state list of the list item label text + */ + var listItemButtonTextColors: ColorStateList? + get() = listItemButton.textColorStateList + set(value) { + listItemButton.textColorStateList = value + } + + /** + * The background of the list item label text + */ + var listItemButtonBackground: Drawable? + get() = listItemButton.background + set(value) { + listItemButton.background = value + } + + /** + * Enable/Disable button + */ + var listItemButtonEnabled: Boolean + get() = listItemButton.isEnabled + set(value) { + listItemButton.isEnabled = value + } + + /** + * The visibility of the list item button + */ + var listItemButtonVisibility: Boolean + get() = listItemButton.visibility == View.VISIBLE + set(value) { + if (value) { + listItemButton.show() + } else { + listItemButton.hide() + } + } + + //endregion + + init { + when (widgetType) { + WidgetType.LABEL -> { + configureLabelWidget() + } + WidgetType.BUTTON -> { + configureButtonWidget() + } + WidgetType.LABEL_BUTTON -> { + configureLabelButtonWidget() + } + } + val paddingValue = resources.getDimension(R.dimen.uxsdk_pre_flight_checklist_item_padding).toInt() + setContentPadding(0, paddingValue, 0, paddingValue) + attrs?.let { initAttributes(context, it) } + } + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.ListItemLabelButtonWidget, 0, defaultStyle).use { typedArray -> + typedArray.getResourceIdAndUse(R.styleable.ListItemLabelButtonWidget_uxsdk_list_item_label_appearance) { + setListItemLabelTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.ListItemLabelButtonWidget_uxsdk_list_item_label_text_size) { + listItemLabelTextSize = it + } + typedArray.getColorAndUse(R.styleable.ListItemLabelButtonWidget_uxsdk_list_item_label_text_color) { + listItemLabelTextColor = it + } + typedArray.getColorStateListAndUse(R.styleable.ListItemLabelButtonWidget_uxsdk_list_item_label_text_color) { + listItemLabelTextColors = it + } + typedArray.getDrawableAndUse(R.styleable.ListItemLabelButtonWidget_uxsdk_list_item_label_background) { + listItemLabelBackground = it + } + listItemLabelVisibility = typedArray.getBoolean(R.styleable.ListItemLabelButtonWidget_uxsdk_list_item_label_visibility, + listItemLabelVisibility) + listItemLabel = + typedArray.getString(R.styleable.ListItemLabelButtonWidget_uxsdk_list_item_label, + getString(R.string.uxsdk_string_default_value)) + + typedArray.getResourceIdAndUse(R.styleable.ListItemLabelButtonWidget_uxsdk_list_item_button_appearance) { + setListItemButtonTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.ListItemLabelButtonWidget_uxsdk_list_item_button_text_size) { + listItemButtonTextSize = it + } + typedArray.getColorAndUse(R.styleable.ListItemLabelButtonWidget_uxsdk_list_item_button_text_color) { + listItemButtonTextColor = it + } + typedArray.getColorStateListAndUse(R.styleable.ListItemLabelButtonWidget_uxsdk_list_item_button_text_color) { + listItemButtonTextColors = it + } + typedArray.getDrawableAndUse(R.styleable.ListItemLabelButtonWidget_uxsdk_list_item_button_background) { + listItemButtonBackground = it + } + listItemButtonVisibility = typedArray.getBoolean(R.styleable.ListItemLabelButtonWidget_uxsdk_list_item_button_visibility, + listItemButtonVisibility) + listItemButtonEnabled = typedArray.getBoolean(R.styleable.ListItemLabelButtonWidget_uxsdk_list_item_button_enabled, + listItemButtonEnabled) + + listItemButtonText = + typedArray.getString(R.styleable.ListItemLabelButtonWidget_uxsdk_list_item_button_text, + getString(R.string.uxsdk_string_default_value)) + + } + } + + + private fun initLabel() { + listItemLabelTextView.id = ViewIDGenerator.generateViewId() + listItemLabelTextView.gravity = Gravity.CENTER_VERTICAL or Gravity.END + listItemLabelTextColors = resources.getColorStateList(R.color.uxsdk_selector_text_color) + listItemLabelTextSize = getDimension(R.dimen.uxsdk_list_item_label_text_size) + listItemLabel = getString(R.string.uxsdk_string_default_value) + } + + private fun initButton() { + listItemButton.id = ViewIDGenerator.generateViewId() + listItemButtonBackground = getDrawable(R.drawable.uxsdk_system_status_button_background_selector) + listItemButtonTextColors = resources.getColorStateList(R.color.uxsdk_selector_text_color) + listItemButtonText = getString(R.string.uxsdk_string_default_value) + listItemButton.setOnClickListener(this) + listItemButton.gravity = Gravity.CENTER + listItemButton.minWidth = getDimension(R.dimen.uxsdk_list_item_button_min_width).toInt() + listItemButtonTextSize = getDimension(R.dimen.uxsdk_list_item_button_text_size) + val buttonPaddingHorizontal: Int = getDimension(R.dimen.uxsdk_list_item_button_padding_horizontal).toInt() + val buttonPaddingVertical: Int = getDimension(R.dimen.uxsdk_list_item_button_padding_vertical).toInt() + listItemButton.setPadding(buttonPaddingHorizontal, buttonPaddingVertical, buttonPaddingHorizontal, buttonPaddingVertical) + } + + private fun configureLabelWidget() { + initLabel() + val layoutParams = LayoutParams(0, ConstraintSet.WRAP_CONTENT) + layoutParams.rightToLeft = clickIndicatorId + layoutParams.topToTop = guidelineTop.id + layoutParams.bottomToBottom = guidelineBottom.id + layoutParams.leftToRight = guidelineCenter.id + listItemLabelTextView.layoutParams = layoutParams + addView(listItemLabelTextView) + } + + private fun configureButtonWidget() { + initButton() + val layoutParams = LayoutParams(ConstraintSet.WRAP_CONTENT, ConstraintSet.WRAP_CONTENT) + layoutParams.rightToLeft = clickIndicatorId + layoutParams.topToTop = guidelineTop.id + layoutParams.bottomToBottom = guidelineBottom.id + listItemButton.layoutParams = layoutParams + addView(listItemButton) + } + + private fun configureLabelButtonWidget() { + initLabel() + initButton() + val labelLayoutParams = LayoutParams(0, ConstraintSet.WRAP_CONTENT) + labelLayoutParams.leftToRight = listItemButton.id + labelLayoutParams.rightToLeft = clickIndicatorId + labelLayoutParams.topToTop = guidelineTop.id + labelLayoutParams.bottomToBottom = guidelineBottom.id + listItemLabelTextView.layoutParams = labelLayoutParams + val buttonLayoutParams = LayoutParams(ConstraintSet.WRAP_CONTENT, ConstraintSet.WRAP_CONTENT) + buttonLayoutParams.rightMargin = getDimension(R.dimen.uxsdk_list_item_button_padding_horizontal).toInt() + buttonLayoutParams.rightToLeft = listItemLabelTextView.id + buttonLayoutParams.topToTop = guidelineTop.id + buttonLayoutParams.bottomToBottom = guidelineBottom.id + buttonLayoutParams.leftToRight = guidelineCenter.id + buttonLayoutParams.horizontalChainStyle = ConstraintSet.CHAIN_PACKED + buttonLayoutParams.horizontalBias = 1.0f + listItemButton.layoutParams = buttonLayoutParams + addView(listItemLabelTextView) + addView(listItemButton) + } + + /** + * Set the background of the item button + * + * @param resourceId Integer ID of the background resource + */ + fun setListItemButtonBackground(@DrawableRes resourceId: Int) { + listItemButtonBackground = getDrawable(resourceId) + } + + /** + * Set the text appearance of the item button + * + * @param textAppearanceResId Style resource for text appearance + */ + fun setListItemButtonTextAppearance(@StyleRes textAppearanceResId: Int) { + listItemButton.setTextAppearance(context, textAppearanceResId) + } + + /** + * Set the background of the item label + * + * @param resourceId Integer ID of the background resource + */ + fun setListItemLabelBackground(@DrawableRes resourceId: Int) { + listItemLabelBackground = getDrawable(resourceId) + } + + /** + * Set the text appearance of the item label + * + * @param textAppearanceResId Style resource for text appearance + */ + fun setListItemLabelTextAppearance(@StyleRes textAppearanceResId: Int) { + listItemLabelTextView.setTextAppearance(context, textAppearanceResId) + } + + override fun setEnabled(enabled: Boolean) { + super.setEnabled(enabled) + listItemButton.isEnabled = enabled + listItemLabelTextView.isEnabled = enabled + } + + @CallSuper + override fun onClick(view: View?) { + super.onClick(view) + if (view == listItemButton) { + uiUpdateStateProcessor.onNext(UIState.ButtonClicked) + onButtonClick() + } + } + + @CallSuper + override fun onListItemClick() { + uiUpdateStateProcessor.onNext(UIState.ListItemClicked) + } + + abstract fun onButtonClick() + + /** + * Widget UI update State + */ + sealed class UIState { + /** + * List Item click update + */ + object ListItemClicked : UIState() + + /** + * Button click update + */ + object ButtonClicked : UIState() + + /** + * Dialog shown update + */ + data class DialogDisplayed(val info: Any?) : UIState() + + /** + * Dialog action confirm + */ + data class DialogActionConfirmed(val info: Any?) : UIState() + + /** + * Dialog action cancel + */ + data class DialogActionCanceled(val info: Any?) : UIState() + + /** + * Dialog action dismiss + */ + data class DialogDismissed(val info: Any?) : UIState() + } + + /** + * Defines the type of widget + */ + enum class WidgetType { + + /** + * The type represents the item with icon, + * item name and item string label + */ + LABEL, + + /** + * The type represents the item with icon, + * item name and button for action + */ + BUTTON, + + /** + * The class represents the item with icon, + * item name, item string label + * and button for action + */ + LABEL_BUTTON + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/listitem/ListItemRadioButtonWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/listitem/ListItemRadioButtonWidget.kt new file mode 100644 index 00000000..34e983f3 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/listitem/ListItemRadioButtonWidget.kt @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base.panel.listitem + +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.Gravity +import android.widget.LinearLayout +import android.widget.RadioButton +import android.widget.RadioGroup +import androidx.annotation.StyleRes +import androidx.constraintlayout.widget.ConstraintSet +import androidx.core.content.res.use +import androidx.core.view.get +import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.processors.PublishProcessor +import dji.v5.ux.R +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.util.ViewIDGenerator + +/** + * This is the base class to be used for radio button type list item + * The class represents the item with icon, item name and radio group options + */ +abstract class ListItemRadioButtonWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + defaultStyle: Int +) : ListItemTitleWidget(context, attrs, defStyleAttr, defaultStyle), + RadioGroup.OnCheckedChangeListener { + + protected val uiUpdateStateProcessor: PublishProcessor = PublishProcessor.create() + + private val radioGroup: RadioGroup = RadioGroup(context) + + /** + * Background selector of radio button in center + * + * Recommended states in selector + * 1. android_state_enabled = false + * 2. android_state_checked = false + * 3. android_state_checked = true + */ + var centerOptionBackgroundSelector: Drawable? = getDrawable(R.drawable.uxsdk_selector_radio_button_middle) + + /** + * Background selector of radio button on the extreme left + * i.e. the first item + * + * Recommended states in selector + * 1. android_state_enabled = false + * 2. android_state_checked = false + * 3. android_state_checked = true + */ + var firstOptionBackgroundSelector: Drawable? = getDrawable(R.drawable.uxsdk_selector_radio_button_first) + + /** + * Background selector of radio button on the extreme right + * i.e. the last item + * + * Recommended states in selector + * 1. android_state_enabled = false + * 2. android_state_checked = false + * 3. android_state_checked = true + */ + var lastOptionBackgroundSelector: Drawable? = getDrawable(R.drawable.uxsdk_selector_radio_button_last) + + + /** + * Text color state list for radio button text + * + * Recommended states in selector + * 1. android_state_enabled = false + * 2. android_state_checked = false + * 3. android_state_checked = true + */ + var optionColorStateList: ColorStateList? = resources.getColorStateList(R.color.uxsdk_selector_radio_button_colors) + set(value) { + field = value + for (i in 0 until radioGroup.childCount) { + val radioButton: RadioButton? = radioGroup.getChildAt(i) as RadioButton + radioButton?.textColorStateList = field + } + } + + /** + * Text size for the radio button text + */ + var optionTextSize: Float = getDimension(R.dimen.uxsdk_list_item_radio_button_text_size) + set(value) { + field = value + for (i in 0 until radioGroup.childCount) { + val radioButton: RadioButton? = radioGroup.getChildAt(i) as RadioButton + radioButton?.textSize = field + } + } + + /** + * The count of option items + */ + val optionCount: Int = radioGroup.childCount + + /** + * Get the [UIState] updates + */ + fun getUIStateUpdates(): Flowable { + return uiUpdateStateProcessor.onBackpressureBuffer() + } + + init { + radioGroup.id = ViewIDGenerator.generateViewId() + radioGroup.orientation = LinearLayout.HORIZONTAL + radioGroup.setOnCheckedChangeListener(this) + radioGroup.gravity = Gravity.CENTER_VERTICAL or Gravity.END + val layoutParams = LayoutParams(0, ConstraintSet.WRAP_CONTENT) + layoutParams.rightToLeft = clickIndicatorId + layoutParams.topToTop = guidelineTop.id + layoutParams.bottomToBottom = guidelineBottom.id + layoutParams.leftToRight = guidelineCenter.id + radioGroup.layoutParams = layoutParams + addView(radioGroup) + val paddingValue = resources.getDimension(R.dimen.uxsdk_pre_flight_checklist_item_padding).toInt() + setContentPadding(0, paddingValue, 0, paddingValue) + initAttributes(context, attrs) + } + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet?) { + context.obtainStyledAttributes(attrs, R.styleable.ListItemRadioButtonWidget, 0, defaultStyle).use { typedArray -> + typedArray.getResourceIdAndUse(R.styleable.ListItemRadioButtonWidget_uxsdk_option_text_appearance) { + setOptionTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.ListItemRadioButtonWidget_uxsdk_option_text_size) { + optionTextSize = it + } + typedArray.getDrawableAndUse(R.styleable.ListItemRadioButtonWidget_uxsdk_center_option_background_selector) { + centerOptionBackgroundSelector = it + } + typedArray.getDrawableAndUse(R.styleable.ListItemRadioButtonWidget_uxsdk_first_option_background_selector) { + firstOptionBackgroundSelector = it + } + typedArray.getDrawableAndUse(R.styleable.ListItemRadioButtonWidget_uxsdk_last_option_background_selector) { + lastOptionBackgroundSelector = it + } + typedArray.getColorStateListAndUse(R.styleable.ListItemRadioButtonWidget_uxsdk_option_color_state_list) { + optionColorStateList = it + } + } + } + + protected fun addOptionToGroup(label: String): Int { + val radioButton = RadioButton(context) + radioButton.id = ViewIDGenerator.generateViewId() + radioButton.text = label + radioButton.textColorStateList = optionColorStateList + radioButton.isChecked = true + radioButton.buttonDrawable = null + radioButton.textSize = optionTextSize + val paddingValue = resources.getDimension(R.dimen.uxsdk_pre_flight_checklist_item_padding).toInt() + radioButton.setPadding(paddingValue, 0, paddingValue, 0) + radioGroup.addView(radioButton, radioGroup.childCount) + restyleRadioGroup() + return radioGroup.childCount - 1 + } + + protected fun removeOptionFromGroup(index: Int) { + radioGroup.removeViewAt(index) + restyleRadioGroup() + } + + protected fun setSelected(index: Int) { + radioGroup.setOnCheckedChangeListener(null) + radioGroup.getChildAt(index)?.let { + val radioButton: RadioButton = it as RadioButton + radioButton.isChecked = true + } + radioGroup.setOnCheckedChangeListener(this) + } + + private fun restyleRadioGroup() { + when (val childCount = radioGroup.childCount) { + 1 -> radioGroup[0].background = centerOptionBackgroundSelector + 2 -> { + radioGroup[0].background = firstOptionBackgroundSelector + radioGroup[childCount - 1].background = lastOptionBackgroundSelector + } + else -> { + radioGroup[0].background = firstOptionBackgroundSelector + radioGroup[childCount - 1].background = lastOptionBackgroundSelector + for (i in 1 until childCount - 1) { + radioGroup[i].background = centerOptionBackgroundSelector + } + } + } + + + } + + override fun onCheckedChanged(group: RadioGroup?, radioButtonId: Int) { + for (i in 0 until radioGroup.childCount) { + if (radioGroup[i].id == radioButtonId) { + val radioButton: RadioButton? = findViewById(radioButtonId) + if (radioButton != null) { + uiUpdateStateProcessor.onNext(UIState.OptionSelected(i, + radioButton.text.toString())) + onOptionTapped(i, radioButton.text.toString()) + } + break + } + + } + } + + override fun onListItemClick() { + uiUpdateStateProcessor.onNext(UIState.ListItemClicked) + } + + override fun setEnabled(enabled: Boolean) { + super.setEnabled(enabled) + for (i in 0 until radioGroup.childCount) { + radioGroup[i].isEnabled = enabled + } + } + + abstract fun onOptionTapped(optionIndex: Int, optionLabel: String) + + /** + * Set the text of the radio button by index + */ + protected fun setOptionTextByIndex(index: Int, text: String) { + val radioButton = radioGroup.getChildAt(index) as RadioButton? + radioButton?.text = text + } + + /** + * Set the text of the radio button by index + */ + fun setOptionTextAppearance(@StyleRes textAppearance: Int) { + for (i in 0 until radioGroup.childCount) { + val radioButton: RadioButton? = radioGroup.getChildAt(i) as RadioButton + radioButton?.setTextAppearance(context, textAppearance) + } + + } + + /** + * Widget UI update State + */ + sealed class UIState { + /** + * List Item click update + */ + object ListItemClicked : UIState() + + /** + * Option click update + */ + data class OptionSelected(val optionIndex: Int, val optionLabel: String) : UIState() + + /** + * Dialog shown update + */ + data class DialogDisplayed(val info: Any?) : UIState() + + /** + * Dialog action dismiss + */ + data class DialogDismissed(val info: Any?) : UIState() + + /** + * Never show again checkbox checked + */ + data class NeverShowAgainCheckChanged(val isChecked: Boolean) : UIState() + + } + + protected companion object { + const val INVALID_OPTION_INDEX = -1 + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/listitem/ListItemSwitchWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/listitem/ListItemSwitchWidget.kt new file mode 100644 index 00000000..6e991d95 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/listitem/ListItemSwitchWidget.kt @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base.panel.listitem + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.widget.CompoundButton +import android.widget.Switch +import androidx.annotation.DrawableRes +import androidx.constraintlayout.widget.ConstraintSet +import androidx.core.content.res.use +import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.processors.PublishProcessor +import dji.v5.ux.R +import dji.v5.ux.core.extension.getDrawable +import dji.v5.ux.core.extension.getDrawableAndUse +import dji.v5.ux.core.util.ViewIDGenerator + +/** + * This is the base class to be used for + * switch type list item. + */ +abstract class ListItemSwitchWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + defaultStyle: Int +) : ListItemTitleWidget(context, attrs, defStyleAttr, defaultStyle), + CompoundButton.OnCheckedChangeListener { + + //region Fields + private val listItemSwitch: Switch = Switch(context) + protected val uiUpdateStateProcessor: PublishProcessor = PublishProcessor.create() + + /** + * The icon used for thumb for list item switch + */ + var switchThumbIcon: Drawable? = listItemSwitch.thumbDrawable + + /** + * The icon used for track for list item switch + */ + var switchTrackIcon: Drawable? = listItemSwitch.trackDrawable + + /** + * The background of the list item switch + */ + var switchBackground: Drawable? = listItemSwitch.background + //endregion + + init { + configureSwitchWidget() + val paddingValue = resources.getDimension(R.dimen.uxsdk_pre_flight_checklist_item_padding).toInt() + setContentPadding(0, paddingValue, 0, paddingValue) + initAttributes(context, attrs) + } + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet?) { + context.obtainStyledAttributes(attrs, R.styleable.ListItemSwitchWidget, 0, defaultStyle).use { typedArray -> + typedArray.getDrawableAndUse(R.styleable.ListItemSwitchWidget_uxsdk_list_item_switch_background) { + switchBackground = it + } + typedArray.getDrawableAndUse(R.styleable.ListItemSwitchWidget_uxsdk_list_item_switch_thumb_icon) { + switchThumbIcon = it + } + typedArray.getDrawableAndUse(R.styleable.ListItemSwitchWidget_uxsdk_list_item_switch_track_icon) { + switchTrackIcon = it + } + + } + } + + private fun configureSwitchWidget() { + initSwitch() + val layoutParams = LayoutParams(ConstraintSet.WRAP_CONTENT, ConstraintSet.WRAP_CONTENT) + layoutParams.rightToLeft = clickIndicatorId + layoutParams.topToTop = guidelineTop.id + layoutParams.bottomToBottom = guidelineBottom.id + listItemSwitch.layoutParams = layoutParams + addView(listItemSwitch) + } + + private fun initSwitch() { + listItemSwitch.id = ViewIDGenerator.generateViewId() + listItemSwitch.setOnCheckedChangeListener(this) + listItemSwitch.setThumbResource(R.drawable.uxsdk_selector_switch_thumb) + listItemSwitch.setTrackResource(R.drawable.uxsdk_switch_background) + } + + + override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) { + if (buttonView == listItemSwitch) { + uiUpdateStateProcessor.onNext(UIState.SwitchChanged) + onSwitchToggle(isChecked) + } + } + + override fun onListItemClick() { + uiUpdateStateProcessor.onNext(UIState.ListItemClicked) + } + + override fun setEnabled(enabled: Boolean) { + super.setEnabled(enabled) + listItemSwitch.isEnabled = enabled + } + + abstract fun onSwitchToggle(isChecked: Boolean) + + protected fun setChecked(isSwitchChecked: Boolean) { + listItemSwitch.setOnCheckedChangeListener(null) + listItemSwitch.isChecked = isSwitchChecked + listItemSwitch.setOnCheckedChangeListener(this) + } + + /** + * Set the resource ID for the list item switch thumb icon + * + * @param resourceId Integer ID of the drawable resource + */ + fun setSwitchThumbIcon(@DrawableRes resourceId: Int) { + switchThumbIcon = getDrawable(resourceId) + } + + /** + * Set the resource ID for the list item switch track icon + * + * @param resourceId Integer ID of the drawable resource + */ + fun setSwitchTrackIcon(@DrawableRes resourceId: Int) { + switchTrackIcon = getDrawable(resourceId) + } + + /** + * Set the resource ID for the list item switch background + * + * @param resourceId Integer ID of the drawable resource + */ + fun setSwitchBackground(@DrawableRes resourceId: Int) { + switchBackground = getDrawable(resourceId) + } + + /** + * Get the [UIState] updates + */ + open fun getUIStateUpdates(): Flowable { + return uiUpdateStateProcessor.onBackpressureBuffer() + } + + /** + * Widget UI update State + */ + sealed class UIState { + /** + * List Item click update + */ + object ListItemClicked : UIState() + + /** + * Button click update + */ + object SwitchChanged : UIState() + + /** + * Dialog shown update + */ + data class DialogDisplayed(val info: Any?) : UIState() + + /** + * Dialog action confirm + */ + data class DialogActionConfirmed(val info: Any?) : UIState() + + /** + * Dialog action cancel + */ + data class DialogActionCanceled(val info: Any?) : UIState() + + /** + * Dialog action dismiss + */ + data class DialogDismissed(val info: Any?) : UIState() + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/listitem/ListItemTitleWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/listitem/ListItemTitleWidget.kt new file mode 100644 index 00000000..13ccb0c6 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/panel/listitem/ListItemTitleWidget.kt @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base.panel.listitem + +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.PorterDuff +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.View +import android.widget.ImageView +import android.widget.TextView +import androidx.annotation.* +import androidx.constraintlayout.widget.Guideline +import androidx.core.content.res.use +import dji.v5.ux.R +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.util.ViewIDGenerator +import kotlin.math.roundToInt + + +/** + * This is the base class used for list item. The class represents + * the item title and item icon. + * @property defaultStyle - Resource id for tyle used for defining the default setup + * of the widget. + */ +abstract class ListItemTitleWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + @StyleRes protected val defaultStyle: Int +) : ConstraintLayoutWidget(context, attrs, defStyleAttr), View.OnClickListener { + + private val listItemTitleTextView = findViewById(R.id.text_view_list_item_title) + private val listItemTitleImageView = findViewById(R.id.image_view_title_icon) + protected val guidelineLeft: Guideline = findViewById(R.id.guideline_left) + protected val guidelineTop: Guideline = findViewById(R.id.guideline_top) + protected val guidelineRight: Guideline = findViewById(R.id.guideline_right) + protected val guidelineBottom: Guideline = findViewById(R.id.guideline_bottom) + protected val guidelineCenter: Guideline = findViewById(R.id.guideline_column) + private val clickIndicatorImageView: ImageView = findViewById(R.id.image_view_chevron) + + /** + * ID of the click indicator view + */ + val clickIndicatorId = clickIndicatorImageView.id + + /** + * Icon for showing the click indicator + */ + var clickIndicatorIcon: Drawable? + get() = clickIndicatorImageView.imageDrawable + set(@Nullable value) { + clickIndicatorImageView.imageDrawable = value + } + + /** + * Toggle clickable functionality of the list item + */ + var listItemClickable: Boolean = false + set(value) { + field = value + if (value) { + clickIndicatorImageView.visibility = View.VISIBLE + } else { + clickIndicatorImageView.visibility = View.INVISIBLE + } + } + + /** + * Color of label text when disconnected + */ + @ColorInt + var disconnectedValueColor: Int = getColor(R.color.uxsdk_white_60_percent) + + /** + * Color of the label text when state is normal + */ + @ColorInt + var normalValueColor: Int = getColor(R.color.uxsdk_status_normal) + + /** + * Color of the label text when state is warning + */ + @ColorInt + var warningValueColor: Int = getColor(R.color.uxsdk_status_warning) + + /** + * Color of the label text when state is error + */ + @ColorInt + var errorValueColor: Int = getColor(R.color.uxsdk_status_error) + + /** + * The list item title string + */ + var listItemTitle: String? + get() = listItemTitleTextView.text.toString() + set(@Nullable value) { + listItemTitleTextView.text = value + } + + /** + * The list item title icon + */ + var listItemTitleIcon: Drawable? + get() = listItemTitleImageView.imageDrawable + set(@Nullable value) { + listItemTitleImageView.imageDrawable = value + } + + /** + * The color of the icon + */ + @get:ColorInt + var listItemTitleIconColor: Int = getColor(R.color.uxsdk_white) + set(@ColorInt value) { + field = value + listItemTitleImageView.setColorFilter(value, PorterDuff.Mode.SRC_IN) + } + + /** + * The size of the list title text + */ + var listItemTitleTextSize: Float + @Dimension get() = listItemTitleTextView.textSize + set(@Dimension value) { + listItemTitleTextView.textSize = value + } + + /** + * The color of the list item title text + */ + var listItemTitleTextColor: Int + @ColorInt get() = listItemTitleTextView.textColor + set(@ColorInt value) { + listItemTitleTextView.textColor = value + } + + /** + * The color state list of the list item title + */ + var listItemTitleTextColors: ColorStateList? + get() = listItemTitleTextView.textColorStateList + set(value) { + listItemTitleTextView.textColorStateList = value + } + + /** + * The background of the list item title + */ + var listItemTitleBackground: Drawable? + get() = listItemTitleTextView.background + set(value) { + listItemTitleTextView.background = value + } + + /** + * Left padding of the list item content + */ + var contentPaddingLeft: Int = getDimension(R.dimen.uxsdk_pre_flight_checklist_item_padding).toInt() + set(value) { + field = value + guidelineLeft.setGuidelineBegin(value) + } + + /** + * Top padding of the list item content + */ + var contentPaddingTop: Int = getDimension(R.dimen.uxsdk_pre_flight_checklist_item_padding).toInt() + set(value) { + field = value + guidelineTop.setGuidelineBegin(value) + } + + /** + * Right padding of the list item content + */ + var contentPaddingRight: Int = getDimension(R.dimen.uxsdk_pre_flight_checklist_item_padding).toInt() + set(value) { + field = value + guidelineRight.setGuidelineEnd(value) + } + + /** + * Bottom padding of the list item content + */ + var contentPaddingBottom: Int = getDimension(R.dimen.uxsdk_pre_flight_checklist_item_padding).toInt() + set(value) { + field = value + guidelineBottom.setGuidelineEnd(value) + } + + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + View.inflate(context, R.layout.uxsdk_list_item_title_widget, this) + } + + init { + if (id == View.NO_ID) { + id = ViewIDGenerator.generateViewId() + } + isClickable = true + setOnClickListener(this) + val padding = (getDimension(R.dimen.uxsdk_pre_flight_checklist_item_padding)).roundToInt() + setPadding(padding, 0, padding, 0) + initAttributes(context, attrs) + } + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet?) { + context.obtainStyledAttributes(attrs, R.styleable.ListItemTitleWidget, 0, defaultStyle).use { typedArray -> + typedArray.getResourceIdAndUse(R.styleable.ListItemTitleWidget_uxsdk_list_item_title_appearance) { + setListItemTitleTextAppearance(it) + } + typedArray.getDrawableAndUse(R.styleable.ListItemTitleWidget_uxsdk_list_item_icon) { + listItemTitleIcon = it + } + typedArray.getColorAndUse(R.styleable.ListItemTitleWidget_uxsdk_list_item_icon_color) { + listItemTitleIconColor = it + } + typedArray.getDrawableAndUse(R.styleable.ListItemTitleWidget_uxsdk_list_item_title_text_background) { + listItemTitleBackground = it + } + typedArray.getDimensionAndUse(R.styleable.ListItemTitleWidget_uxsdk_list_item_title_text_size) { + listItemTitleTextSize = it + } + typedArray.getColorAndUse(R.styleable.ListItemTitleWidget_uxsdk_list_item_title_text_color) { + listItemTitleTextColor = it + } + typedArray.getColorStateListAndUse(R.styleable.ListItemTitleWidget_uxsdk_list_item_title_text_color) { + listItemTitleTextColors = it + } + typedArray.getDimensionAndUse(R.styleable.ListItemTitleWidget_uxsdk_list_item_padding_left) { + contentPaddingLeft = it.toInt() + } + typedArray.getDimensionAndUse(R.styleable.ListItemTitleWidget_uxsdk_list_item_padding_top) { + contentPaddingTop = it.toInt() + } + typedArray.getDimensionAndUse(R.styleable.ListItemTitleWidget_uxsdk_list_item_padding_right) { + contentPaddingRight = it.toInt() + } + typedArray.getDimensionAndUse(R.styleable.ListItemTitleWidget_uxsdk_list_item_padding_bottom) { + contentPaddingBottom = it.toInt() + } + typedArray.getColorAndUse(R.styleable.ListItemTitleWidget_uxsdk_list_item_disconnected_color) { + disconnectedValueColor = it + } + typedArray.getColorAndUse(R.styleable.ListItemTitleWidget_uxsdk_list_item_normal_color) { + normalValueColor = it + } + typedArray.getColorAndUse(R.styleable.ListItemTitleWidget_uxsdk_list_item_warning_color) { + warningValueColor = it + } + typedArray.getColorAndUse(R.styleable.ListItemTitleWidget_uxsdk_list_item_error_color) { + errorValueColor = it + } + listItemTitle = + typedArray.getString( + R.styleable.ListItemTitleWidget_uxsdk_list_item_title, + getString(R.string.uxsdk_string_default_value) + ) + typedArray.getDrawableAndUse(R.styleable.ListItemTitleWidget_uxsdk_list_item_click_indicator_icon) { + clickIndicatorIcon = it + } + typedArray.getBooleanAndUse(R.styleable.ListItemTitleWidget_uxsdk_list_item_clickable, false) { + listItemClickable = it + } + } + } + + override fun setEnabled(enabled: Boolean) { + super.setEnabled(enabled) + clickIndicatorImageView.isEnabled = enabled + } + + override fun onClick(v: View?) { + if (v?.id == id && listItemClickable) { + onListItemClick() + } + } + + abstract fun onListItemClick() + + /** + * Set the background of the list item title + * + * @param resourceId Integer ID of the background resource + */ + fun setListItemTitleBackground(@DrawableRes resourceId: Int) { + listItemTitleBackground = getDrawable(resourceId) + } + + /** + * Set the text appearance of the title + * + * @param textAppearanceResId Style resource for text appearance + */ + fun setListItemTitleTextAppearance(@StyleRes textAppearanceResId: Int) { + listItemTitleTextView.setTextAppearance(context, textAppearanceResId) + } + + /** + * Set padding to the content of the list item + */ + fun setContentPadding(left: Int, top: Int, right: Int, bottom: Int) { + contentPaddingLeft = left + contentPaddingTop = top + contentPaddingRight = right + contentPaddingBottom = bottom + } + + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/widget/BaseTelemetryWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/widget/BaseTelemetryWidget.kt new file mode 100644 index 00000000..7c758fad --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/widget/BaseTelemetryWidget.kt @@ -0,0 +1,669 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base.widget + +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.ColorStateList +import android.content.res.TypedArray +import android.graphics.PorterDuff +import android.graphics.drawable.Drawable +import android.text.TextPaint +import android.util.AttributeSet +import android.view.View +import android.widget.ImageView +import android.widget.TextView +import androidx.annotation.* +import androidx.constraintlayout.widget.ConstraintSet +import androidx.constraintlayout.widget.Guideline +import androidx.core.content.res.use +import dji.v5.ux.R +import dji.v5.ux.core.base.widget.BaseTelemetryWidget.WidgetType +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.util.UnitConversionUtil +import dji.v5.ux.core.util.ViewIDGenerator +import java.text.DecimalFormat + +/** + * Base class for telemetry widgets + * @property widgetType - The [WidgetType] for the widget. + * @property widgetTheme - Resource id for styling the widget. + * @property defaultStyle - Resource id for style used for defining the default setup + * of the widget. + */ +abstract class BaseTelemetryWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + val widgetType: WidgetType, + protected val widgetTheme: Int = 0, + @StyleRes protected val defaultStyle: Int +) : ConstraintLayoutWidget(context, attrs, defStyleAttr) { + + private val guidelineLeft: Guideline = findViewById(R.id.guideline_left) + private val guidelineTop: Guideline = findViewById(R.id.guideline_top) + private val guidelineRight: Guideline = findViewById(R.id.guideline_right) + private val guidelineBottom: Guideline = findViewById(R.id.guideline_bottom) + private val labelTextView: TextView = findViewById(R.id.text_view_label) + private val valueTextView: TextView = findViewById(R.id.text_view_value) + private val unitTextView: TextView = findViewById(R.id.text_view_unit) + private val imageView: ImageView = ImageView(context) + protected abstract val metricDecimalFormat: DecimalFormat + protected abstract val imperialDecimalFormat: DecimalFormat + + //region color customizations + /** + * Color of the value is in error state + */ + @ColorInt + var errorValueColor: Int = getColor(R.color.uxsdk_red) + + /** + * Color of the value is in normal state + */ + @ColorInt + var normalValueColor: Int = getColor(R.color.uxsdk_white) + + //endregion + + + //region widget customizations + /** + * Left padding of the list item content + */ + var contentPaddingLeft: Int = getDimension(R.dimen.uxsdk_telemetry_item_padding).toInt() + set(value) { + field = value + guidelineLeft.setGuidelineBegin(value) + } + + /** + * Top padding of the list item content + */ + var contentPaddingTop: Int = getDimension(R.dimen.uxsdk_telemetry_item_padding).toInt() + set(value) { + field = value + guidelineTop.setGuidelineBegin(value) + } + + /** + * Right padding of the list item content + */ + var contentPaddingRight: Int = getDimension(R.dimen.uxsdk_telemetry_item_padding).toInt() + set(value) { + field = value + guidelineRight.setGuidelineEnd(value) + } + + /** + * Bottom padding of the list item content + */ + var contentPaddingBottom: Int = getDimension(R.dimen.uxsdk_telemetry_item_padding).toInt() + set(value) { + field = value + guidelineBottom.setGuidelineEnd(value) + } + //endregion + + //region image customizations + /** + * The icon for the widget + */ + var widgetIcon: Drawable? + get() = imageView.imageDrawable + set(@Nullable value) { + imageView.imageDrawable = value + } + + /** + * The color of the icon + */ + @get:ColorInt + var widgetIconColor: Int = getColor(R.color.uxsdk_white) + set(@ColorInt value) { + field = value + imageView.setColorFilter(value, PorterDuff.Mode.SRC_IN) + } + + /** + * The background of the widget icon + */ + var widgetIconBackground: Drawable? + get() = imageView.background + set(@Nullable value) { + imageView.background = value + } + + /** + * Visibility of the icon + */ + var widgetIconVisibility: Boolean + get() = imageView.visibility == View.VISIBLE + set(value) { + if (value) { + imageView.show() + } else { + imageView.hide() + } + } + //endregion + + //region label customizations + /** + * String value of label + */ + var labelString: String? + @Nullable get() = labelTextView.text.toString() + set(value) { + labelTextView.text = value + } + + /** + * Float text size of the label + */ + var labelTextSize: Float + @Dimension get() = labelTextView.textSize + set(@Dimension value) { + labelTextView.textSize = value + } + + /** + * Integer color for label + */ + var labelTextColor: Int + @ColorInt get() = labelTextView.textColor + set(@ColorInt value) { + labelTextView.textColor = value + } + + /** + * Color state list of the label + */ + var labelTextColors: ColorStateList? + get() = labelTextView.textColorStateList + set(value) { + labelTextView.textColorStateList = value + } + + /** + * Background of the label + */ + var labelBackground: Drawable? + get() = labelTextView.background + set(value) { + labelTextView.background = value + } + + /** + * Visibility of the label + */ + var labelVisibility: Boolean + get() = labelTextView.visibility == View.VISIBLE + set(value) { + if (value) { + labelTextView.show() + } else { + labelTextView.hide() + } + } + + //endregion + + //region value customizations + /** + * String for value text view + */ + var valueString: String? + @Nullable get() = valueTextView.text.toString() + set(value) { + valueTextView.text = value + } + + /** + * Float text size of the value + */ + var valueTextSize: Float + @Dimension get() = valueTextView.textSize + set(@Dimension value) { + valueTextView.textSize = value + } + + /** + * Integer color for value + */ + var valueTextColor: Int + @ColorInt get() = valueTextView.textColor + set(@ColorInt value) { + valueTextView.textColor = value + } + + /** + * Color state list of the value + */ + var valueTextColors: ColorStateList? + get() = valueTextView.textColorStateList + set(value) { + valueTextView.textColorStateList = value + } + + /** + * Background of the value + */ + var valueBackground: Drawable? + get() = valueTextView.background + set(value) { + valueTextView.background = value + } + + /** + * Visibility of the value + */ + var valueVisibility: Boolean + get() = valueTextView.visibility == View.VISIBLE + set(value) { + if (value) { + valueTextView.show() + } else { + valueTextView.hide() + } + } + + /** + * Text position of the value + */ + var valueTextGravity: Int + get() = valueTextView.gravity + set(value) { + valueTextView.gravity = value + } + + //endregion + + //region value customizations + /** + * String for unit text view + */ + var unitString: String? + @Nullable get() = unitTextView.text.toString() + set(value) { + unitTextView.text = value + } + + /** + * Float text size of the unit + */ + var unitTextSize: Float + @Dimension get() = unitTextView.textSize + set(@Dimension value) { + unitTextView.textSize = value + } + + /** + * Integer color for unit + */ + var unitTextColor: Int + @ColorInt get() = unitTextView.textColor + set(@ColorInt value) { + unitTextView.textColor = value + } + + /** + * Color state list of the unit + */ + var unitTextColors: ColorStateList? + get() = unitTextView.textColorStateList + set(value) { + unitTextView.textColorStateList = value + } + + /** + * Background of the unit + */ + var unitBackground: Drawable? + get() = unitTextView.background + set(value) { + unitTextView.background = value + } + + /** + * Visibility of the unit + */ + var unitVisibility: Boolean + get() = unitTextView.visibility == View.VISIBLE + set(value) { + if (value) { + unitTextView.show() + } else { + unitTextView.hide() + } + } + + //endregion + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + View.inflate(context, R.layout.uxsdk_widget_base_telemetry, this) + } + + init { + if (widgetType == WidgetType.TEXT_IMAGE_RIGHT) { + configureRightImageTypeWidget() + } else if (widgetType == WidgetType.TEXT_IMAGE_LEFT) { + configureLeftImageTypeWidget() + } + initBaseTelemetryAttributes(context) + setValueTextViewMinWidthByText("888.8") + initAttributes(context, attrs) + } + + @SuppressLint("Recycle") + private fun initBaseTelemetryAttributes(context: Context) { + val baseTelemetryAttributeArray: IntArray = R.styleable.BaseTelemetryWidget + context.obtainStyledAttributes(widgetTheme, baseTelemetryAttributeArray).use { + initAttributesByTypedArray(it) + } + } + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet?) { + context.obtainStyledAttributes(attrs, R.styleable.BaseTelemetryWidget, 0, defaultStyle).use { typedArray -> + initAttributesByTypedArray(typedArray) + } + } + + private fun initAttributesByTypedArray(typedArray: TypedArray) { + typedArray.getResourceIdAndUse(R.styleable.BaseTelemetryWidget_uxsdk_label_text_appearance) { + setLabelTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.BaseTelemetryWidget_uxsdk_label_text_size) { + labelTextSize = it + } + typedArray.getColorAndUse(R.styleable.BaseTelemetryWidget_uxsdk_label_text_color) { + labelTextColor = it + } + typedArray.getColorStateListAndUse(R.styleable.BaseTelemetryWidget_uxsdk_label_text_color) { + labelTextColors = it + } + typedArray.getDrawableAndUse(R.styleable.BaseTelemetryWidget_uxsdk_label_background) { + labelBackground = it + } + labelVisibility = typedArray.getBoolean( + R.styleable.BaseTelemetryWidget_uxsdk_label_visibility, + labelVisibility + ) + labelString = + typedArray.getString( + R.styleable.BaseTelemetryWidget_uxsdk_label_string, + getString(R.string.uxsdk_string_default_value) + ) + + typedArray.getResourceIdAndUse(R.styleable.BaseTelemetryWidget_uxsdk_value_text_appearance) { + setValueTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.BaseTelemetryWidget_uxsdk_value_text_size) { + valueTextSize = it + } + typedArray.getColorAndUse(R.styleable.BaseTelemetryWidget_uxsdk_value_text_color) { + valueTextColor = it + } + typedArray.getColorStateListAndUse(R.styleable.BaseTelemetryWidget_uxsdk_value_text_color) { + valueTextColors = it + } + typedArray.getDrawableAndUse(R.styleable.BaseTelemetryWidget_uxsdk_value_background) { + valueBackground = it + } + valueVisibility = typedArray.getBoolean( + R.styleable.BaseTelemetryWidget_uxsdk_value_visibility, + valueVisibility + ) + typedArray.getIntegerAndUse(R.styleable.BaseTelemetryWidget_uxsdk_value_gravity) { + valueTextGravity = it + } + valueString = + typedArray.getString( + R.styleable.BaseTelemetryWidget_uxsdk_value_string, + getString(R.string.uxsdk_string_default_value) + ) + + typedArray.getResourceIdAndUse(R.styleable.BaseTelemetryWidget_uxsdk_unit_text_appearance) { + setUnitTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.BaseTelemetryWidget_uxsdk_unit_text_size) { + unitTextSize = it + } + typedArray.getColorAndUse(R.styleable.BaseTelemetryWidget_uxsdk_unit_text_color) { + unitTextColor = it + } + typedArray.getColorStateListAndUse(R.styleable.BaseTelemetryWidget_uxsdk_unit_text_color) { + unitTextColors = it + } + typedArray.getDrawableAndUse(R.styleable.BaseTelemetryWidget_uxsdk_unit_background) { + unitBackground = it + } + unitVisibility = typedArray.getBoolean( + R.styleable.BaseTelemetryWidget_uxsdk_unit_visibility, + unitVisibility + ) + unitString = + typedArray.getString( + R.styleable.BaseTelemetryWidget_uxsdk_unit_string, + getString(R.string.uxsdk_string_default_value) + ) + + typedArray.getDrawableAndUse(R.styleable.BaseTelemetryWidget_uxsdk_widget_icon) { + widgetIcon = it + } + typedArray.getColorAndUse(R.styleable.BaseTelemetryWidget_uxsdk_widget_icon_color) { + widgetIconColor = it + } + typedArray.getDrawableAndUse(R.styleable.BaseTelemetryWidget_uxsdk_widget_icon_background) { + widgetIconBackground = it + } + widgetIconVisibility = typedArray.getBoolean( + R.styleable.BaseTelemetryWidget_uxsdk_widget_icon_visibility, + widgetIconVisibility + ) + typedArray.getDimensionAndUse(R.styleable.BaseTelemetryWidget_uxsdk_widget_padding_left) { + contentPaddingLeft = it.toInt() + } + typedArray.getDimensionAndUse(R.styleable.BaseTelemetryWidget_uxsdk_widget_padding_top) { + contentPaddingTop = it.toInt() + } + typedArray.getDimensionAndUse(R.styleable.BaseTelemetryWidget_uxsdk_widget_padding_right) { + contentPaddingRight = it.toInt() + } + typedArray.getDimensionAndUse(R.styleable.BaseTelemetryWidget_uxsdk_widget_padding_bottom) { + contentPaddingBottom = it.toInt() + } + typedArray.getColorAndUse(R.styleable.BaseTelemetryWidget_uxsdk_normal_text_color) { + normalValueColor = it + } + typedArray.getColorAndUse(R.styleable.BaseTelemetryWidget_uxsdk_error_text_color) { + errorValueColor = it + } + } + + private fun configureLeftImageTypeWidget() { + imageView.id = ViewIDGenerator.generateViewId() + val set = ConstraintSet() + set.clone(this) + set.clear(imageView.id) + imageView.adjustViewBounds = true + set.setMargin(imageView.id, ConstraintSet.RIGHT, getDimension(R.dimen.uxsdk_telemetry_view_margin).toInt()) + set.clear(labelTextView.id, ConstraintSet.LEFT) + set.constrainHeight(imageView.id, 0) + set.setDimensionRatio(imageView.id, "1:1") + set.setHorizontalChainStyle(imageView.id, ConstraintSet.CHAIN_SPREAD) + set.connect(imageView.id, ConstraintSet.TOP, guidelineTop.id, ConstraintSet.TOP) + set.connect(imageView.id, ConstraintSet.BOTTOM, guidelineBottom.id, ConstraintSet.BOTTOM) + set.connect(imageView.id, ConstraintSet.LEFT, guidelineLeft.id, ConstraintSet.LEFT) + set.connect(imageView.id, ConstraintSet.RIGHT, labelTextView.id, ConstraintSet.LEFT) + set.connect(labelTextView.id, ConstraintSet.LEFT, imageView.id, ConstraintSet.RIGHT) + addView(imageView) + set.applyTo(this) + + } + + + private fun configureRightImageTypeWidget() { + imageView.id = ViewIDGenerator.generateViewId() + val set = ConstraintSet() + set.clone(this) + set.clear(imageView.id) + imageView.adjustViewBounds = true + set.setMargin(imageView.id, ConstraintSet.LEFT, getDimension(R.dimen.uxsdk_telemetry_view_margin).toInt()) + set.clear(unitTextView.id, ConstraintSet.RIGHT) + set.constrainHeight(imageView.id, 0) + set.setDimensionRatio(imageView.id, "1:1") + set.setHorizontalChainStyle(imageView.id, ConstraintSet.CHAIN_SPREAD) + set.connect(imageView.id, ConstraintSet.TOP, guidelineTop.id, ConstraintSet.TOP) + set.connect(imageView.id, ConstraintSet.BOTTOM, guidelineBottom.id, ConstraintSet.BOTTOM) + set.connect(imageView.id, ConstraintSet.RIGHT, guidelineRight.id, ConstraintSet.RIGHT) + set.connect(imageView.id, ConstraintSet.LEFT, unitTextView.id, ConstraintSet.RIGHT) + set.connect(unitTextView.id, ConstraintSet.RIGHT, imageView.id, ConstraintSet.LEFT) + addView(imageView) + set.applyTo(this) + + } + + protected fun setValueTextViewMinWidthByText(maxText: String) { + val textPaint = TextPaint() + textPaint.textSize = valueTextView.textSize + valueTextView.minWidth = textPaint.measureText(maxText).toInt() + } + + protected fun getDecimalFormat(unitType: UnitConversionUtil.UnitType): DecimalFormat { + return if (unitType == UnitConversionUtil.UnitType.IMPERIAL) { + imperialDecimalFormat + } else { + metricDecimalFormat + } + } + + /** + * Set the icon + * + * @param resourceId Integer ID of the background resource + */ + fun setIcon(@DrawableRes resourceId: Int) { + widgetIcon = getDrawable(resourceId) + } + + /** + * Set the background of the icon + * + * @param resourceId Integer ID of the background resource + */ + fun setIconBackground(@DrawableRes resourceId: Int) { + widgetIconBackground = getDrawable(resourceId) + } + + /** + * Set the background of the label + * + * @param resourceId Integer ID of the background resource + */ + fun setLabelBackground(@DrawableRes resourceId: Int) { + labelBackground = getDrawable(resourceId) + } + + /** + * Set the text appearance of the label + * + * @param textAppearanceResId Style resource for text appearance + */ + fun setLabelTextAppearance(@StyleRes textAppearanceResId: Int) { + labelTextView.setTextAppearance(context, textAppearanceResId) + } + + /** + * Set the background of the value + * + * @param resourceId Integer ID of the background resource + */ + fun setValueBackground(@DrawableRes resourceId: Int) { + valueBackground = getDrawable(resourceId) + } + + /** + * Set the text appearance of the value + * + * @param textAppearanceResId Style resource for text appearance + */ + fun setValueTextAppearance(@StyleRes textAppearanceResId: Int) { + valueTextView.setTextAppearance(context, textAppearanceResId) + } + + /** + * Set the background of the unit + * + * @param resourceId Integer ID of the background resource + */ + fun setUnitBackground(@DrawableRes resourceId: Int) { + unitBackground = getDrawable(resourceId) + } + + /** + * Set the text appearance of the unit + * + * @param textAppearanceResId Style resource for text appearance + */ + fun setUnitTextAppearance(@StyleRes textAppearanceResId: Int) { + unitTextView.setTextAppearance(context, textAppearanceResId) + } + + /** + * Set padding to the content of the item + */ + fun setContentPadding(left: Int, top: Int, right: Int, bottom: Int) { + contentPaddingLeft = left + contentPaddingTop = top + contentPaddingRight = right + contentPaddingBottom = bottom + } + + + /** + * Defines the type of widget + */ + enum class WidgetType { + + /** + * The type represents + * | LABEL | VALUE | UNIT | + */ + TEXT, + + /** + * The class represents the with icon, + * | IMAGE | LABEL | VALUE | UNIT | + */ + TEXT_IMAGE_LEFT, + + /** + * The class represents the with icon, + * | LABEL | VALUE | UNIT | IMAGE | + */ + TEXT_IMAGE_RIGHT + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/widget/BasicRangeSeekBarWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/widget/BasicRangeSeekBarWidget.kt new file mode 100644 index 00000000..1d6a9c93 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/widget/BasicRangeSeekBarWidget.kt @@ -0,0 +1,523 @@ +package dji.v5.ux.core.base.widget + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.* +import android.graphics.drawable.BitmapDrawable +import android.graphics.drawable.Drawable +import android.os.Bundle +import android.os.Parcelable +import android.util.AttributeSet +import android.view.MotionEvent +import android.view.View +import android.view.ViewConfiguration +import androidx.annotation.ColorInt +import androidx.core.content.ContextCompat +import dji.v5.utils.common.AndUtil +import dji.v5.ux.R +import kotlin.math.abs +import kotlin.math.max +import kotlin.math.min +import kotlin.math.roundToInt + +private const val DEFAULT_MIN = 0f +private const val DEFAULT_MAX = 100f +private const val DEFAULT_STEP = 1f +private const val DEFAULT_GAP = 0f + +private const val INVALID_POINTER_ID = 255 + +class BasicRangeSeekBar @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 +) : View(context, attrs, defStyleAttr) { + + /* Attrs values */ + private val leftThumbImg: Bitmap + private val rightThumbImg: Bitmap + private var rightThumbOffset = 14 + private var leftThumbOffset = 14 + + + var minValue = DEFAULT_MIN + private set + private var maxValue = DEFAULT_MAX + private var stepValue = DEFAULT_STEP + private var gapValue = DEFAULT_GAP + + private var lowerBoundaryValue = DEFAULT_MAX + private var largerBoundaryValue = DEFAULT_MIN + + @ColorInt + var leftSideBarColor = AndUtil.getResColor(R.color.uxsdk_checklist_seekbar_red_color) + set(value) { + field = value + invalidate() + } + + @ColorInt + var centerBarColor = AndUtil.getResColor(R.color.uxsdk_checklist_warning_bg_color) + set(value) { + field = value + invalidate() + } + + @ColorInt + var rightSideBarColor = AndUtil.getResColor(R.color.uxsdk_checklist_seekbar_gray_color) + set(value) { + field = value + invalidate() + } + + var listener: OnRangeSeekBarListener? = null + + var isShowLeftThumb = true + set(value) { + field = value + invalidate() + } + + private var barHeight = 0 + private var thumbLeftPointerPadding = 0 + private var thumbRightPointerPadding = 24 + private var thumbBackPadding = 0 + + /* System values */ + private var isDragging = false + + private var stepsCount = 0 + private val scaledTouchSlop by lazy { ViewConfiguration.get(getContext()).scaledTouchSlop } + + private var activePointerId = INVALID_POINTER_ID + private var downMotionX = 0f + + private var leftPadding = 0f + private var rightPadding = 0f + + private var normalizedMinValue = 0.0 + private var normalizedMaxValue = 1.0 + private var normalizedGapValue = 0.0 + private var normalizedLowerBoundaryValue = 1.0 + private var normalizedLargerBoundaryValue = 0.0 + + private var pressedThumb: Thumb? = null + + companion object { + private val srcThumbRect: Rect = Rect() + private val dstThumbRectF: RectF = RectF() + private val center: Point = Point(0, 0) + } + + private val paint = Paint(Paint.ANTI_ALIAS_FLAG) + + init { + context.resources.apply { + leftThumbImg = toBitmap(ContextCompat.getDrawable(context,R.drawable.uxsdk_ic_slider_block_red)!!) + rightThumbImg = toBitmap(ContextCompat.getDrawable(context,R.drawable.uxsdk_ic_slider_block_orange)!!) + } + thumbBackPadding = AndUtil.getDimension(R.dimen.uxsdk_5_dp).toInt() + thumbLeftPointerPadding = AndUtil.getDimension(R.dimen.uxsdk_4_dp).toInt() + + attrs?.let { + context.obtainStyledAttributes(it, R.styleable.BasicRangeSeekBar).apply { + centerBarColor = getColor(R.styleable.BasicRangeSeekBar_uxsdk_bar_center_color, centerBarColor) + leftSideBarColor = getColor(R.styleable.BasicRangeSeekBar_uxsdk_bar_left_side_color, leftSideBarColor) + rightSideBarColor = getColor(R.styleable.BasicRangeSeekBar_uxsdk_bar_right_side_color, rightSideBarColor) + + minValue = getFloat(R.styleable.BasicRangeSeekBar_uxsdk_bar_min_value, minValue) + maxValue = getFloat(R.styleable.BasicRangeSeekBar_uxsdk_bar_max_value, maxValue) + stepValue = getFloat(R.styleable.BasicRangeSeekBar_uxsdk_bar_step_value, stepValue) + if (maxValue < minValue) throw Exception("Min value can't be higher than max value") + if (!stepValueValidation(minValue, maxValue, stepValue)) throw Exception("Incorrect min/max/step, it must be: (maxValue - minValue) % stepValue == 0f") + stepsCount = ((maxValue - minValue) / stepValue).toInt() + barHeight = getDimensionPixelSize(R.styleable.BasicRangeSeekBar_uxsdk_bar_height, barHeight) + recycle() + } + } + + isFocusable = true + isFocusableInTouchMode = true + } + + @Suppress("NAME_SHADOWING") + @SuppressLint("ClickableViewAccessibility") + override fun onTouchEvent(event: MotionEvent?): Boolean { + if (!isEnabled) return false + event?.let { event -> + val pointerIndex: Int + when (event.action and MotionEvent.ACTION_MASK) { + MotionEvent.ACTION_DOWN -> { + activePointerId = event.getPointerId(event.pointerCount - 1) + pointerIndex = event.findPointerIndex(activePointerId) + downMotionX = event.getX(pointerIndex) + + pressedThumb = evalPressedThumb(downMotionX) + pressedThumb ?: return super.onTouchEvent(event) + + isPressed = true + invalidate() + isDragging = true + trackTouchEvent(event) + parent?.requestDisallowInterceptTouchEvent(true) + println() + } + + MotionEvent.ACTION_MOVE -> { + onActionMove(event) + } + + MotionEvent.ACTION_UP -> { + if (isDragging) { + trackTouchEvent(event) + isDragging = false + isPressed = false + } else { + isDragging = true + trackTouchEvent(event) + isDragging = false + } + + listener?.onValuesChanged(getSelectedMinValue().toFloat(), getSelectedMaxValue().toFloat()) + + pressedThumb = null + invalidate() + } + MotionEvent.ACTION_POINTER_DOWN -> { + val index = event.pointerCount - 1 + downMotionX = event.getX(index) + activePointerId = event.getPointerId(index) + invalidate() + } + + MotionEvent.ACTION_POINTER_UP -> { + onSecondaryPointerUp(event) + invalidate() + } + MotionEvent.ACTION_CANCEL -> { + if (isDragging) isDragging = false; isPressed = false + invalidate() + } + } + } ?: run { return false } + return true + } + + private fun onActionMove(event: MotionEvent) { + pressedThumb?.let { + val pointerIndex: Int + listener?.onValuesChanging(getSelectedMinValue().toFloat(), getSelectedMaxValue().toFloat()) + + if (isDragging) { + trackTouchEvent(event) + } else { + pointerIndex = event.findPointerIndex(activePointerId) + val x = event.getX(pointerIndex) + + if (abs(x - downMotionX) > scaledTouchSlop) { + isPressed = true + invalidate() + isDragging = true + trackTouchEvent(event) + parent?.requestDisallowInterceptTouchEvent(true) + println() + } + } + } + println() + } + + @SuppressLint("DrawAllocation") + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + + leftPadding = (leftThumbImg.width + thumbLeftPointerPadding).toFloat() + rightPadding = (width - rightThumbImg.width - thumbRightPointerPadding).toFloat() + + center.set(width / 2, height / 2) + + val top = center.y - barHeight / 2f + val bottom = center.y + barHeight / 2f + + val minScreenPos = normalizedToScreen(normalizedMinValue) + val maxScreenPos = normalizedToScreen(normalizedMaxValue) + + paint.style = Paint.Style.FILL + paint.isAntiAlias = true + + canvas?.apply { + /* left rect */ + val rectUnusedArea = RectF() + rectUnusedArea.top = top + rectUnusedArea.bottom = bottom + rectUnusedArea.left = leftPadding + rectUnusedArea.right = minScreenPos + + paint.color = if (isShowLeftThumb) leftSideBarColor else centerBarColor + + val bufRect = RectF(rectUnusedArea) + bufRect.left += 10 + drawRect(bufRect, paint) + drawRoundRect(rectUnusedArea, 10f, 10f, paint) + + /* right rect */ + rectUnusedArea.right = rightPadding + rectUnusedArea.left = maxScreenPos + + paint.color = rightSideBarColor + + val bufRect1 = RectF(rectUnusedArea) + bufRect1.right -= 10 + drawRect(bufRect1, paint) + drawRoundRect(rectUnusedArea, 10f, 10f, paint) + + rectUnusedArea.left = minScreenPos + rectUnusedArea.right = maxScreenPos + + paint.color = centerBarColor + + drawRect(rectUnusedArea, paint) + + /* draw thumb */ + if (isShowLeftThumb) { + drawLeftThumb(minScreenPos, canvas) + } + drawRightThumb(maxScreenPos, canvas) + } + } + + private fun stepValueValidation(minValue: Float, maxValue: Float, stepValue: Float) = + (maxValue.toBigDecimal() - minValue.toBigDecimal()) % stepValue.toBigDecimal() == 0f.toBigDecimal() + + private fun drawLeftThumb(screenCoord: Float, canvas: Canvas) { + srcThumbRect.set(0, 0, leftThumbImg.width, leftThumbImg.height) + dstThumbRectF.set( + screenCoord - leftThumbImg.width + leftThumbOffset, + center.y.toFloat() - leftThumbImg.height * 0.5f, + screenCoord + leftThumbOffset, + center.y.toFloat() + leftThumbImg.height * 0.5f + ) + canvas.drawBitmap(leftThumbImg, srcThumbRect, dstThumbRectF, paint) + } + + private fun drawRightThumb(screenCoord: Float, canvas: Canvas) { + srcThumbRect.set(0, 0, rightThumbImg.width, rightThumbImg.height) + dstThumbRectF.set( + screenCoord - rightThumbOffset, + center.y.toFloat() - rightThumbImg.height * 0.5f, + screenCoord + rightThumbImg.width - rightThumbOffset, + center.y.toFloat() + rightThumbImg.height * 0.5f + ) + canvas.drawBitmap(rightThumbImg, srcThumbRect, dstThumbRectF, paint) + } + + private fun evalPressedThumb(touchX: Float): Thumb? { + val minThumbPressed = isInLeftThumbRange(touchX) + val maxThumbPressed = isInRightThumbRange(touchX) + return if (minThumbPressed && maxThumbPressed) { + if (isShowLeftThumb && touchX / width > 0.5f) Thumb.MIN else Thumb.MAX + } else if (isShowLeftThumb && minThumbPressed) { + Thumb.MIN + } else if (maxThumbPressed) { + Thumb.MAX + } else null + } + + private fun onSecondaryPointerUp(ev: MotionEvent) { + (ev.action and MotionEvent.ACTION_POINTER_INDEX_MASK shr MotionEvent.ACTION_POINTER_INDEX_SHIFT).apply { + if (ev.getPointerId(this) == activePointerId) { + val newPointerIndex = if (this == 0) 1 else 0 + downMotionX = ev.getX(newPointerIndex) + activePointerId = ev.getPointerId(newPointerIndex) + } + } + } + + private fun isInLeftThumbRange(touchX: Float) = normalizedToScreen(normalizedMinValue) - touchX in -4f..(leftThumbImg.width + 40f) + private fun isInRightThumbRange(touchX: Float) = touchX - normalizedToScreen(normalizedMaxValue) in -4f..(rightThumbImg.width + 40f) + + private fun normalizedToScreen(normalizedPos: Double) = (leftPadding + normalizedPos * (width - leftPadding * 2)).toFloat() + + + private fun trackTouchEvent(event: MotionEvent) { + val pointerIndex = event.findPointerIndex(activePointerId) + val x = event.getX(pointerIndex) + + if (Thumb.MIN == pressedThumb) { + setNormalizedMinValue(screenToNormalized(x)) + } else if (Thumb.MAX == pressedThumb) { + setNormalizedMaxValue(screenToNormalized(x)) + } + } + + private fun setNormalizedMinValue(value: Double) { + normalizedMinValue = max(0.0, min(1.0, min(value, min(normalizedMaxValue + normalizedGapValue, normalizedLowerBoundaryValue)))) + invalidate() + } + + private fun setNormalizedMaxValue(value: Double) { + normalizedMaxValue = max(0.0, min(1.0, max(value, max(normalizedMinValue - normalizedGapValue, normalizedLargerBoundaryValue)))) + invalidate() + } + + private fun screenToNormalized(screenPos: Float): Double { + val width = width + return if (width <= leftPadding * 2) { + 0.0 //divide by zero safe + } else { + val result = ((screenPos - leftPadding) / (width - leftPadding * 2)).toDouble() + min(1.0, max(0.0, result)) + } + } + + private fun valueToNormalize(value: Double) = ((maxValue - minValue) * (value * 100)) / 100 + minValue + private fun normalizeToValue(value: Float) = (((value - minValue) * 100) / (maxValue - minValue)) / 100 + + private fun getSelectedMinValue() = getValueAccordingToStep(valueToNormalize(normalizedMinValue)) + private fun getSelectedMaxValue() = getValueAccordingToStep(valueToNormalize(normalizedMaxValue)) + + private fun getValueAccordingToStep(value: Double) = ((value.toBigDecimal() / stepValue.toBigDecimal()).toDouble().roundToInt()).toBigDecimal() * stepValue.toBigDecimal() + + private fun resetRange() { + if (maxValue < minValue) throw Exception("Min value can't be higher than max value") + if (!stepValueValidation(minValue, maxValue, stepValue)) throw Exception("Incorrect min/max/step, it must be: (maxValue - minValue) % stepValue == 0f") + + normalizedMinValue = 0.0 + normalizedMaxValue = 1.0 + normalizedGapValue = normalizeToValue(gapValue).toDouble() + normalizedLowerBoundaryValue = normalizeToValue(lowerBoundaryValue).toDouble() + normalizedLargerBoundaryValue = normalizeToValue(largerBoundaryValue).toDouble() + + + invalidate() + } + + fun setRange(minValue: Float, maxValue: Float, stepValue: Float) { + setRange(minValue, maxValue, stepValue, DEFAULT_GAP, DEFAULT_MAX, DEFAULT_MIN) + } + + fun setRange(minValue: Float, maxValue: Float, stepValue: Float, gapValue: Float) { + setRange(minValue, maxValue, stepValue, gapValue, DEFAULT_MAX, DEFAULT_MIN) + } + + fun setRange( + minValue: Float, maxValue: Float, stepValue: Float, + gapValue: Float, lowerBoundaryValue: Float, largerBoundaryValue: Float + ) { + val notChange = this.minValue.compareTo(minValue) == 0 + && this.maxValue.compareTo(maxValue) == 0 + && this.stepValue.compareTo(stepValue) == 0 + && this.gapValue.compareTo(gapValue) == 0 + && this.lowerBoundaryValue.compareTo(lowerBoundaryValue) == 0 + && this.largerBoundaryValue.compareTo(largerBoundaryValue) == 0 + if (notChange) { + return + } + this.minValue = minValue + this.maxValue = maxValue + this.stepValue = stepValue + this.gapValue = gapValue + this.lowerBoundaryValue = lowerBoundaryValue + this.largerBoundaryValue = largerBoundaryValue + + resetRange() + } + + fun setCurrentValues(leftValue: Float, rightValue: Float) { + if (leftValue > rightValue) throw Exception("LeftValue $leftValue can't be higher than rightValue $rightValue") + if (leftValue < minValue || rightValue > maxValue) throw Exception("$leftValue or $rightValue Out of range[$minValue, $maxValue]") + if (!stepValueValidation(leftValue, maxValue, stepValue) || !stepValueValidation(minValue, rightValue, stepValue)) throw Exception("You can't set these values according to your step") + + val newNormalizedMinValue = normalizeToValue(leftValue).toDouble() + val newNormalizedMaxValue = normalizeToValue(rightValue).toDouble() + val valueNotChanged = this.normalizedMinValue.compareTo(newNormalizedMinValue) == 0 + && this.normalizedMaxValue.compareTo(newNormalizedMaxValue) == 0 + if (valueNotChanged) { + return + } + normalizedMinValue = newNormalizedMinValue + normalizedMaxValue = newNormalizedMaxValue + + invalidate() + } + + fun getRangeInfo() = RangeInfo(minValue, maxValue, stepValue, gapValue) + + fun getCurrentValues() = Range(getSelectedMinValue().toFloat(), getSelectedMaxValue().toFloat()) + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + var width = 200 + if (MeasureSpec.UNSPECIFIED != MeasureSpec.getMode(widthMeasureSpec)) { + width = MeasureSpec.getSize(widthMeasureSpec) + } + + var height = leftThumbImg.height + + if (MeasureSpec.UNSPECIFIED != MeasureSpec.getMode(heightMeasureSpec)) { + height = max(height, MeasureSpec.getSize(heightMeasureSpec)) + } + setMeasuredDimension(width, height) + } + + override fun onSaveInstanceState(): Parcelable { + val bundle = Bundle() + bundle.putParcelable("SUPER", super.onSaveInstanceState()) + bundle.putDouble("LEFT_VALUE", normalizedMinValue) + bundle.putDouble("RIGHT_VALUE", normalizedMaxValue) + + bundle.putFloat("MIN_VALUE", minValue) + bundle.putFloat("MAX_VALUE", maxValue) + + bundle.putFloat("STEP_VALUE", stepValue) + + bundle.putInt("SIDE_BAR_COLOR", leftSideBarColor) + bundle.putInt("CENTER_BAR_COLOR", centerBarColor) + bundle.putInt("TRANSITION_BAR_COLOR", rightSideBarColor) + return bundle + } + + override fun onRestoreInstanceState(parcel: Parcelable) { + val bundle = parcel as Bundle + super.onRestoreInstanceState(bundle.getParcelable("SUPER")) + normalizedMinValue = bundle.getDouble("LEFT_VALUE") + normalizedMaxValue = bundle.getDouble("RIGHT_VALUE") + + minValue = bundle.getFloat("MIN_VALUE") + maxValue = bundle.getFloat("MAX_VALUE") + + stepValue = bundle.getFloat("STEP_VALUE") + + leftSideBarColor = bundle.getInt("SIDE_BAR_COLOR") + centerBarColor = bundle.getInt("CENTER_BAR_COLOR") + rightSideBarColor = bundle.getInt("TRANSITION_BAR_COLOR") + invalidate() + } + + interface OnRangeSeekBarListener { + fun onValuesChanging(minValue: Float, maxValue: Float) + fun onValuesChanged(minValue: Float, maxValue: Float) + } + + data class Range(val leftValue: Float, val rightValue: Float) + data class RangeInfo(val minValue: Float, val maxValue: Float, val stepValue: Float, val gapValue: Float) + + private enum class Thumb { + MIN, MAX + } + + private fun toBitmap(drawable: Drawable): Bitmap { + if (drawable is BitmapDrawable) return drawable.bitmap + drawable.apply { + val width = if (!bounds.isEmpty) bounds.width() else intrinsicWidth + val height = if (!bounds.isEmpty) bounds.height() else intrinsicHeight + + val bitmap = Bitmap.createBitmap( + if (width <= 0) 1 else width, if (height <= 0) 1 else height, + Bitmap.Config.ARGB_8888 + ) + Canvas(bitmap).apply { + setBounds(0, 0, width, height) + draw(this) + } + return bitmap + } + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/widget/ConstraintLayoutWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/widget/ConstraintLayoutWidget.kt new file mode 100644 index 00000000..313a7046 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/widget/ConstraintLayoutWidget.kt @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base.widget + +import android.content.Context +import android.util.AttributeSet +import androidx.constraintlayout.widget.ConstraintLayout +import dji.v5.utils.common.LogUtils +import dji.v5.ux.core.base.WidgetSizeDescription +import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.disposables.CompositeDisposable +import io.reactivex.rxjava3.disposables.Disposable +import io.reactivex.rxjava3.processors.PublishProcessor + +/** + * This is a base class for widgets requiring ConstraintLayout. + * T is the type of Widget State Update, @see[getWidgetStateUpdate]. + */ +abstract class ConstraintLayoutWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ConstraintLayout(context, attrs, defStyleAttr) { + + protected val logTag = LogUtils.getTag(this) + + //region Properties + private var reactionDisposables: CompositeDisposable? = null + private var compositeDisposable: CompositeDisposable? = null + + /** + * Publish state data updates + */ + protected val widgetStateDataProcessor: PublishProcessor = PublishProcessor.create() + + //endregion + + //region Constructor + init { + initView(context, attrs, defStyleAttr) + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (isInEditMode) { + return + } + reactionDisposables = CompositeDisposable() + compositeDisposable = CompositeDisposable() + reactToModelChanges() + } + + override fun onDetachedFromWindow() { + unregisterReactions() + disposeAll() + super.onDetachedFromWindow() + } + + /** + * Invoked during the initialization of the class. + * Inflate should be done here. For Kotlin, load attributes, findViewById should be done in + * the init block. + * + * @param context Context + * @param attrs Attribute set + * @param defStyleAttr Style attribute + */ + protected abstract fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) + + /** + * Call addReaction here to bind to the model. + */ + protected abstract fun reactToModelChanges() + + /** + * Add a disposable which is automatically disposed with the view's lifecycle. + * + * @param disposable the disposable to add + */ + protected fun addDisposable(disposable: Disposable) { + compositeDisposable?.add(disposable) + } + //endregion + //region Customization + /** + * Ideal dimension ratio in the format width:height. + * + * @return dimension ratio string. + */ + open fun getIdealDimensionRatioString(): String? = null + + /** + * Ideal widget size. + * By default the widget size is a ratio + */ + open val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.RATIO) + + //endregion + //region Reactions + /** + * Add a reaction which is automatically disposed with the view's lifecycle. + * + * @param reaction the reaction to add. + */ + protected fun addReaction(reaction: Disposable) { + checkNotNull(reactionDisposables) { "Called this method only from reactToModelChanges." } + reactionDisposables?.add(reaction) + } + + private fun unregisterReactions() { + reactionDisposables?.dispose() + reactionDisposables = null + } + + private fun disposeAll() { + compositeDisposable?.dispose() + compositeDisposable = null + } + //endregion + + /** + * Get the update for the widget state + * + * @return update with widget state + */ + open fun getWidgetStateUpdate(): Flowable = widgetStateDataProcessor.onBackpressureBuffer() + + companion object { + private const val TAG = "ConstraintLayoutWidget" + const val INVALID_RESOURCE = -1 + const val INVALID_COLOR = 0 + const val INVALID_DIMENSION = 0f + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/widget/FrameLayoutWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/widget/FrameLayoutWidget.kt new file mode 100644 index 00000000..affbb546 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/widget/FrameLayoutWidget.kt @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base.widget + +import android.content.Context +import android.os.Looper +import android.util.AttributeSet +import android.view.View +import android.widget.FrameLayout +import dji.v5.utils.common.LogUtils +import dji.v5.ux.BuildConfig +import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.disposables.CompositeDisposable +import io.reactivex.rxjava3.disposables.Disposable +import io.reactivex.rxjava3.processors.PublishProcessor +import dji.v5.ux.core.base.WidgetSizeDescription +import java.lang.RuntimeException +import java.lang.StringBuilder + +/** + * This is a base class for widgets requiring FrameLayout. + * T is the type of Widget State Update, @see[getWidgetStateUpdate]. + */ +abstract class FrameLayoutWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, +) : FrameLayout(context, attrs, defStyleAttr) { + protected val tag = LogUtils.getTag(this) + + //region Fields + private var reactionDisposables: CompositeDisposable? = null + private var compositeDisposable: CompositeDisposable? = null + + /** + * Publish state data updates + */ + protected val widgetStateDataProcessor: PublishProcessor = PublishProcessor.create() + + //endregion + + //region Constructor + init { + initView(context, attrs, defStyleAttr) + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (isInEditMode) { + return + } + reactionDisposables = CompositeDisposable() + compositeDisposable = CompositeDisposable() + reactToModelChanges() + } + + override fun onDetachedFromWindow() { + unregisterReactions() + disposeAll() + super.onDetachedFromWindow() + } + + /** + * Invoked during the initialization of the class. + * Inflate should be done here. For Kotlin, load attributes, findViewById should be done in + * the init block. + * + * @param context Context + * @param attrs Attribute set + * @param defStyleAttr Style attribute + */ + protected abstract fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) + + /** + * Call addReaction here to bind to the model. + */ + protected abstract fun reactToModelChanges() + + /** + * Add a disposable which is automatically disposed with the view's lifecycle. + * + * @param disposable the disposable to add + */ + protected fun addDisposable(disposable: Disposable) { + compositeDisposable?.add(disposable) + } + //endregion + + //region Customization + /** + * Ideal dimension ratio in the format width:height. + * + * @return dimension ratio string. + */ + open fun getIdealDimensionRatioString(): String? = null + + /** + * Ideal widget size. + * By default the widget size is a ratio + */ + open val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.RATIO) + //endregion + + //region Reactions + /** + * Add a reaction which is automatically disposed with the view's lifecycle. + * + * @param reaction the reaction to add. + */ + protected fun addReaction(reaction: Disposable) { + checkNotNull(reactionDisposables) { "Called this method only from reactToModelChanges." } + reactionDisposables?.add(reaction) + } + + private fun unregisterReactions() { + reactionDisposables?.dispose() + reactionDisposables = null + + } + + private fun disposeAll() { + compositeDisposable?.dispose() + compositeDisposable = null + } + //endregion + + /** + * Get the update for the widget state + * + * @return update with widget state + */ + open fun getWidgetStateUpdate(): Flowable = widgetStateDataProcessor.onBackpressureBuffer() + //endregion + + companion object { + private const val TAG: String = "FrameLayoutWidget" + const val INVALID_RESOURCE: Int = -1 + const val INVALID_COLOR: Int = 0 + } + + /** + * 接管处理下可能存在的异步invalidate + * https://cloud.tencent.com/developer/article/1846821 + */ + override fun invalidate() { + if (Looper.myLooper() == Looper.getMainLooper()) { + super.invalidate() + } else { + recordInvalidateCallStack(this) + } + } + + open fun recordInvalidateCallStack(view: View) { + view.postInvalidate() + if (BuildConfig.DEBUG) { + throw RuntimeException("Only the original thread that created a view hierarchy can touch its views.") + } else { + val stringBuilder = StringBuilder() + for (stackTraceElement in Thread.currentThread().stackTrace) { + stringBuilder.append(stackTraceElement) + stringBuilder.append("\n") + } + LogUtils.e(TAG, " async call invalidate \n$stringBuilder") + } + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/widget/IconButtonWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/widget/IconButtonWidget.kt new file mode 100644 index 00000000..d1a79652 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/widget/IconButtonWidget.kt @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.base.widget + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.View +import android.widget.ImageView +import androidx.annotation.CallSuper +import androidx.annotation.ColorInt +import androidx.annotation.DrawableRes +import androidx.core.content.res.use +import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.processors.PublishProcessor +import dji.v5.ux.R +import dji.v5.ux.core.extension.* + +/** + * Abstract class that represents a widget with a single Image View. + * The class provides functionality and customizations for widgets to reuse + */ +abstract class IconButtonWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ConstraintLayoutWidget(context, attrs, defStyleAttr), View.OnClickListener { + + //region Fields + + protected val foregroundImageView: ImageView = findViewById(R.id.image_view_button) + protected val uiUpdateStateProcessor: PublishProcessor = PublishProcessor.create() + + /** + * The color of the icon when the product is connected + */ + @get:ColorInt + var connectedStateIconColor: Int = getColor(R.color.uxsdk_transparent) + set(@ColorInt value) { + field = value + checkAndUpdateIconColor() + } + + /** + * The color of the icon when the product is disconnected + */ + @get:ColorInt + var disconnectedStateIconColor: Int = getColor(R.color.uxsdk_gray_58) + set(@ColorInt value) { + field = value + checkAndUpdateIconColor() + } + + /** + * Get current background of foregroundImageView + */ + var iconBackground: Drawable? + get() = foregroundImageView.background + set(value) { + foregroundImageView.background = value + } + + //endregion + @CallSuper + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + View.inflate(context, R.layout.uxsdk_icon_button_widget, this) + setOnClickListener(this) + } + + init { + attrs?.let { initAttributes(context, it) } + } + + protected abstract fun checkAndUpdateIconColor() + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.IconButtonWidget).use { typedArray -> + typedArray.getDrawableAndUse(R.styleable.IconButtonWidget_uxsdk_iconBackground) { + iconBackground = it + } + typedArray.getColorAndUse(R.styleable.IconButtonWidget_uxsdk_connectedStateIconColor) { + connectedStateIconColor = it + } + typedArray.getColorAndUse(R.styleable.IconButtonWidget_uxsdk_disconnectedStateIconColor) { + disconnectedStateIconColor = it + } + } + } + + @CallSuper + override fun onClick(view: View?) { + uiUpdateStateProcessor.onNext(UIState.WidgetClicked) + } + + override fun getIdealDimensionRatioString(): String { + return getString(R.string.uxsdk_widget_default_ratio) + } + + /** + * Set background to foregroundImageView + * + * @param resourceId Integer ID of the background resource + */ + fun setIconBackground(@DrawableRes resourceId: Int) { + iconBackground = getDrawable(resourceId) + } + + /** + * Get the [UIState] updates + */ + fun getUIStateUpdates(): Flowable { + return uiUpdateStateProcessor.onBackpressureBuffer() + } + + /** + * Widget UI update State + */ + sealed class UIState { + /** + * Widget click update + */ + object WidgetClicked : UIState() + + /** + * Dialog shown update + */ + data class DialogDisplayed(val info: Any?) : UIState() + + /** + * Dialog action confirm + */ + data class DialogActionConfirmed(val info: Any?) : UIState() + + /** + * Dialog action dismiss + */ + data class DialogDismissed(val info: Any?) : UIState() + + /** + * Dialog action dismiss + */ + data class DialogActionCancelled(val info: Any?) : UIState() + + /** + * Dialog checkbox interaction + */ + data class DialogCheckboxCheckChanged(val info: Any?) : UIState() + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/widget/ViewWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/widget/ViewWidget.kt new file mode 100644 index 00000000..31e05346 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/base/widget/ViewWidget.kt @@ -0,0 +1,115 @@ +package dji.v5.ux.core.base.widget + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import dji.v5.utils.common.LogUtils +import dji.v5.ux.core.base.WidgetSizeDescription +import io.reactivex.rxjava3.disposables.CompositeDisposable +import io.reactivex.rxjava3.disposables.Disposable + +/** + * 集成于view的widget,需要自习实现绘制 + * Copyright (c) 2021, DJI All Rights Reserved. + */ +abstract class ViewWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : View(context, attrs, defStyleAttr) { + + protected val logTag = LogUtils.getTag(this) + //region Fields + private var reactionDisposables: CompositeDisposable? = null + private var compositeDisposable: CompositeDisposable? = null + + //endregion + + //region Constructor + init { + initView(context, attrs, defStyleAttr) + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (isInEditMode) { + return + } + reactionDisposables = CompositeDisposable() + compositeDisposable = CompositeDisposable() + reactToModelChanges() + } + + override fun onDetachedFromWindow() { + unregisterReactions() + disposeAll() + super.onDetachedFromWindow() + } + + /** + * Invoked during the initialization of the class. + * Inflate should be done here. For Kotlin, load attributes, findViewById should be done in + * the init block. + * + * @param context Context + * @param attrs Attribute set + * @param defStyleAttr Style attribute + */ + protected abstract fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) + + /** + * Call addReaction here to bind to the model. + */ + protected abstract fun reactToModelChanges() + + /** + * Add a disposable which is automatically disposed with the view's lifecycle. + * + * @param disposable the disposable to add + */ + protected fun addDisposable(disposable: Disposable) { + compositeDisposable?.add(disposable) + } + //endregion + + //region Customization + /** + * Ideal dimension ratio in the format width:height. + * + * @return dimension ratio string. + */ + abstract fun getIdealDimensionRatioString(): String? + + /** + * Ideal widget size. + * By default the widget size is a ratio + */ + open val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.RATIO) + //endregion + + //region Reactions + /** + * Add a reaction which is automatically disposed with the view's lifecycle. + * + * @param reaction the reaction to add. + */ + protected fun addReaction(reaction: Disposable) { + checkNotNull(reactionDisposables) { "Called this method only from reactToModelChanges." } + reactionDisposables?.add(reaction) + } + + private fun unregisterReactions() { + reactionDisposables?.dispose() + reactionDisposables = null + + } + + private fun disposeAll() { + compositeDisposable?.dispose() + compositeDisposable = null + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/BroadcastValues.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/BroadcastValues.java new file mode 100644 index 00000000..2e5adb38 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/BroadcastValues.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.communication; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +/** + * This is a wrapper class used by the UXKey system to + * propagate the previous value and current value of a given + * key to its observers + */ +public class BroadcastValues { + private final ModelValue previousValue; + private final ModelValue currentValue; + + public BroadcastValues(@Nullable ModelValue previousValue, @NonNull ModelValue currentValue) { + this.previousValue = previousValue; + this.currentValue = currentValue; + } + + public ModelValue getPreviousValue() { + return previousValue; + } + + public ModelValue getCurrentValue() { + return currentValue; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/CameraKeys.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/CameraKeys.java new file mode 100644 index 00000000..aa1e3426 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/CameraKeys.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.communication; + +/** + * Class containing all UX keys related to camera functions + */ +public final class CameraKeys extends UXKeys { + + @UXParamKey(type = Integer.class, updateType = UpdateType.ON_CHANGE) + public static final String PEAK_THRESHOLD = "PeakThreshold"; + + private CameraKeys() { + super(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/DefaultGlobalPreferences.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/DefaultGlobalPreferences.kt new file mode 100644 index 00000000..b09be5d5 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/DefaultGlobalPreferences.kt @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.communication + +import android.content.Context +import android.content.SharedPreferences +import android.graphics.Color +import androidx.annotation.ColorInt +import androidx.core.content.edit +import dji.v5.ux.core.ui.CenterPointView +import dji.v5.ux.core.ui.GridLineView.GridLineType +import dji.v5.ux.core.util.SettingDefinitions +import dji.v5.ux.core.util.UnitConversionUtil + + +/** + * Default implementation of the GlobalPreferencesInterface using SharedPreferences. + * These settings will persist across app restarts. + */ +class DefaultGlobalPreferences(context: Context) : GlobalPreferencesInterface { + + private val sharedPreferences: SharedPreferences = getSharedPreferences(context) + + override fun setUpListener() { //Do nothing + } + + override fun cleanup() { //Do nothing + } + + override var unitType: UnitConversionUtil.UnitType + get() = UnitConversionUtil.UnitType.find(sharedPreferences.getInt(PREF_GLOBAL_UNIT_TYPE, + UnitConversionUtil.UnitType.METRIC.value())) + set(unitType) = sharedPreferences.edit { putInt(PREF_GLOBAL_UNIT_TYPE, unitType.value()) } + + override var temperatureUnitType: UnitConversionUtil.TemperatureUnitType + get() = UnitConversionUtil.TemperatureUnitType.find(sharedPreferences.getInt(PREF_TEMPERATURE_UNIT_TYPE, + UnitConversionUtil.UnitType.METRIC.value())) + set(temperatureUnit) = sharedPreferences.edit { putInt(PREF_TEMPERATURE_UNIT_TYPE, temperatureUnit.value()) } + + + @Suppress("INAPPLICABLE_JVM_NAME") + @get:JvmName("getAFCEnabled") + @set:JvmName("setAFCEnabled") + override var afcEnabled: Boolean + get() = sharedPreferences.getBoolean(PREF_IS_AFC_ENABLED, true) + set(enabled) = sharedPreferences.edit { putBoolean(PREF_IS_AFC_ENABLED, enabled) } + + override var isAirSenseTermsNeverShown: Boolean + get() = sharedPreferences.getBoolean(PREF_AIR_SENSE_TERMS_NEVER_SHOWN, false) + set(neverShown) = + sharedPreferences.edit { putBoolean(PREF_AIR_SENSE_TERMS_NEVER_SHOWN, neverShown) } + + override var gridLineType: GridLineType + get() = GridLineType.find(sharedPreferences.getInt(PREF_GRID_LINE_TYPE, + GridLineType.NONE.value)) + set(gridLineType) = + sharedPreferences.edit { putInt(PREF_GRID_LINE_TYPE, gridLineType.value) } + + + override var centerPointType: CenterPointView.CenterPointType + get() = CenterPointView.CenterPointType.find(sharedPreferences.getInt(PREF_CENTER_POINT_TYPE, + CenterPointView.CenterPointType.NONE.value)) + set(centerPointType) = + sharedPreferences.edit { putInt(PREF_CENTER_POINT_TYPE, centerPointType.value) } + + @get:ColorInt + @setparam:ColorInt + override var centerPointColor: Int + get() = sharedPreferences.getInt(PREF_CENTER_POINT_COLOR, Color.WHITE) + set(centerPointColor) = + sharedPreferences.edit { putInt(PREF_CENTER_POINT_COLOR, centerPointColor) } + + override var controlMode: SettingDefinitions.ControlMode + get() = SettingDefinitions.ControlMode.find(sharedPreferences.getInt(PREF_CONTROL_MODE, + SettingDefinitions.ControlMode.SPOT_METER.value())) + set(controlMode) = sharedPreferences.edit { putInt(PREF_CONTROL_MODE, controlMode.value()) } + + override var isUnitModeDialogNeverShown: Boolean + get() = sharedPreferences.getBoolean(PREF_UNIT_MODE_DIALOG_NEVER_SHOWN, false) + set(neverShown) = + sharedPreferences.edit { putBoolean(PREF_UNIT_MODE_DIALOG_NEVER_SHOWN, neverShown) } + + companion object { + //region Constants + private const val PREF_IS_AFC_ENABLED: String = "afcEnabled" + private const val PREF_GLOBAL_UNIT_TYPE: String = "globalUnitType" + private const val PREF_TEMPERATURE_UNIT_TYPE: String = "temperatureUnitType" + private const val PREF_AIR_SENSE_TERMS_NEVER_SHOWN: String = "airSenseTerms" + private const val PREF_GRID_LINE_TYPE: String = "gridLineType" + private const val PREF_CENTER_POINT_TYPE: String = "centerPointType" + private const val PREF_CENTER_POINT_COLOR: String = "centerPointColor" + private const val PREF_CONTROL_MODE: String = "controlMode" + private const val PREF_UNIT_MODE_DIALOG_NEVER_SHOWN: String = "unitMode" + private fun getSharedPreferences(context: Context): SharedPreferences = + context.getSharedPreferences(context.packageName, Context.MODE_PRIVATE) + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/FlatStore.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/FlatStore.java new file mode 100644 index 00000000..78a95f37 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/FlatStore.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.communication; + +import androidx.annotation.NonNull; + +import java.util.concurrent.ConcurrentHashMap; + +/** + * This class is responsible for the underlying storage for UXKeys + */ +public class FlatStore { + private static final int INITIAL_CAPACITY = 100; + private final ConcurrentHashMap store; + + private FlatStore() { + store = new ConcurrentHashMap<>(INITIAL_CAPACITY); + } + + public static FlatStore getInstance() { + return SingletonHolder.instance; + } + + /** + * Update and store the given value for the given key + * + * @param value ModelValue to be stored for key + * @param keyPath UXKey path to be used for storing this value + */ + public void setModelValue(@NonNull ModelValue value, @NonNull String keyPath) { + store.put(keyPath, value); + } + + /** + * Get the current value for the given key + * + * @param keyPath UXKey path to be used to retrieve value + * @return ModelValue store for the given key + */ + public ModelValue getModelValue(@NonNull String keyPath) { + return store.get(keyPath); + } + + private static class SingletonHolder { + private static FlatStore instance = new FlatStore(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/GlobalPreferenceKeys.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/GlobalPreferenceKeys.java new file mode 100644 index 00000000..a7143e00 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/GlobalPreferenceKeys.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.communication; + +import dji.v5.ux.core.util.SettingDefinitions; +import dji.v5.ux.core.util.UnitConversionUtil; + +/** + * Class containing UXKeys related to global preferences + */ +public final class GlobalPreferenceKeys extends UXKeys { + @UXParamKey(type = UnitConversionUtil.UnitType.class, updateType = UpdateType.ON_CHANGE) + public static final String UNIT_TYPE = "UnitType"; + + @UXParamKey(type = Boolean.class, updateType = UpdateType.ON_CHANGE) + public static final String AFC_ENABLED = "AFCEnabled"; + +// @UXParamKey(type = ColorWaveformSettings.ColorWaveformDisplayState.class, updateType = UpdateType.ON_CHANGE) +// public static final String COLOR_WAVEFORM_DISPLAY_STATE = "ColorWaveformDisplayState"; + + @UXParamKey(type = Boolean.class, updateType = UpdateType.ON_CHANGE) + public static final String COLOR_WAVEFORM_ENABLED = "ColorWaveformEnabled"; + + @UXParamKey(type = SettingDefinitions.ControlMode.class, updateType = UpdateType.ON_CHANGE) + public static final String CONTROL_MODE = "ControlMode"; + + @UXParamKey(type = UnitConversionUtil.TemperatureUnitType.class, updateType = UpdateType.ON_CHANGE) + public static final String TEMPERATURE_UNIT_TYPE = "TemperatureUnitType"; + + @UXParamKey(type = Boolean.class, updateType = UpdateType.ON_EVENT) + public static final String GIMBAL_ADJUST_CLICKED = "gimbalAdujustClicled"; + + private GlobalPreferenceKeys() { + super(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/GlobalPreferencesInterface.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/GlobalPreferencesInterface.kt new file mode 100644 index 00000000..3600d940 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/GlobalPreferencesInterface.kt @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.communication + +import androidx.annotation.ColorInt +import dji.v5.ux.core.ui.CenterPointView.CenterPointType +import dji.v5.ux.core.ui.GridLineView.GridLineType +import dji.v5.ux.core.util.SettingDefinitions.ControlMode +import dji.v5.ux.core.util.UnitConversionUtil.TemperatureUnitType +import dji.v5.ux.core.util.UnitConversionUtil.UnitType + + +/** + * Interface to be implemented for functions included under + * global preferences. These settings will persist across app restarts. + */ +interface GlobalPreferencesInterface { + /** + * Set up the listeners for the global preferences interface + */ + fun setUpListener() + + /** + * Clean up the listeners for the global preferences interface + */ + fun cleanup() + + //region global Settings interface + /** + * [UnitType] value saved. + */ + var unitType: UnitType + + /** + * [TemperatureUnitType] value saved. + */ + var temperatureUnitType: TemperatureUnitType + + /** + * Boolean value indicating if AFC is enabled if saved. + */ + @Suppress("INAPPLICABLE_JVM_NAME") + @get:JvmName("getAFCEnabled") + @set:JvmName("setAFCEnabled") + var afcEnabled: Boolean + + /** + * Boolean value indicating if the AirSense terms should never be shown. + */ + var isAirSenseTermsNeverShown: Boolean + + /** + * [GridLineType] for the grid line overlay. + */ + var gridLineType: GridLineType + + /** + * Center Point Type from [CenterPointType] + */ + var centerPointType: CenterPointType + + /** + * Center point color int + */ + @get:ColorInt + @setparam:ColorInt + var centerPointColor: Int + + /** + * Control mode from [ControlMode] + */ + var controlMode: ControlMode + + /** + * Boolean value indicating if the Unit Mode dialog should never be shown. + */ + var isUnitModeDialogNeverShown: Boolean + //endregion +} + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/GlobalPreferencesManager.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/GlobalPreferencesManager.java new file mode 100644 index 00000000..a5c45818 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/GlobalPreferencesManager.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.communication; + +import androidx.annotation.NonNull; + +/** + * Class used for initializing and getting an instance of the implementation + * of {@link GlobalPreferencesInterface} being used. + */ +public final class GlobalPreferencesManager { + //region Fields + private static GlobalPreferencesInterface instance = null; + //endregion + + private GlobalPreferencesManager() { + //Empty + } + + /** + * This function is used to get an instance of the implementation of the + * {@link GlobalPreferencesManager} using the {@link GlobalPreferencesInterface}. + * + * @return instance An instance of the class implementing the {@link GlobalPreferencesInterface}. + */ + public static GlobalPreferencesInterface getInstance() { + synchronized (GlobalPreferencesManager.class) { + return instance; + } + } + + /** + * This function is used to initialize the {@link GlobalPreferencesManager} with an + * implementation of the {@link GlobalPreferencesInterface}. This can be the default built in + * {@link DefaultGlobalPreferences} or a custom class that implements the + * {@link GlobalPreferencesInterface}. This must be called before initializing any widgets that + * use this. + * + * @param preferencesManager An instance of the class implementing the + * {@link GlobalPreferencesInterface}. + */ + public static void initialize(@NonNull GlobalPreferencesInterface preferencesManager) { + instance = preferencesManager; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/MessagingKeys.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/MessagingKeys.java new file mode 100644 index 00000000..73294e41 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/MessagingKeys.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.communication; + +import dji.v5.ux.core.model.VoiceNotificationType; +import dji.v5.ux.core.model.WarningMessage; + +/** + * Class containing UXKeys related to sending messages + */ +public final class MessagingKeys extends UXKeys { + @UXParamKey(type = WarningMessage.class, updateType = UpdateType.ON_CHANGE) + public static final String SEND_WARNING_MESSAGE = "SendWarningMessage"; + + @UXParamKey(type = VoiceNotificationType.class, updateType = UpdateType.ON_CHANGE) + public static final String SEND_VOICE_NOTIFICATION = "SendVoiceNotification"; + + private MessagingKeys() { + super(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/ModelValue.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/ModelValue.java new file mode 100644 index 00000000..dbdb06b7 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/ModelValue.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.communication; + +import java.util.Arrays; + +import androidx.annotation.Nullable; +import dji.v5.utils.common.LogUtils; + +/** + * This is a wrapper class used by the UXKey system to + * propagate data of `Object` type through to the users + */ +public class ModelValue { + + private static final String TAG = "ModelValue"; + private final Object data; + + public ModelValue(@Nullable Object data) { + this.data = data; + } + + public Object getData() { + return data; + } + + @Override + public int hashCode() { + return data != null ? data.hashCode() : 0; + } + + @Override + public boolean equals(Object o) { + //True if both o and data are null, false otherwise + if (o == null && data == null) { + return true; + } else if (o != null && data != null) { + if (data.getClass().isArray() && o.getClass().isArray()) { + return arrayEquals(data, o); + } else { + if (o instanceof ModelValue) { + return o.equals(data); + } + } + } + return false; + } + + private boolean arrayEquals(Object a, Object b) { + boolean returnEqual = false; + if (a.getClass() == int[].class) { + returnEqual = Arrays.equals((int[]) a, (int[]) b); + } else if (a.getClass() == boolean[].class) { + returnEqual = Arrays.equals((boolean[]) a, (boolean[]) b); + } else if (a.getClass() == byte[].class) { + returnEqual = Arrays.equals((byte[]) a, (byte[]) b); + } else if (a.getClass() == char[].class) { + returnEqual = Arrays.equals((char[]) a, (char[]) b); + } else if (a.getClass() == long[].class) { + returnEqual = Arrays.equals((long[]) a, (long[]) b); + } else if (a.getClass() == short[].class) { + returnEqual = Arrays.equals((short[]) a, (short[]) b); + } else if (a.getClass() == float[].class) { + returnEqual = Arrays.equals((float[]) a, (float[]) b); + } else if (a.getClass() == double[].class) { + returnEqual = Arrays.equals((double[]) a, (double[]) b); + } else { + try { + returnEqual = Arrays.equals((Object[]) a, (Object[]) b); + } catch (Exception e) { + LogUtils.e(TAG, e.getMessage()); + } + } + return returnEqual; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/ObservableInMemoryKeyedStore.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/ObservableInMemoryKeyedStore.java new file mode 100644 index 00000000..34b06b55 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/ObservableInMemoryKeyedStore.java @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.communication; + +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantLock; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import dji.v5.ux.core.base.SchedulerProvider; +import dji.v5.ux.core.base.UXSDKError; +import dji.v5.ux.core.base.UXSDKErrorDescription; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.processors.PublishProcessor; + +/** + * `ObservableInMemoryKeyedStore` provides access to the keyed interface using `UXKeys` and + * corresponding subclass objects. It implements the ObservableKeyedStore interface. + */ +public class ObservableInMemoryKeyedStore implements ObservableKeyedStore { + private static final int INITIAL_CAPACITY = 100; + private final ConcurrentHashMap> keyStringProcessorMap; + private final FlatStore store; + + private final Lock lock = new ReentrantLock(); + + private ObservableInMemoryKeyedStore() { + keyStringProcessorMap = new ConcurrentHashMap<>(INITIAL_CAPACITY); + store = FlatStore.getInstance(); + //Initialize any internal default UXKey classes here + UXKeys.addNewKeyClass(GlobalPreferenceKeys.class); + UXKeys.addNewKeyClass(MessagingKeys.class); + } + + public static ObservableInMemoryKeyedStore getInstance() { + return SingletonHolder.instance; + } + + /** + * Adds an observer object which will receive all changes of value for the given key. + * + * @param key A valid UXKey + * @return A flowable that emits BroadcastValues based on the given key. + * This flowable can be used to subscribe to the keys as required. + */ + @Override + @NonNull + public Flowable addObserver(@NonNull UXKey key) { + lock.lock(); + try { + PublishProcessor processor = keyStringProcessorMap.get(key.getKeyPath()); + if (processor == null) { + processor = PublishProcessor.create(); + } + keyStringProcessorMap.put(key.getKeyPath(), processor); + return processor.observeOn(SchedulerProvider.computation()).onBackpressureLatest(); + } finally { + lock.unlock(); + } + } + + /** + * Removes the observer object for the given key so it no longer receives updates + * + * @param disposable Disposable used for observing key values + * @param key A valid UXKey + */ + @Override + public void removeObserver(@NonNull Disposable disposable, @NonNull UXKey key) { + if (!disposable.isDisposed()) { + disposable.dispose(); + } + } + + /** + * Removes the subscription to updates for all observers of a specific key value. + * Does not affect the observers of any other key. + * + * @param key A valid UXKey + */ + @Override + public void removeAllObserversForKey(@NonNull UXKey key) { + lock.lock(); + try { + PublishProcessor removedProcessor = keyStringProcessorMap.remove(key.getKeyPath()); + if (removedProcessor != null){ + removedProcessor.onComplete(); + } + } finally { + lock.unlock(); + } + } + + /** + * Stops the subscription to updates for all observers of all key values. + * There will be no active observers on any key after this function is called. + */ + @Override + public void removeAllObservers() { + lock.lock(); + try { + for (PublishProcessor processorToRemove : keyStringProcessorMap.values()) { + processorToRemove.onComplete(); + } + keyStringProcessorMap.clear(); + } finally { + lock.unlock(); + } + } + + /** + * Performs a get on a UXKey and returns the latest known value for the key + * if available, null otherwise. + * + * @param key A valid UXKey + * @return Object value for the key if available, null otherwise. + */ + @Override + @Nullable + public Object getValue(@NonNull UXKey key) { + lock.lock(); + try { + //This function will return the value or return null if it doesn't + //have a reference to the key - it should not have any other errors. + ModelValue value = store.getModelValue(key.getKeyPath()); + if (value != null) { + return value.getData(); + } else { + return null; + } + } finally { + lock.unlock(); + } + } + + /** + * Performs a set on a UXKey, changing the value for the key. + * + * @param key A valid settable key + * @param value A value object relevant to the given key + * @return Completable which indicates success or error setting the value. + */ + @Override + @NonNull + public Completable setValue(@NonNull UXKey key, @NonNull Object value) { + lock.lock(); + try { + return Completable.create(emitter -> { + if (value.getClass().equals(key.getValueType())) { + ModelValue previousValue = store.getModelValue(key.getKeyPath()); + if (key.getUpdateType() == UXKeys.UpdateType.ON_EVENT || + (key.getUpdateType() == UXKeys.UpdateType.ON_CHANGE && + (previousValue == null || !previousValue.getData().equals(value)))) { + ModelValue currentValue = new ModelValue(value); + store.setModelValue(currentValue, key.getKeyPath()); + if (keyStringProcessorMap.containsKey(key.getKeyPath())) { + PublishProcessor processor = keyStringProcessorMap.get(key.getKeyPath()); + if (processor != null){ + processor.onNext(new BroadcastValues(previousValue, currentValue)); + } + } + } + emitter.onComplete(); + } else { + emitter.onError(new UXSDKError(UXSDKErrorDescription.FACTORY.build(UXSDKErrorDescription.VALUE_TYPE_MISMATCH))); + } + }).subscribeOn(SchedulerProvider.computation()); + } finally { + lock.unlock(); + } + } + + private static class SingletonHolder { + private static final ObservableInMemoryKeyedStore instance = new ObservableInMemoryKeyedStore(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/ObservableKeyedStore.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/ObservableKeyedStore.java new file mode 100644 index 00000000..a145c972 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/ObservableKeyedStore.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.communication; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.disposables.Disposable; + +public interface ObservableKeyedStore { + /** + * Adds an observer object which will receive all changes of value for the given key. + * + * @param key A valid UXKey + * @return A flowable that emits BroadcastValues based on the given key. + * This flowable can be used to subscribe to the keys as required. + */ + @NonNull + Flowable addObserver(@NonNull UXKey key); + + /** + * Removes the observer object for the given key so it no longer receives updates + * + * @param disposable Disposable used for observing key values + * @param key A valid UXKey + */ + void removeObserver(@NonNull Disposable disposable, @NonNull UXKey key); + + /** + * Removes the subscription to updates for all observers of a specific key value. + * Does not affect the observers of any other key. + * receive any further updates for this key + * + * @param key A valid UXKey + */ + void removeAllObserversForKey(@NonNull UXKey key); + + /** + * Stops the subscription to updates for all observers of all key values. + * There will be no active observers on any key after this function is called. + */ + void removeAllObservers(); + + /** + * Performs a get on a UXKey and returns the latest known value for the key + * if available, null otherwise. + * + * @param key A valid UXKey + * @return Object value for the key if available, null otherwise. + */ + @Nullable + Object getValue(@NonNull UXKey key); + + /** + * Performs a set on a UXKey, changing the value for the key. + * + * @param key A valid settable key + * @param value A value object relevant to the given key + * @return Completable which indicates success or error setting the value. + */ + @NonNull + Completable setValue(@NonNull UXKey key, Object value); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/OnStateChangeCallback.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/OnStateChangeCallback.kt new file mode 100644 index 00000000..3a4a1186 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/OnStateChangeCallback.kt @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.communication + +/** + * Interface to be implemented by widgets for coupled 1:1 communication + */ +interface OnStateChangeCallback { + + /** + * Called when the state has changed + */ + fun onStateChange(state: T?) +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/UXKey.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/UXKey.java new file mode 100644 index 00000000..6756e873 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/UXKey.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.communication; + +import androidx.annotation.NonNull; + +/** + * This is a class to define a UXKey. + *

+ * String key: String value of UXParamKey as defined in its parent class + * Class valueType: Type of value this key will take for setting or return + * to getters and observers. + * String keyString: The full path of this key used for storage which includes + * the index of the component. + * UpdateType updateType: The update type of this key. + */ +public class UXKey { + private final String key; + private final Class valueType; + private final String keyPath; + private final UXKeys.UpdateType updateType; + + public UXKey(@NonNull String key, @NonNull Class valueType, @NonNull String keyPath, @NonNull UXKeys.UpdateType updateType) { + this.key = key; + this.valueType = valueType; + this.keyPath = keyPath; + this.updateType = updateType; + } + + public String getKey() { + return key; + } + + public Class getValueType() { + return valueType; + } + + public String getKeyPath() { + return keyPath; + } + + public UXKeys.UpdateType getUpdateType() { + return updateType; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/UXKeys.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/UXKeys.java new file mode 100644 index 00000000..fd46be47 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/communication/UXKeys.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.communication; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import androidx.annotation.CheckResult; +import androidx.annotation.NonNull; +import dji.v5.utils.common.LogUtils; + + +/** + * This class is used to create valid UX keys from given String UXParamKeys and indices. + * This class can be extended by any subclasses to define custom UX keys. + */ +public class UXKeys { + private static final String TAG = "UXKeys"; + private final static int DEFAULT_INDEX = 0; + private static final Map keysPathMap = new ConcurrentHashMap<>(); + private static final Map> keyValueMap = new ConcurrentHashMap<>(); + private static final Map keyUpdateTypeMap = new ConcurrentHashMap<>(); + + protected UXKeys() { + //Do Nothing + } + + private static void initializeKeyValueTypes(Class clazz) { + if (clazz == null) return; + Field[] fields = clazz.getFields(); + for (Field field : fields) { + if (field.getType() == String.class && isStatic(field.getModifiers()) && (field.isAnnotationPresent( + UXParamKey.class))) { + try { + String paramKey = (String) field.get(null); + UXParamKey paramKeyAnnotation = field.getAnnotation(UXParamKey.class); + if (paramKey != null && paramKeyAnnotation != null) { + addKeyValueTypeToMap(paramKey, paramKeyAnnotation.type()); + addKeyUpdateTypeToMap(paramKey, paramKeyAnnotation.updateType()); + } + } catch (Exception e) { + LogUtils.e(TAG, e.getMessage()); + } + } + } + } + + /** + * Use this function to initialize any classes containing UXParamKeys + * + * @param componentClass Class which extends the `UXKeys` class and contains UXParamKeys + */ + public static void addNewKeyClass(@NonNull Class componentClass) { + initializeKeyValueTypes(componentClass); + } + + /** + * This functions allows creation of a UXKey using a param key (String) + * + * @param key String param key with UXParamKey annotation defined in class UXKeys or its children + * @return UXKey if value-type of key has been registered - null otherwise + */ + public static UXKey create(@NonNull String key) { + return create(key, DEFAULT_INDEX); + } + + /** + * This functions allows creation of a UXKey using a param key (String) and an index (int) + * + * @param key String param key with UXParamKey annotation defined in class UXKeys or its children + * @param index Index of the component the key is being created for - default is 0 + * @return UXKey if value-type of key has been registered - null otherwise + */ + @CheckResult + public static UXKey create(@NonNull String key, int index) { + String keyPath = producePathFromElements(key, index); + UXKey uxKey = getCache(keyPath); + if (uxKey == null) { + Class valueType = keyValueMap.get(key); + UpdateType updateType = keyUpdateTypeMap.get(key); + if (valueType != null && updateType != null) { + uxKey = new UXKey(key, valueType, keyPath, updateType); + putCache(keyPath, uxKey); + } + } + return uxKey; + } + + /** + * Use this function to initialize any custom keys created + * + * @param key String key with UXParamKey annotation to be initialized + * @param valueType Non-primitive class value-type of the key to be initialized (eg. Integer, Boolean etc) + */ + private static void addKeyValueTypeToMap(@NonNull String key, @NonNull Class valueType) { + keyValueMap.put(key, valueType); + } + + private static void addKeyUpdateTypeToMap(@NonNull String key, @NonNull UpdateType updateType) { + keyUpdateTypeMap.put(key, updateType); + } + + private static String producePathFromElements(@NonNull String param, int index) { + return param + "/" + index; + } + + private static UXKey getCache(String keyStr) { + if (keyStr != null) { + return keysPathMap.get(keyStr); + } else { + return null; + } + } + + private static void putCache(String keyStr, UXKey key) { + if (keyStr != null && key != null) { + keysPathMap.put(keyStr, key); + } + } + + private static boolean isStatic(int modifiers) { + return ((modifiers & Modifier.STATIC) != 0); + } + + public enum UpdateType { + /** + * The key will update its listeners only when there is a change in the value + */ + ON_CHANGE, + + /** + * The key will update its listeners every time a value is received + */ + ON_EVENT + } + + @Retention(RetentionPolicy.RUNTIME) + @Target({ElementType.FIELD, ElementType.PARAMETER}) + protected @interface UXParamKey { + /** + * The type of param that the method associated to this key will take or return + * + * @return The class type of the param + */ + @NonNull Class type(); + + /** + * The update type of this key. + * + * @return UpdateType type for this key. + */ + @NonNull UpdateType updateType(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/extension/AnimationExtensions.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/extension/AnimationExtensions.kt new file mode 100644 index 00000000..c1255419 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/extension/AnimationExtensions.kt @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.extension + +import android.view.animation.Animation + +/** + * Add a listener to this Animation using the provided actions. + * + * @return the [Animation.AnimationListener] added to the Animation + */ +inline fun Animation.addListener( + crossinline onEnd: (animation: Animation) -> Unit = {}, + crossinline onStart: (animation: Animation) -> Unit = {}, + crossinline onRepeat: (animation: Animation) -> Unit = {} +): Animation.AnimationListener { + val listener = object : Animation.AnimationListener { + override fun onAnimationRepeat(animation: Animation) = onRepeat(animation) + override fun onAnimationEnd(animation: Animation) = onEnd(animation) + override fun onAnimationStart(animation: Animation) = onStart(animation) + } + setAnimationListener(listener) + return listener +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/extension/CameraExtensions.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/extension/CameraExtensions.kt new file mode 100644 index 00000000..44deb77c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/extension/CameraExtensions.kt @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +@file:JvmName("CameraExtensions") + +package dji.v5.ux.core.extension + +import dji.sdk.keyvalue.value.camera.CameraFlatMode +import dji.sdk.keyvalue.value.camera.CameraMode +import dji.sdk.keyvalue.value.camera.CameraShootPhotoMode + +/** + * Convert [CameraFlatMode] to [CameraShootPhotoMode] + */ +fun CameraMode.toShootPhotoMode(): CameraShootPhotoMode { + return when (this) { + CameraMode.PHOTO_NORMAL -> CameraShootPhotoMode.NORMAL + CameraMode.PHOTO_INTERVAL -> CameraShootPhotoMode.INTERVAL + CameraMode.PHOTO_HYPER_LIGHT -> CameraShootPhotoMode.HYPER_LIGHT + CameraMode.PHOTO_PANORAMA -> CameraShootPhotoMode.VISION_PANO + CameraMode.PHOTO_SUPER_RESOLUTION -> CameraShootPhotoMode.PANO_APP + else -> CameraShootPhotoMode.UNKNOWN + } +} + +/** + * Convert [CameraShootPhotoMode] to [CameraFlatMode] + */ +fun CameraShootPhotoMode.toFlatCameraMode(): CameraFlatMode { + return when (this) { + CameraShootPhotoMode.NORMAL -> CameraFlatMode.PHOTO_NORMAL + CameraShootPhotoMode.HDR -> CameraFlatMode.PHOTO_HDR + CameraShootPhotoMode.BURST -> CameraFlatMode.PHOTO_BURST + CameraShootPhotoMode.AEB -> CameraFlatMode.PHOTO_AEB + CameraShootPhotoMode.INTERVAL -> CameraFlatMode.PHOTO_INTERVAL + CameraShootPhotoMode.VISION_PANO -> CameraFlatMode.PHOTO_PANO + CameraShootPhotoMode.EHDR -> CameraFlatMode.PHOTO_EHDR + CameraShootPhotoMode.HYPER_LIGHT -> CameraFlatMode.PHOTO_HYPERLIGHT + else -> CameraFlatMode.UNKNOWN + } +} + +/** + * Check if flat camera mode is picture mode + */ +fun CameraMode.isPictureMode(): Boolean { + return this == CameraMode.PHOTO_NORMAL + || this == CameraMode.PHOTO_INTERVAL + || this == CameraMode.PHOTO_HYPER_LIGHT + || this == CameraMode.PHOTO_PANORAMA + || this == CameraMode.PHOTO_SUPER_RESOLUTION +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/extension/ContextExt.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/extension/ContextExt.kt new file mode 100644 index 00000000..2a143459 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/extension/ContextExt.kt @@ -0,0 +1,24 @@ +package dji.v5.ux.core.extension + +import android.content.Context +import android.graphics.Point +import android.util.Size +import android.view.WindowManager + +/** + * 获取横屏的屏幕 + */ +fun Context.getLandScreenSize(): Size { + val windowManager = getSystemService(Context.WINDOW_SERVICE) as WindowManager + + var screenWidth: Int + var screenHeight: Int + + val display = windowManager.defaultDisplay + val outSize = Point() + display.getRealSize(outSize) + screenWidth = if (outSize.x > outSize.y) outSize.x else outSize.y + screenHeight = if (outSize.x > outSize.y) outSize.y else outSize.x + + return Size(screenWidth, screenHeight) +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/extension/MathExtensions.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/extension/MathExtensions.kt new file mode 100644 index 00000000..98c55cb6 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/extension/MathExtensions.kt @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +@file:JvmName("MathExtensions") + +package dji.v5.ux.core.extension + +import dji.v5.ux.core.util.UnitConversionUtil +import dji.v5.ux.core.util.UnitConversionUtil.UnitType + +/** + * Convert milliVolts to Volts + */ +fun Float.milliVoltsToVolts(): Float = this / 1000f + +/** + * Convert velocity to appropriate value by unit + */ +fun Float.toVelocity(unitType: UnitType): Float { + return if (unitType == UnitType.IMPERIAL) { + UnitConversionUtil.convertMetersPerSecToMilesPerHr(this) + } else this +} + +fun Double.toVelocity(unitType: UnitType): Double { + return if (unitType == UnitType.IMPERIAL) { + UnitConversionUtil.convertMetersPerSecToMilesPerHr(this) + } else this +} + +/** + * Convert distance to appropriate value by unit + */ +fun Float.toDistance(unitType: UnitType): Float { + return if (unitType == UnitType.IMPERIAL) { + UnitConversionUtil.convertMetersToFeet(this) + } else this +} + +/** + * Convert distance to appropriate value by unit + */ +fun Double.toDistance(unitType: UnitType): Double { + return if (unitType == UnitType.IMPERIAL) { + UnitConversionUtil.convertMetersToFeet(this) + } else this +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/extension/TypedArrayExtensions.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/extension/TypedArrayExtensions.kt new file mode 100644 index 00000000..bb5a1534 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/extension/TypedArrayExtensions.kt @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +@file:JvmName("TypedArrayExtensions") + +package dji.v5.ux.core.extension + +import android.content.res.ColorStateList +import android.content.res.TypedArray +import android.graphics.drawable.Drawable +import androidx.annotation.StyleableRes + +const val INVALID_RESOURCE = -1 +const val INVALID_DIMENSION = -1f +const val INVALID_STRING = "" + +/** + * Retrieve the string value for the attribute at [index]. + * Returns the found value or [defValue] if not found. + */ +fun TypedArray.getString(@StyleableRes index: Int, defValue: String): String = + getString(index) ?: defValue + +/** + * Retrieve the string value for the attribute at [index] and executes the given [block] + * function with the retrieved resource. + * + * @see TypedArray.getString + */ +inline fun TypedArray.getStringAndUse(@StyleableRes index: Int, block: (String) -> R) { + val string = getString(index, INVALID_STRING) + if (string != INVALID_STRING) { + block(string) + } +} + +/** + * Retrieve the color value for the attribute at [index] and executes the given [block] + * function with the retrieved resource. + * + * @see TypedArray.getColor + */ +inline fun TypedArray.getColorAndUse(@StyleableRes index: Int, block: (Int) -> R) { + val colorInt = getColor(index, INVALID_RESOURCE) + if (colorInt != INVALID_RESOURCE) { + block(colorInt) + } +} + +/** + * Retrieve the color state list value for the attribute at [index] and executes the given [block] + * function with the retrieved resource. + * + * @see TypedArray.getColorStateList + */ +inline fun TypedArray.getColorStateListAndUse(@StyleableRes index: Int, block: (ColorStateList) -> R) { + val colorStateList = getColorStateList(index) + colorStateList?.let { block(it) } +} + +/** + * Retrieve the dimension value for the attribute at [index] and executes the given [block] + * function with the retrieved resource. + * + * @see TypedArray.getDimension + */ +inline fun TypedArray.getDimensionAndUse(@StyleableRes index: Int, block: (Float) -> R) { + val dimension = getDimension(index, INVALID_DIMENSION) + if (dimension != INVALID_DIMENSION) { + block(dimension) + } +} + +/** + * Retrieve the drawable for the attribute at [index] and executes the given [block] + * function with the retrieved resource. + * + * @see TypedArray.getDrawable + */ +inline fun TypedArray.getDrawableAndUse(@StyleableRes index: Int, block: (Drawable) -> R) { + val drawable = getDrawable(index) + drawable?.let { block(drawable) } +} + +/** + * Retrieve the int value for the attribute at [index] and executes the given [block] + * function with the retrieved resource. + * + * @see TypedArray.getDrawable + */ +inline fun TypedArray.getIntAndUse(@StyleableRes index: Int, block: (Int) -> R) { + val int = getInt(index, INVALID_RESOURCE) + if (int != INVALID_RESOURCE) { + block(int) + } +} + +/** + * Retrieve the resource identifier for the attribute at [index] and executes the given [block] + * function with the retrieved resource. + * + * @see TypedArray.getResourceId + */ +inline fun TypedArray.getResourceIdAndUse(@StyleableRes index: Int, block: (Int) -> R) { + val resourceId = getResourceId(index, INVALID_RESOURCE) + if (resourceId != INVALID_RESOURCE) { + block(resourceId) + } +} + +/** + * Retrieve the float value for the attribute at [index] and executes the given [block] + * function with the retrieved resource. + * + * @see TypedArray.getResourceId + */ +inline fun TypedArray.getFloatAndUse(@StyleableRes index: Int, block: (Float) -> R) { + val floatValue = getFloat(index, INVALID_DIMENSION) + if (floatValue != INVALID_DIMENSION) { + block(floatValue) + } +} + +/** + * Retrieve the integer value for the attribute at [index] and executes the given [block] + * function with the retrieved resource. + * + * @see TypedArray.getResourceId + */ +inline fun TypedArray.getIntegerAndUse(@StyleableRes index: Int, block: (Int) -> R) { + val intValue = getInteger(index, INVALID_RESOURCE) + if (intValue != INVALID_RESOURCE) { + block(intValue) + } +} + +/** + * Retrieve the integer value for the attribute at [index] and executes the given [block] + * function with the retrieved resource or the [defaultValue]. + * + * @see TypedArray.getResourceId + */ +inline fun TypedArray.getBooleanAndUse(@StyleableRes index: Int, defaultValue: Boolean, block: (Boolean) -> R) { + val booleanValue = getBoolean(index, defaultValue) + block(booleanValue) +} + +/** + * Retrieve the drawable array value for the attribute at [index] and executes the given [block] + * function with the retrieved resource. + */ +inline fun TypedArray.getDrawableArrayAndUse(@StyleableRes index: Int, block: (Array) -> R) { + val arrayResourceId = getResourceId(index, INVALID_RESOURCE) + if (arrayResourceId != INVALID_RESOURCE) { + val resourceArray = resources.obtainTypedArray(arrayResourceId) + val drawableArray = Array(resourceArray.length()) { i -> + resourceArray.getDrawable(i) + } + block(drawableArray) + resourceArray.recycle() + } +} + + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/extension/ViewExtensions.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/extension/ViewExtensions.kt new file mode 100644 index 00000000..ad484d06 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/extension/ViewExtensions.kt @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +@file:JvmName("ViewExtensions") + +package dji.v5.ux.core.extension + +import android.content.DialogInterface +import android.content.res.ColorStateList +import android.graphics.drawable.ColorDrawable +import android.graphics.drawable.Drawable +import android.graphics.drawable.LayerDrawable +import android.os.Build +import android.util.SparseLongArray +import android.view.View +import android.widget.Button +import android.widget.ImageView +import android.widget.TextView +import android.widget.Toast +import androidx.annotation.* +import androidx.appcompat.app.AlertDialog +import androidx.recyclerview.widget.RecyclerView +import dji.v5.ux.R +import dji.v5.ux.core.util.UnitConversionUtil.UnitType + + +/** + * Get the [String] for the given [stringRes]. + */ +fun View.getString(@StringRes stringRes: Int, vararg value: Any): String = context.resources.getString(stringRes, *value) + +/** + * Get the [Drawable] for the given [drawableRes]. + */ +fun View.getDrawable(@DrawableRes drawableRes: Int): Drawable = context.resources.getDrawable(drawableRes) + +/** + * The the color int for the given [colorRes]. + */ +@ColorInt +fun View.getColor(@ColorRes colorRes: Int): Int = context.resources.getColor(colorRes) + +/** + * The the px size for the given [dimenRes]. + */ +@Px +fun View.getDimension(@DimenRes dimenRes: Int): Float = context.resources.getDimension(dimenRes) + +/** + * Set the view [View.VISIBLE]. + */ +fun View.show() { + visibility = View.VISIBLE +} + +/** + * Set the view [View.GONE]. + */ +fun View.hide() { + visibility = View.GONE +} + +/** + * Toggle the view between [View.GONE] and [View.VISIBLE] + */ +fun View.toggleVisibility() { + if (visibility == View.VISIBLE) hide() + else show() +} + +/** + * Show a short length toast with the given [messageResId]. + */ +fun View.showShortToast(@StringRes messageResId: Int) { + Toast.makeText( + context, + messageResId, + Toast.LENGTH_SHORT + ) + .show() +} + +/** + * Show a long length toast with the given [messageResId]. + */ +fun View.showLongToast(@StringRes messageResId: Int) { + Toast.makeText( + context, + messageResId, + Toast.LENGTH_LONG + ) + .show() +} + +/** + * Show a short length toast with the given [String]. + */ +fun View.showShortToast(message: String?) { + Toast.makeText( + context, + message, + Toast.LENGTH_SHORT + ) + .show() +} + +/** + * Show a long length toast with the given [String]. + */ +fun View.showLongToast(message: String?) { + Toast.makeText( + context, + message, + Toast.LENGTH_LONG + ) + .show() +} + +/** + * The [TextView]'s text color int. + */ +var TextView.textColor: Int + @ColorInt + get() = this.currentTextColor + set(@ColorInt value) { + this.setTextColor(value) + } + +/** + * The [TextView]'s text color state list. + */ +var TextView.textColorStateList: ColorStateList? + get() = this.textColors + set(value) { + this.setTextColor(value) + } + +/** + * The [ImageView]'s drawable. + */ +var ImageView.imageDrawable: Drawable? + get() = this.drawable + set(value) { + this.setImageDrawable(value) + } + +/** + * Show an alert dialog. + * @param dialogTheme The style of the dialog + * @param isCancellable Dismiss the dialog when touch outside its bounds + * @param title Dialog title text + * @param icon Dialog title icon + * @param message Dialog message + * @param dismissButton Dismiss button text + * @param dialogClickListener + */ +fun View.showAlertDialog( + @StyleRes dialogTheme: Int = com.airbnb.lottie.R.style.Theme_AppCompat_Dialog, + title: String? = getString(R.string.uxsdk_alert), + icon: Drawable? = null, + message: String? = null, + dismissButton: String? = getString(R.string.uxsdk_app_ok), + dialogClickListener: DialogInterface.OnClickListener? = null, + dialogDismissListener: DialogInterface.OnDismissListener? = null, +) { + val builder = AlertDialog.Builder(context, dialogTheme) + builder.setTitle(title) + builder.setIcon(icon) + builder.setCancelable(true) + builder.setMessage(message) + builder.setPositiveButton(dismissButton, dialogClickListener) + builder.setOnDismissListener(dialogDismissListener) + val dialog = builder.create() + dialog.show() +} + +/** + * Show an alert dialog. + * @param dialogTheme The style of the dialog + * @param isCancellable Dismiss the dialog when touch outside its bounds + * @param title Dialog title text + * @param icon Dialog title icon + * @param message Dialog message + * @param positiveButton Positive button text + * @param negativeButton Negative button text + * @param dialogClickListener + */ +fun View.showConfirmationDialog( + @StyleRes dialogTheme: Int = com.airbnb.lottie.R.style.Theme_AppCompat_Dialog, + title: String? = getString(R.string.uxsdk_alert), + icon: Drawable? = null, + message: String? = null, + dialogClickListener: DialogInterface.OnClickListener? = null, + dialogDismissListener: DialogInterface.OnDismissListener? = null, +) { + val builder = AlertDialog.Builder(context, dialogTheme) + builder.setIcon(icon) + builder.setTitle(title) + builder.setCancelable(true) + builder.setMessage(message) + builder.setPositiveButton(getString(R.string.uxsdk_app_ok), dialogClickListener) + builder.setNegativeButton(getString(R.string.uxsdk_app_cancel), dialogClickListener) + builder.setOnDismissListener(dialogDismissListener) + val dialog = builder.create() + dialog.show() +} + +/** + * Get the unit string for velocity based on [UnitType] + */ +fun View.getVelocityString(unitType: UnitType): String { + return if (unitType == UnitType.IMPERIAL) { + getString(R.string.uxsdk_unit_mile_per_hr) + } else { + getString(R.string.uxsdk_unit_meter_per_second) + } +} + +/** + * Get the unit string for distance based on [UnitType] + */ +fun View.getDistanceString(unitType: UnitType): String { + return if (unitType == UnitType.IMPERIAL) { + getString(R.string.uxsdk_unit_feet) + } else { + getString(R.string.uxsdk_unit_meters) + } +} + +/** + * Set the border to a view. + * The extension creates a layered background which can be used to set up a border to the view. + * + * @param backgroundColor - The color for the solid background. + * @param borderColor - The color for the border for the view. + * @param leftBorder - The size of the left border. + * @param topBorder - The size of the top border. + * @param rightBorder - The size of the right border. + * @param bottomBorder - The size of the bottom border. + * + */ +fun View.setBorder( + @ColorInt backgroundColor: Int = getColor(R.color.uxsdk_transparent), + @ColorInt borderColor: Int = getColor(R.color.uxsdk_transparent), + leftBorder: Int = 0, + topBorder: Int = 0, + rightBorder: Int = 0, + bottomBorder: Int = 0, +) { + val borderColorDrawable = ColorDrawable(borderColor) + val backgroundColorDrawable = ColorDrawable(backgroundColor) + + // Initialize a new array of drawable objects + val drawables = arrayOf(borderColorDrawable, backgroundColorDrawable) + + // Initialize a new layer drawable instance from drawables array + val layerDrawable = LayerDrawable(drawables) + + // Set padding for background color layer + layerDrawable.setLayerInset( + 1, // Index of the drawable to adjust [background color layer] + leftBorder, // Number of pixels to add to the left bound [left border] + topBorder, // Number of pixels to add to the top bound [top border] + rightBorder, // Number of pixels to add to the right bound [right border] + bottomBorder // Number of pixels to add to the bottom bound [bottom border] + ) + this.background = layerDrawable + +} + +/** + * On click listener for recycler view. + */ +fun T.listen(event: (position: Int) -> Unit): T { + itemView.setOnClickListener { + event.invoke(adapterPosition) + } + return this +} + +const val TRANSITION_OFFSET = 80 +private const val FAST_CLICK_DURATION = 300 +private val sClickTimes: SparseLongArray = SparseLongArray() + +/** + * 判断是否点击过快 + * @param viewId + * @param duration + * @return + */ +fun Button.isFastClick(duration: Int): Boolean { + val prevTime: Long = sClickTimes.get(this.id) + val now = System.currentTimeMillis() + val isFast = now - prevTime < duration + if (!isFast) { + sClickTimes.put(this.id, now) + } + return isFast +} + +/** + * 判断是否点击过快 + * @param viewId + * @return + */ +fun Button.isFastClick(): Boolean { + return isFastClick(FAST_CLICK_DURATION) +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/model/VoiceNotificationType.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/model/VoiceNotificationType.kt new file mode 100644 index 00000000..ab03e135 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/model/VoiceNotificationType.kt @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +package dji.v5.ux.core.model + +import androidx.annotation.RawRes +import dji.v5.ux.R + +/** + * Enum represents voice notification type + */ +enum class VoiceNotificationType(@param:RawRes private val resId: Int) { + + /** + * Notification of attitude mode + */ + ATTI(R.raw.uxsdk_tips_voice_atti_mode); + + @RawRes + fun value(): Int { + return resId + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/model/WarningMessage.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/model/WarningMessage.java new file mode 100644 index 00000000..75e50f7d --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/model/WarningMessage.java @@ -0,0 +1,548 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.model; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.Objects; + +/** + * The class represents warning messages. + * The messages will guide the user through the flight. + */ +public class WarningMessage { + + private static final int DEFAULT_DISPLAY_DURATION = 5; + + /** + * Warning levels for warning message + */ + public enum Level { + /** + * Message is a notification + */ + NOTIFY(0), + + /** + * Message is a warning + */ + WARNING(1), + + /** + * Message implies dangerous condition + */ + DANGEROUS(2); + + private int value; + + Level(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + private static Level[] values; + + public static Level[] getValues() { + if (values == null) { + values = values(); + } + return values; + } + + public static Level find(int value) { + for (Level item : getValues()) { + if (item.getValue() == value) { + return item; + } + } + return NOTIFY; + } + } + + /** + * Type of message behavior + */ + public enum Type { + + /** + * Message will auto disappear from the screen + * after the number of seconds specified by showDuration. + */ + AUTO_DISAPPEAR(0), + + /** + * Message stays until a removal message is sent. + */ + PUSH(1), + + /** + * Message will be pinned above other messages and will + * have a close button to dismiss it. + */ + PINNED(2), + + /** + * Message will be pinned above other messages and cannot + * be dismissed by user. + */ + PINNED_NOT_CLOSE(3); + + private int value; + + Type(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + private static Type[] values; + + public static Type[] getValues() { + if (values == null) { + values = values(); + } + return values; + } + + public static Type find(int value) { + for (Type item : getValues()) { + if (item.getValue() == value) { + return item; + } + } + return AUTO_DISAPPEAR; + } + } + + /** + * Action for warning message + */ + public enum Action { + /** + * Insert warning message + */ + INSERT, + + /** + * Remove warning message + */ + REMOVE + } + + /** + * The type of the warning message component + */ + public enum WarningType { + /** + * Air 1860 + */ + AIR1860(0), + + /** + * Battery + */ + BATTERY(1), + + /** + * Camera + */ + CAMERA(2), + + /** + * Center board + */ + CENTER_BOARD(3), + + /** + * OSD + */ + OSD(4), + + /** + * Flight Controller + */ + FLIGHT_CONTROLLER(5), + + /** + * Gimbal + */ + GIMBAL(6), + + /** + * Lightbridge + */ + LIGHT_BRIDGE(7), + + /** + * Remote controller + */ + REMOTE_CONTROLLER(8), + + /** + * Vision + */ + VISION(9), + + /** + * Flight record + */ + FLIGHT_RECORD(10), + + /** + * Fly safe + */ + FLY_SAFE(11), + + /** + * RTK + */ + RTK(12), + + /** + * LTE + */ + LTE(13), + + /** + * Other + */ + OTHER(100); + + private int value; + + WarningType(int value) { + this.value = value; + } + + public int getValue() { + return value; + } + + private static WarningType[] values; + + public static WarningType[] getValues() { + if (values == null) { + values = values(); + } + return values; + } + + public static WarningType find(int value) { + for (WarningType item : getValues()) { + if (item.getValue() == value) { + return item; + } + } + return OTHER; + } + } + + private WarningType warningType; + private int code; + private int subCode; + private int componentIndex; + private String reason; + private String solution; + private Level level = Level.WARNING; + private Type type = Type.AUTO_DISAPPEAR; + private Action action = Action.INSERT; + private int showDuration = DEFAULT_DISPLAY_DURATION; + private int iconRes; + + private WarningMessage(@Nullable WarningType type, @Nullable String reason, @Nullable String solution) { + this.reason = reason; + this.solution = solution; + this.code = WarningType.OTHER.getValue(); + this.subCode = WarningMessageError.CUSTOMER_USE_ERROR.value(); + this.warningType = type; + if (this.reason != null) { + this.code = this.reason.hashCode(); + } + if (this.solution != null) { + this.code = this.code + this.solution.hashCode(); + } + } + + public WarningMessage(@Nullable WarningType warningType, int code, int subCode, @Nullable String reason, @Nullable String solution) { + this(warningType, code, subCode, 0, reason, solution); + } + + public WarningMessage(@Nullable WarningType warningType, int code, int subCode, int componentIndex, @Nullable String reason, @Nullable String solution) { + this.warningType = warningType; + this.code = code; + this.subCode = subCode; + this.componentIndex = componentIndex; + this.reason = reason; + this.solution = solution; + } + + @Nullable + public WarningType getWarningType() { + return warningType; + } + + public void setWarningType(@Nullable WarningType type) { + this.warningType = type; + } + + public int getCode() { + return code; + } + + public void setSubCode(int subCode) { + this.subCode = subCode; + } + + public int getSubCode() { + return subCode; + } + + public void setCode(int code) { + this.code = code; + } + + public int getComponentIndex() { + return componentIndex; + } + + public void setComponentIndex(int componentIndex) { + this.componentIndex = componentIndex; + } + + @Nullable + public String getReason() { + return reason; + } + + public void setReason(@Nullable String reason) { + this.reason = reason; + } + + @Nullable + public String getSolution() { + return solution; + } + + public void setSolution(@Nullable String solution) { + this.solution = solution; + } + + @Nullable + public Level getLevel() { + return level; + } + + public void setLevel(@Nullable Level level) { + this.level = level; + } + + @Nullable + public Type getType() { + return type; + } + + public void setType(@Nullable Type type) { + this.type = type; + } + + public int getShowDuration() { + return showDuration; + } + + public void setShowDuration(int showDuration) { + this.showDuration = showDuration; + } + + @Nullable + public Action getAction() { + return action; + } + + public void setAction(@Nullable Action action) { + this.action = action; + } + + public int getIconRes() { + return iconRes; + } + + public void setIconRes(int iconRes) { + this.iconRes = iconRes; + } + + @Override + @NonNull + public String toString() { + return "WarningMessage{" + + "WarningType=" + + (warningType == null ? "is null" : warningType.name()) + + ", code=" + + code + + ", subCode=" + + subCode + + ", componentIndex=" + + componentIndex + + ", reason='" + + reason + + '\'' + + ", solution='" + + solution + + '\'' + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + WarningMessage that = (WarningMessage) o; + + if (warningType != that.warningType) return false; + if (code != that.code) return false; + if (subCode != that.subCode) return false; + if (componentIndex != that.componentIndex) return false; + if (!Objects.equals(reason, that.reason)) return false; + return Objects.equals(solution, that.solution); + } + + @Override + public int hashCode() { + int result = code; + result = 31 * result + subCode; + result = 31 * result + (warningType == null ? 0 : warningType.getValue()); + result = 31 * result + componentIndex; + result = 31 * result + (reason != null ? reason.hashCode() : 0); + result = 31 * result + (solution != null ? solution.hashCode() : 0); + return result; + } + + public static class Builder { + private WarningType warningType; + private int code; + private int subCode; + private int componentIndex; + private String reason; + private String solution; + private Level level = Level.WARNING; + private Type type = Type.AUTO_DISAPPEAR; + private Action action = Action.INSERT; + private int showDuration = DEFAULT_DISPLAY_DURATION; + private int iconRes; + + public Builder(@Nullable WarningType warningType) { + this.warningType = warningType; + } + + @NonNull + public Builder code(int code) { + this.code = code; + return this; + } + + @NonNull + public Builder warningType(@Nullable WarningType warningType) { + this.warningType = warningType; + return this; + } + + @NonNull + public Builder subCode(int subCode) { + this.subCode = subCode; + return this; + } + + @NonNull + public Builder componentIndex(int componentIndex) { + this.componentIndex = componentIndex; + return this; + } + + @NonNull + public Builder reason(@Nullable String reason) { + this.reason = reason; + return this; + } + + @NonNull + public Builder solution(@Nullable String solution) { + this.solution = solution; + return this; + } + + @NonNull + public Builder level(@Nullable Level level) { + this.level = level; + return this; + } + + @NonNull + public Builder type(@Nullable Type type) { + this.type = type; + return this; + } + + @NonNull + public Builder showDuration(int showDuration) { + this.showDuration = showDuration; + return this; + } + + @NonNull + public Builder action(@Nullable Action action) { + this.action = action; + return this; + } + + @NonNull + public Builder iconRes(int iconRes) { + this.iconRes = iconRes; + return this; + } + + @NonNull + public WarningMessage build() { + WarningMessage warningMessage = new WarningMessage(warningType, reason, solution); + if (this.code != -1) { + warningMessage.setCode(this.code); + } + warningMessage.setSubCode(this.subCode); + warningMessage.setLevel(this.level); + warningMessage.setType(this.type); + warningMessage.setComponentIndex(this.componentIndex); + warningMessage.setShowDuration(this.showDuration); + warningMessage.setAction(this.action); + warningMessage.setIconRes(iconRes); + + return warningMessage; + } + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/model/WarningMessageError.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/model/WarningMessageError.java new file mode 100644 index 00000000..97bc263f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/model/WarningMessageError.java @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.model; + +/** + * {@link WarningMessage} errors + */ +public enum WarningMessageError { + + /** + * Vision/Obstacle avoidance sensor message + */ + VISION_AVOID(1004), + + /** + * There are aircraft in vicinity + */ + OTHER_AIRCRAFT_NEARBY(1022), + + /** + * Error due to customer use + */ + CUSTOMER_USE_ERROR(10000), + + /** + * Unknown error + */ + UNKNOWN(0); + + private int value; + + WarningMessageError(int value) { + this.value = value; + } + + public int value() { + return this.value; + } + + private boolean _equals(int b) { + return value == b; + } + + private static WarningMessageError[] values; + + public static WarningMessageError[] getValues() { + if (values == null) { + values = values(); + } + return values; + } + + public static WarningMessageError find(int b) { + WarningMessageError result = UNKNOWN; + for (int i = 0; i < getValues().length; i++) { + if (getValues()[i]._equals(b)) { + result = getValues()[i]; + break; + } + } + return result; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/module/FlatCameraModule.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/module/FlatCameraModule.kt new file mode 100644 index 00000000..0151e021 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/module/FlatCameraModule.kt @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.module + +import dji.sdk.keyvalue.key.CameraKey +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.value.camera.CameraMode +import dji.sdk.keyvalue.value.camera.CameraShootPhotoMode +import dji.sdk.keyvalue.value.common.CameraLensType +import dji.sdk.keyvalue.value.common.ComponentIndexType +import dji.v5.ux.core.base.BaseModule +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.ICameraIndex +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.extension.isPictureMode +import dji.v5.ux.core.extension.toShootPhotoMode +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Completable + +/** + * Abstraction for getting and setting camera mode and photo mode. + */ +class FlatCameraModule : BaseModule(), ICameraIndex { + + //region Fields + private val isFlatCameraModeSupportedDataProcessor: DataProcessor = DataProcessor.create(false) + private var cameraIndex = ComponentIndexType.LEFT_OR_MAIN + private var lensType = CameraLensType.CAMERA_LENS_ZOOM + + /** + * The camera mode. + */ + val cameraModeDataProcessor: DataProcessor = DataProcessor.create( + CameraMode.UNKNOWN) + + /** + * The shoot photo mode. + */ + val shootPhotoModeProcessor: DataProcessor = DataProcessor.create(CameraShootPhotoMode.UNKNOWN) + //endregion + + //region Lifecycle + override fun setup(widgetModel: WidgetModel) { + bindDataProcessor(widgetModel, KeyTools.createKey( + CameraKey.KeyCameraMode, cameraIndex), cameraModeDataProcessor) + bindDataProcessor(widgetModel, KeyTools.createKey( + CameraKey.KeyShootPhotoMode, cameraIndex), shootPhotoModeProcessor) + val isFlatCameraModeSupportedKey = KeyTools.createKey( + CameraKey.KeyCameraFlatModeSupported, cameraIndex) + bindDataProcessor(widgetModel, isFlatCameraModeSupportedKey, isFlatCameraModeSupportedDataProcessor) + } + + override fun cleanup() { + // no code + } + //endregion + + //region Actions + /** + * Set camera mode + * + * @return Completable + */ + fun setCameraMode(djiSdkModel: DJISDKModel, cameraMode: CameraMode): Completable { + return djiSdkModel.setValue( + KeyTools.createKey( + CameraKey.KeyCameraMode, cameraIndex), cameraMode); + } + + override fun getCameraIndex() = cameraIndex + + override fun getLensType() = lensType + + override fun updateCameraSource(cameraIndex: ComponentIndexType, lensType: CameraLensType) { + this.cameraIndex = cameraIndex + this.lensType = lensType + } + + //region Helpers + private fun updateModes(flatCameraMode: CameraMode) { + cameraModeDataProcessor.onNext( + if (flatCameraMode.isPictureMode()) { + CameraMode.PHOTO_NORMAL + } else { + CameraMode.VIDEO_NORMAL + } + ) + shootPhotoModeProcessor.onNext(flatCameraMode.toShootPhotoMode()) + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/aircraftbatterytemperature/AircraftBatteryTemperatureListItemWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/aircraftbatterytemperature/AircraftBatteryTemperatureListItemWidget.kt new file mode 100644 index 00000000..a66dcd03 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/aircraftbatterytemperature/AircraftBatteryTemperatureListItemWidget.kt @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.aircraftbatterytemperature + +import android.content.Context +import android.util.AttributeSet +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.panel.listitem.ListItemLabelButtonWidget +import dji.v5.ux.core.communication.GlobalPreferencesManager +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getColor +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.panel.listitem.aircraftbatterytemperature.AircraftBatteryTemperatureListItemWidgetModel.AircraftBatteryTemperatureItemState +import dji.v5.ux.core.panel.listitem.aircraftbatterytemperature.AircraftBatteryTemperatureListItemWidgetModel.AircraftBatteryTemperatureItemState.AircraftBatteryState +import dji.v5.ux.core.panel.listitem.aircraftbatterytemperature.AircraftBatteryTemperatureListItemWidgetModel.AircraftBatteryTemperatureItemState.ProductDisconnected +import dji.v5.ux.core.util.UnitConversionUtil.TemperatureUnitType.* + +/** + * Aircraft battery temperature list item + * + */ +open class AircraftBatteryTemperatureListItemWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ListItemLabelButtonWidget( + context, + attrs, + defStyleAttr, + WidgetType.LABEL, + R.style.UXSDKAircraftBatteryTemperatureListItem +) { + + private val widgetModel by lazy { + AircraftBatteryTemperatureListItemWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + GlobalPreferencesManager.getInstance() + ) + } + + override fun reactToModelChanges() { + addReaction(widgetModel.aircraftBatteryTemperatureState + .observeOn(SchedulerProvider.ui()) + .subscribe { this.updateUI(it) }) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun getIdealDimensionRatioString(): String? = null + + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription( + WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP + ) + + private fun updateUI(aircraftBatteryTemperatureItemState: AircraftBatteryTemperatureItemState) { + when (aircraftBatteryTemperatureItemState) { + is ProductDisconnected -> { + isEnabled = false + listItemLabelTextColor = disconnectedValueColor + listItemLabel = resources.getString(R.string.uxsdk_string_default_value) + } + is AircraftBatteryState -> { + listItemLabelTextColor = getColor(R.color.uxsdk_white) + listItemLabel = when (aircraftBatteryTemperatureItemState.unitType) { + CELSIUS -> getString(R.string.uxsdk_celsius_unit, aircraftBatteryTemperatureItemState.temperature) + FAHRENHEIT -> getString(R.string.uxsdk_celsius_unit, aircraftBatteryTemperatureItemState.temperature) + KELVIN -> getString(R.string.uxsdk_celsius_unit, aircraftBatteryTemperatureItemState.temperature) + } + } + } + + } + + override fun onButtonClick() { + // No code needed + } + + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/aircraftbatterytemperature/AircraftBatteryTemperatureListItemWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/aircraftbatterytemperature/AircraftBatteryTemperatureListItemWidgetModel.kt new file mode 100644 index 00000000..33e7a240 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/aircraftbatterytemperature/AircraftBatteryTemperatureListItemWidgetModel.kt @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.aircraftbatterytemperature + +import dji.sdk.keyvalue.key.BatteryKey +import dji.sdk.keyvalue.key.KeyTools +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.GlobalPreferenceKeys +import dji.v5.ux.core.communication.GlobalPreferencesInterface +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.panel.listitem.aircraftbatterytemperature.AircraftBatteryTemperatureListItemWidgetModel.AircraftBatteryTemperatureItemState.AircraftBatteryState +import dji.v5.ux.core.panel.listitem.aircraftbatterytemperature.AircraftBatteryTemperatureListItemWidgetModel.AircraftBatteryTemperatureItemState.ProductDisconnected +import dji.v5.ux.core.util.DataProcessor +import dji.v5.ux.core.util.UnitConversionUtil +import dji.v5.ux.core.util.UnitConversionUtil.TemperatureUnitType +import dji.v5.ux.core.util.UnitConversionUtil.TemperatureUnitType.* + + +/** + * Widget Model for the [AircraftBatteryTemperatureListItemWidget] used to define + * the underlying logic and communication + */ +class AircraftBatteryTemperatureListItemWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, + private val preferencesManager: GlobalPreferencesInterface? +) : WidgetModel(djiSdkModel, keyedStore) { + + //region Fields + + private val batteryTemperatureStateProcessor: DataProcessor = DataProcessor.create(ProductDisconnected) + private val batteryTemperatureProcessor: DataProcessor = DataProcessor.create(0.0) + private val temperatureUnitTypeProcessor: DataProcessor = DataProcessor.create(CELSIUS) + + //endregion + + //region Data + /** + * Get the aircraft battery temperature state + */ + val aircraftBatteryTemperatureState: Flowable + get() = batteryTemperatureStateProcessor.toFlowable() + + //endregion + + //region Lifecycle + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyBatteryTemperature), batteryTemperatureProcessor) + val temperatureUnitTypeKey = GlobalPreferenceKeys.create(GlobalPreferenceKeys.TEMPERATURE_UNIT_TYPE) + bindDataProcessor(temperatureUnitTypeKey, temperatureUnitTypeProcessor) + preferencesManager?.setUpListener() + } + + override fun inCleanup() { + preferencesManager?.cleanup() + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + val temperatureValue = when (temperatureUnitTypeProcessor.value) { + CELSIUS -> batteryTemperatureProcessor.value + FAHRENHEIT -> UnitConversionUtil.celsiusToFahrenheit(batteryTemperatureProcessor.value) + KELVIN -> UnitConversionUtil.celsiusToKelvin(batteryTemperatureProcessor.value) + } + batteryTemperatureStateProcessor.onNext(AircraftBatteryState(temperatureValue, temperatureUnitTypeProcessor.value)) + } else { + batteryTemperatureStateProcessor.onNext(ProductDisconnected) + } + + } + + /** + * Class to represent states of AircraftBatteryItem + */ + sealed class AircraftBatteryTemperatureItemState { + /** + * When product is disconnected + */ + object ProductDisconnected : AircraftBatteryTemperatureItemState() + + /** + * When product is connected and battery temperature is received. + */ + data class AircraftBatteryState(val temperature: Double, val unitType: TemperatureUnitType) : AircraftBatteryTemperatureItemState() + } +} +//endregion \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/emmcstatus/EMMCStatusListItemWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/emmcstatus/EMMCStatusListItemWidget.kt new file mode 100644 index 00000000..2ad6a6cc --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/emmcstatus/EMMCStatusListItemWidget.kt @@ -0,0 +1,346 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.emmcstatus + +import android.annotation.SuppressLint +import android.content.Context +import android.content.DialogInterface +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import androidx.annotation.StyleRes +import androidx.core.content.res.use +import dji.sdk.keyvalue.value.camera.CameraSDCardState +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.UXSDKError +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.panel.listitem.ListItemLabelButtonWidget +import dji.v5.ux.core.base.panel.listitem.ListItemLabelButtonWidget.UIState.* +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.panel.listitem.emmcstatus.EMMCStatusListItemWidget.DialogType.* +import dji.v5.ux.core.panel.listitem.emmcstatus.EMMCStatusListItemWidget.ModelState +import dji.v5.ux.core.panel.listitem.emmcstatus.EMMCStatusListItemWidget.ModelState.ProductConnected +import dji.v5.ux.core.util.UnitConversionUtil.getSpaceWithUnit + + +/** + * eMMC status list item + * + * It displays the remaining capacity of the eMMC (internal storage) along with + * any warnings / errors related to the eMMC. + * It provides a button to format eMMC. + */ +open class EMMCStatusListItemWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ListItemLabelButtonWidget( + context, + attrs, + defStyleAttr, + WidgetType.LABEL_BUTTON, + R.style.UXSDKEMMCStatusListItem +) { + + //region Fields + /** + * Theme for the dialogs shown for format + */ + @StyleRes + var dialogTheme: Int = R.style.UXSDKDialogTheme + + /** + * Icon for the dialog which shows format confirmation message + */ + var formatConfirmationDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_alert_yellow) + + /** + * Icon for the dialog which shows format success message + */ + var formatSuccessDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_alert_good) + + /** + * Icon for the dialog which shows format error message + */ + var formatErrorDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_alert_error) + + private val widgetModel: EMMCStatusListItemWidgetModel by lazy { + EMMCStatusListItemWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()) + } + //endregion + + //region Constructor + init { + initAttributes(context, attrs) + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + + override fun reactToModelChanges() { + addReaction(widgetModel.eMMCState + .observeOn(SchedulerProvider.ui()) + .subscribe { this.updateUI(it) }) + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + } + + override fun onButtonClick() { + val dialogListener = DialogInterface.OnClickListener { dialogInterface, buttonId: Int -> + if (buttonId == DialogInterface.BUTTON_POSITIVE) { + uiUpdateStateProcessor.onNext(DialogActionConfirmed(FormatConfirmation)) + formatEMMC() + } else if (buttonId == DialogInterface.BUTTON_NEGATIVE) { + uiUpdateStateProcessor.onNext(DialogActionCanceled(FormatConfirmation)) + } + dialogInterface.dismiss() + + } + val dialogDismissListener = DialogInterface.OnDismissListener { + uiUpdateStateProcessor.onNext(DialogDismissed(FormatConfirmation)) + } + + showConfirmationDialog(title = getString(R.string.uxsdk_emmc_dialog_title), + icon = formatConfirmationDialogIcon, + dialogTheme = dialogTheme, + message = getString(R.string.uxsdk_emmc_format_confirmation), + dialogClickListener = dialogListener, + dialogDismissListener = dialogDismissListener) + uiUpdateStateProcessor.onNext(DialogDisplayed(FormatConfirmation)) + } + //endregion + + //region Reaction to model + private fun updateUI(eMMCState: EMMCStatusListItemWidgetModel.EMMCState) { + widgetStateDataProcessor.onNext(ModelState.EMMCStateUpdated(eMMCState)) + when (eMMCState) { + EMMCStatusListItemWidgetModel.EMMCState.ProductDisconnected, + EMMCStatusListItemWidgetModel.EMMCState.NotSupported -> updateDisabledState(eMMCState) + is EMMCStatusListItemWidgetModel.EMMCState.CurrentEMMCState -> { + isEnabled = true + listItemLabel = getEMMCMessage(eMMCState.eMMCOperationState, + eMMCState.remainingSpace) + listItemLabelTextColor = getEMMCMessageColor(eMMCState.eMMCOperationState) + listItemButtonEnabled = getFormatButtonVisibility(eMMCState.eMMCOperationState) + } + } + } + + private fun updateDisabledState(eMMCState: EMMCStatusListItemWidgetModel.EMMCState) { + listItemLabel = if (eMMCState is EMMCStatusListItemWidgetModel.EMMCState.ProductDisconnected) { + getString(R.string.uxsdk_string_default_value) + } else { + getString(R.string.uxsdk_storage_status_not_supported) + } + listItemLabelTextColor = if (eMMCState is EMMCStatusListItemWidgetModel.EMMCState.ProductDisconnected) { + disconnectedValueColor + } else { + errorValueColor + } + isEnabled = false + } + //endregion + + //region private helpers + private fun formatEMMC() { + var dialogType: DialogType? = null + val dialogDismissListener = DialogInterface.OnDismissListener { + uiUpdateStateProcessor.onNext(DialogDismissed(dialogType)) + } + addDisposable(widgetModel.formatEMMC() + .observeOn(SchedulerProvider.ui()) + .subscribe({ + dialogType = FormatSuccess + showAlertDialog(title = getString(R.string.uxsdk_emmc_dialog_title), + icon = formatSuccessDialogIcon, + dialogTheme = dialogTheme, + message = getString(R.string.uxsdk_emmc_format_complete), + dialogDismissListener = dialogDismissListener) + uiUpdateStateProcessor.onNext(DialogDisplayed(dialogType)) + }) { error -> + if (error is UXSDKError) { + dialogType = FormatError + showAlertDialog( + title = getString(R.string.uxsdk_emmc_dialog_title), + icon = formatErrorDialogIcon, + dialogTheme = dialogTheme, + message = getString(R.string.uxsdk_emmc_format_error, error.djiError.description()), + dialogDismissListener = dialogDismissListener + ) + uiUpdateStateProcessor.onNext(DialogDisplayed(dialogType)) + } + }) + + } + + private fun getFormatButtonVisibility(eMMCOperationState: CameraSDCardState): Boolean { + return when (eMMCOperationState) { + CameraSDCardState.NORMAL, + CameraSDCardState.FORMAT_RECOMMENDED, + CameraSDCardState.FULL, + CameraSDCardState.SLOW, + CameraSDCardState.WRITING_SLOWLY, + CameraSDCardState.INVALID_FILE_SYSTEM, + CameraSDCardState.FORMAT_NEEDED -> true + else -> false + } + } + + private fun getEMMCMessageColor(eMMCOperationState: CameraSDCardState): Int { + return when (eMMCOperationState) { + CameraSDCardState.NORMAL -> normalValueColor + else -> warningValueColor + } + } + + private fun getEMMCMessage(eMMCOperationState: CameraSDCardState, + space: Int): String? { + return when (eMMCOperationState) { + CameraSDCardState.NORMAL -> getSpaceWithUnit(context, space) + CameraSDCardState.NOT_INSERTED -> getString(R.string.uxsdk_storage_status_missing) + CameraSDCardState.INVALID -> getString(R.string.uxsdk_storage_status_invalid) + CameraSDCardState.READ_ONLY -> getString(R.string.uxsdk_storage_status_write_protect) + CameraSDCardState.INVALID_FILE_SYSTEM, + CameraSDCardState.FORMAT_NEEDED -> getString(R.string.uxsdk_storage_status_needs_formatting) + CameraSDCardState.FORMATTING -> getString(R.string.uxsdk_storage_status_formatting) + CameraSDCardState.BUSY -> getString(R.string.uxsdk_storage_status_busy) + CameraSDCardState.FULL -> getString(R.string.uxsdk_storage_status_full) + CameraSDCardState.SLOW -> getString(R.string.uxsdk_storage_status_slow, getSpaceWithUnit(context, space)) + CameraSDCardState.NO_REMAINING_FILE_INDICES -> getString(R.string.uxsdk_storage_status_file_indices) + CameraSDCardState.INITIALIZING -> getString(R.string.uxsdk_storage_status_initial) + CameraSDCardState.FORMAT_RECOMMENDED -> getString(R.string.uxsdk_storage_status_formatting_recommended) + CameraSDCardState.RECOVERING_FILES -> getString(R.string.uxsdk_storage_status_recover_file) + CameraSDCardState.WRITING_SLOWLY -> getString(R.string.uxsdk_storage_status_write_slow) + CameraSDCardState.USB_CONNECTED -> getString(R.string.uxsdk_storage_status_usb_connected) + CameraSDCardState.UNKNOWN_ERROR -> getString(R.string.uxsdk_storage_status_unknown_error) + CameraSDCardState.UNKNOWN -> getString(R.string.uxsdk_string_default_value) + } + + } + //endregion + + //region Customization + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP) + + override fun getIdealDimensionRatioString(): String? { + return null + } + + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet?) { + context.obtainStyledAttributes(attrs, R.styleable.EMMCStatusListItemWidget, 0, defaultStyle).use { typedArray -> + typedArray.getDrawableAndUse(R.styleable.EMMCStatusListItemWidget_uxsdk_list_item_confirmation_dialog_icon) { + formatConfirmationDialogIcon = it + } + typedArray.getDrawableAndUse(R.styleable.EMMCStatusListItemWidget_uxsdk_list_item_success_dialog_icon) { + formatSuccessDialogIcon = it + } + typedArray.getDrawableAndUse(R.styleable.EMMCStatusListItemWidget_uxsdk_list_item_error_dialog_icon) { + formatErrorDialogIcon = it + } + typedArray.getResourceIdAndUse(R.styleable.EMMCStatusListItemWidget_uxsdk_list_item_dialog_theme) { + dialogTheme = it + } + + } + } + //endregion + + //region Hooks + /** + * Get the [ListItemLabelButtonWidget.UIState] updates + * The info parameter is instance of [DialogType] + */ + override fun getUIStateUpdates(): Flowable { + return uiUpdateStateProcessor.onBackpressureBuffer() + } + + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * eMMC List Item Dialog Identifiers + */ + sealed class DialogType { + /** + * Dialog shown for format confirmation + */ + object FormatConfirmation : DialogType() + + /** + * Dialog shown for format success + */ + object FormatSuccess : DialogType() + + /** + * Dialog shown for format fail + */ + object FormatError : DialogType() + } + + /** + * Class defines widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Current eMMC List Item State + */ + data class EMMCStateUpdated(val eMMCState: EMMCStatusListItemWidgetModel.EMMCState) : ModelState() + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/emmcstatus/EMMCStatusListItemWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/emmcstatus/EMMCStatusListItemWidgetModel.kt new file mode 100644 index 00000000..a81adb75 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/emmcstatus/EMMCStatusListItemWidgetModel.kt @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.emmcstatus + +import dji.sdk.keyvalue.key.CameraKey +import dji.sdk.keyvalue.value.camera.CameraSDCardState +import dji.sdk.keyvalue.value.camera.CameraStorageLocation +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.value.common.ComponentIndexType +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Completable + +/** + * Widget Model for the [EMMCStatusListItemWidget] used to define + * the underlying logic and communication + */ +class EMMCStatusListItemWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + + + private val eMMCStateProcessor: DataProcessor = DataProcessor.create(EMMCState.ProductDisconnected) + private val eMMCRemainingCapacityProcessor = DataProcessor.create(0) + private val eMMCSupportedProcessor = DataProcessor.create(false) + private val eMMCOperationStateProcessor = DataProcessor.create(CameraSDCardState.UNKNOWN) + + /** + * Index of eMMC + */ + var cameraIndex = ComponentIndexType.LEFT_OR_MAIN + set(value) { + field = value + restart() + } + + /** + * Get the eMMC state + */ + val eMMCState: Flowable = eMMCStateProcessor.toFlowable() + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + CameraKey.KeyIsInternalStorageSupported, cameraIndex), eMMCSupportedProcessor) + bindDataProcessor( + KeyTools.createKey( + CameraKey.KeyInternalStorageRemainSpace, cameraIndex), eMMCRemainingCapacityProcessor) + bindDataProcessor( + KeyTools.createKey( + CameraKey.KeyInternalStorageState, cameraIndex), eMMCOperationStateProcessor) + } + + override fun inCleanup() { + //No clean up necessary + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + if (eMMCSupportedProcessor.value) { + eMMCStateProcessor.onNext( + EMMCState.CurrentEMMCState( + eMMCOperationStateProcessor.value, + eMMCRemainingCapacityProcessor.value + ) + ) + } else { + eMMCStateProcessor.onNext(EMMCState.NotSupported) + } + } else { + eMMCStateProcessor.onNext(EMMCState.ProductDisconnected) + } + + } + + /** + * Format eMMC + */ + fun formatEMMC(): Completable { + return djiSdkModel.performActionWithOutResult( + KeyTools.createKey(CameraKey.KeyFormatStorage,cameraIndex), + CameraStorageLocation.INTERNAL + ) + } + + /** + * Class represents states of eMMC Item + */ + sealed class EMMCState { + /** + * When product is disconnected + */ + object ProductDisconnected : EMMCState() + + /** + * When product does not support eMMC + */ + object NotSupported : EMMCState() + + /** + * When product is connected + * @property eMMCOperationState - Current operation State of eMMC + * @property remainingSpace - Remaining space in MB + */ + data class CurrentEMMCState( + val eMMCOperationState: CameraSDCardState, + val remainingSpace: Int + ) : EMMCState() + + } + + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/flightmode/FlightModeListItemWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/flightmode/FlightModeListItemWidget.kt new file mode 100644 index 00000000..73204e11 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/flightmode/FlightModeListItemWidget.kt @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.flightmode + +import android.content.Context +import android.util.AttributeSet +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.panel.listitem.ListItemLabelButtonWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.panel.listitem.flightmode.FlightModeListItemWidget.ModelState +import dji.v5.ux.core.panel.listitem.flightmode.FlightModeListItemWidget.ModelState.ProductConnected +import dji.v5.ux.core.widget.flightmode.FlightModeWidgetModel + +/** + * Widget displays the current flight mode + * + */ +open class FlightModeListItemWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ListItemLabelButtonWidget( + context, + attrs, + defStyleAttr, + WidgetType.LABEL, + R.style.UXSDKFlightModeListItem +) { + + //region Fields + private val widgetModel by lazy { + FlightModeWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()) + } + //endregion + + //region Lifecycle + override fun reactToModelChanges() { + addReaction(widgetModel.flightModeState + .observeOn(SchedulerProvider.ui()) + .subscribe { this.updateUI(it) }) + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun onButtonClick() { + // No code needed + } + //endregion + + //region Customization + override fun getIdealDimensionRatioString(): String? = null + + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP) + + //endregion + + //region Reactions to Model + private fun updateUI(flightModeState: FlightModeWidgetModel.FlightModeState) { + if (flightModeState is FlightModeWidgetModel.FlightModeState.FlightModeUpdated) { + listItemLabel = flightModeState.flightModeString + listItemLabelTextColor = normalValueColor + widgetStateDataProcessor.onNext(ModelState.FlightModeUpdated(flightModeState.flightModeString)) + } else { + listItemLabel = getString(R.string.uxsdk_string_default_value) + listItemLabelTextColor = disconnectedValueColor + + } + } + //endregion + + //region Hooks + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines the widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Flight mode text update + */ + data class FlightModeUpdated(val flightModeText: String) : ModelState() + } + //endregion + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/maxaltitude/MaxAltitudeListItemWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/maxaltitude/MaxAltitudeListItemWidget.kt new file mode 100644 index 00000000..856bcb2b --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/maxaltitude/MaxAltitudeListItemWidget.kt @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.maxaltitude + +import android.annotation.SuppressLint +import android.content.Context +import android.content.DialogInterface +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import androidx.annotation.StyleRes +import androidx.core.content.res.use +import dji.v5.utils.common.LogUtils +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.UXSDKError +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.panel.listitem.ListItemEditTextButtonWidget +import dji.v5.ux.core.base.panel.listitem.ListItemEditTextButtonWidget.UIState.* +import dji.v5.ux.core.communication.GlobalPreferencesManager +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.panel.listitem.maxaltitude.MaxAltitudeListItemWidget.DialogType.* +import dji.v5.ux.core.panel.listitem.maxaltitude.MaxAltitudeListItemWidget.ModelState +import dji.v5.ux.core.panel.listitem.maxaltitude.MaxAltitudeListItemWidget.ModelState.MaxAltitudeStateUpdated +import dji.v5.ux.core.panel.listitem.maxaltitude.MaxAltitudeListItemWidget.ModelState.ProductConnected +import dji.v5.ux.core.panel.listitem.maxaltitude.MaxAltitudeListItemWidgetModel.MaxAltitudeState +import dji.v5.ux.core.util.UnitConversionUtil.* +import kotlin.math.roundToInt + +private const val TAG = "MaxAltitudeListItemWidget" +private const val ALARM_LIMIT_METRIC = 120 +private const val ALARM_LIMIT_IMPERIAL = 400 + +/** + * Widget shows the current flight height limit. + * Based on the product connected and the mode that it currently is in, + * the widget will allow the user to update the flight height limit. + * Tap on the limit and enter the new value to modify the flight height limit. + */ +open class MaxAltitudeListItemWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleArr: Int = 0 +) : ListItemEditTextButtonWidget( + context, + attrs, + defStyleArr, + WidgetType.EDIT, + R.style.UXSDKMaxAltitudeListItem +) { + + //region Fields + /** + * Icon for confirmation dialog + */ + var confirmationDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_alert_yellow) + + /** + * Icon for error dialog + */ + var errorDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_alert_error) + + /** + * Enable/Disable toast messages in the widget + */ + var toastMessagesEnabled: Boolean = true + + /** + * Theme for the dialogs shown in the widget + */ + @StyleRes + var dialogTheme: Int = R.style.UXSDKDialogTheme + + + private val widgetModel: MaxAltitudeListItemWidgetModel by lazy { + MaxAltitudeListItemWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + GlobalPreferencesManager.getInstance() + ) + } + //endregion + + //region Constructor + init { + initAttributes(context, attrs) + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + + override fun reactToModelChanges() { + addReaction(widgetModel.maxAltitudeState + .observeOn(SchedulerProvider.ui()) + .subscribe { + widgetStateDataProcessor.onNext(MaxAltitudeStateUpdated(it)) + updateUI(it) + }) + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + } + + override fun onButtonClick() { + // No code required + } + + override fun onEditorTextChanged(currentText: String?) { + listItemEditTextColor = if (!currentText.isNullOrBlank() + && currentText.toIntOrNull() != null + && widgetModel.isInputInRange(currentText.toInt())) { + editTextNormalColor + } else { + errorValueColor + } + + } + + override fun onKeyboardDoneAction() { + val currentValue = listItemEditTextValue?.toIntOrNull() + if (currentValue != null + && widgetModel.isInputInRange(currentValue)) { + addDisposable( + widgetModel.maxAltitudeState.firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe({ + if (it is MaxAltitudeState.MaxAltitudeValue) { + when { + isOverAlarmLimit(currentValue, it.unitType) -> { + showOverAlarmLimitDialog(currentValue, it.returnToHomeHeight, it.unitType) + } + else -> { + verifyReturnHomeAltitudeValue(currentValue, it.returnToHomeHeight, it.unitType) + } + } + } + }, { + LogUtils.d(TAG, it.message) + }) + ) + + } else { + showToast(getString(R.string.uxsdk_list_item_value_out_of_range)) + resetToDefaultValue() + } + + } + //endregion + + //region Reactions to model + private fun updateUI(maxAltitudeState: MaxAltitudeState) { + when (maxAltitudeState) { + MaxAltitudeState.ProductDisconnected -> updateProductDisconnectedState() + is MaxAltitudeState.NoviceMode -> updateNoviceMode(maxAltitudeState.unitType) + is MaxAltitudeState.MaxAltitudeValue -> updateMaxAltitudeValue(maxAltitudeState) + } + } + + private fun updateMaxAltitudeValue(maxAltitudeListItemState: MaxAltitudeState.MaxAltitudeValue) { + listItemEditTextVisibility = true + listItemHintVisibility = true + listItemHint = if (maxAltitudeListItemState.unitType == UnitType.METRIC) { + getString(R.string.uxsdk_altitude_range_meters, maxAltitudeListItemState.minAltitudeLimit, maxAltitudeListItemState.maxAltitudeLimit) + } else { + getString(R.string.uxsdk_altitude_range_feet, maxAltitudeListItemState.minAltitudeLimit, maxAltitudeListItemState.maxAltitudeLimit) + } + listItemEditTextValue = maxAltitudeListItemState.altitudeLimit.toString() + isEnabled = true + listItemEditTextColor = editTextNormalColor + } + + + private fun updateNoviceMode(unitType: UnitType) { + listItemEditTextVisibility = true + listItemHintVisibility = false + listItemEditTextValue = if (unitType == UnitType.METRIC) { + getString(R.string.uxsdk_novice_mode_altitude_meters) + } else { + getString(R.string.uxsdk_novice_mode_altitude_feet) + } + isEnabled = false + listItemEditTextColor = disconnectedValueColor + } + + private fun updateProductDisconnectedState() { + listItemEditTextVisibility = true + listItemHintVisibility = false + listItemEditTextValue = getString(R.string.uxsdk_string_default_value) + isEnabled = false + listItemEditTextColor = disconnectedValueColor + } + //endregion + + //region Helpers + private fun showToast(message: String?) { + if (toastMessagesEnabled) { + showShortToast(message) + } + } + + private fun showOverAlarmLimitDialog(currentValue: Int, currentReturnToHomeValue: Int, unitType: UnitType) { + val dialogListener = DialogInterface.OnClickListener { dialogInterface, buttonId: Int -> + if (buttonId == DialogInterface.BUTTON_POSITIVE) { + verifyReturnHomeAltitudeValue(currentValue, currentReturnToHomeValue, unitType) + uiUpdateStateProcessor.onNext(DialogActionConfirmed(MaxAltitudeOverAlarmConfirmation)) + } else { + uiUpdateStateProcessor.onNext(DialogActionCanceled(MaxAltitudeOverAlarmConfirmation)) + resetToDefaultValue() + } + dialogInterface.dismiss() + + } + val dialogDismissListener = DialogInterface.OnDismissListener { + uiUpdateStateProcessor.onNext(DialogDismissed(MaxAltitudeOverAlarmConfirmation)) + } + showConfirmationDialog( + dialogTheme = dialogTheme, + title = getString(R.string.uxsdk_list_item_max_flight_altitude), + icon = confirmationDialogIcon, + message = getString(R.string.uxsdk_limit_high_notice), + dialogClickListener = dialogListener, + dialogDismissListener = dialogDismissListener + ) + uiUpdateStateProcessor.onNext(DialogDisplayed(MaxAltitudeOverAlarmConfirmation)) + + } + + private fun isOverAlarmLimit(currentVal: Int, unitType: UnitType): Boolean { + return if (unitType == UnitType.METRIC) { + currentVal > ALARM_LIMIT_METRIC + } else { + currentVal > ALARM_LIMIT_IMPERIAL + } + } + + private fun verifyReturnHomeAltitudeValue(currentValue: Int, currentReturnToHomeValue: Int, unitType: UnitType) { + if (currentValue < currentReturnToHomeValue) { + val metricHeight: Int = if (unitType == UnitType.METRIC) { + currentValue + } else { + convertFeetToMeters(currentValue.toFloat()).roundToInt() + } + val imperialHeight: Int = if (unitType == UnitType.METRIC) { + convertMetersToFeet(currentValue.toFloat()).roundToInt() + } else { + currentValue + } + + val dialogListener = DialogInterface.OnClickListener { dialogInterface, buttonId: Int -> + if (buttonId == DialogInterface.BUTTON_POSITIVE) { + setMaxAltitudeValue(currentValue) + uiUpdateStateProcessor.onNext(DialogActionConfirmed(ReturnHomeAltitudeUpdate)) + } else { + uiUpdateStateProcessor.onNext(DialogActionCanceled(ReturnHomeAltitudeUpdate)) + resetToDefaultValue() + } + dialogInterface.dismiss() + } + + val dialogDismissListener = DialogInterface.OnDismissListener { + uiUpdateStateProcessor.onNext(DialogDismissed(ReturnHomeAltitudeUpdate)) + } + showConfirmationDialog( + dialogTheme = dialogTheme, + icon = confirmationDialogIcon, + title = getString(R.string.uxsdk_list_item_max_flight_altitude), + message = getString(R.string.uxsdk_limit_return_home_warning, imperialHeight, metricHeight), + dialogClickListener = dialogListener, + dialogDismissListener = dialogDismissListener + ) + uiUpdateStateProcessor.onNext(DialogDisplayed(ReturnHomeAltitudeUpdate)) + } else { + setMaxAltitudeValue(currentValue) + } + + } + + private fun setMaxAltitudeValue(currentValue: Int) { + addDisposable( + widgetModel.setFlightMaxAltitude(currentValue) + .observeOn(SchedulerProvider.ui()) + .subscribe({ + showToast(getString(R.string.uxsdk_success)) + widgetStateDataProcessor.onNext(ModelState.SetMaxAltitudeSucceeded) + }, { error -> + resetToDefaultValue() + if (error is UXSDKError) { + showToast(error.djiError.description()) + widgetStateDataProcessor.onNext(ModelState.SetMaxAltitudeFailed(error)) + } + }) + ) + } + + private fun resetToDefaultValue() { + addDisposable( + widgetModel.maxAltitudeState.firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe({ + updateUI(it) + }, { + LogUtils.e(TAG, it.message) + }) + ) + } + //endregion + + //region Customization + override fun getIdealDimensionRatioString(): String? { + return null + } + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription( + WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP + ) + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet?) { + context.obtainStyledAttributes(attrs, R.styleable.MaxAltitudeListItemWidget, 0, defaultStyle).use { typedArray -> + toastMessagesEnabled = typedArray.getBoolean(R.styleable.MaxAltitudeListItemWidget_uxsdk_toast_messages_enabled, toastMessagesEnabled) + typedArray.getResourceIdAndUse(R.styleable.MaxAltitudeListItemWidget_uxsdk_list_item_dialog_theme) { + dialogTheme = it + } + typedArray.getDrawableAndUse(R.styleable.SDCardStatusListItemWidget_uxsdk_list_item_confirmation_dialog_icon) { + confirmationDialogIcon = it + } + typedArray.getDrawableAndUse(R.styleable.SDCardStatusListItemWidget_uxsdk_list_item_error_dialog_icon) { + errorDialogIcon = it + } + } + } + //endregion + + //region Hooks + /** + * Get the [ListItemEditTextButtonWidget.UIState] updates + * The info parameter is instance of [DialogType] + */ + override fun getUIStateUpdates(): Flowable { + return uiUpdateStateProcessor.onBackpressureBuffer() + } + + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Max altitude List Item Dialog Identifiers + */ + sealed class DialogType { + /** + * Dialog shown when max altitude is over alarm + * levels. + */ + object MaxAltitudeOverAlarmConfirmation : DialogType() + + /** + * Dialog shown when flight limit is restricted and the user + * tries to set a higher value + */ + object FlightLimitNeededError : DialogType() + + /** + * Dialog shown to confirm that the user will have to update return home + * altitude along with max flight limit + */ + object ReturnHomeAltitudeUpdate : DialogType() + + } + + /** + * Class defines widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Max altitude set action successful + */ + object SetMaxAltitudeSucceeded : ModelState() + + /** + * Max altitude set action failed + */ + data class SetMaxAltitudeFailed(val error: UXSDKError) : ModelState() + + /** + * Max altitude state update + */ + data class MaxAltitudeStateUpdated(val maxAltitudeState: MaxAltitudeState) : ModelState() + } + + //endregion + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/maxaltitude/MaxAltitudeListItemWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/maxaltitude/MaxAltitudeListItemWidgetModel.kt new file mode 100644 index 00000000..13a3d96f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/maxaltitude/MaxAltitudeListItemWidgetModel.kt @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.maxaltitude + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.value.common.IntValueConfig +import dji.v5.et.create +import dji.v5.utils.common.LogUtils +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.GlobalPreferenceKeys +import dji.v5.ux.core.communication.GlobalPreferencesInterface +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.panel.listitem.maxaltitude.MaxAltitudeListItemWidgetModel.MaxAltitudeState.MaxAltitudeValue +import dji.v5.ux.core.panel.listitem.maxaltitude.MaxAltitudeListItemWidgetModel.MaxAltitudeState.ProductDisconnected +import dji.v5.ux.core.util.DataProcessor +import dji.v5.ux.core.util.UnitConversionUtil.* +import io.reactivex.rxjava3.core.Completable +import kotlin.math.roundToInt + +private const val TAG = "MaxAltitudeListItemWidgetModel" + +/** + * Widget Model for the [MaxAltitudeListItemWidget] used to define + * the underlying logic and communication + */ +class MaxAltitudeListItemWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, + private val preferencesManager: GlobalPreferencesInterface? +) : WidgetModel(djiSdkModel, keyedStore) { + + private val minFlightHeight = 20 + private val maxFlightHeight = 120 + private val maxFlightHeightProcessor: DataProcessor = DataProcessor.create(0) + private val returnHomeFlightHeightProcessor: DataProcessor = DataProcessor.create(0) + private val noviceModeProcessor: DataProcessor = DataProcessor.create(false) + private val maxFlightHeightRangeProcessor: DataProcessor = DataProcessor.create(IntValueConfig(minFlightHeight, maxFlightHeight, minFlightHeight)) + private val maxAltitudeStateProcessor: DataProcessor = DataProcessor.create(ProductDisconnected) + private val unitTypeDataProcessor: DataProcessor = DataProcessor.create(UnitType.METRIC) + + /** + * Get the max altitude state + */ + val maxAltitudeState: Flowable + get() = maxAltitudeStateProcessor.toFlowable() + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyHeightLimit), maxFlightHeightProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyGoHomeHeight), returnHomeFlightHeightProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyHeightLimitRange), maxFlightHeightRangeProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyNoviceModeEnabled), noviceModeProcessor) + bindDataProcessor(GlobalPreferenceKeys.create(GlobalPreferenceKeys.UNIT_TYPE), unitTypeDataProcessor) + preferencesManager?.setUpListener() + preferencesManager?.let { unitTypeDataProcessor.onNext(it.unitType) } + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + if (noviceModeProcessor.value) { + maxAltitudeStateProcessor.onNext(MaxAltitudeState.NoviceMode(unitTypeDataProcessor.value)) + + } else { + val minLimit = getMinLimit() + val maxLimit = getMaxLimit() + val currentMaxFlightValue = getCurrentMaxFlightValue() + maxAltitudeStateProcessor.onNext( + MaxAltitudeValue( + altitudeLimit = currentMaxFlightValue, + minAltitudeLimit = minLimit, + maxAltitudeLimit = maxLimit, + unitType = unitTypeDataProcessor.value, + returnToHomeHeight = getReturnHomeHeightByUnit() + ) + ) + } + } else { + maxAltitudeStateProcessor.onNext(ProductDisconnected) + } + } + + private fun getCurrentMaxFlightValue(): Int { + return if (unitTypeDataProcessor.value == UnitType.METRIC) { + maxFlightHeightProcessor.value + } else { + convertMetersToFeet(maxFlightHeightProcessor.value.toFloat()).roundToInt() + } + } + + private fun getMinLimit(): Int { + val tempMinValue: Int = maxFlightHeightRangeProcessor.value.min + return if (unitTypeDataProcessor.value == UnitType.METRIC) { + tempMinValue + } else { + convertMetersToFeet(tempMinValue.toFloat()).roundToInt() + } + } + + private fun getMaxLimit(): Int { + val tempMaxValue: Int = maxFlightHeightRangeProcessor.value.max + return if (unitTypeDataProcessor.value == UnitType.METRIC) { + tempMaxValue + } else { + convertMetersToFeet(tempMaxValue.toFloat()).roundToInt() + } + } + + private fun getReturnHomeHeightByUnit(): Int { + return if (unitTypeDataProcessor.value == UnitType.METRIC) { + returnHomeFlightHeightProcessor.value + } else { + convertMetersToFeet(returnHomeFlightHeightProcessor.value.toFloat()).roundToInt() + } + } + + /** + * Set flight height limit + * + * @return Completable to determine status of action + */ + fun setFlightMaxAltitude(maxAltitudeLimit: Int): Completable { + val tempLimit: Int = if (unitTypeDataProcessor.value == UnitType.IMPERIAL) { + convertFeetToMeters(maxAltitudeLimit.toFloat()).roundToInt() + } else { + maxAltitudeLimit + } + return djiSdkModel.setValue( + KeyTools.createKey( + FlightControllerKey.KeyHeightLimit), tempLimit) + .doOnComplete { + if (tempLimit < returnHomeFlightHeightProcessor.value) { + addDisposable(setReturnHomeMaxAltitude(tempLimit).subscribe({ + }, { + LogUtils.e(TAG, it.message) + })) + } + } + } + + + private fun setReturnHomeMaxAltitude(maxAltitudeLimit: Int): Completable { + return djiSdkModel.setValue(FlightControllerKey.KeyGoHomeHeight.create(), maxAltitudeLimit) + } + + /** + * Check if input is in range + * + * @return Boolean + * true - if the input is in range + * false - if the input is out of range + */ + fun isInputInRange(input: Int): Boolean { + return input >= getMinLimit() && input <= getMaxLimit() + } + + override fun inCleanup() { + preferencesManager?.cleanup() + } + + /** + * Class represents states of Max Altitude List Item + */ + sealed class MaxAltitudeState { + /** + * When product is disconnected + */ + object ProductDisconnected : MaxAltitudeState() + + /** + * When product is in beginner mode + * @property unitType - current unit system used + */ + data class NoviceMode(val unitType: UnitType) : MaxAltitudeState() + + /** + * Product returns max altitude levels and unit settings + * are metric scale + * + * @property altitudeLimit - current altitude limit + * @property minAltitudeLimit - altitude limit range minimum + * @property maxAltitudeLimit - altitude limit range maximum + * @property unitType - current unit system used + * @property needFlightLimit - needs flight limit + * @property returnToHomeHeight - altitude used while returning to home + */ + data class MaxAltitudeValue( + val altitudeLimit: Int, + val minAltitudeLimit: Int, + val maxAltitudeLimit: Int, + val unitType: UnitType, + val returnToHomeHeight: Int + ) : MaxAltitudeState() + + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/maxflightdistance/MaxFlightDistanceListItemWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/maxflightdistance/MaxFlightDistanceListItemWidget.kt new file mode 100644 index 00000000..7db9097e --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/maxflightdistance/MaxFlightDistanceListItemWidget.kt @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.maxflightdistance + +import android.annotation.SuppressLint +import android.content.Context +import android.util.AttributeSet +import androidx.core.content.res.use +import dji.v5.utils.common.LogUtils +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.UXSDKError +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.panel.listitem.ListItemEditTextButtonWidget +import dji.v5.ux.core.communication.GlobalPreferencesManager +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.extension.getStringAndUse +import dji.v5.ux.core.extension.showShortToast +import dji.v5.ux.core.panel.listitem.maxflightdistance.MaxFlightDistanceListItemWidget.ModelState +import dji.v5.ux.core.panel.listitem.maxflightdistance.MaxFlightDistanceListItemWidget.ModelState.MaxFlightDistanceStateUpdated +import dji.v5.ux.core.panel.listitem.maxflightdistance.MaxFlightDistanceListItemWidget.ModelState.ProductConnected +import dji.v5.ux.core.panel.listitem.maxflightdistance.MaxFlightDistanceListItemWidgetModel.MaxFlightDistanceState +import dji.v5.ux.core.panel.listitem.maxflightdistance.MaxFlightDistanceListItemWidgetModel.MaxFlightDistanceState.MaxFlightDistanceValue +import dji.v5.ux.core.util.UnitConversionUtil.UnitType + +private const val TAG = "MaxFlightDistanceItem" + +/** + * Widget shows the current flight distance limit. + * Based on the product connected and the mode that it currently is in, + * the widget will allow the user to update the flight distance limit. + * Tap on the limit and enter the new value to modify the flight distance limit. + */ +open class MaxFlightDistanceListItemWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleArr: Int = 0 +) : ListItemEditTextButtonWidget( + context, + attrs, + defStyleArr, + WidgetType.EDIT_BUTTON, + R.style.UXSDKMaxFlightDistanceListItem +) { + + //region Fields + private val widgetModel: MaxFlightDistanceListItemWidgetModel by lazy { + MaxFlightDistanceListItemWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + GlobalPreferencesManager.getInstance()) + } + + /** + * String for enable action button + */ + var enableActionButtonString: String = getString(R.string.uxsdk_enable) + + /** + * String for disable action button + */ + var disableActionButtonString: String = getString(R.string.uxsdk_disable) + + /** + * Enable/Disable toast messages in the widget + */ + var toastMessagesEnabled: Boolean = true + + //endregion + + //region Constructor + init { + initAttributes(context, attrs) + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun onButtonClick() { + addDisposable(widgetModel.toggleFlightDistanceAvailability() + .observeOn(SchedulerProvider.ui()) + .subscribe({ + }, { error -> + if (error is UXSDKError) { + showToast(error.djiError.description()) + } + })) + } + + override fun reactToModelChanges() { + addReaction(widgetModel.maxFlightDistanceState + .observeOn(SchedulerProvider.ui()) + .subscribe { + widgetStateDataProcessor.onNext(MaxFlightDistanceStateUpdated(it)) + updateUI(it) + }) + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + } + + override fun onKeyboardDoneAction() { + val currentValue = listItemEditTextValue?.toIntOrNull() + if (currentValue == null || !widgetModel.isInputInRange(currentValue)) { + showToast(getString(R.string.uxsdk_list_item_value_out_of_range)) + resetToDefaultValue() + } else { + setMaxFlightDistance(currentValue) + } + } + + override fun onEditorTextChanged(currentText: String?) { + listItemEditTextColor = if (!currentText.isNullOrBlank() + && currentText.toIntOrNull() != null + && widgetModel.isInputInRange(currentText.toInt())) { + editTextNormalColor + } else { + errorValueColor + } + } + //endregion + + //region Reactions to model + private fun updateUI(maxFlightDistanceState: MaxFlightDistanceState) { + when (maxFlightDistanceState) { + MaxFlightDistanceState.ProductDisconnected -> updateProductDisconnectedState() + MaxFlightDistanceState.Disabled -> updateDisabledState() + is MaxFlightDistanceState.NoviceMode -> updateNoviceMode(maxFlightDistanceState.unitType) + is MaxFlightDistanceValue -> updateMaxFlightDistance(maxFlightDistanceState) + } + } + + private fun updateMaxFlightDistance(maxFlightDistanceState: MaxFlightDistanceValue) { + isEnabled = true + listItemHintVisibility = true + listItemEditTextVisibility = true + listItemButtonVisibility = true + listItemHint = if (maxFlightDistanceState.unitType == UnitType.METRIC) { + getString(R.string.uxsdk_altitude_range_meters, maxFlightDistanceState.minDistanceLimit, maxFlightDistanceState.maxDistanceLimit) + } else { + getString(R.string.uxsdk_altitude_range_feet, maxFlightDistanceState.minDistanceLimit, maxFlightDistanceState.maxDistanceLimit) + } + listItemEditTextValue = maxFlightDistanceState.flightDistanceLimit.toString() + listItemEditTextColor = editTextNormalColor + listItemButtonText = disableActionButtonString + } + + private fun updateNoviceMode(unitType: UnitType) { + listItemEditTextVisibility = true + listItemHintVisibility = false + listItemButtonVisibility = false + listItemEditTextValue = if (unitType == UnitType.METRIC) { + getString(R.string.uxsdk_novice_mode_distance_meters) + } else { + getString(R.string.uxsdk_novice_mode_distance_feet) + } + isEnabled = false + listItemEditTextColor = disconnectedValueColor + } + + private fun updateDisabledState() { + isEnabled = true + listItemHintVisibility = false + listItemEditTextVisibility = false + listItemButtonVisibility = true + listItemButtonText = enableActionButtonString + } + + private fun updateProductDisconnectedState() { + listItemEditTextVisibility = true + listItemHintVisibility = false + listItemButtonVisibility = false + listItemEditTextValue = getString(R.string.uxsdk_string_default_value) + listItemEditTextColor = disconnectedValueColor + listItemButtonText = getString(R.string.uxsdk_string_default_value) + isEnabled = false + + } + //endregion + + //region Helpers + private fun showToast(message: String?) { + if (toastMessagesEnabled) { + showShortToast(message) + } + } + + private fun resetToDefaultValue() { + addDisposable(widgetModel.maxFlightDistanceState.firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe({ + updateUI(it) + }, { + LogUtils.e(TAG, it.message) + })) + } + + private fun setMaxFlightDistance(maxFlightDistance: Int) { + addDisposable(widgetModel.setMaxFlightDistance(maxFlightDistance) + .observeOn(SchedulerProvider.ui()) + .subscribe({ + showToast(getString(R.string.uxsdk_success)) + widgetStateDataProcessor.onNext(ModelState.SetMaxFlightDistanceSucceeded) + }, { + if (it is UXSDKError) { + showToast(it.djiError.description()) + widgetStateDataProcessor.onNext(ModelState.SetMaxFlightDistanceFailed(it)) + } + resetToDefaultValue() + })) + } + //endregion + + //region Customization + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet?) { + context.obtainStyledAttributes(attrs, R.styleable.MaxFlightDistanceListItemWidget, 0, defaultStyle).use { typedArray -> + toastMessagesEnabled = typedArray.getBoolean(R.styleable.MaxFlightDistanceListItemWidget_uxsdk_toast_messages_enabled, toastMessagesEnabled) + typedArray.getStringAndUse(R.styleable.MaxFlightDistanceListItemWidget_uxsdk_enable_action_button_string) { + enableActionButtonString = it + } + typedArray.getStringAndUse(R.styleable.MaxFlightDistanceListItemWidget_uxsdk_disable_action_button_string) { + disableActionButtonString = it + } + } + } + + override fun getIdealDimensionRatioString(): String? { + return null + } + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP) + + //endregion + + //region Hooks + + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Max flight distance set action successful + */ + object SetMaxFlightDistanceSucceeded : ModelState() + + /** + * Max flight distance set action failed + */ + data class SetMaxFlightDistanceFailed(val error: UXSDKError) : ModelState() + + /** + * Max flight distance state updated + */ + data class MaxFlightDistanceStateUpdated(val maxFlightDistanceState: MaxFlightDistanceState) : ModelState() + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/maxflightdistance/MaxFlightDistanceListItemWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/maxflightdistance/MaxFlightDistanceListItemWidgetModel.kt new file mode 100644 index 00000000..4098819e --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/maxflightdistance/MaxFlightDistanceListItemWidgetModel.kt @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.maxflightdistance + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.value.common.IntValueConfig +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.GlobalPreferenceKeys +import dji.v5.ux.core.communication.GlobalPreferencesInterface +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.panel.listitem.maxflightdistance.MaxFlightDistanceListItemWidgetModel.MaxFlightDistanceState.* +import dji.v5.ux.core.util.DataProcessor +import dji.v5.ux.core.util.UnitConversionUtil.* +import io.reactivex.rxjava3.core.Completable +import kotlin.math.roundToInt + +/** + * Widget Model for the [MaxFlightDistanceListItemWidget] used to define + * the underlying logic and communication + */ +class MaxFlightDistanceListItemWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, + private val preferencesManager: GlobalPreferencesInterface? +) : WidgetModel(djiSdkModel, keyedStore) { + + private val maxFlightDistanceEnabledProcessor: DataProcessor = DataProcessor.create(false) + private val maxFlightDistanceProcessor: DataProcessor = DataProcessor.create(0) + private val maxFlightDistanceRangeProcessor: DataProcessor = DataProcessor.create(IntValueConfig()) + private val unitTypeProcessor: DataProcessor = DataProcessor.create(UnitType.METRIC) + private val maxFlightDistanceStateProcessor: DataProcessor = DataProcessor.create(ProductDisconnected) + private val noviceModeProcessor: DataProcessor = DataProcessor.create(false) + + /** + * Get the max flight distance state + */ + val maxFlightDistanceState: Flowable + get() = maxFlightDistanceStateProcessor.toFlowable() + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyDistanceLimitEnabled), maxFlightDistanceEnabledProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyDistanceLimit), maxFlightDistanceProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyDistanceLimitRange), maxFlightDistanceRangeProcessor) + bindDataProcessor(GlobalPreferenceKeys.create(GlobalPreferenceKeys.UNIT_TYPE), unitTypeProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyNoviceModeEnabled), noviceModeProcessor) + preferencesManager?.setUpListener() + preferencesManager?.let { unitTypeProcessor.onNext(it.unitType) } + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + when { + noviceModeProcessor.value -> { + maxFlightDistanceStateProcessor.onNext(NoviceMode(unitTypeProcessor.value)) + } + maxFlightDistanceEnabledProcessor.value -> { + maxFlightDistanceStateProcessor.onNext(MaxFlightDistanceValue( + flightDistanceLimit = getMaxFlightDistanceValue(), + minDistanceLimit = getMinLimit(), + maxDistanceLimit = getMaxLimit(), + unitType = unitTypeProcessor.value)) + + } + else -> { + maxFlightDistanceStateProcessor.onNext(Disabled) + } + } + } else { + maxFlightDistanceStateProcessor.onNext(ProductDisconnected) + } + } + + override fun inCleanup() { + preferencesManager?.cleanup() + } + + private fun getMaxFlightDistanceValue(): Int { + return if (unitTypeProcessor.value == UnitType.IMPERIAL) { + convertMetersToFeet(maxFlightDistanceProcessor.value.toFloat()).roundToInt() + } else { + maxFlightDistanceProcessor.value + } + } + + private fun getMinLimit(): Int { + return if (unitTypeProcessor.value == UnitType.IMPERIAL) { + convertMetersToFeet(maxFlightDistanceRangeProcessor.value.min.toFloat()).roundToInt() + } else { + maxFlightDistanceRangeProcessor.value.min.toInt() + } + } + + private fun getMaxLimit(): Int { + return if (unitTypeProcessor.value == UnitType.IMPERIAL) { + convertMetersToFeet(maxFlightDistanceRangeProcessor.value.max.toFloat()).roundToInt() + } else { + maxFlightDistanceRangeProcessor.value.max.toInt() + } + } + + /** + * Enable or disable max flight distance + * + * @return Completable to determine status of action + */ + fun toggleFlightDistanceAvailability(): Completable { + return djiSdkModel.setValue( + KeyTools.createKey( + FlightControllerKey.KeyDistanceLimitEnabled), !maxFlightDistanceEnabledProcessor.value) + } + + /** + * Set max flight distance + * + * @return Completable to determine status of action + */ + fun setMaxFlightDistance(flightDistance: Int): Completable { + val tempFlightDistance: Int = if (unitTypeProcessor.value == UnitType.IMPERIAL) { + convertFeetToMeters(flightDistance.toFloat()).toInt() + } else { + flightDistance + } + return djiSdkModel.setValue( + KeyTools.createKey( + FlightControllerKey.KeyDistanceLimit), tempFlightDistance) + + } + + /** + * Check if input is in range + * + * @return Boolean + * true - if the input is in range + * false - if the input is out of range + */ + fun isInputInRange(input: Int): Boolean = input >= getMinLimit() && input <= getMaxLimit() + + /** + * Class represents states of Max Flight Distance State + */ + sealed class MaxFlightDistanceState { + /** + * When product is disconnected + */ + object ProductDisconnected : MaxFlightDistanceState() + + /** + * When max flight distance limit is disabled + */ + object Disabled : MaxFlightDistanceState() + + /** + * When product is in beginner mode + * @property unitType - current unit system used + */ + data class NoviceMode(val unitType: UnitType) : MaxFlightDistanceState() + + /** + * Flight distance value with unit + * + * @property flightDistanceLimit - current flight distance limit + * @property minDistanceLimit - flight distance limit range minimum + * @property maxDistanceLimit - flight distance limit range maximum + * @property unitType - current unit system used + */ + data class MaxFlightDistanceValue(val flightDistanceLimit: Int, + val minDistanceLimit: Int, + val maxDistanceLimit: Int, + val unitType: UnitType) : MaxFlightDistanceState() + + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/novicemode/NoviceModeListItemWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/novicemode/NoviceModeListItemWidget.kt new file mode 100644 index 00000000..5021587f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/novicemode/NoviceModeListItemWidget.kt @@ -0,0 +1,294 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.novicemode + +import android.annotation.SuppressLint +import android.content.Context +import android.content.DialogInterface +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import androidx.annotation.StyleRes +import androidx.core.content.res.use +import dji.v5.utils.common.LogUtils +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.UXSDKError +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.panel.listitem.ListItemSwitchWidget +import dji.v5.ux.core.base.panel.listitem.ListItemSwitchWidget.UIState.* +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.panel.listitem.novicemode.NoviceModeListItemWidget.DialogType.NoviceModeDisableConfirmation +import dji.v5.ux.core.panel.listitem.novicemode.NoviceModeListItemWidget.DialogType.NoviceModeEnabled +import dji.v5.ux.core.panel.listitem.novicemode.NoviceModeListItemWidget.ModelState +import dji.v5.ux.core.panel.listitem.novicemode.NoviceModeListItemWidget.ModelState.NoviceModeStateUpdated +import dji.v5.ux.core.panel.listitem.novicemode.NoviceModeListItemWidget.ModelState.ProductConnected +import dji.v5.ux.core.panel.listitem.novicemode.NoviceModeListItemWidgetModel.NoviceModeState + +private const val TAG = "NoviceModeListItemW" + +/** + * Widget shows the current status of the Novice Mode, also known + * as Beginner Mode. + * It also provides an option to switch between ON/OFF state + */ +open class NoviceModeListItemWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleArr: Int = 0 +) : ListItemSwitchWidget( + context, + attrs, + defStyleArr, + R.style.UXSDKNoviceModeListItem +) { + + //region Fields + private val widgetModel: NoviceModeListItemWidgetModel by lazy { + NoviceModeListItemWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()) + } + + /** + * Icon for confirmation dialog + */ + var confirmationDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_alert_yellow) + + + /** + * Icon for success dialog + */ + var successDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_alert_good) + + /** + * Theme for the dialogs shown in the widget + */ + @StyleRes + var dialogTheme: Int = R.style.UXSDKDialogTheme + //endregion + + //region Constructor + init { + initAttributes(context, attrs) + } + //endregion + + //region Lifecycle + override fun reactToModelChanges() { + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + addReaction(widgetModel.noviceModeState + .observeOn(SchedulerProvider.ui()) + .subscribe { + widgetStateDataProcessor.onNext(NoviceModeStateUpdated(it)) + updateUI(it) + }) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun onSwitchToggle(isChecked: Boolean) { + if (isChecked) { + toggleNoviceMode(isChecked) + } else { + showNoviceModeConfirmationDialog() + } + } + //endregion + + //region Reactions to Model + private fun updateUI(noviceModeState: NoviceModeState) { + when (noviceModeState) { + NoviceModeState.ProductDisconnected -> isEnabled = false + NoviceModeState.Enabled -> { + updateState(true) + } + NoviceModeState.Disabled -> { + updateState(false) + } + } + } + + private fun updateState(noviceModeEnabled: Boolean) { + isEnabled = true + setChecked(noviceModeEnabled) + } + //endregion + + //region Helpers + private fun toggleNoviceMode(checked: Boolean) { + addDisposable(widgetModel.toggleNoviceMode() + .observeOn(SchedulerProvider.ui()) + .subscribe({ + if (checked) { + showEnabledDialog() + } + LogUtils.d(TAG, " toggle success ") + }, { + if (it is UXSDKError) { + LogUtils.e(TAG, it.djiError.description()) + } + resetSwitchState() + })) + } + + private fun showNoviceModeConfirmationDialog() { + val dialogListener = DialogInterface.OnClickListener { dialogInterface, buttonId: Int -> + if (buttonId == DialogInterface.BUTTON_POSITIVE) { + toggleNoviceMode(false) + uiUpdateStateProcessor.onNext(DialogActionConfirmed(NoviceModeDisableConfirmation)) + } else { + uiUpdateStateProcessor.onNext(DialogActionCanceled(NoviceModeDisableConfirmation)) + resetSwitchState() + } + dialogInterface.dismiss() + } + val dialogDismissListener = DialogInterface.OnDismissListener { + uiUpdateStateProcessor.onNext(DialogDismissed(NoviceModeDisableConfirmation)) + } + showConfirmationDialog(dialogTheme = dialogTheme, + icon = confirmationDialogIcon, + title = getString(R.string.uxsdk_list_item_novice_mode), + message = getString(R.string.uxsdk_novice_mode_disabled_message), + dialogClickListener = dialogListener, + dialogDismissListener = dialogDismissListener) + uiUpdateStateProcessor.onNext(DialogDisplayed(NoviceModeDisableConfirmation)) + } + + private fun showEnabledDialog() { + val dialogDismissListener = DialogInterface.OnDismissListener { + uiUpdateStateProcessor.onNext(DialogDismissed(NoviceModeEnabled)) + } + showAlertDialog(dialogTheme = dialogTheme, + icon = successDialogIcon, + title = getString(R.string.uxsdk_list_item_novice_mode), + message = getString(R.string.uxsdk_novice_mode_enabled_message), + dialogDismissListener = dialogDismissListener) + uiUpdateStateProcessor.onNext(DialogDisplayed(NoviceModeEnabled)) + } + + private fun resetSwitchState() { + addDisposable(widgetModel.noviceModeState.firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe({ + updateUI(it) + }, { + LogUtils.e(TAG, it.message) + })) + } + //endregion + + //region Customization + override fun getIdealDimensionRatioString(): String? { + return null + } + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP) + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet?) { + context.obtainStyledAttributes(attrs, R.styleable.NoviceModeListItemWidget, 0, defaultStyle).use { typedArray -> + typedArray.getDrawableAndUse(R.styleable.NoviceModeListItemWidget_uxsdk_list_item_confirmation_dialog_icon) { + confirmationDialogIcon = it + } + typedArray.getDrawableAndUse(R.styleable.NoviceModeListItemWidget_uxsdk_list_item_success_dialog_icon) { + successDialogIcon = it + } + typedArray.getResourceIdAndUse(R.styleable.NoviceModeListItemWidget_uxsdk_list_item_dialog_theme) { + dialogTheme = it + } + + } + } + //endregion + + //region Hooks + + /** + * Get the [ListItemSwitchWidget.UIState] updates + * The info parameter is instance of [DialogType] + */ + override fun getUIStateUpdates(): Flowable { + return uiUpdateStateProcessor.onBackpressureBuffer() + } + + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Novice mode dialog identifiers + */ + sealed class DialogType { + /** + * Dialog shown when novice mode is enabled successfully + */ + object NoviceModeEnabled : DialogType() + + /** + * Dialog shown when switching from enabled to disabled + */ + object NoviceModeDisableConfirmation : DialogType() + } + + /** + * Class defines widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Current novice mode state + */ + data class NoviceModeStateUpdated(val noviceModeState: NoviceModeState) : ModelState() + + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/novicemode/NoviceModeListItemWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/novicemode/NoviceModeListItemWidgetModel.kt new file mode 100644 index 00000000..4712830c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/novicemode/NoviceModeListItemWidgetModel.kt @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.novicemode + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.key.KeyTools +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.panel.listitem.novicemode.NoviceModeListItemWidgetModel.NoviceModeState.ProductDisconnected +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Completable + +/** + * Widget Model for the [NoviceModeListItemWidget] used to define + * the underlying logic and communication + */ +class NoviceModeListItemWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + + private val noviceModeDataProcessor = DataProcessor.create(false) + private val noviceModeStateDataProcessor: DataProcessor = DataProcessor.create(ProductDisconnected) + + /** + * Get the novice mode state + */ + val noviceModeState: Flowable + get() = noviceModeStateDataProcessor.toFlowable() + + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyNoviceModeEnabled), noviceModeDataProcessor) + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + if (noviceModeDataProcessor.value) { + noviceModeStateDataProcessor.onNext(NoviceModeState.Enabled) + } else { + noviceModeStateDataProcessor.onNext(NoviceModeState.Disabled) + } + } else { + noviceModeStateDataProcessor.onNext(ProductDisconnected) + } + } + + override fun inCleanup() { + // no clean up required + } + + /** + * Toggle novice mode on/off + */ + fun toggleNoviceMode(): Completable { + return djiSdkModel.setValue( + KeyTools.createKey( + FlightControllerKey.KeyNoviceModeEnabled), !noviceModeDataProcessor.value) + } + + /** + * Class represents states of Novice Mode Item + */ + sealed class NoviceModeState { + /** + * When product is disconnected + */ + object ProductDisconnected : NoviceModeState() + + /** + * When novice (beginner) mode is enabled + */ + object Enabled : NoviceModeState() + + /** + * When novice (beginner) mode is disabled + */ + object Disabled : NoviceModeState() + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/obstacleavoidance/ObstacleAvoidanceListItemWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/obstacleavoidance/ObstacleAvoidanceListItemWidget.kt new file mode 100644 index 00000000..9f6d80aa --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/obstacleavoidance/ObstacleAvoidanceListItemWidget.kt @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.obstacleavoidance + +import android.content.Context +import android.util.AttributeSet +import dji.sdk.keyvalue.value.flightcontroller.ObstacleActionType +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.panel.listitem.ListItemRadioButtonWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.panel.listitem.rcstickmode.RCStickModeListItemWidget.ModelState + +open class ObstacleAvoidanceListItemWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ListItemRadioButtonWidget( + context, + attrs, + defStyleAttr, + R.style.UXSDKObstacleAvoidanceListItemWidget +) { + + //region Fields + private val widgetModel by lazy { + ObstacleAvoidanceListItemWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()) + } + + private var obstacleActionCloseIndex: Int = INVALID_OPTION_INDEX + private var obstacleActionStopIndex: Int = INVALID_OPTION_INDEX + private var obstacleActionAvoidIndex: Int = INVALID_OPTION_INDEX + //endregion + + //region Constructor + init { + obstacleActionCloseIndex = addOptionToGroup(getString(R.string.uxsdk_obstacle_action_type_close)) + obstacleActionStopIndex = addOptionToGroup(getString(R.string.uxsdk_obstacle_action_type_stop)) + obstacleActionAvoidIndex = addOptionToGroup(getString(R.string.uxsdk_obstacle_action_type_avoid)) + } + //endregion + + //region Lifecycle + override fun reactToModelChanges() { + addReaction(widgetModel.obstacleActionTypeProcessor.toFlowable() + .observeOn(SchedulerProvider.ui()) + .subscribe { updateUI(it) }) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun onOptionTapped(optionIndex: Int, optionLabel: String) { + val type = when (optionIndex) { + obstacleActionCloseIndex -> { + ObstacleActionType.CLOSE + } + obstacleActionStopIndex -> { + ObstacleActionType.STOP + } + obstacleActionAvoidIndex -> { + ObstacleActionType.APAS + } + else -> return + } + addDisposable( + widgetModel.setObstacleActionType(type) + .observeOn(SchedulerProvider.ui()) + .subscribe() + ) + } + + private fun updateUI(type: ObstacleActionType) { + when (type) { + ObstacleActionType.UNKNOWN -> { + isEnabled = false + } + ObstacleActionType.CLOSE -> { + isEnabled = true + setSelected(obstacleActionCloseIndex) + } + ObstacleActionType.STOP -> { + isEnabled = true + setSelected(obstacleActionStopIndex) + } + ObstacleActionType.APAS -> { + isEnabled = true + setSelected(obstacleActionAvoidIndex) + } + } + } + + override fun getIdealDimensionRatioString(): String? { + return null + } + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription( + WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP + ) + + sealed class ModelState +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/obstacleavoidance/ObstacleAvoidanceListItemWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/obstacleavoidance/ObstacleAvoidanceListItemWidgetModel.kt new file mode 100644 index 00000000..6edadc7a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/obstacleavoidance/ObstacleAvoidanceListItemWidgetModel.kt @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.obstacleavoidance + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.value.flightcontroller.ObstacleActionType +import dji.v5.common.callback.CommonCallbacks +import dji.v5.common.error.IDJIError +import dji.v5.et.create +import dji.v5.manager.aircraft.perception.PerceptionManager +import dji.v5.manager.aircraft.perception.data.ObstacleAvoidanceType +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Completable + +private const val TAG = "ObstacleAvoidanceListItemWidgetModel" + +/** + * Widget Model for the [ObstacleAvoidanceListItemWidgetModel] used to define + * the underlying logic and communication + */ +class ObstacleAvoidanceListItemWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, +) : WidgetModel(djiSdkModel, keyedStore) { + + val obstacleActionTypeProcessor = DataProcessor.create(ObstacleActionType.UNKNOWN) + + private val flyControlConnectionProcessor = DataProcessor.create(false) + + + fun setObstacleActionType(type: ObstacleActionType): Completable { + return Completable.create { + PerceptionManager.getInstance().setObstacleAvoidanceType(getObstacleAvoidanceType(type), object : + CommonCallbacks.CompletionCallback { + override fun onSuccess() { + it.onComplete() + } + + override fun onFailure(error: IDJIError) { + it.onError(Throwable("setObstacleAvoidanceType failed!")) + } + }) + } + } + + override fun inSetup() { + bindDataProcessor(FlightControllerKey.KeyConnection.create(), flyControlConnectionProcessor) + } + + private fun updateObstacleActionType() { + if (!flyControlConnectionProcessor.value) { + obstacleActionTypeProcessor.onNext(ObstacleActionType.UNKNOWN) + return + } + PerceptionManager.getInstance().getObstacleAvoidanceType(object : + CommonCallbacks.CompletionCallbackWithParam { + override fun onSuccess(t: ObstacleAvoidanceType?) { + if (t != null) { + obstacleActionTypeProcessor.onNext(getObstacleActionType(t)) + } + } + + override fun onFailure(error: IDJIError) { + //do nothing + } + }) + + } + + override fun inCleanup() { + // No clean up needed + } + + override fun updateStates() { + updateObstacleActionType() + } + + fun getObstacleActionType(obstacleAvoidanceType: ObstacleAvoidanceType?): ObstacleActionType { + val obstacleActionType: ObstacleActionType = when (obstacleAvoidanceType) { + ObstacleAvoidanceType.BRAKE -> ObstacleActionType.STOP + ObstacleAvoidanceType.CLOSE -> ObstacleActionType.CLOSE + else -> ObstacleActionType.APAS + } + return obstacleActionType + } + + private fun getObstacleAvoidanceType(obstacleActionType: ObstacleActionType?): ObstacleAvoidanceType? { + if (obstacleActionType == null) { + return null + } + val obstacleAvoidanceType: ObstacleAvoidanceType = when (obstacleActionType) { + ObstacleActionType.STOP -> ObstacleAvoidanceType.BRAKE + ObstacleActionType.APAS -> ObstacleAvoidanceType.BYPASS + else -> ObstacleAvoidanceType.CLOSE + } + return obstacleAvoidanceType + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/overview/OverviewListItemWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/overview/OverviewListItemWidget.kt new file mode 100644 index 00000000..b9be8c38 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/overview/OverviewListItemWidget.kt @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.overview + +import android.content.Context +import android.util.AttributeSet +import dji.v5.manager.diagnostic.WarningLevel +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.panel.listitem.ListItemLabelButtonWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.panel.listitem.overview.OverviewListItemWidget.ModelState +import dji.v5.ux.core.panel.listitem.overview.OverviewListItemWidget.ModelState.OverviewStateUpdated +import dji.v5.ux.core.panel.listitem.overview.OverviewListItemWidget.ModelState.ProductConnected +import dji.v5.ux.core.panel.listitem.overview.OverviewListItemWidgetModel.OverviewState + +/** + * Widget displays the overall status of the aircraft + */ +open class OverviewListItemWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ListItemLabelButtonWidget( + context, + attrs, + defStyleAttr, + WidgetType.LABEL, + R.style.UXSDKOverviewListItem +) { + + //region Fields + private val widgetModel by lazy { + OverviewListItemWidgetModel(DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()) + } + //endregion + + //region Lifecycle + override fun reactToModelChanges() { + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + addReaction(widgetModel.overviewStatus + .observeOn(SchedulerProvider.ui()) + .subscribe { updateUI(it) }) + } + + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun onButtonClick() { + // No code needed + } + //endregion + + //region Reactions to model + private fun updateUI(overviewState: OverviewState) { + widgetStateDataProcessor.onNext(OverviewStateUpdated(overviewState)) + if (overviewState is OverviewState.CurrentStatus) { + listItemLabelTextColor = when (overviewState.warningStatusItem.warningLevel()) { + WarningLevel.NORMAL -> normalValueColor + WarningLevel.NOTICE -> normalValueColor + WarningLevel.CAUTION -> normalValueColor + WarningLevel.WARNING -> warningValueColor + WarningLevel.SERIOUS_WARNING -> errorValueColor + else -> normalValueColor + } + listItemLabel = overviewState.warningStatusItem.description() + isEnabled = true + } else { + listItemLabel = getString(R.string.uxsdk_string_default_value) + listItemLabelTextColor = disconnectedValueColor + isEnabled = false + } + } + //endregion + + //region Customization + override fun getIdealDimensionRatioString(): String? = null + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP) + + // endregion + + //region Hooks + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines the widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Overview status update + */ + data class OverviewStateUpdated(val overviewState: OverviewState) : ModelState() + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/overview/OverviewListItemWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/overview/OverviewListItemWidgetModel.kt new file mode 100644 index 00000000..f1c21152 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/overview/OverviewListItemWidgetModel.kt @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.overview + +import dji.v5.manager.diagnostic.DJIDeviceStatus +import dji.v5.manager.diagnostic.DJIDeviceStatusChangeListener +import dji.v5.manager.diagnostic.DeviceStatusManager +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.panel.listitem.overview.OverviewListItemWidgetModel.OverviewState.CurrentStatus +import dji.v5.ux.core.util.DataProcessor + +/** + * Widget Model for the [OverviewListItemWidget] used to define + * the underlying logic and communication + */ +class OverviewListItemWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + + private val systemStatusProcessor: DataProcessor = DataProcessor.create( + DJIDeviceStatus.NORMAL) + private val overviewStateProcessor: DataProcessor = DataProcessor.create(OverviewState.ProductDisconnected) + + private val deviceStatusChangeListener = DJIDeviceStatusChangeListener { _, to -> + systemStatusProcessor.onNext(to) + updateStates() + } + + /** + * Get the overview status + * + * @return Flowable for the DataProcessor that user should subscribe to. + */ + val overviewStatus: Flowable + get() = overviewStateProcessor.toFlowable() + + override fun inSetup() { + DeviceStatusManager.getInstance().addDJIDeviceStatusChangeListener(deviceStatusChangeListener) + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + overviewStateProcessor.onNext(CurrentStatus(systemStatusProcessor.value)) + } else { + overviewStateProcessor.onNext(OverviewState.ProductDisconnected) + } + } + + override fun inCleanup() { + DeviceStatusManager.getInstance().removeDJIDeviceStatusChangeListener(deviceStatusChangeListener) + } + + sealed class OverviewState { + + object ProductDisconnected : OverviewState() + + data class CurrentStatus(val warningStatusItem: DJIDeviceStatus) : OverviewState() + } + + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/rcbattery/RCBatteryListItemWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/rcbattery/RCBatteryListItemWidget.kt new file mode 100644 index 00000000..856712f6 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/rcbattery/RCBatteryListItemWidget.kt @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.rcbattery + +import android.content.Context +import android.util.AttributeSet +import dji.v5.utils.common.JsonUtil +import dji.v5.utils.common.LogUtils +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.panel.listitem.ListItemLabelButtonWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.panel.listitem.rcbattery.RCBatteryListItemWidget.ModelState +import dji.v5.ux.core.panel.listitem.rcbattery.RCBatteryListItemWidget.ModelState.ProductConnected +import dji.v5.ux.core.panel.listitem.rcbattery.RCBatteryListItemWidget.ModelState.RCBatteryStateUpdated +import dji.v5.ux.core.panel.listitem.rcbattery.RCBatteryListItemWidgetModel.RCBatteryState + +/** + * Remote controller battery list item + */ +open class RCBatteryListItemWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ListItemLabelButtonWidget( + context, + attrs, + defStyleAttr, + WidgetType.LABEL, + R.style.UXSDKRCBatteryListItem +) { + + //region Fields + private val widgetModel by lazy { + RCBatteryListItemWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance() + ) + } + //endregion + + //region Lifecycle + override fun reactToModelChanges() { + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + addReaction(widgetModel.rcBatteryState + .observeOn(SchedulerProvider.ui()) + .subscribe { this.updateUI(it) }) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun onButtonClick() { + // No implementation needed + } + //endregion + + //region Reactions to model + private fun updateUI(rcBatteryState: RCBatteryState) { + widgetStateDataProcessor.onNext(RCBatteryStateUpdated(rcBatteryState)) + when (rcBatteryState) { + RCBatteryState.RCDisconnected -> { + listItemLabelTextColor = disconnectedValueColor + listItemLabel = getString(R.string.uxsdk_string_default_value) + } + is RCBatteryState.Normal -> { + listItemLabelTextColor = normalValueColor + listItemLabel = getString(R.string.uxsdk_rc_battery_percent, rcBatteryState.remainingChargePercent) + } + is RCBatteryState.Low -> { + listItemLabelTextColor = errorValueColor + listItemLabel = getString(R.string.uxsdk_rc_battery_percent, rcBatteryState.remainingChargePercent) + } + } + } + //endregion + + //region Customization + override fun getIdealDimensionRatioString(): String? = null + + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription( + WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP + ) + + //endregion + + //region Hooks + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines the widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * RC battery State update + */ + data class RCBatteryStateUpdated(val rcBatteryState: RCBatteryState) : ModelState() + } + //endregion + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/rcbattery/RCBatteryListItemWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/rcbattery/RCBatteryListItemWidgetModel.kt new file mode 100644 index 00000000..9cb21d70 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/rcbattery/RCBatteryListItemWidgetModel.kt @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.rcbattery + +import dji.sdk.keyvalue.key.RemoteControllerKey +import dji.sdk.keyvalue.value.remotecontroller.BatteryInfo +import dji.sdk.keyvalue.key.KeyTools +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.panel.listitem.rcbattery.RCBatteryListItemWidgetModel.RCBatteryState.RCDisconnected +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Flowable + +/** + * Widget Model for the [RCBatteryListItemWidget] used to define + * the underlying logic and communication + */ + +class RCBatteryListItemWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + + //region Fields + + private val rcBatteryLevelProcessor: DataProcessor = DataProcessor.create(BatteryInfo()) + private val rcBatteryStateProcessor: DataProcessor = DataProcessor.create(RCDisconnected) + private val rcConnectionProcessor: DataProcessor = DataProcessor.create(false) + //endregion + + //region Data + /** + * Get the RC battery state + */ + val rcBatteryState: Flowable + get() = rcBatteryStateProcessor.toFlowable() + + //endregion + + //region Lifecycle + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + RemoteControllerKey.KeyConnection), rcConnectionProcessor) + bindDataProcessor( + KeyTools.createKey( + RemoteControllerKey.KeyBatteryInfo), rcBatteryLevelProcessor) + } + + override fun inCleanup() { + // No Clean up + } + + override fun updateStates() { + val rcBatteryLevelPercent = rcBatteryLevelProcessor.value.batteryPercent + if (rcConnectionProcessor.value && rcBatteryLevelPercent < 30) { + rcBatteryStateProcessor.onNext(RCBatteryState.Low(rcBatteryLevelPercent)) + } else if (rcConnectionProcessor.value) { + rcBatteryStateProcessor.onNext(RCBatteryState.Normal(rcBatteryLevelPercent)) + } else { + rcBatteryStateProcessor.onNext(RCDisconnected) + } + } + + /** + * Class to represent states of RCBatteryListItem + */ + sealed class RCBatteryState { + /** + * When remote controller is disconnected + */ + object RCDisconnected : RCBatteryState() + + /** + * When product is connected and rc battery is normal + */ + data class Normal(val remainingChargePercent: Int) : RCBatteryState() + + /** + * When product is connected and rc battery is critically low + */ + data class Low(val remainingChargePercent: Int) : RCBatteryState() + } + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/rcstickmode/RCStickModeListItemWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/rcstickmode/RCStickModeListItemWidget.kt new file mode 100644 index 00000000..0705fbd2 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/rcstickmode/RCStickModeListItemWidget.kt @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.rcstickmode + +import android.content.Context +import android.util.AttributeSet +import dji.sdk.keyvalue.value.remotecontroller.ControlMode +import dji.v5.utils.common.LogUtils +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.UXSDKError +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.panel.listitem.ListItemRadioButtonWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.panel.listitem.rcstickmode.RCStickModeListItemWidget.ModelState +import dji.v5.ux.core.panel.listitem.rcstickmode.RCStickModeListItemWidget.ModelState.* +import dji.v5.ux.core.panel.listitem.rcstickmode.RCStickModeListItemWidgetModel.RCStickModeState + +private const val TAG = "RCStickModeListItemWidget" + +/** + * Widget shows the various options for RC Stick mode. + * The current mode is shown selected. Tapping on another mode will + * change the mode. + */ +open class RCStickModeListItemWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ListItemRadioButtonWidget( + context, + attrs, + defStyleAttr, + R.style.UXSDKRCStickModeListItem +) { + + //region Fields + private val widgetModel by lazy { + RCStickModeListItemWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()) + } + + private var mode1ItemIndex: Int = INVALID_OPTION_INDEX + private var mode2ItemIndex: Int = INVALID_OPTION_INDEX + private var mode3ItemIndex: Int = INVALID_OPTION_INDEX + private var modeCustomItemIndex: Int = INVALID_OPTION_INDEX + //endregion + + //region Constructor + init { + mode1ItemIndex = addOptionToGroup(getString(R.string.uxsdk_rc_stick_mode_jp)) + mode2ItemIndex = addOptionToGroup(getString(R.string.uxsdk_rc_stick_mode_usa)) + mode3ItemIndex = addOptionToGroup(getString(R.string.uxsdk_rc_stick_mode_ch)) + } + //endregion + + //region Lifecycle + override fun reactToModelChanges() { + addReaction(widgetModel.rcStickModeState + .observeOn(SchedulerProvider.ui()) + .subscribe { updateUI(it) }) + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun onOptionTapped(optionIndex: Int, optionLabel: String) { + val rcStickModeState = when (optionIndex) { + mode1ItemIndex -> { + ControlMode.JP + } + mode2ItemIndex -> { + ControlMode.USA + } + mode3ItemIndex -> { + ControlMode.CH + } + modeCustomItemIndex -> { + ControlMode.CUSTOM + } + else -> return + } + addDisposable(widgetModel.setControlStickMode(rcStickModeState) + .observeOn(SchedulerProvider.ui()) + .subscribe({ + widgetStateDataProcessor.onNext(SetRCStickModeSucceeded) + }) { + widgetStateDataProcessor.onNext(SetRCStickModeFailed(it as UXSDKError)) + LogUtils.d(TAG, "failed " + it.djiError.description()) + }) + } + //endregion + + //region Reaction to model + private fun updateUI(rcStickModeState: RCStickModeState) { + widgetStateDataProcessor.onNext(RCStickModeUpdated(rcStickModeState)) + when (rcStickModeState) { + RCStickModeState.ProductDisconnected -> { + isEnabled = false + } + RCStickModeState.JP -> { + isEnabled = true + setSelected(mode1ItemIndex) + } + RCStickModeState.USA -> { + isEnabled = true + setSelected(mode2ItemIndex) + } + RCStickModeState.CH -> { + isEnabled = true + setSelected(mode3ItemIndex) + } + is RCStickModeState.Custom -> { + isEnabled = true + setSelected(modeCustomItemIndex) + } + } + } + //endregion + + //region Customization + override fun getIdealDimensionRatioString(): String? { + return null + } + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP) + //endregion + + //region Hooks + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Set RC stick mode success + */ + object SetRCStickModeSucceeded : ModelState() + + /** + * Set RC stick mode failed + */ + data class SetRCStickModeFailed(val error: UXSDKError) : ModelState() + + /** + * RC stick mode state updated + */ + data class RCStickModeUpdated(val rcStickModeState: RCStickModeState) : ModelState() + + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/rcstickmode/RCStickModeListItemWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/rcstickmode/RCStickModeListItemWidgetModel.kt new file mode 100644 index 00000000..4aae7c1a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/rcstickmode/RCStickModeListItemWidgetModel.kt @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.rcstickmode + +import dji.sdk.keyvalue.key.RemoteControllerKey +import dji.sdk.keyvalue.value.remotecontroller.ControlMode +import dji.v5.et.create +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import dji.v5.ux.core.util.UxErrorHandle +import io.reactivex.rxjava3.core.Completable +import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.core.Single + +private const val TAG = "RCStickModeListItemWidgetModel" + +/** + * Widget Model for the [RCStickModeListItemWidget] used to define + * the underlying logic and communication + */ +class RCStickModeListItemWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + + private val rcStickModeStateProcessor: DataProcessor = DataProcessor.create(RCStickModeState.ProductDisconnected) + private val controlModeProcessor: DataProcessor = DataProcessor.create(ControlMode.UNKNOWN) + + /** + * Get the current rc stick list item state + */ + val rcStickModeState: Flowable = rcStickModeStateProcessor.toFlowable() + + /** + * Set control stick mode to RC + * + * @param mode - state representing stick mode to be set to RC + * @return Completable representing the action + */ + fun setControlStickMode(mode: ControlMode): Completable { + return djiSdkModel.setValue(RemoteControllerKey.KeyControlMode.create(), mode) + } + + override fun inSetup() { + bindDataProcessor(RemoteControllerKey.KeyControlMode.create(), controlModeProcessor) { + updateCurrentStickMode(it) + } + } + + override fun inCleanup() { + // No clean up needed + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + addDisposable( + getControlStickMode() + .subscribe( + { updateCurrentStickMode(it) }, + UxErrorHandle.logErrorConsumer(TAG, "getMappingStyle ") + ) + ) + } else { + rcStickModeStateProcessor.onNext(RCStickModeState.ProductDisconnected) + } + } + + private fun updateCurrentStickMode(mode: ControlMode) { + when (mode) { + ControlMode.JP -> rcStickModeStateProcessor.onNext(RCStickModeState.JP) + ControlMode.USA -> rcStickModeStateProcessor.onNext(RCStickModeState.USA) + ControlMode.CH -> rcStickModeStateProcessor.onNext(RCStickModeState.CH) + ControlMode.CUSTOM -> rcStickModeStateProcessor.onNext(RCStickModeState.Custom) + ControlMode.UNKNOWN -> rcStickModeStateProcessor.onNext(RCStickModeState.ProductDisconnected) + } + } + + private fun getControlStickMode(): Single { + return djiSdkModel.getValue(RemoteControllerKey.KeyControlMode.create()) + } + + /** + * Class representing states for RCStickMode + */ + sealed class RCStickModeState { + /** + * When product is disconnected + */ + object ProductDisconnected : RCStickModeState() + + /** + * When product is connected and stick mode is JP + */ + object JP : RCStickModeState() + + /** + * When product is connected and stick mode is USA + */ + object USA : RCStickModeState() + + /** + * When product is connected and stick mode is CH + */ + object CH : RCStickModeState() + + /** + * When product is connected and stick mode is custom + */ + object Custom : RCStickModeState() + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/returntohomealtitude/ReturnToHomeAltitudeListItemWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/returntohomealtitude/ReturnToHomeAltitudeListItemWidget.kt new file mode 100644 index 00000000..806cafc5 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/returntohomealtitude/ReturnToHomeAltitudeListItemWidget.kt @@ -0,0 +1,374 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.returntohomealtitude + +import android.annotation.SuppressLint +import android.content.Context +import android.content.DialogInterface +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import androidx.annotation.StyleRes +import androidx.core.content.res.use +import dji.v5.utils.common.LogUtils +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.UXSDKError +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.panel.listitem.ListItemEditTextButtonWidget +import dji.v5.ux.core.base.panel.listitem.ListItemEditTextButtonWidget.UIState.DialogDismissed +import dji.v5.ux.core.base.panel.listitem.ListItemEditTextButtonWidget.UIState.DialogDisplayed +import dji.v5.ux.core.communication.GlobalPreferencesManager +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.panel.listitem.returntohomealtitude.ReturnToHomeAltitudeListItemWidget.DialogType.MaxAltitudeExceeded +import dji.v5.ux.core.panel.listitem.returntohomealtitude.ReturnToHomeAltitudeListItemWidget.ModelState +import dji.v5.ux.core.panel.listitem.returntohomealtitude.ReturnToHomeAltitudeListItemWidget.ModelState.ProductConnected +import dji.v5.ux.core.panel.listitem.returntohomealtitude.ReturnToHomeAltitudeListItemWidget.ModelState.ReturnToHomeAltitudeStateUpdated +import dji.v5.ux.core.panel.listitem.returntohomealtitude.ReturnToHomeAltitudeListItemWidgetModel.ReturnToHomeAltitudeState +import dji.v5.ux.core.panel.listitem.returntohomealtitude.ReturnToHomeAltitudeListItemWidgetModel.ReturnToHomeAltitudeState.ReturnToHomeAltitudeValue +import dji.v5.ux.core.util.UnitConversionUtil.UnitType + +private const val TAG = "RTHAltitudeListItem" + +/** + * Widget shows the current return to home altitude. + * The widget enables the user to modify this value. Tap on the limit and enter + * the new value to modify the return home altitude. + * The return to home altitude cannot exceed the maximum flight altitude. + */ +open class ReturnToHomeAltitudeListItemWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleArr: Int = 0 +) : ListItemEditTextButtonWidget( + context, + attrs, + defStyleArr, + WidgetType.EDIT, + R.style.UXSDKReturnToHomeAltitudeListItem +) { + + //region Fields + /** + * Enable/Disable toast messages in the widget + */ + var toastMessagesEnabled: Boolean = true + + /** + * Theme for the dialogs shown in the widget + */ + @StyleRes + var dialogTheme: Int = R.style.UXSDKDialogTheme + + /** + * Icon for error dialog + */ + var errorDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_alert_error) + + /** + * Icon for success dialog + */ + var successDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_alert_good) + + private val widgetModel: ReturnToHomeAltitudeListItemWidgetModel by lazy { + ReturnToHomeAltitudeListItemWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + GlobalPreferencesManager.getInstance() + ) + } + //endregion + + //region Constructor + init { + initAttributes(context, attrs) + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.returnToHomeAltitudeState + .observeOn(SchedulerProvider.ui()) + .subscribe { + widgetStateDataProcessor.onNext(ReturnToHomeAltitudeStateUpdated(it)) + this.updateUI(it) + }) + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + } + + override fun onButtonClick() { + // Do nothing + } + + override fun onKeyboardDoneAction() { + val currentValue = listItemEditTextValue?.toIntOrNull() + if (currentValue != null + && widgetModel.isInputInRange(currentValue)) { + addDisposable( + widgetModel.returnToHomeAltitudeState.firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe({ + if (it is ReturnToHomeAltitudeValue) { + if (it.maxFlightAltitude < currentValue) { + val dialogDismissListener = DialogInterface.OnDismissListener { + uiUpdateStateProcessor.onNext(DialogDismissed(MaxAltitudeExceeded)) + } + showAlertDialog( + dialogTheme = dialogTheme, + icon = errorDialogIcon, + title = getString(R.string.uxsdk_list_rth_dialog_title), + message = getString(R.string.uxsdk_rth_error_dialog_message, it.maxFlightAltitude), + dialogDismissListener = dialogDismissListener + ) + uiUpdateStateProcessor.onNext(DialogDisplayed(MaxAltitudeExceeded)) + resetToDefaultValue() + } else { + setReturnToHomeAltitude(currentValue) + } + } + }, { + resetToDefaultValue() + LogUtils.d(TAG, it.message) + }) + ) + + } else { + resetToDefaultValue() + showToast(getString(R.string.uxsdk_list_item_value_out_of_range)) + } + } + + override fun onEditorTextChanged(currentText: String?) { + listItemEditTextColor = if (!currentText.isNullOrBlank() + && currentText.toIntOrNull() != null + && widgetModel.isInputInRange(currentText.toInt())) { + editTextNormalColor + } else { + errorValueColor + } + } + //endregion + + //region Reactions to model + private fun updateUI(returnToHomeAltitudeState: ReturnToHomeAltitudeState) { + when (returnToHomeAltitudeState) { + ReturnToHomeAltitudeState.ProductDisconnected -> updateProductDisconnectedState() + is ReturnToHomeAltitudeState.NoviceMode -> updateNoviceMode(returnToHomeAltitudeState.unitType) + is ReturnToHomeAltitudeValue -> updateReturnToHomeValue(returnToHomeAltitudeState) + } + } + + private fun updateReturnToHomeValue(returnToHomeAltitudeListItemState: ReturnToHomeAltitudeValue) { + listItemEditTextVisibility = true + listItemHintVisibility = true + listItemHint = if (returnToHomeAltitudeListItemState.unitType == UnitType.METRIC) { + getString(R.string.uxsdk_altitude_range_meters, returnToHomeAltitudeListItemState.minLimit, returnToHomeAltitudeListItemState.maxLimit) + } else { + getString(R.string.uxsdk_altitude_range_feet, returnToHomeAltitudeListItemState.minLimit, returnToHomeAltitudeListItemState.maxLimit) + } + listItemEditTextValue = returnToHomeAltitudeListItemState.returnToHomeAltitude.toString() + isEnabled = true + listItemEditTextColor = editTextNormalColor + } + + private fun updateProductDisconnectedState() { + listItemEditTextVisibility = true + listItemHintVisibility = false + listItemEditTextValue = getString(R.string.uxsdk_string_default_value) + isEnabled = false + listItemEditTextColor = disconnectedValueColor + } + + private fun updateNoviceMode(unitType: UnitType) { + listItemEditTextVisibility = true + listItemHintVisibility = false + listItemEditTextValue = if (unitType == UnitType.METRIC) { + getString(R.string.uxsdk_novice_mode_altitude_meters) + } else { + getString(R.string.uxsdk_novice_mode_altitude_feet) + } + isEnabled = false + listItemEditTextColor = disconnectedValueColor + } + //endregion + + //region Helpers + private fun showToast(message: String?) { + if (toastMessagesEnabled) { + showShortToast(message) + } + } + + private fun setReturnToHomeAltitude(currentValue: Int) { + addDisposable( + widgetModel.setReturnToHomeAltitude(currentValue) + .observeOn(SchedulerProvider.ui()) + .subscribe({ + val dialogDismissListener = DialogInterface.OnDismissListener { + uiUpdateStateProcessor.onNext(DialogDismissed(DialogType.ReturnHomeAltitudeChangeConfirmation)) + } + showAlertDialog( + dialogTheme = dialogTheme, + icon = successDialogIcon, + title = getString(R.string.uxsdk_list_rth_dialog_title), + message = getString(R.string.uxsdk_rth_success_dialog_message), + dialogDismissListener = dialogDismissListener + ) + uiUpdateStateProcessor.onNext(DialogDisplayed(DialogType.ReturnHomeAltitudeChangeConfirmation)) + widgetStateDataProcessor.onNext(ModelState.SetReturnToHomeAltitudeSucceeded) + }, { error -> + if (error is UXSDKError) { + showToast(error.djiError.description()) + widgetStateDataProcessor.onNext(ModelState.SetReturnToHomeAltitudeFailed(error)) + LogUtils.e(TAG, error.djiError.description()) + } + }) + ) + } + + private fun resetToDefaultValue() { + addDisposable( + widgetModel.returnToHomeAltitudeState.firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe({ + updateUI(it) + }, { + LogUtils.e(TAG, it.message) + }) + ) + } + //endregion + + //region Customization + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet?) { + context.obtainStyledAttributes(attrs, R.styleable.ReturnToHomeAltitudeListItemWidget, 0, defaultStyle).use { typedArray -> + toastMessagesEnabled = typedArray.getBoolean(R.styleable.ReturnToHomeAltitudeListItemWidget_uxsdk_toast_messages_enabled, toastMessagesEnabled) + typedArray.getResourceIdAndUse(R.styleable.ReturnToHomeAltitudeListItemWidget_uxsdk_list_item_dialog_theme) { + dialogTheme = it + } + typedArray.getDrawableAndUse(R.styleable.ReturnToHomeAltitudeListItemWidget_uxsdk_list_item_error_dialog_icon) { + errorDialogIcon = it + } + typedArray.getDrawableAndUse(R.styleable.ReturnToHomeAltitudeListItemWidget_uxsdk_list_item_success_dialog_icon) { + successDialogIcon = it + } + } + } + + override fun getIdealDimensionRatioString(): String? { + return null + } + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription( + WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP + ) + //endregion + + + //region Hooks + + /** + * Get the [ListItemEditTextButtonWidget.UIState] updates + * The info parameter is instance of [DialogType] + */ + override fun getUIStateUpdates(): Flowable { + return uiUpdateStateProcessor.onBackpressureBuffer() + } + + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Return to home list item dialog identifiers + */ + sealed class DialogType { + /** + * Dialog shown when return to home altitude + * exceeds max altitude limit + */ + object MaxAltitudeExceeded : DialogType() + + /** + * Dialog shown to warn user when return to home altitude is + * updated successfully + */ + object ReturnHomeAltitudeChangeConfirmation : DialogType() + + } + + /** + * Class defines widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Return to home altitude set action successful + */ + object SetReturnToHomeAltitudeSucceeded : ModelState() + + /** + * Return to home altitude set action failed + */ + data class SetReturnToHomeAltitudeFailed(val error: UXSDKError) : ModelState() + + /** + * Return to home altitude state updated + */ + data class ReturnToHomeAltitudeStateUpdated(val maxAltitudeState: ReturnToHomeAltitudeState) : + ModelState() + } + //endregion + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/returntohomealtitude/ReturnToHomeAltitudeListItemWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/returntohomealtitude/ReturnToHomeAltitudeListItemWidgetModel.kt new file mode 100644 index 00000000..11f27c07 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/returntohomealtitude/ReturnToHomeAltitudeListItemWidgetModel.kt @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.returntohomealtitude + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.value.common.IntValueConfig +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.GlobalPreferenceKeys +import dji.v5.ux.core.communication.GlobalPreferencesInterface +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.panel.listitem.returntohomealtitude.ReturnToHomeAltitudeListItemWidgetModel.ReturnToHomeAltitudeState.* +import dji.v5.ux.core.util.DataProcessor +import dji.v5.ux.core.util.UnitConversionUtil.* +import io.reactivex.rxjava3.core.Completable +import kotlin.math.roundToInt + +private const val MIN_LIMIT = 20 +private const val MAX_LIMIT = 500 + +/** + * Widget Model for the [ReturnToHomeAltitudeListItemWidget] used to define + * the underlying logic and communication + */ +class ReturnToHomeAltitudeListItemWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, + private val preferencesManager: GlobalPreferencesInterface? +) : WidgetModel(djiSdkModel, keyedStore) { + + private val maxFlightAltitudeProcessor: DataProcessor = DataProcessor.create(0) + private val returnToHomeAltitudeProcessor: DataProcessor = DataProcessor.create(0) + private val unitTypeProcessor: DataProcessor = DataProcessor.create(UnitType.METRIC) + private val returnToHomeAltitudeStateProcessor: DataProcessor = DataProcessor.create(ProductDisconnected) + private val noviceModeProcessor: DataProcessor = DataProcessor.create(false) + private val maxFlightHeightRangeProcessor: DataProcessor = DataProcessor.create(IntValueConfig()) + + /** + * Get the return to home altitude state + */ + val returnToHomeAltitudeState: Flowable + get() = returnToHomeAltitudeStateProcessor.toFlowable() + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyGoHomeHeight), returnToHomeAltitudeProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyHeightLimit), maxFlightAltitudeProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyHeightLimitRange), maxFlightHeightRangeProcessor) + val unitTypeKey = GlobalPreferenceKeys.create(GlobalPreferenceKeys.UNIT_TYPE) + bindDataProcessor(unitTypeKey, unitTypeProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyNoviceModeEnabled), noviceModeProcessor) + preferencesManager?.setUpListener() + preferencesManager?.let { unitTypeProcessor.onNext(it.unitType) } + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + if (noviceModeProcessor.value) { + returnToHomeAltitudeStateProcessor.onNext(NoviceMode(unitTypeProcessor.value)) + } else { + returnToHomeAltitudeStateProcessor.onNext( + ReturnToHomeAltitudeValue(returnToHomeAltitude = getReturnToHomeAltitudeValue(), + minLimit = getMinLimit(), + maxLimit = getMaxLimit(), + unitType = unitTypeProcessor.value, + maxFlightAltitude = getMaxAltitudeLimitByUnit())) + } + } else { + returnToHomeAltitudeStateProcessor.onNext(ProductDisconnected) + } + } + + private fun getMaxAltitudeLimitByUnit(): Int { + return if (unitTypeProcessor.value == UnitType.IMPERIAL) { + convertMetersToFeet(maxFlightAltitudeProcessor.value.toFloat()).roundToInt() + } else { + maxFlightAltitudeProcessor.value + } + } + + + override fun inCleanup() { + preferencesManager?.cleanup() + } + + private fun getReturnToHomeAltitudeValue(): Int { + return if (unitTypeProcessor.value == UnitType.IMPERIAL) { + convertMetersToFeet(returnToHomeAltitudeProcessor.value.toFloat()).roundToInt() + } else { + returnToHomeAltitudeProcessor.value + } + } + + private fun getMinLimit(): Int { + val tempMinValue: Int = maxFlightHeightRangeProcessor.value.min + return if (unitTypeProcessor.value == UnitType.METRIC) { + tempMinValue + } else { + convertMetersToFeet(tempMinValue.toFloat()).roundToInt() + } + } + + private fun getMaxLimit(): Int { + val tempMaxValue: Int = maxFlightHeightRangeProcessor.value.max + return if (unitTypeProcessor.value == UnitType.METRIC) { + tempMaxValue + } else { + convertMetersToFeet(tempMaxValue.toFloat()).roundToInt() + } + } + + /** + * Set return to home altitude + * + * @return Completable to determine status of action + */ + fun setReturnToHomeAltitude(returnToHomeAltitude: Int): Completable { + val tempAltitude: Int = if (unitTypeProcessor.value == UnitType.IMPERIAL) { + convertFeetToMeters(returnToHomeAltitude.toFloat()).toInt() + } else { + returnToHomeAltitude + } + return djiSdkModel.setValue( + KeyTools.createKey( + FlightControllerKey.KeyGoHomeHeight), tempAltitude) + } + + /** + * Check if input is in range + * + * @return Boolean + * true - if the input is in range + * false - if the input is out of range + */ + fun isInputInRange(input: Int): Boolean = input >= getMinLimit() && input <= getMaxLimit() + + /** + * Class represents states of Return To Home Altitude List Item + */ + sealed class ReturnToHomeAltitudeState { + /** + * When product is disconnected + */ + object ProductDisconnected : ReturnToHomeAltitudeState() + + /** + * When product is in beginner mode + * @property unitType - current unit system used + */ + data class NoviceMode(val unitType: UnitType) : ReturnToHomeAltitudeState() + + + /** + * Return to home value and range + * along with unit + * @property returnToHomeAltitude - Return to home altitude + * @property minLimit - Minimum limit of return to home altitude + * @property maxLimit - Maximum limit of return to home altitude + * @property unitType - Unit of values + * @property maxFlightAltitude - Maximum permitted flight altitude. + */ + data class ReturnToHomeAltitudeValue(val returnToHomeAltitude: Int, + val minLimit: Int, + val maxLimit: Int, + val unitType: UnitType, + val maxFlightAltitude: Int) : ReturnToHomeAltitudeState() + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/sdcardstatus/SDCardStatusListItemWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/sdcardstatus/SDCardStatusListItemWidget.kt new file mode 100644 index 00000000..e569c329 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/sdcardstatus/SDCardStatusListItemWidget.kt @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.sdcardstatus + +import android.annotation.SuppressLint +import android.content.Context +import android.content.DialogInterface +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import androidx.annotation.StyleRes +import androidx.core.content.res.use +import dji.sdk.keyvalue.value.camera.CameraSDCardState +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.UXSDKError +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.panel.listitem.ListItemLabelButtonWidget +import dji.v5.ux.core.base.panel.listitem.ListItemLabelButtonWidget.UIState.DialogDismissed +import dji.v5.ux.core.base.panel.listitem.ListItemLabelButtonWidget.UIState.DialogDisplayed +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.panel.listitem.sdcardstatus.SDCardStatusListItemWidget.DialogType.* +import dji.v5.ux.core.panel.listitem.sdcardstatus.SDCardStatusListItemWidget.ModelState +import dji.v5.ux.core.panel.listitem.sdcardstatus.SDCardStatusListItemWidget.ModelState.ProductConnected +import dji.v5.ux.core.util.UnitConversionUtil.getSpaceWithUnit + +/** + * SDCard status list item + */ +open class SDCardStatusListItemWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ListItemLabelButtonWidget( + context, + attrs, + defStyleAttr, + WidgetType.LABEL_BUTTON, + R.style.UXSDKSDCardStatusListItem +) { + + //region Fields + /** + * Theme for the dialogs shown for format + */ + @StyleRes + var dialogTheme: Int = R.style.UXSDKDialogTheme + + /** + * Icon for the dialog which shows format confirmation message + */ + var formatConfirmationDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_alert_yellow) + + /** + * Icon for the dialog which shows format success message + */ + var formatSuccessDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_alert_good) + + /** + * Icon for the dialog which shows format error message + */ + var formatErrorDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_alert_error) + + private val widgetModel: SDCardStatusListItemWidgetModel by lazy { + SDCardStatusListItemWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()) + } + //endregion + + //region Constructor + init { + initAttributes(context, attrs) + } + //endregion + + //region Lifecycle + override fun reactToModelChanges() { + addReaction(widgetModel.sdCardState + .observeOn(SchedulerProvider.ui()) + .subscribe { this.updateUI(it) }) + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + } + + override fun onButtonClick() { + val dialogListener = DialogInterface.OnClickListener { dialogInterface, buttonId: Int -> + if (buttonId == DialogInterface.BUTTON_POSITIVE) { + uiUpdateStateProcessor.onNext(UIState.DialogActionConfirmed(FormatConfirmation)) + formatSDCard() + } else { + uiUpdateStateProcessor.onNext(UIState.DialogActionCanceled(FormatConfirmation)) + } + dialogInterface.dismiss() + } + val dialogDismissListener = DialogInterface.OnDismissListener { + uiUpdateStateProcessor.onNext(DialogDismissed(FormatConfirmation)) + } + showConfirmationDialog(title = getString(R.string.uxsdk_sd_card_dialog_title), + icon = formatConfirmationDialogIcon, + dialogTheme = dialogTheme, + message = getString(R.string.uxsdk_sd_card_format_confirmation), + dialogClickListener = dialogListener, + dialogDismissListener = dialogDismissListener) + uiUpdateStateProcessor.onNext(DialogDisplayed(FormatConfirmation)) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + //endregion + + //region Reactions to model + private fun updateUI(sdCardState: SDCardStatusListItemWidgetModel.SDCardState) { + widgetStateDataProcessor.onNext(ModelState.SDCardStateUpdated(sdCardState)) + when (sdCardState) { + SDCardStatusListItemWidgetModel.SDCardState.ProductDisconnected -> { + listItemLabel = getString(R.string.uxsdk_string_default_value) + listItemLabelTextColor = disconnectedValueColor + isEnabled = false + } + is SDCardStatusListItemWidgetModel.SDCardState.CurrentSDCardState -> { + isEnabled = true + listItemLabel = getSDCardMessage(sdCardState.sdCardOperationState, + sdCardState.remainingSpace) + listItemLabelTextColor = getSDCardMessageColor(sdCardState.sdCardOperationState) + listItemButtonEnabled = getFormatButtonVisibility(sdCardState.sdCardOperationState) + } + } + } + //endregion + + //region Helpers + private fun formatSDCard() { + var dialogType: DialogType? = null + val dialogDismissListener = DialogInterface.OnDismissListener { + uiUpdateStateProcessor.onNext(DialogDismissed(dialogType)) + } + addDisposable(widgetModel.formatSDCard() + .observeOn(SchedulerProvider.ui()) + .subscribe({ + dialogType = FormatSuccess + showAlertDialog(title = getString(R.string.uxsdk_sd_card_dialog_title), + icon = formatSuccessDialogIcon, + dialogTheme = dialogTheme, + message = getString(R.string.uxsdk_sd_card_format_complete), + dialogDismissListener = dialogDismissListener) + uiUpdateStateProcessor.onNext(DialogDisplayed(dialogType)) + }, { error -> + if (error is UXSDKError) { + dialogType = FormatError + showAlertDialog(title = getString(R.string.uxsdk_sd_card_dialog_title), + icon = formatErrorDialogIcon, + dialogTheme = dialogTheme, + message = String.format(getString(R.string.uxsdk_sd_card_format_error), + error.djiError.description()), + dialogDismissListener = dialogDismissListener) + uiUpdateStateProcessor.onNext(DialogDisplayed(dialogType)) + } + })) + } + + + private fun getFormatButtonVisibility(sdCardOperationState: CameraSDCardState): Boolean { + return when (sdCardOperationState) { + CameraSDCardState.NORMAL, + CameraSDCardState.FORMAT_RECOMMENDED, + CameraSDCardState.FULL, + CameraSDCardState.SLOW, + CameraSDCardState.WRITING_SLOWLY, + CameraSDCardState.INVALID_FILE_SYSTEM, + CameraSDCardState.FORMAT_NEEDED -> true + else -> false + } + } + + private fun getSDCardMessageColor(sdCardOperationState: CameraSDCardState): Int { + return when (sdCardOperationState) { + CameraSDCardState.NORMAL -> normalValueColor + else -> warningValueColor + } + } + + private fun getSDCardMessage(sdCardOperationState: CameraSDCardState, + space: Int): String? { + return when (sdCardOperationState) { + CameraSDCardState.NORMAL -> getSpaceWithUnit(context, space) + CameraSDCardState.NOT_INSERTED -> getString(R.string.uxsdk_storage_status_missing) + CameraSDCardState.INVALID -> getString(R.string.uxsdk_storage_status_invalid) + CameraSDCardState.READ_ONLY -> getString(R.string.uxsdk_storage_status_write_protect) + CameraSDCardState.INVALID_FILE_SYSTEM, + CameraSDCardState.FORMAT_NEEDED -> getString(R.string.uxsdk_storage_status_needs_formatting) + CameraSDCardState.FORMATTING -> getString(R.string.uxsdk_storage_status_formatting) + CameraSDCardState.BUSY -> getString(R.string.uxsdk_storage_status_busy) + CameraSDCardState.FULL -> getString(R.string.uxsdk_storage_status_full) + CameraSDCardState.SLOW -> String.format(getString(R.string.uxsdk_storage_status_slow), getSpaceWithUnit(context, space)) + CameraSDCardState.NO_REMAINING_FILE_INDICES -> getString(R.string.uxsdk_storage_status_file_indices) + CameraSDCardState.INITIALIZING -> getString(R.string.uxsdk_storage_status_initial) + CameraSDCardState.FORMAT_RECOMMENDED -> getString(R.string.uxsdk_storage_status_formatting_recommended) + CameraSDCardState.RECOVERING_FILES -> getString(R.string.uxsdk_storage_status_recover_file) + CameraSDCardState.WRITING_SLOWLY -> getString(R.string.uxsdk_storage_status_write_slow) + CameraSDCardState.USB_CONNECTED -> getString(R.string.uxsdk_storage_status_usb_connected) + CameraSDCardState.UNKNOWN_ERROR -> getString(R.string.uxsdk_storage_status_unknown_error) + CameraSDCardState.UNKNOWN -> getString(R.string.uxsdk_string_default_value) + } + + } + //endregion + + //region Customization + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet?) { + context.obtainStyledAttributes(attrs, R.styleable.SDCardStatusListItemWidget,0, defaultStyle).use { typedArray -> + typedArray.getDrawableAndUse(R.styleable.SDCardStatusListItemWidget_uxsdk_list_item_confirmation_dialog_icon) { + formatConfirmationDialogIcon = it + } + typedArray.getDrawableAndUse(R.styleable.SDCardStatusListItemWidget_uxsdk_list_item_success_dialog_icon) { + formatSuccessDialogIcon = it + } + typedArray.getDrawableAndUse(R.styleable.SDCardStatusListItemWidget_uxsdk_list_item_error_dialog_icon) { + formatErrorDialogIcon = it + } + typedArray.getResourceIdAndUse(R.styleable.SDCardStatusListItemWidget_uxsdk_list_item_dialog_theme) { + dialogTheme = it + } + + } + } + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP) + + override fun getIdealDimensionRatioString(): String? { + return null + } + //endregion + + //region Hooks + + /** + * Get the [ListItemLabelButtonWidget.UIState] updates + * The info parameter is instance of [DialogType] + */ + override fun getUIStateUpdates(): Flowable { + return uiUpdateStateProcessor.onBackpressureBuffer() + } + + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * SD Card List Item Dialog Identifiers + */ + sealed class DialogType { + /** + * Dialog shown for format confirmation + */ + object FormatConfirmation : DialogType() + + /** + * Dialog shown for format success + */ + object FormatSuccess : DialogType() + + /** + * Dialog shown for format fail + */ + object FormatError : DialogType() + } + + /** + * Class defines widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Current SD Card List Item State + */ + data class SDCardStateUpdated(val sdCardState: SDCardStatusListItemWidgetModel.SDCardState) : ModelState() + } + //endregion + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/sdcardstatus/SDCardStatusListItemWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/sdcardstatus/SDCardStatusListItemWidgetModel.kt new file mode 100644 index 00000000..b95c6799 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/sdcardstatus/SDCardStatusListItemWidgetModel.kt @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.sdcardstatus + +import dji.sdk.keyvalue.key.CameraKey +import dji.sdk.keyvalue.value.camera.CameraSDCardState +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.value.common.ComponentIndexType +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Completable + + +/** + * Widget Model for the [SDCardStatusListItemWidget] used to define + * the underlying logic and communication + */ +class SDCardStatusListItemWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + + + private val sdCardStateProcessor: DataProcessor = DataProcessor.create(SDCardState.ProductDisconnected) + private val sdCardRemainingCapacityProcessor = DataProcessor.create(0) + private val sdCardOperationStateProcessor = DataProcessor.create(CameraSDCardState.UNKNOWN) + + /** + * Index of sdCard + */ + var cameraIndex = ComponentIndexType.LEFT_OR_MAIN + set(value) { + field = value + restart() + } + + /** + * Get the sd card state + */ + val sdCardState: Flowable = sdCardStateProcessor.toFlowable() + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + CameraKey.KeySSDRemainingSpaceInMB, cameraIndex), sdCardRemainingCapacityProcessor) + bindDataProcessor( + KeyTools.createKey( + CameraKey.KeyCameraSDCardState, cameraIndex), sdCardOperationStateProcessor) + + } + + override fun inCleanup() { + //No clean up necessary + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + sdCardStateProcessor.onNext( + SDCardState.CurrentSDCardState( + sdCardOperationStateProcessor.value, + sdCardRemainingCapacityProcessor.value + ) + ) + } else { + sdCardStateProcessor.onNext(SDCardState.ProductDisconnected) + } + + } + + /** + * Format SDCard + */ + fun formatSDCard(): Completable { + return djiSdkModel.performActionWithOutResult( + KeyTools.createKey( + CameraKey.KeyFormatStorage, cameraIndex)) + } + + /** + * Class represents states of SDCard List Item + */ + sealed class SDCardState { + /** + * When product is disconnected + */ + object ProductDisconnected : SDCardState() + + /** + * When product is connected + * @property sdCardOperationState - Current operation State of SDCard + * @property remainingSpace - Remaining space in MB + */ + data class CurrentSDCardState( + val sdCardOperationState: CameraSDCardState, + val remainingSpace: Int + ) : SDCardState() + + } + + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/ssdstatus/SSDStatusListItemWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/ssdstatus/SSDStatusListItemWidget.kt new file mode 100644 index 00000000..51f4112f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/ssdstatus/SSDStatusListItemWidget.kt @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.ssdstatus + +import android.annotation.SuppressLint +import android.content.Context +import android.content.DialogInterface +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import androidx.annotation.StyleRes +import androidx.core.content.res.use +import dji.sdk.keyvalue.value.camera.SSDOperationState +import dji.v5.utils.common.JsonUtil +import dji.v5.utils.common.LogUtils +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.UXSDKError +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.panel.listitem.ListItemLabelButtonWidget +import dji.v5.ux.core.base.panel.listitem.ListItemLabelButtonWidget.UIState.* +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.panel.listitem.ssdstatus.SSDStatusListItemWidget.DialogType.* +import dji.v5.ux.core.panel.listitem.ssdstatus.SSDStatusListItemWidget.ModelState +import dji.v5.ux.core.panel.listitem.ssdstatus.SSDStatusListItemWidget.ModelState.ProductConnected +import dji.v5.ux.core.panel.listitem.ssdstatus.SSDStatusListItemWidget.ModelState.SSDStateUpdated +import dji.v5.ux.core.panel.listitem.ssdstatus.SSDStatusListItemWidgetModel.SSDState +import dji.v5.ux.core.util.UnitConversionUtil +import io.reactivex.rxjava3.core.Flowable + +/** + * SSD status list item + * + * It displays the remaining capacity of the SSD along with + * any warnings / errors related to the SSD. + * It provides a button to format SSD. + */ +open class SSDStatusListItemWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ListItemLabelButtonWidget( + context, + attrs, + defStyleAttr, + WidgetType.LABEL_BUTTON, + R.style.UXSDKSSDStatusListItem +) { + + //region Fields + /** + * Theme for the dialogs shown for format + */ + @StyleRes + var dialogTheme: Int = R.style.UXSDKDialogTheme + + /** + * Icon for the dialog which shows format confirmation message + */ + var formatConfirmationDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_alert_yellow) + + /** + * Icon for the dialog which shows format success message + */ + var formatSuccessDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_alert_good) + + /** + * Icon for the dialog which shows format error message + */ + var formatErrorDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_alert_error) + + private val widgetModel: SSDStatusListItemWidgetModel by lazy { + SSDStatusListItemWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()) + } + //endregion + + //region Constructor + init { + initAttributes(context, attrs) + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun onButtonClick() { + val dialogListener = DialogInterface.OnClickListener { dialogInterface, buttonId: Int -> + if (buttonId == DialogInterface.BUTTON_POSITIVE) { + uiUpdateStateProcessor.onNext(DialogActionConfirmed(FormatConfirmation)) + formatSSD() + } else { + uiUpdateStateProcessor.onNext(DialogActionCanceled(FormatConfirmation)) + } + dialogInterface.dismiss() + + } + val dialogDismissListener = DialogInterface.OnDismissListener { + uiUpdateStateProcessor.onNext(DialogDismissed(FormatConfirmation)) + } + showConfirmationDialog(title = getString(R.string.uxsdk_ssd_dialog_title), + icon = formatConfirmationDialogIcon, + dialogTheme = dialogTheme, + message = getString(R.string.uxsdk_ssd_format_confirmation), + dialogClickListener = dialogListener, + dialogDismissListener = dialogDismissListener) + uiUpdateStateProcessor.onNext(DialogDisplayed(FormatConfirmation)) + } + + override fun reactToModelChanges() { + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + addReaction(widgetModel.ssdState + .observeOn(SchedulerProvider.ui()) + .subscribe { this.updateUI(it) }) + + } + + //endregion + + //region Reactions to models + + private fun updateUI(ssdState: SSDState) { + LogUtils.i(logTag,JsonUtil.toJson(ssdState)) + widgetStateDataProcessor.onNext(SSDStateUpdated(ssdState)) + when (ssdState) { + SSDState.ProductDisconnected, + SSDState.NotSupported -> updateDisabledState(ssdState) + + is SSDState.CurrentSSDState -> { + isEnabled = true + listItemLabel = getSSDMessage(ssdState.ssdOperationState, ssdState.remainingSpace) + listItemLabelTextColor = getSSDMessageColor(ssdState.ssdOperationState) + listItemButtonEnabled = getFormatButtonVisibility(ssdState.ssdOperationState) + } + } + } + //endregion + + //region Helpers + private fun getSSDMessage(ssdState: SSDOperationState, remainingSpace: Int): String { + return when (ssdState) { + SSDOperationState.NOT_FOUND -> getString(R.string.uxsdk_ssd_not_found) + SSDOperationState.IDLE -> UnitConversionUtil.getSpaceWithUnit(context, remainingSpace) + SSDOperationState.SAVING -> getString(R.string.uxsdk_ssd_saving) + SSDOperationState.FORMATTING -> getString(R.string.uxsdk_ssd_formatting) + SSDOperationState.INITIALIZING -> getString(R.string.uxsdk_ssd_initializing) + SSDOperationState.STATE_ERROR -> getString(R.string.uxsdk_ssd_error) + SSDOperationState.FULL -> getString(R.string.uxsdk_ssd_full) + SSDOperationState.POOR_CONNECTION -> getString(R.string.uxsdk_ssd_poor_connection) + SSDOperationState.SWITCHING_LICENSE -> getString(R.string.uxsdk_ssd_switching_license) + SSDOperationState.FORMATTING_REQUIRED -> getString(R.string.uxsdk_ssd_formatting_required) + SSDOperationState.NOT_INITIALIZED -> getString(R.string.uxsdk_ssd_not_initialized) + SSDOperationState.INVALID_FILE_SYSTEM -> getString(R.string.uxsdk_ssd_formatting_required) + SSDOperationState.UNKNOWN -> getString(R.string.uxsdk_string_default_value) + } + } + + private fun getSSDMessageColor(ssdState: SSDOperationState): Int { + return when (ssdState) { + SSDOperationState.IDLE -> normalValueColor + SSDOperationState.STATE_ERROR -> errorValueColor + else -> warningValueColor + } + } + + private fun getFormatButtonVisibility(ssdState: SSDOperationState): Boolean { + return when (ssdState) { + SSDOperationState.FORMATTING_REQUIRED, + SSDOperationState.INVALID_FILE_SYSTEM, + SSDOperationState.FULL, + SSDOperationState.IDLE -> true + else -> false + } + } + + private fun updateDisabledState(ssdState: SSDState) { + listItemLabel = if (ssdState is SSDState.ProductDisconnected) { + getString(R.string.uxsdk_string_default_value) + } else { + getString(R.string.uxsdk_storage_status_not_supported) + } + listItemLabelTextColor = if (ssdState is SSDState.ProductDisconnected) { + disconnectedValueColor + } else { + errorValueColor + } + isEnabled = false + } + + private fun formatSSD() { + var dialogType: DialogType? = null + val dialogDismissListener = DialogInterface.OnDismissListener { + uiUpdateStateProcessor.onNext(DialogDismissed(dialogType)) + } + addDisposable(widgetModel.formatSSD() + .observeOn(SchedulerProvider.ui()) + .subscribe({ + dialogType = FormatSuccess + showAlertDialog(title = getString(R.string.uxsdk_ssd_dialog_title), + icon = formatSuccessDialogIcon, + dialogTheme = dialogTheme, + message = getString(R.string.uxsdk_ssd_format_complete), + dialogDismissListener = dialogDismissListener) + uiUpdateStateProcessor.onNext(DialogDisplayed(dialogType)) + }, { error -> + if (error is UXSDKError) { + dialogType = FormatError + showAlertDialog(title = getString(R.string.uxsdk_ssd_dialog_title), + icon = formatErrorDialogIcon, + dialogTheme = dialogTheme, + message = getString(R.string.uxsdk_ssd_format_error, error.djiError.description()), + dialogDismissListener = dialogDismissListener) + uiUpdateStateProcessor.onNext(DialogDisplayed(dialogType)) + } + })) + } + //endregion + + //region Customizations + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet?) { + context.obtainStyledAttributes(attrs, R.styleable.SSDStatusListItemWidget, 0, defaultStyle).use { typedArray -> + typedArray.getDrawableAndUse(R.styleable.SSDStatusListItemWidget_uxsdk_list_item_confirmation_dialog_icon) { + formatConfirmationDialogIcon = it + } + typedArray.getDrawableAndUse(R.styleable.SSDStatusListItemWidget_uxsdk_list_item_success_dialog_icon) { + formatSuccessDialogIcon = it + } + typedArray.getDrawableAndUse(R.styleable.SSDStatusListItemWidget_uxsdk_list_item_error_dialog_icon) { + formatErrorDialogIcon = it + } + typedArray.getResourceIdAndUse(R.styleable.SSDStatusListItemWidget_uxsdk_list_item_dialog_theme) { + dialogTheme = it + } + + } + } + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP) + + override fun getIdealDimensionRatioString(): String? { + return null + } + //endregion + + //region Hooks + /** + * Get the [ListItemLabelButtonWidget.UIState] updates + * The info parameter is instance of [DialogType] + */ + override fun getUIStateUpdates(): Flowable { + return uiUpdateStateProcessor.onBackpressureBuffer() + } + + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * SSD List Item Dialog Identifiers + */ + sealed class DialogType { + /** + * Dialog shown for format confirmation + */ + object FormatConfirmation : DialogType() + + /** + * Dialog shown for format success + */ + object FormatSuccess : DialogType() + + /** + * Dialog shown for format fail + */ + object FormatError : DialogType() + } + + + /** + * Class defines widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Current SSD List Item State + */ + data class SSDStateUpdated(val ssdState: SSDState) : ModelState() + } + //endregion + + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/ssdstatus/SSDStatusListItemWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/ssdstatus/SSDStatusListItemWidgetModel.kt new file mode 100644 index 00000000..158258f4 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/ssdstatus/SSDStatusListItemWidgetModel.kt @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.ssdstatus + +import dji.sdk.keyvalue.key.CameraKey +import dji.sdk.keyvalue.value.camera.SSDOperationState +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.value.common.ComponentIndexType +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Completable + +/** + * Widget Model for the [SSDStatusListItemWidget] used to define + * the underlying logic and communication + */ +class SSDStatusListItemWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + + private val ssdStateProcessor: DataProcessor = DataProcessor.create(SSDState.ProductDisconnected) + private val ssdRemainingCapacityProcessor = DataProcessor.create(0) + private val ssdOperationStateProcessor = DataProcessor.create(SSDOperationState.UNKNOWN) + private val ssdSupportedProcessor = DataProcessor.create(false) + + /** + * Index of sdCard + */ + var cameraIndex = ComponentIndexType.LEFT_OR_MAIN + set(value) { + field = value + restart() + } + + /** + * Get the sd card state + */ + val ssdState: Flowable = ssdStateProcessor.toFlowable() + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + CameraKey.KeyIsInternalSSDSupported, cameraIndex), ssdSupportedProcessor) + bindDataProcessor( + KeyTools.createKey( + CameraKey.KeySSDRemainingSpaceInMB, cameraIndex), ssdRemainingCapacityProcessor) + bindDataProcessor( + KeyTools.createKey( + CameraKey.KeySSDOperationState, cameraIndex), ssdOperationStateProcessor) + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + if (ssdSupportedProcessor.value) { + ssdStateProcessor.onNext(SSDState.CurrentSSDState(ssdOperationStateProcessor.value, + ssdRemainingCapacityProcessor.value)) + } else { + ssdStateProcessor.onNext(SSDState.NotSupported) + } + } else { + ssdStateProcessor.onNext(SSDState.ProductDisconnected) + } + } + + override fun inCleanup() { + //No clean up necessary + } + + /** + * Format SSD + */ + fun formatSSD(): Completable { + return djiSdkModel.performActionWithOutResult( + KeyTools.createKey( + CameraKey.KeyFormatStorage, cameraIndex)) + } + + + /** + * Class represents states of SSD List Item + */ + sealed class SSDState { + /** + * When product is disconnected + */ + object ProductDisconnected : SSDState() + + /** + * When product does not support SSD + */ + object NotSupported : SSDState() + + /** + * When product is connected + * + * @property ssdOperationState - Current operation State of SSD + * @property remainingSpace - Remaining space in MB + */ + data class CurrentSSDState(val ssdOperationState: SSDOperationState, + val remainingSpace: Int) : SSDState() + + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/travelmode/TravelModeListItemWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/travelmode/TravelModeListItemWidget.kt new file mode 100644 index 00000000..2fc4d340 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/travelmode/TravelModeListItemWidget.kt @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.travelmode + +import android.annotation.SuppressLint +import android.content.Context +import android.content.DialogInterface +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import androidx.annotation.StyleRes +import androidx.core.content.res.use +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.UXSDKError +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.panel.listitem.ListItemLabelButtonWidget +import dji.v5.ux.core.base.panel.listitem.ListItemLabelButtonWidget.UIState.* +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.panel.listitem.travelmode.TravelModeListItemWidget.DialogType.* +import dji.v5.ux.core.panel.listitem.travelmode.TravelModeListItemWidget.ModelState +import dji.v5.ux.core.panel.listitem.travelmode.TravelModeListItemWidget.ModelState.ProductConnected +import dji.v5.ux.core.panel.listitem.travelmode.TravelModeListItemWidget.ModelState.TravelModeStateUpdated +import dji.v5.ux.core.panel.listitem.travelmode.TravelModeListItemWidgetModel.TravelModeState + +/** + * Travel Mode List Item + * + */ +open class TravelModeListItemWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ListItemLabelButtonWidget( + context, + attrs, + defStyleAttr, + WidgetType.BUTTON, + R.style.UXSDKTravelModeListItem +) { + + //region Fields + /** + * Icon when landing gear is not in travel mode + */ + var travelModeActiveIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_travel_mode_active) + + /** + * Icon when landing gear is not in travel mode + */ + var travelModeInactiveIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_travel_mode_inactive) + + /** + * Label for button when landing gear is in travel mode + */ + var exitTravelModeButtonString: String = getString(R.string.uxsdk_travel_mode_exit) + + /** + * Label for button when landing gear is not in travel mode + */ + var enterTravelModeButtonString: String = getString(R.string.uxsdk_travel_mode_enter) + + /** + * Icon for confirmation dialog + */ + var confirmationDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_alert_yellow) + + /** + * Icon for error dialog + */ + var errorDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_alert_error) + + /** + * Icon for success dialog + */ + var successDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_alert_good) + + /** + * Theme for the dialogs shown + */ + @StyleRes + var dialogTheme: Int = R.style.UXSDKDialogTheme + + private val widgetModel: TravelModeListItemWidgetModel by lazy { + TravelModeListItemWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()) + } + //endregion + + //region Constructor + init { + initAttributes(context, attrs) + listItemTitleIcon = travelModeInactiveIcon + } + //endregion + + //region Lifecycle + override fun reactToModelChanges() { + addReaction(widgetModel.travelModeState + .observeOn(SchedulerProvider.ui()) + .subscribe { this.updateUI(it) }) + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun onButtonClick() { + checkAndToggleTravelMode() + } + //endregion + + //region Reactions to model + private fun updateUI(travelModeState: TravelModeState) { + widgetStateDataProcessor.onNext(TravelModeStateUpdated(travelModeState)) + when (travelModeState) { + TravelModeState.ProductDisconnected, + TravelModeState.NotSupported -> { + isEnabled = false + listItemTitleIcon = travelModeInactiveIcon + listItemButtonText = getString(R.string.uxsdk_string_default_value) + } + TravelModeState.Active -> { + isEnabled = true + listItemTitleIcon = travelModeActiveIcon + listItemButtonText = exitTravelModeButtonString + } + TravelModeState.Inactive -> { + isEnabled = true + listItemTitleIcon = travelModeInactiveIcon + listItemButtonText = enterTravelModeButtonString + } + } + + } + + //endregion + + //region Helpers + private fun checkAndToggleTravelMode() { + addDisposable(widgetModel.travelModeState.firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe({ + when (it) { + TravelModeState.Inactive -> { + showEnterTravelModeConfirmationDialog() + } + TravelModeState.Active -> { + exitTravelMode() + } + else -> { + //do something + } + } + }, { })) + } + + private fun showEnterTravelModeConfirmationDialog() { + val dialogListener = DialogInterface.OnClickListener { dialogInterface, buttonId: Int -> + if (buttonId == DialogInterface.BUTTON_POSITIVE) { + enterTravelMode() + uiUpdateStateProcessor.onNext(DialogActionConfirmed(EnterTravelModeConfirmation)) + } else { + uiUpdateStateProcessor.onNext(DialogActionCanceled(EnterTravelModeConfirmation)) + } + dialogInterface.dismiss() + } + val dialogDismissListener = DialogInterface.OnDismissListener { + uiUpdateStateProcessor.onNext(DialogDismissed(EnterTravelModeConfirmation)) + } + showConfirmationDialog(title = getString(R.string.uxsdk_list_item_travel_mode), + icon = confirmationDialogIcon, + dialogTheme = dialogTheme, + message = getString(R.string.uxsdk_travel_mode_enter_confirmation), + dialogClickListener = dialogListener, + dialogDismissListener = dialogDismissListener) + uiUpdateStateProcessor.onNext(DialogDisplayed(EnterTravelModeConfirmation)) + } + + private fun exitTravelMode() { + addDisposable(widgetModel.exitTravelMode() + .observeOn(SchedulerProvider.ui()) + .subscribe( + { }, + { error -> + if (error is UXSDKError) { + val dialogDismissListener = DialogInterface.OnDismissListener { + uiUpdateStateProcessor.onNext(DialogDismissed(ExitTravelModeError)) + } + showAlertDialog(title = getString(R.string.uxsdk_list_item_travel_mode), + icon = errorDialogIcon, + dialogTheme = dialogTheme, + message = getString(R.string.uxsdk_exit_travel_mode_failed, error.djiError.description()), + dialogDismissListener = dialogDismissListener) + uiUpdateStateProcessor.onNext(DialogDisplayed(ExitTravelModeError)) + } + } + )) + + } + + private fun enterTravelMode() { + var dialogType: DialogType? = null + val dialogDismissListener = DialogInterface.OnDismissListener { + uiUpdateStateProcessor.onNext(DialogDismissed(dialogType)) + } + addDisposable(widgetModel.enterTravelMode() + .observeOn(SchedulerProvider.ui()) + .subscribe( + { + dialogType = EnterTravelModeSuccess + showAlertDialog(title = getString(R.string.uxsdk_list_item_travel_mode), + icon = successDialogIcon, + dialogTheme = dialogTheme, + message = getString(R.string.uxsdk_enter_travel_mode_success), + dialogDismissListener = dialogDismissListener) + uiUpdateStateProcessor.onNext(DialogDisplayed(dialogType)) + }, + { error -> + if (error is UXSDKError) { + dialogType = EnterTravelModeError + showAlertDialog(title = getString(R.string.uxsdk_list_item_travel_mode), + icon = errorDialogIcon, + dialogTheme = dialogTheme, + message = getString(R.string.uxsdk_enter_travel_mode_failed, error.djiError.description()), + dialogDismissListener = dialogDismissListener) + uiUpdateStateProcessor.onNext(DialogDisplayed(dialogType)) + } + } + )) + + } + + + //endregion + + //region Customization + override fun getIdealDimensionRatioString(): String? = null + + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP) + + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet?) { + context.obtainStyledAttributes(attrs, R.styleable.TravelModeListItemWidget, 0, defaultStyle).use { typedArray -> + typedArray.getDrawableAndUse(R.styleable.TravelModeListItemWidget_uxsdk_travel_mode_active_icon) { + travelModeActiveIcon = it + } + typedArray.getDrawableAndUse(R.styleable.TravelModeListItemWidget_uxsdk_travel_mode_inactive_icon) { + travelModeInactiveIcon = it + } + typedArray.getDrawableAndUse(R.styleable.TravelModeListItemWidget_uxsdk_list_item_confirmation_dialog_icon) { + confirmationDialogIcon = it + } + typedArray.getDrawableAndUse(R.styleable.TravelModeListItemWidget_uxsdk_list_item_error_dialog_icon) { + errorDialogIcon = it + } + typedArray.getDrawableAndUse(R.styleable.TravelModeListItemWidget_uxsdk_list_item_success_dialog_icon) { + successDialogIcon = it + } + + enterTravelModeButtonString = typedArray.getString(R.styleable.TravelModeListItemWidget_uxsdk_enter_travel_mode_button_string, enterTravelModeButtonString) + exitTravelModeButtonString = typedArray.getString(R.styleable.TravelModeListItemWidget_uxsdk_exit_travel_mode_button_string, exitTravelModeButtonString) + typedArray.getResourceIdAndUse(R.styleable.TravelModeListItemWidget_uxsdk_list_item_dialog_theme) { + dialogTheme = it + } + + } + } + + //endregion + + //region Hooks + + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Get the [ListItemLabelButtonWidget.UIState] updates + * The info parameter is instance of [DialogType] + */ + override fun getUIStateUpdates(): Flowable { + return uiUpdateStateProcessor.onBackpressureBuffer() + } + + /** + * Travel mode List Item Dialog Identifiers + */ + sealed class DialogType { + /** + * Dialog shown for confirmation to enter travel mode + */ + object EnterTravelModeConfirmation : DialogType() + + /** + * Dialog shown when entering travel mode success + */ + object EnterTravelModeSuccess : DialogType() + + /** + * Dialog shown when entering travel mode fails + */ + object EnterTravelModeError : DialogType() + + /** + * Dialog shown when exiting travel mode fails + */ + object ExitTravelModeError : DialogType() + + } + + /** + * Class defines widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Travel mode state updated + */ + data class TravelModeStateUpdated(val travelModeState: TravelModeState) : ModelState() + + } + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/travelmode/TravelModeListItemWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/travelmode/TravelModeListItemWidgetModel.kt new file mode 100644 index 00000000..9172abad --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/travelmode/TravelModeListItemWidgetModel.kt @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.travelmode + +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Completable + +/** + * Widget Model for the [TravelModeListItemWidget] used to define + * the underlying logic and communication + */ +class TravelModeListItemWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + + //region Fields + + private val travelModeStateProcessor: DataProcessor = DataProcessor.create(TravelModeState.ProductDisconnected) + + //private val landingGearModeProcessor: DataProcessor = DataProcessor.create(LandingGearMode.UNKNOWN) + + + //endregion + + //region Data + /** + * Get the travel mode state processor + */ + val travelModeState: Flowable + get() = travelModeStateProcessor.toFlowable() + + //endregion + + //region Lifecycle + override fun inSetup() { +// val landingGearModeKey = FlightControllerKey.create(FlightControllerKey.LANDING_GEAR_MODE) +// bindDataProcessor(landingGearModeKey, landingGearModeProcessor) + } + + override fun inCleanup() { + // No Clean up + } + + override fun updateStates() { +// if (productConnectionProcessor.value) { +// if (landingGearModeProcessor.value == LandingGearMode.TRANSPORT) { +// travelModeStateProcessor.onNext(TravelModeState.Active) +// } else { +// travelModeStateProcessor.onNext(TravelModeState.Inactive) +// } +// } else { +// travelModeStateProcessor.onNext(TravelModeState.ProductDisconnected) +// } + } + + + /** + * Enter travel mode + */ + fun enterTravelMode(): Completable { +// val enterTransportModeKey = FlightControllerKey.create(FlightControllerKey.ENTER_TRANSPORT_MODE) +// return djiSdkModel.performAction(enterTransportModeKey) + return Completable.complete() + } + + /** + * Exit travel mode + */ + fun exitTravelMode(): Completable { +// val enterTransportModeKey = FlightControllerKey.create(FlightControllerKey.EXIT_TRANSPORT_MODE) +// return djiSdkModel.performAction(enterTransportModeKey) + return Completable.complete() + } + + + /** + * Class to represent states of travel mode state + */ + sealed class TravelModeState { + /** + * When product is disconnected + */ + object ProductDisconnected : TravelModeState() + + /** + * When product is connected and travel mode is not supported + */ + object NotSupported : TravelModeState() + + /** + * When product is connected and landing gear is in transport mode + */ + object Active : TravelModeState() + + /** + * When product is connected and landing gear is not in transport mode + */ + object Inactive : TravelModeState() + } +} +//endregion \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/unittype/UnitModeListItemWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/unittype/UnitModeListItemWidget.kt new file mode 100644 index 00000000..d72967fe --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/unittype/UnitModeListItemWidget.kt @@ -0,0 +1,348 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.unittype + +import android.annotation.SuppressLint +import android.app.AlertDialog +import android.content.Context +import android.content.DialogInterface +import android.content.res.ColorStateList +import android.graphics.drawable.Drawable +import android.text.Layout +import android.text.SpannableString +import android.text.SpannableStringBuilder +import android.text.style.AlignmentSpan +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.CheckBox +import android.widget.CompoundButton +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.annotation.Dimension +import androidx.annotation.DrawableRes +import androidx.annotation.StyleRes +import androidx.appcompat.view.ContextThemeWrapper +import androidx.core.content.res.use +import dji.v5.utils.common.DisplayUtil +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.UXSDKError +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.panel.listitem.ListItemRadioButtonWidget +import dji.v5.ux.core.communication.GlobalPreferencesManager +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.panel.listitem.unittype.UnitModeListItemWidget.ModelState +import dji.v5.ux.core.panel.listitem.unittype.UnitModeListItemWidget.ModelState.* +import dji.v5.ux.core.panel.listitem.unittype.UnitModeListItemWidgetModel.UnitTypeState +import dji.v5.ux.core.util.UnitConversionUtil.UnitType + +/** + * Widget shows the current [UnitType] being used. + * It also provides an option to switch between them. + */ +open class UnitModeListItemWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ListItemRadioButtonWidget( + context, + attrs, + defStyleAttr, + R.style.UXSDKUnitModeListItem +) { + + //region Fields + private val widgetModel: UnitModeListItemWidgetModel by lazy { + UnitModeListItemWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + GlobalPreferencesManager.getInstance()) + } + + private var imperialItemIndex: Int = INVALID_OPTION_INDEX + private var metricItemIndex: Int = INVALID_OPTION_INDEX + + /** + * Theme for the dialogs shown for format + */ + @StyleRes + var dialogTheme: Int = R.style.UXSDKDialogTheme + + /** + * The text appearance of the check box label + */ + @get:StyleRes + @setparam:StyleRes + var checkBoxTextAppearance = 0 + + /** + * The text color state list of the check box label + */ + var checkBoxTextColor: ColorStateList? = null + + /** + * The background of the check box + */ + var checkBoxTextBackground: Drawable? = null + + /** + * The text size of the check box label + */ + @get:Dimension + @setparam:Dimension + var checkBoxTextSize: Float = 0f + + //endregion + + //region Constructor + init { + imperialItemIndex = addOptionToGroup(getString(R.string.uxsdk_list_item_unit_mode_imperial)) + metricItemIndex = addOptionToGroup(getString(R.string.uxsdk_list_item_unit_mode_metric)) + initAttributes(context, attrs) + } + //endregion + + //region Lifecycle + override fun reactToModelChanges() { + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + addReaction(widgetModel.unitTypeState + .observeOn(SchedulerProvider.ui()) + .subscribe { + widgetStateDataProcessor.onNext(UnitTypeUpdated(it)) + updateUI(it) + }) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun onOptionTapped(optionIndex: Int, optionLabel: String) { + val newUnitType: UnitType = if (optionIndex == imperialItemIndex) { + UnitType.IMPERIAL + } else { + UnitType.METRIC + } + addDisposable(widgetModel.setUnitType(newUnitType) + .observeOn(SchedulerProvider.ui()) + .subscribe({ + widgetStateDataProcessor.onNext(SetUnitTypeSucceeded) + if (newUnitType == UnitType.IMPERIAL + && !GlobalPreferencesManager.getInstance().isUnitModeDialogNeverShown) { + showWarningDialog() + } + }, { + widgetStateDataProcessor.onNext(SetUnitTypeFailed(it as UXSDKError)) + resetUI() + })) + + } + + //endregion + + //region Reactions to model + + private fun updateUI(unitTypeState: UnitTypeState) { + isEnabled = if (unitTypeState is UnitTypeState.CurrentUnitType) { + if (unitTypeState.unitType == UnitType.IMPERIAL) { + setSelected(imperialItemIndex) + } else { + setSelected(metricItemIndex) + } + true + } else { + false + } + } + + //endregion + + //region Helpers + @SuppressLint("InflateParams") + private fun showWarningDialog() { + val dialogListener = DialogInterface.OnClickListener { dialogInterface, _: Int -> + dialogInterface.dismiss() + } + val dialogDismissListener = DialogInterface.OnDismissListener { + uiUpdateStateProcessor.onNext(UIState.DialogDismissed(null)) + } + val ctw = ContextThemeWrapper(context, dialogTheme) + val inflater: LayoutInflater = ctw.getSystemService(Context.LAYOUT_INFLATER_SERVICE) as LayoutInflater + val view = inflater.inflate(R.layout.uxsdk_layout_dialog_checkbox, null) + val builder = AlertDialog.Builder(context, dialogTheme) + builder.setPositiveButton(getString(R.string.uxsdk_app_ok), dialogListener) + builder.setOnDismissListener(dialogDismissListener) + builder.setCancelable(true) + builder.setTitle(getString(R.string.uxsdk_list_item_unit_mode)) + val neverShowAgainCheckBox = view.findViewById(R.id.checkbox_dont_show_again) + neverShowAgainCheckBox.setTextColor(getColor(R.color.uxsdk_white)) + if (checkBoxTextAppearance != INVALID_RESOURCE) { + neverShowAgainCheckBox.setTextAppearance(context, checkBoxTextAppearance) + } + if (checkBoxTextColor != null) { + neverShowAgainCheckBox.setTextColor(checkBoxTextColor) + } + if (checkBoxTextBackground != null) { + neverShowAgainCheckBox.background = checkBoxTextBackground + } + if (checkBoxTextSize != INVALID_DIMENSION) { + neverShowAgainCheckBox.textSize = checkBoxTextSize + } + val textView = view.findViewById(R.id.textview_dialog_content) + textView.setText(getSpannableString(), TextView.BufferType.SPANNABLE) + neverShowAgainCheckBox.setOnCheckedChangeListener { _: CompoundButton?, checked: Boolean -> + GlobalPreferencesManager.getInstance().isUnitModeDialogNeverShown = checked + uiUpdateStateProcessor.onNext(UIState.NeverShowAgainCheckChanged(checked)) + } + builder.setView(view) + builder.create().show() + uiUpdateStateProcessor.onNext(UIState.DialogDisplayed(null)) + } + + private fun resetUI() { + addDisposable(widgetModel.unitTypeState + .observeOn(SchedulerProvider.ui()) + .subscribe { updateUI(it) }) + } + + private fun getSpannableString(): SpannableStringBuilder { + val builder = SpannableStringBuilder() + + val str1 = SpannableString(getString(R.string.uxsdk_dialog_unit_change_notice)) + str1.setSpan(AlignmentSpan.Standard(Layout.Alignment.ALIGN_NORMAL), 0, str1.length, 0) + builder.appendln(str1).appendln() + + val str2 = SpannableString(resources.getString(R.string.uxsdk_dialog_unit_change_example)) + str2.setSpan(AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER), 0, str2.length, 0) + builder.append(str2) + return builder + } + //endregion + + //region Customizations + + override fun getIdealDimensionRatioString(): String? { + return null + } + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP) + + /** + * Set the text color for the check box label + * + * @param color color integer resource + */ + fun setCheckBoxTextColor(@ColorInt color: Int) { + if (color != INVALID_COLOR) { + checkBoxTextColor = ColorStateList.valueOf(color) + } + } + + /** + * Set the resource ID for the background of the check box + * + * @param resourceId Integer ID of the text view's background resource + */ + fun setCheckBoxBackground(@DrawableRes resourceId: Int) { + checkBoxTextBackground = getDrawable(resourceId) + } + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet?) { + context.obtainStyledAttributes(attrs, R.styleable.UnitModeListItemWidget, 0, defaultStyle).use { typedArray -> + typedArray.getResourceIdAndUse(R.styleable.UnitModeListItemWidget_uxsdk_list_item_dialog_theme) { + dialogTheme = it + } + typedArray.getResourceIdAndUse(R.styleable.UnitModeListItemWidget_uxsdk_checkBoxTextAppearance) { + checkBoxTextAppearance = it + } + typedArray.getColorStateListAndUse(R.styleable.UnitModeListItemWidget_uxsdk_checkBoxTextColor) { + checkBoxTextColor = it + } + typedArray.getDrawableAndUse(R.styleable.UnitModeListItemWidget_uxsdk_checkBoxTextBackground) { + checkBoxTextBackground = it + } + typedArray.getDimensionAndUse(R.styleable.UnitModeListItemWidget_uxsdk_checkBoxTextSize) { + checkBoxTextSize = DisplayUtil.pxToSp(context, it) + } + } + } + + //endregion + + //region Hooks + + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Set unit type success + */ + object SetUnitTypeSucceeded : ModelState() + + /** + * Set unit type failed + */ + data class SetUnitTypeFailed(val error: UXSDKError) : ModelState() + + /** + * Unit type updated + */ + data class UnitTypeUpdated(val unitTypeState: UnitTypeState) : ModelState() + } + //endregion + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/unittype/UnitModeListItemWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/unittype/UnitModeListItemWidgetModel.kt new file mode 100644 index 00000000..0d177812 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/listitem/unittype/UnitModeListItemWidgetModel.kt @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.listitem.unittype + +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.* +import dji.v5.ux.core.panel.listitem.unittype.UnitModeListItemWidgetModel.UnitTypeState.CurrentUnitType +import dji.v5.ux.core.panel.listitem.unittype.UnitModeListItemWidgetModel.UnitTypeState.ProductDisconnected +import dji.v5.ux.core.util.DataProcessor +import dji.v5.ux.core.util.UnitConversionUtil.UnitType +import io.reactivex.rxjava3.core.Completable + +/** + * Widget Model for the [UnitModeListItemWidget] used to define + * the underlying logic and communication + */ +class UnitModeListItemWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, + private val preferencesManager: GlobalPreferencesInterface? +) : WidgetModel(djiSdkModel, keyedStore) { + + private val unitTypeStateProcessor: DataProcessor = DataProcessor.create(ProductDisconnected) + private val unitTypeProcessor: DataProcessor = DataProcessor.create(UnitType.METRIC) + private val unitTypeKey: UXKey = UXKeys.create(GlobalPreferenceKeys.UNIT_TYPE) + + /** + * Get the unit type state + */ + val unitTypeState: Flowable + get() = unitTypeStateProcessor.toFlowable() + + override fun inSetup() { + bindDataProcessor(unitTypeKey, unitTypeProcessor) + preferencesManager?.setUpListener() + preferencesManager?.let { unitTypeProcessor.onNext(it.unitType) } + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + unitTypeStateProcessor.onNext(CurrentUnitType(unitTypeProcessor.value)) + } else { + unitTypeStateProcessor.onNext(ProductDisconnected) + } + } + + override fun inCleanup() { + preferencesManager?.cleanup() + } + + /** + * Set unit type + */ + fun setUnitType(unitType: UnitType): Completable { + if (unitType == unitTypeProcessor.value) return Completable.complete() + preferencesManager?.unitType = unitType + return uxKeyManager.setValue(unitTypeKey, unitType) + } + + /** + * Class represents states of Unit Type + */ + sealed class UnitTypeState { + /** + * When product is disconnected + */ + object ProductDisconnected : UnitTypeState() + + /** + * Represents current unit system used + */ + data class CurrentUnitType(val unitType: UnitType) : UnitTypeState() + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/systemstatus/SmartListInternalModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/systemstatus/SmartListInternalModel.kt new file mode 100644 index 00000000..f6b81409 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/systemstatus/SmartListInternalModel.kt @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.systemstatus + +import dji.sdk.keyvalue.key.ProductKey +import dji.sdk.keyvalue.value.product.ProductType +import dji.sdk.keyvalue.key.KeyTools +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor + +/** + * Smart list internal model will detect the connected + * product. It can be used to configure the list. + */ +class SmartListInternalModel( + djiSdkModel: DJISDKModel, + uxKeyManager: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, uxKeyManager) { + + //region Fields + private val modelProcessor: DataProcessor = DataProcessor.create(ProductType.UNKNOWN) + //endregion + + /** + * Flowable with the current connected model + */ + val aircraftModel: Flowable + get() = modelProcessor.toFlowable() + + + //region Lifecycle + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + ProductKey.KeyProductType), modelProcessor) + } + + override fun inCleanup() { + // Nothing to do + } + + override fun updateStates() { + // Nothing to do + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/systemstatus/SystemStatusListPanelWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/systemstatus/SystemStatusListPanelWidget.kt new file mode 100644 index 00000000..3f2c2839 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/systemstatus/SystemStatusListPanelWidget.kt @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.systemstatus + +import android.annotation.SuppressLint +import android.content.Context +import android.util.AttributeSet +import androidx.core.content.res.use +import dji.v5.utils.common.LogUtils +import dji.v5.ux.R +import dji.v5.ux.core.base.panel.ListPanelWidget +import dji.v5.ux.core.base.panel.PanelWidgetConfiguration +import dji.v5.ux.core.base.panel.PanelWidgetType +import dji.v5.ux.core.base.panel.WidgetID +import dji.v5.ux.core.communication.OnStateChangeCallback +import dji.v5.ux.core.extension.getIntegerAndUse +import dji.v5.ux.core.extension.toggleVisibility +import dji.v5.ux.core.panel.listitem.aircraftbatterytemperature.AircraftBatteryTemperatureListItemWidget +import dji.v5.ux.core.panel.listitem.emmcstatus.EMMCStatusListItemWidget +import dji.v5.ux.core.panel.listitem.flightmode.FlightModeListItemWidget +import dji.v5.ux.core.panel.listitem.maxaltitude.MaxAltitudeListItemWidget +import dji.v5.ux.core.panel.listitem.maxflightdistance.MaxFlightDistanceListItemWidget +import dji.v5.ux.core.panel.listitem.overview.OverviewListItemWidget +import dji.v5.ux.core.panel.listitem.rcbattery.RCBatteryListItemWidget +import dji.v5.ux.core.panel.listitem.rcstickmode.RCStickModeListItemWidget +import dji.v5.ux.core.panel.listitem.returntohomealtitude.ReturnToHomeAltitudeListItemWidget +import dji.v5.ux.core.panel.listitem.sdcardstatus.SDCardStatusListItemWidget +import dji.v5.ux.core.panel.listitem.travelmode.TravelModeListItemWidget +import dji.v5.ux.core.widget.systemstatus.SystemStatusWidget + +/** + * To Allow the user to toggle hide and show this panel widget, use in conjunction + * with [SystemStatusWidget]. + * + * This panel widget shows the system status list that includes a list of items (like IMU, GPS, etc.). + * The current version of this panel widget is a sample and more items are to come + * in future releases. + * + * Customization: + * Use the attribute "excludeItem" to permanently remove items from the list. This will prevent a + * certain item from being created and shown throughout the lifecycle of the panel widget. Here are + * all the flags: flight_mode, compass, vision_sensor, radio_quality, rc_stick_mode, rc_battery, + * aircraft_battery_temperature, sd_card_status, emmc_status, max_altitude, max_flight_distance, + * travel_mode. + * + * Note that multiple flags can be used simultaneously by logically OR'ing + * them. For example, to hide sd card status and rc stick mode, it can be done by the + * following two steps. + * Define custom xmlns in its layout file: + * xmlns:app="http://schemas.android.com/apk/res-auto" + * Then, add following attribute to the SystemStatusListPanelWidget: + * app:excludeItem="sd_card_status|rc_stick_mode". + * + * This panel widget also passes attributes to each of the child widgets created. See each + * widget for individual customizations: + * [OverviewListItemWidget], + * [ReturnToHomeAltitudeListItemWidget], + * [FlightModeListItemWidget], + * [RCStickModeListItemWidget], + * [RCBatteryListItemWidget], + * [AircraftBatteryTemperatureListItemWidget], + * [SDCardStatusListItemWidget], + * [EMMCStatusListItemWidget], + * [MaxAltitudeListItemWidget], + * [MaxFlightDistanceListItemWidget], + * [TravelModeListItemWidget]. + * + * To customize the individual widgets, pass a theme in XML: + * android:theme="@style/UXSDKSystemStatusListTheme"(context, attrs, defStyleAttr, configuration) { + + //region Lifecycle + override fun initPanelWidget(context: Context, attrs: AttributeSet?, defStyleAttr: Int, widgetConfiguration: PanelWidgetConfiguration?) { + // Nothing to do + } + + init { + val excludedItemsValue = attrs?.let { initAttributes(context, it) } + val excludedItemsSet = getExcludedItems(excludedItemsValue) + + smartListModel = SystemStatusSmartListModel(context, attrs, excludedItemsSet) + } + + override fun onSmartListModelCreated() { + // Nothing to do + } + + + override fun reactToModelChanges() { + // Nothing to do + } + + //region Customizations + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet): Int { + context.obtainStyledAttributes(attrs, R.styleable.SystemStatusListPanelWidget).use { typedArray -> + typedArray.getIntegerAndUse(R.styleable.SystemStatusListPanelWidget_uxsdk_excludeItem) { + return it + } + } + return 0 + } + //endregion + + //region Helpers + private fun getExcludedItems(excludedItemsValue: Int?): Set? { + return if (excludedItemsValue != null) { + SystemStatusSmartListModel.SystemStatusListItem.values + .filter { it.isItemExcluded(excludedItemsValue) } + .map { it.widgetID } + .toSet() + } else { + null + } + } + //endregion + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/systemstatus/SystemStatusSmartListModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/systemstatus/SystemStatusSmartListModel.kt new file mode 100644 index 00000000..94011c35 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/systemstatus/SystemStatusSmartListModel.kt @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.systemstatus + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import dji.sdk.keyvalue.value.product.ProductType +import dji.v5.ux.core.base.panel.SmartListModel +import dji.v5.ux.core.base.panel.WidgetID +import dji.v5.ux.core.panel.listitem.aircraftbatterytemperature.AircraftBatteryTemperatureListItemWidget +import dji.v5.ux.core.panel.listitem.emmcstatus.EMMCStatusListItemWidget +import dji.v5.ux.core.panel.listitem.flightmode.FlightModeListItemWidget +import dji.v5.ux.core.panel.listitem.maxaltitude.MaxAltitudeListItemWidget +import dji.v5.ux.core.panel.listitem.maxflightdistance.MaxFlightDistanceListItemWidget +import dji.v5.ux.core.panel.listitem.novicemode.NoviceModeListItemWidget +import dji.v5.ux.core.panel.listitem.obstacleavoidance.ObstacleAvoidanceListItemWidget +import dji.v5.ux.core.panel.listitem.overview.OverviewListItemWidget +import dji.v5.ux.core.panel.listitem.rcbattery.RCBatteryListItemWidget +import dji.v5.ux.core.panel.listitem.rcstickmode.RCStickModeListItemWidget +import dji.v5.ux.core.panel.listitem.returntohomealtitude.ReturnToHomeAltitudeListItemWidget +import dji.v5.ux.core.panel.listitem.sdcardstatus.SDCardStatusListItemWidget +import dji.v5.ux.core.panel.listitem.ssdstatus.SSDStatusListItemWidget +import dji.v5.ux.core.panel.listitem.travelmode.TravelModeListItemWidget +import dji.v5.ux.core.panel.listitem.unittype.UnitModeListItemWidget +import dji.v5.ux.core.panel.systemstatus.SystemStatusSmartListModel.SystemStatusListItem.* + +private const val TAG = "systemstatuslist" + +/** + * [SmartListModel] to handheld what items should be shown for the [SystemStatusListPanelWidget]. + */ +open class SystemStatusSmartListModel @JvmOverloads constructor( + context: Context, + private val attrs: AttributeSet? = null, + excludedItems: Set? = null +) : SmartListModel(context, attrs, excludedItems) { + + //region Default Items + /** + * List of [WidgetID] of widgets that are allowed in this list. + */ + override val registeredWidgetIDList: List by lazy { + listOf( + OVERVIEW_STATUS.widgetID, + RTH_ALTITUDE.widgetID, + MAX_ALTITUDE.widgetID, + MAX_FLIGHT_DISTANCE.widgetID, + FLIGHT_MODE.widgetID, + RC_STICK_MODE.widgetID, + RC_BATTERY.widgetID, + AIRCRAFT_BATTERY_TEMPERATURE.widgetID, + TRAVEL_MODE.widgetID, + NOVICE_MODE.widgetID, + OBSTACLE_AVOIDANCE.widgetID + ) + } + + /** + * Default set of widgets that should be shown + */ + override val defaultActiveWidgetSet: Set by lazy { + registeredWidgetIDList.toSet() + .minus(EMMC_STATUS.widgetID) + .minus(TRAVEL_MODE.widgetID) + .minus(SSD_STATUS.widgetID) + } + //endregion + + //region Lifecycle + override fun inSetUp() { + //暂无实现 + } + + + override fun inCleanUp() { + //暂无实现 + } + + override fun onAircraftModelChanged(model: ProductType) { + resetSystemStatusListToDefault() + } + + override fun onProductConnectionChanged(isConnected: Boolean) { + if (!isConnected) { + resetSystemStatusListToDefault() + } + } + + override fun createWidget(widgetID: WidgetID): View { + return when (SystemStatusListItem.from(widgetID)) { + OVERVIEW_STATUS -> OverviewListItemWidget(context) + RTH_ALTITUDE -> ReturnToHomeAltitudeListItemWidget(context) + FLIGHT_MODE -> FlightModeListItemWidget(context) + RC_STICK_MODE -> RCStickModeListItemWidget(context) + RC_BATTERY -> RCBatteryListItemWidget(context) + AIRCRAFT_BATTERY_TEMPERATURE -> AircraftBatteryTemperatureListItemWidget(context) + SD_CARD_STATUS -> SDCardStatusListItemWidget(context) + EMMC_STATUS -> EMMCStatusListItemWidget(context) + MAX_ALTITUDE -> MaxAltitudeListItemWidget(context) + MAX_FLIGHT_DISTANCE -> MaxFlightDistanceListItemWidget(context) + TRAVEL_MODE -> TravelModeListItemWidget(context) + UNIT_MODE -> UnitModeListItemWidget(context) + SSD_STATUS -> SSDStatusListItemWidget(context) + NOVICE_MODE -> NoviceModeListItemWidget(context) + OBSTACLE_AVOIDANCE -> ObstacleAvoidanceListItemWidget(context) + null -> throw IllegalStateException("The WidgetID ($widgetID) is not recognized.") + } + } + //endregion + + //region Helpers + private fun resetSystemStatusListToDefault() { + onLandingGearUpdate(false) + onInternalStorageSupported(false) + onSSDSupported(false) + } + + private fun onLandingGearUpdate(movable: Boolean) { + if (!movable) { + updateListMinus(TRAVEL_MODE.widgetID) + } else { + updateListPlus(TRAVEL_MODE.widgetID) + } + } + + private fun onInternalStorageSupported(supported: Boolean) { + if (!supported) { + updateListMinus(EMMC_STATUS.widgetID) + } else { + updateListPlus(EMMC_STATUS.widgetID) + } + } + + private fun onSSDSupported(supported: Boolean) { + if (!supported) { + updateListMinus(SSD_STATUS.widgetID) + } else { + updateListPlus(SSD_STATUS.widgetID) + } + } + //endregion + + /** + * Default Widgets for the [SystemStatusListPanelWidget] + * @property widgetID Identifier for the item + * @property value Int value for excluding items + */ + enum class SystemStatusListItem(val widgetID: WidgetID, val value: Int) { + + /** + * Maps to [FlightModeListItemWidget]. + */ + FLIGHT_MODE("flight_mode", 1), + + /** + * Maps to [RCStickModeListItemWidget]. + */ + RC_STICK_MODE("rc_stick_mode", 2), + + /** + * Maps to [RCBatteryListItemWidget]. + */ + RC_BATTERY("rc_battery", 3), + + /** + * Maps to [AircraftBatteryTemperatureListItemWidget]. + */ + AIRCRAFT_BATTERY_TEMPERATURE("aircraft_battery_temperature", 4), + + /** + * Maps to [SDCardStatusListItemWidget]. + */ + SD_CARD_STATUS("sd_card_status", 5), + + /** + * Maps to [EMMCStatusListItemWidget]. + */ + EMMC_STATUS("emmc_status", 6), + + /** + * Maps to [MaxAltitudeListItemWidget]. + */ + MAX_ALTITUDE("max_altitude", 7), + + /** + * Maps to [MaxFlightDistanceListItemWidget]. + */ + MAX_FLIGHT_DISTANCE("max_flight_distance", 8), + + /** + * Maps to [TravelModeListItemWidget]. + */ + TRAVEL_MODE("travel_mode", 9), + + /** + * Maps to [UnitModeListItemWidget]. + */ + UNIT_MODE("unit_mode", 10), + + /** + * Maps to [SSDStatusListItemWidget]. + */ + SSD_STATUS("ssd_status", 11), + + /** + * Maps to [NoviceModeListItemWidget]. + */ + NOVICE_MODE("novice_mode", 12), + + /** + * Maps to [OverviewListItemWidget]. + */ + OVERVIEW_STATUS("overview_status", 13), + + /** + * Maps to [ReturnToHomeAltitudeListItemWidget]. + */ + RTH_ALTITUDE("rth_altitude", 14), + + /** + * Maps to [ObstacleAvoidanceListItemWidget]. + */ + OBSTACLE_AVOIDANCE("obstacle_avoidance", 15); + + /** + * Checks if the item is excluded given the flag [excludeItems]. + */ + fun isItemExcluded(excludeItems: Int): Boolean { + return excludeItems and this.value == this.value + } + + companion object { + @JvmStatic + val values = values() + + /** + * Create a [SystemStatusListItem] from a [WidgetID]. + */ + @JvmStatic + fun from(widgetID: WidgetID): SystemStatusListItem? = + values.find { it.widgetID == widgetID } + + /** + * Create a [SystemStatusListItem] from an int value. + */ + @JvmStatic + fun from(value: Int): SystemStatusListItem? = + values.find { it.value == value } + } + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/telemetry/TelemetryPanelWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/telemetry/TelemetryPanelWidget.kt new file mode 100644 index 00000000..b96e990a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/telemetry/TelemetryPanelWidget.kt @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.telemetry + +import android.annotation.SuppressLint +import android.content.Context +import android.util.AttributeSet +import android.view.View +import androidx.core.content.res.use +import dji.v5.ux.R +import dji.v5.ux.core.base.panel.FreeFormPanelWidget +import dji.v5.ux.core.base.panel.PanelWidgetConfiguration +import dji.v5.ux.core.base.panel.PanelWidgetType +import dji.v5.ux.core.extension.getDimension +import dji.v5.ux.core.extension.getIntegerAndUse +import dji.v5.ux.core.extension.getResourceIdAndUse +import dji.v5.ux.core.widget.altitude.AGLAltitudeWidget +import dji.v5.ux.core.widget.altitude.AMSLAltitudeWidget +import dji.v5.ux.core.widget.distancehome.DistanceHomeWidget +import dji.v5.ux.core.widget.distancerc.DistanceRCWidget +import dji.v5.ux.core.widget.horizontalvelocity.HorizontalVelocityWidget +import dji.v5.ux.core.widget.location.LocationWidget +import dji.v5.ux.core.widget.verticalvelocity.VerticalVelocityWidget +import dji.v5.ux.core.widget.vps.VPSWidget + +typealias WidgetID = String + +/** + * Compound widget that aggregates important physical state information + * about the aircraft into a dashboard. + *

+ * It includes the [AMSLAltitudeWidget], [AGLAltitudeWidget], + * [DistanceHomeWidget], [DistanceRCWidget], [HorizontalVelocityWidget], + * [VerticalVelocityWidget], [VPSWidget] and the [LocationWidget]. + *

+ * This widget can be customized to exclude any of these widgets + * as required. A widget excluded will not be created. + * Individual widgets can be accessed using the paneID of each widget + * and the function [TelemetryPanelWidget.viewInPane]. + * + */ +open class TelemetryPanelWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + configuration: PanelWidgetConfiguration = PanelWidgetConfiguration( + context = context, + panelWidgetType = PanelWidgetType.FREE_FORM), + private var widgetTheme: Int = 0, +) : FreeFormPanelWidget(context, attrs, defStyleAttr, configuration) { + + //region fields + + private var excludedItemSet = emptySet() + + /** + * Pane ID of the [AMSLAltitudeWidget] + */ + val amslAltitudeWidgetPaneID: Int + + /** + * Pane ID of the [AGLAltitudeWidget] + */ + val aglAltitudeWidgetPaneID: Int + + /** + * Pane ID of the [HorizontalVelocityWidget] + */ + val horizontalVelocityWidgetPaneID: Int + + /** + * Pane ID of the [DistanceRCWidget] + */ + val distanceRCWidgetPaneID: Int + + /** + * Pane ID of the [DistanceHomeWidget] + */ + val distanceHomeWidgetPaneID: Int + + /** + * Pane ID of the [VerticalVelocityWidget] + */ + val verticalVelocityWidgetPaneID: Int + + /** + * Pane ID of the [VPSWidget] + */ + val vpsWidgetPaneID: Int + + /** + * Pane ID of the [LocationWidget] + */ + val locationWidgetPaneID: Int + + //endregion + + //region constructor + init { + // Create 4 rows + val rowList = splitPane(rootID, SplitType.VERTICAL, arrayOf(0.25f, 0.25f, 0.25f, 0.25f)) + // Create 3 columns for second row + val columnList1 = splitPane(rowList[1], SplitType.HORIZONTAL, arrayOf(0.3f, 0.4f, 0.3f)) + // Create 3 columns for third row + val columnList2 = splitPane(rowList[2], SplitType.HORIZONTAL, arrayOf(0.3f, 0.4f, 0.3f)) + + //Assign the paneIds based on position in the panel + amslAltitudeWidgetPaneID = rowList[0] + aglAltitudeWidgetPaneID = columnList1[0] + horizontalVelocityWidgetPaneID = columnList1[1] + distanceRCWidgetPaneID = columnList1[2] + distanceHomeWidgetPaneID = columnList2[0] + verticalVelocityWidgetPaneID = columnList2[1] + vpsWidgetPaneID = columnList2[2] + locationWidgetPaneID = rowList[3] + + // Get the excluded items list. + attrs?.let { initAttributes(context, it) } + addWidgetsToPanel() + } + //endregion + + //region helpers + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.TelemetryPanelWidget).use { typedArray -> + typedArray.getIntegerAndUse(R.styleable.TelemetryPanelWidget_uxsdk_excludeTelemetryItem) { + excludedItemSet = getExcludeListSet(it) + } + typedArray.getResourceIdAndUse(R.styleable.TelemetryPanelWidget_uxsdk_telemetry_widget_theme) { + widgetTheme = it + } + } + + } + + private fun getExcludeListSet(excludeListValue: Int?): Set { + return if (excludeListValue != null) { + TelemetryPanelItem.values + .filter { it.isItemExcluded(excludeListValue) } + .map { it.widgetID } + .toSet() + } else { + emptySet() + } + } + + private fun addWidgetsToPanel() { + val widgetMargin = getDimension(R.dimen.uxsdk_telemetry_column_margin).toInt() + + setPane(Pane(TelemetryPanelItem.AMSL_ALTITUDE, amslAltitudeWidgetPaneID, ViewAlignment.LEFT), createWidgetBlock = { + AMSLAltitudeWidget(context, widgetTheme = widgetTheme) + }) + + setPane( + Pane(TelemetryPanelItem.AGL_ALTITUDE, aglAltitudeWidgetPaneID, ViewAlignment.LEFT, rightMargin = widgetMargin), + createWidgetBlock = { + AGLAltitudeWidget(context, widgetTheme = widgetTheme) + }, + ) + + setPane(Pane(TelemetryPanelItem.HORIZONTAL_VELOCITY, horizontalVelocityWidgetPaneID, ViewAlignment.LEFT, leftMargin = widgetMargin, + rightMargin = widgetMargin), createWidgetBlock = { + HorizontalVelocityWidget(context, widgetTheme = widgetTheme) + }) + + setPane(Pane(TelemetryPanelItem.DISTANCE_RC, distanceRCWidgetPaneID, ViewAlignment.LEFT, leftMargin = widgetMargin), + createWidgetBlock = { + DistanceRCWidget(context, widgetTheme = widgetTheme) + }) + + setPane(Pane(TelemetryPanelItem.DISTANCE_HOME, distanceHomeWidgetPaneID, ViewAlignment.LEFT, rightMargin = widgetMargin), + createWidgetBlock = { + DistanceHomeWidget(context, widgetTheme = widgetTheme) + }) + + setPane(Pane(TelemetryPanelItem.VERTICAL_VELOCITY, verticalVelocityWidgetPaneID, ViewAlignment.LEFT, leftMargin = widgetMargin, + rightMargin = widgetMargin), createWidgetBlock = { + VerticalVelocityWidget(context, widgetTheme = widgetTheme) + }) + + setPane(Pane(TelemetryPanelItem.VPS, vpsWidgetPaneID, ViewAlignment.LEFT, leftMargin = widgetMargin), + createWidgetBlock = { + VPSWidget(context, widgetTheme = widgetTheme) + }) + + setPane(Pane(TelemetryPanelItem.LOCATION, locationWidgetPaneID, ViewAlignment.LEFT), + createWidgetBlock = { + LocationWidget(context, widgetTheme = widgetTheme) + }) + } + + private inline fun setPane( + pane: Pane, + createWidgetBlock: () -> R, + ) { + val paneID = pane.paneID + if (excludedItemSet.contains(pane.panelItem.widgetID)) { + setPaneVisibility(paneID, false) + } else { + val widget = createWidgetBlock() + addView(paneID, widget, pane.position, pane.leftMargin, pane.topMargin, pane.rightMargin, pane.bottomMargin) + setPaneVisibility(paneID, true) + } + } + + private data class Pane( + val panelItem: TelemetryPanelItem, + val paneID: Int, + val position: ViewAlignment = ViewAlignment.CENTER, + val leftMargin: Int = 0, + val topMargin: Int = 0, + val rightMargin: Int = 0, + val bottomMargin: Int = 0, + ) + //endregion + + //region lifecycle + override fun reactToModelChanges() { + // Empty method + } + + override fun getIdealDimensionRatioString(): String? { + return null + } + //endregion + + + /** + * Default Widgets for the [TelemetryPanelWidget] + * @property widgetID Identifier for the item + * @property value Int value for excluding items + */ + enum class TelemetryPanelItem(val widgetID: WidgetID, val value: Int) { + + /** + * Maps to [AMSLAltitudeWidget]. + */ + AMSL_ALTITUDE("amsl_altitude", 1), + + /** + * Maps to [AGL_ALTITUDE]. + */ + AGL_ALTITUDE("agl_altitude", 2), + + /** + * Maps to [HorizontalVelocityWidget]. + */ + HORIZONTAL_VELOCITY("horizontal_velocity", 4), + + /** + * Maps to [DistanceRCWidget]. + */ + DISTANCE_RC("distance_rc", 8), + + /** + * Maps to [DistanceHomeWidget]. + */ + DISTANCE_HOME("distance_home", 16), + + /** + * Maps to [VerticalVelocityWidget]. + */ + VERTICAL_VELOCITY("vertical_velocity", 32), + + /** + * Maps to [VPSWidget]. + */ + VPS("vps", 64), + + /** + * Maps to [LocationWidget]. + */ + LOCATION("location", 128); + + + /** + * Checks if the item is excluded given the flag [excludeItems]. + */ + fun isItemExcluded(excludeItems: Int): Boolean { + return excludeItems and this.value == this.value + } + + + companion object { + @JvmStatic + val values = values() + + /** + * Create a [TelemetryPanelItem] from a [WidgetID]. + */ + @JvmStatic + fun from(widgetID: WidgetID): TelemetryPanelItem? = + values.find { it.widgetID == widgetID } + + /** + * Create a [TelemetryPanelItem] from an int value. + */ + @JvmStatic + fun from(value: Int): TelemetryPanelItem? = + values.find { it.value == value } + } + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/topbar/TopBarPanelWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/topbar/TopBarPanelWidget.kt new file mode 100644 index 00000000..7fd43512 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/panel/topbar/TopBarPanelWidget.kt @@ -0,0 +1,286 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.panel.topbar + +import android.annotation.SuppressLint +import android.content.Context +import android.util.AttributeSet +import androidx.core.content.res.use +import dji.v5.utils.common.LogUtils +import dji.v5.ux.R +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.panel.BarPanelWidget +import dji.v5.ux.core.base.panel.PanelItem +import dji.v5.ux.core.base.panel.PanelWidgetConfiguration +import dji.v5.ux.core.extension.getDimension +import dji.v5.ux.core.extension.getIntegerAndUse +import dji.v5.ux.core.widget.airsense.AirSenseWidget +import dji.v5.ux.core.widget.battery.BatteryWidget +import dji.v5.ux.core.widget.connection.ConnectionWidget +import dji.v5.ux.core.widget.flightmode.FlightModeWidget +import dji.v5.ux.core.widget.gpssignal.GpsSignalWidget +import dji.v5.ux.core.widget.remotecontrollersignal.RemoteControllerSignalWidget +import dji.v5.ux.core.widget.simulator.SimulatorIndicatorWidget +import dji.v5.ux.core.widget.systemstatus.SystemStatusWidget +import dji.v5.ux.core.widget.videosignal.VideoSignalWidget +import dji.v5.ux.core.widget.perception.PerceptionStateWidget +import dji.v5.ux.warning.DeviceHealthAndStatusWidget +import dji.v5.ux.core.widget.setting.SettingWidget +import java.util.* + +/** + * Container for the top bar widgets. This [BarPanelWidget] is divided into two parts. + * The left list contains: + * - [SystemStatusWidget] + * The right list contains + * - [FlightModeWidget] + * - [SimulatorIndicatorWidget] + * - [AirSenseWidget] + * - [GPSSignalWidget] + * - [PerceptionStateWidget] + * - [RemoteControllerSignalWidget] + * - [VideoSignalWidget] + * - [BatteryWidget] + * - [ConnectionWidget] + * + * * Customization: + * Use the attribute "excludeItem" to permanently remove items from the list. This will prevent a + * certain item from being created and shown throughout the lifecycle of the bar panel widget. Here are + * all the flags: system_status, flight_mode, simulator_indicator, air_sense, gps_signal, + * vision, rc_signal, video_signal, battery, connection. + * + * Note that multiple flags can be used simultaneously by logically OR'ing + * them. For example, to hide flight_mode and vision, it can be done by the + * following two steps. + * Define custom xmlns in its layout file: + * xmlns:app="http://schemas.android.com/apk/res-auto" + * Then, add following attribute to the [TopBarPanelWidget]: + * app:excludeItem="flight_mode|vision". + * + * This panel widget also passes attributes to each of the child widgets created. See each + * individual's widget documentation for more customization options. + */ +open class TopBarPanelWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + barPanelWidgetOrientation: BarPanelWidgetOrientation = BarPanelWidgetOrientation.HORIZONTAL +) : BarPanelWidget(context, attrs, defStyleAttr, barPanelWidgetOrientation) { + + //region Widgets Properties + + //region Widgets Properties + val deviceHealthAndStatusWidget: DeviceHealthAndStatusWidget? + + /** + * Getter for [SystemStatusWidget]. Null when excluded from the bar panel. + */ + val systemStatusWidget: SystemStatusWidget? + + /** + * Getter for [FlightModeWidget]. Null when excluded from the bar panel. + */ + val flightModeWidget: FlightModeWidget? + + /** + * Getter for [SimulatorIndicatorWidget]. Null when excluded from the bar panel. + */ + val simulatorIndicatorWidget: SimulatorIndicatorWidget? + + /** + * Getter for [AirSenseWidget]. Null when excluded from the bar panel. + */ + val airSenseWidget: AirSenseWidget? + + /** + * Getter for [GPSSignalWidget]. Null when excluded from the bar panel. + */ + val gpsSignalWidget: GpsSignalWidget? + + /** + * Getter for [PerceptionStateWidget]. Null when excluded from the bar panel. + */ + val visionWidget: PerceptionStateWidget? + + /** + * Getter for [RemoteControllerSignalWidget]. Null when excluded from the bar panel. + */ + val remoteControllerSignalWidget: RemoteControllerSignalWidget? + + /** + * Getter for [VideoSignalWidget]. Null when excluded from the bar panel. + */ + val videoSignalWidget: VideoSignalWidget? + + /** + * Getter for [BatteryWidget]. Null when excluded from the bar panel. + */ + val batteryWidget: BatteryWidget? + + /** + * Getter for [SettingWidget]. Null when excluded from the bar panel. + */ + val settingWidget: SettingWidget? + + /** + * Getter for [ConnectionWidget]. Null when excluded from the bar panel. + */ +// val connectionWidget: ConnectionWidget? + //endregion + + //region Private properties + private var excludedItemsValue = 0 + //endregion + + //region Lifecycle & Setup + + override fun initPanelWidget(context: Context, attrs: AttributeSet?, defStyleAttr: Int, widgetConfiguration: PanelWidgetConfiguration?) { + // Nothing to do + } + + init { + val leftPanelItems = ArrayList() + if (!WidgetValue.SYSTEM_STATUS.isItemExcluded(excludedItemsValue)) { + systemStatusWidget = SystemStatusWidget(context, attrs) + leftPanelItems.add(PanelItem(systemStatusWidget, itemMarginTop = 0, itemMarginBottom = 0)) + } else { + systemStatusWidget = null + } + addLeftWidgets(leftPanelItems.toTypedArray()) + + val rightPanelItems = ArrayList() + if (!WidgetValue.DEVICE_HEALTH.isItemExcluded(excludedItemsValue)) { + deviceHealthAndStatusWidget = DeviceHealthAndStatusWidget(context, attrs) + rightPanelItems.add(PanelItem(deviceHealthAndStatusWidget)) + } else { + deviceHealthAndStatusWidget = null + } + if (!WidgetValue.GPS_SIGNAL.isItemExcluded(excludedItemsValue)) { + gpsSignalWidget = GpsSignalWidget(context, attrs) + rightPanelItems.add(PanelItem(gpsSignalWidget)) + } else { + gpsSignalWidget = null + } + if (!WidgetValue.FLIGHT_MODE.isItemExcluded(excludedItemsValue)) { + flightModeWidget = FlightModeWidget(context, attrs) + rightPanelItems.add(PanelItem(flightModeWidget)) + } else { + flightModeWidget = null + } + if (!WidgetValue.SIMULATOR_INDICATOR.isItemExcluded(excludedItemsValue)) { + simulatorIndicatorWidget = SimulatorIndicatorWidget(context, attrs) + rightPanelItems.add(PanelItem(simulatorIndicatorWidget)) + } else { + simulatorIndicatorWidget = null + } + if (!WidgetValue.AIR_SENSE.isItemExcluded(excludedItemsValue)) { + airSenseWidget = AirSenseWidget(context, attrs) + rightPanelItems.add(PanelItem(airSenseWidget)) + } else { + airSenseWidget = null + } + if (!WidgetValue.VISION.isItemExcluded(excludedItemsValue)) { + visionWidget = PerceptionStateWidget(context, attrs) + rightPanelItems.add(PanelItem(visionWidget)) + } else { + visionWidget = null + } + if (!WidgetValue.RC_SIGNAL.isItemExcluded(excludedItemsValue)) { + remoteControllerSignalWidget = RemoteControllerSignalWidget(context, attrs) + rightPanelItems.add(PanelItem(remoteControllerSignalWidget)) + } else { + remoteControllerSignalWidget = null + } + if (!WidgetValue.VIDEO_SIGNAL.isItemExcluded(excludedItemsValue)) { + videoSignalWidget = VideoSignalWidget(context, attrs) + rightPanelItems.add(PanelItem(videoSignalWidget)) + } else { + videoSignalWidget = null + } + if (!WidgetValue.BATTERY.isItemExcluded(excludedItemsValue)) { + batteryWidget = BatteryWidget(context, attrs) + rightPanelItems.add(PanelItem(batteryWidget)) + } else { + batteryWidget = null + } + + if (!WidgetValue.SETTING.isItemExcluded(excludedItemsValue)) { + settingWidget = SettingWidget(context, attrs) + rightPanelItems.add(PanelItem(settingWidget)) + } else { + settingWidget = null + } + addRightWidgets(rightPanelItems.toTypedArray()) + } + + @SuppressLint("Recycle") + override fun initAttributes(attrs: AttributeSet) { + guidelinePercent = 0.25f + itemsMarginTop = getDimension(R.dimen.uxsdk_bar_panel_margin).toInt() + itemsMarginBottom = getDimension(R.dimen.uxsdk_bar_panel_margin).toInt() + + context.obtainStyledAttributes(attrs, R.styleable.TopBarPanelWidget).use { typedArray -> + typedArray.getIntegerAndUse(R.styleable.TopBarPanelWidget_uxsdk_excludeTopBarItem) { + excludedItemsValue = it + } + } + + super.initAttributes(attrs) + } + + override fun reactToModelChanges() { + // Nothing to do + } + //endregion + + //region Customizations + override fun getIdealDimensionRatioString(): String? = null + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription( + WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.EXPAND + ) + //endregion + + private enum class WidgetValue(val value: Int) { + SYSTEM_STATUS(1), + DEVICE_HEALTH(2), + FLIGHT_MODE(3), + SIMULATOR_INDICATOR(4), + AIR_SENSE(8), + GPS_SIGNAL(16), + VISION(32), + RC_SIGNAL(64), + VIDEO_SIGNAL(128), + BATTERY(256), + SETTING(512), + CONNECTION(1024); + + fun isItemExcluded(excludeItems: Int): Boolean { + return excludeItems and this.value == this.value + } + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/popover/DispatchViewKeyEventToActivityListener.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/popover/DispatchViewKeyEventToActivityListener.kt new file mode 100644 index 00000000..d96c3bf3 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/popover/DispatchViewKeyEventToActivityListener.kt @@ -0,0 +1,34 @@ +package dji.v5.ux.core.popover + +import android.view.KeyEvent +import android.view.View +import dji.v5.ux.core.util.ViewUtil + +/** + * 把View的按键事件透传给Activity + */ +open class DispatchViewKeyEventToActivityListener : View.OnKeyListener { + private var needHandle = false + private var keyDown = false + override fun onKey(v: View?, keyCode: Int, event: KeyEvent): Boolean { + // 返回键交给上面处理 + if (event.keyCode == KeyEvent.KEYCODE_BACK || v == null) { + return false + } else if (!keyDown && event.action == KeyEvent.ACTION_DOWN) { + // repeatCount == 0代表是第一次按下按键,这时开始处理按键事件 + keyDown = true + needHandle = event.repeatCount == 0 + } else if (event.action == KeyEvent.ACTION_UP) { + keyDown = false + } + + return if (!needHandle) { + false + } else { + ViewUtil.dispatchKeyEvent(v.context, event) + true + } + + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/popover/Popover.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/popover/Popover.kt new file mode 100644 index 00000000..fd2c30d2 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/popover/Popover.kt @@ -0,0 +1,602 @@ +package dji.v5.ux.core.popover + +import android.graphics.Color +import android.graphics.Typeface +import android.util.Log +import android.util.TypedValue +import android.view.* +import android.view.View.MeasureSpec +import android.widget.PopupWindow +import android.widget.TextView +import androidx.annotation.LayoutRes +import androidx.annotation.StringRes +import dji.v5.utils.common.LogUtils +import dji.v5.ux.R +import dji.v5.ux.core.extension.getLandScreenSize + + +class Popover(val builder: Builder) { + private val tag = LogUtils.getTag(this) + private var popupWindow: PopupWindow = PopupWindow() + private lateinit var popoverView: PopoverView + + private var width = 0 + private var height = 0 + + private var mDismissListener: PopupWindow.OnDismissListener? = null + + // 是否是文本内容显示 + private var isTextContent = false + + private val onPopupWindowDismiss = PopupWindow.OnDismissListener { + popoverView.removeCallbacks(requestLayoutRunnable) + mDismissListener?.onDismiss() + } + + private val requestLayoutRunnable = { + // 只有处理自定义view的时候才进行下面的重新 + if (!isTextContent) { + val newLocation = configPopupWindow(popoverView) + val height = if (popupWindow.contentView.rootView.height > popoverView.measuredHeight) { + popoverView.measuredHeight + } else { + popupWindow.height + } + val width = if (popupWindow.contentView.rootView.layoutParams.width > popoverView.measuredWidth) { + popoverView.measuredWidth + } else { + popupWindow.width + } + popupWindow.update(newLocation[0] + builder.xOffset, newLocation[1] + builder.yOffset, width, height) + } + } + + init { + popupWindow.setOnDismissListener(onPopupWindowDismiss) + } + + /** + * 获取popupwindow显示坐标 + */ + private fun getShowLocation( + anchorViewLocationInScreen: IntArray, + popoverWidth: Int, + popoverHeight: Int, + anchorWidth: Int, + anchorHeight: Int, + popoverView: PopoverView, + ): IntArray { + + val location = IntArray(2) + + when (builder.position) { + Position.LEFT -> { + location[0] = anchorViewLocationInScreen[0] - popoverWidth + popoverView.paddingLeft + + when (builder.align) { + Align.TOP -> + location[1] = anchorViewLocationInScreen[1] - popoverView.paddingTop + Align.BOTTOM -> + location[1] = anchorViewLocationInScreen[1] + anchorHeight - popoverHeight + popoverView.paddingTop + else -> { + location[1] = anchorViewLocationInScreen[1] + anchorHeight / 2 - popoverHeight / 2 + } + } + } + Position.RIGHT -> { + location[0] = anchorViewLocationInScreen[0] + anchorWidth - popoverView.paddingLeft + + when (builder.align) { + Align.TOP -> + location[1] = anchorViewLocationInScreen[1] - popoverView.paddingTop + Align.BOTTOM -> + location[1] = anchorViewLocationInScreen[1] + anchorHeight - popoverHeight + popoverView.paddingTop + else -> { + location[1] = anchorViewLocationInScreen[1] + anchorHeight / 2 - popoverHeight / 2 + } + } + } + Position.TOP -> { + location[1] = anchorViewLocationInScreen[1] - popoverHeight + popoverView.paddingTop + when (builder.align) { + Align.LEFT -> { + location[0] = anchorViewLocationInScreen[0] - popoverView.paddingLeft + } + Align.RIGHT -> { + location[0] = anchorViewLocationInScreen[0] + anchorWidth - popoverWidth + popoverView.paddingLeft + } + else -> { + location[0] = anchorViewLocationInScreen[0] + anchorWidth / 2 - popoverWidth / 2 + } + } + } + Position.BOTTOM -> { + location[1] = anchorViewLocationInScreen[1] + anchorHeight - popoverView.paddingTop + when (builder.align) { + Align.LEFT -> { + location[0] = anchorViewLocationInScreen[0] - popoverView.paddingLeft + + } + Align.RIGHT -> { + location[0] = anchorViewLocationInScreen[0] + anchorWidth - popoverWidth + popoverView.paddingLeft + + } + else -> { + location[0] = anchorViewLocationInScreen[0] + anchorWidth / 2 - popoverWidth / 2 + } + } + } + } + return location + } + + /** + * 防止popup window显示超出屏幕 + */ + private fun adjustPopupWindowLayoutParams( + location: IntArray, + popoverWidth: Int, + popoverHeight: Int, + screenWidth: Int, + screenHeight: Int, + popoverView: PopoverView, + ) { + if (location[0] + popoverWidth - popoverView.paddingLeft > screenWidth - builder.rightScreenMargin) { + location[0] = screenWidth - popoverWidth + popoverView.paddingLeft - builder.rightScreenMargin + } + + if (location[0] < builder.leftScreenMargin) { + location[0] = -popoverView.paddingLeft + builder.leftScreenMargin + + } + + + if (builder.position != Position.TOP && builder.position != Position.BOTTOM) { + if (location[1] + popoverHeight > screenHeight - builder.bottomScreenMargin) { + location[1] = + screenHeight - popoverHeight + popoverView.paddingBottom - builder.bottomScreenMargin + } + + if (location[1] < builder.topScreenMargin) { + location[1] = -popoverView.paddingTop + builder.topScreenMargin + } + } else { + if (builder.position == Position.BOTTOM && location[1] + popoverHeight > screenHeight - builder.bottomScreenMargin) { + // 向下弹出时,计算最大高度,防止超过距离下方的边距的设置 + popupWindow.height = screenHeight - location[1] - builder.bottomScreenMargin + } else if (builder.position == Position.TOP && location[1] < builder.topScreenMargin) { + // 向上弹出时,计算最大高度,防止超过距离上方边距的设置 + location[1] = -popoverView.paddingTop + builder.topScreenMargin + popupWindow.height = (builder.anchor.y - builder.topScreenMargin).toInt() + } + } + } + + /** + * 配置阴影 + */ + private fun configShadow(popoverView: PopoverView) { + if (builder.enableShadow) { + popoverView.setDropShadow( + builder.dropShadow.blurRadius, + builder.dropShadow.dx, + builder.dropShadow.dy, + builder.dropShadow.color + ) + } + } + + /** + * 配置PopupWindow + */ + private fun configPopupWindow(popoverView: PopoverView): IntArray { + popupWindow.contentView = popoverView + popupWindow.width = WindowManager.LayoutParams.WRAP_CONTENT + popupWindow.height = WindowManager.LayoutParams.WRAP_CONTENT + popupWindow.isFocusable = builder.focusable + popupWindow.isOutsideTouchable = true + popupWindow.animationStyle = android.R.style.Animation_Dialog + // 允许popup window超过屏幕 + popupWindow.isClippingEnabled = false + mDismissListener = builder.dismissListener + + popoverView.isClickable = true + popoverView.setOnClickListener { dismiss() } + + val anchorViewLocationInScreen = IntArray(2) + builder.anchor.getLocationOnScreen(anchorViewLocationInScreen) + + popupWindow.contentView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED) + var popoverWidth = popupWindow.contentView.measuredWidth + var popoverHeight = popupWindow.contentView.measuredHeight + + if (isTextContent) { + popupWindow.width = popoverWidth + popupWindow.height = popoverHeight + } + val anchorWidth = builder.anchor.width + val anchorHeight = builder.anchor.height + val screenWidth = builder.anchor.context.getLandScreenSize().width + val screenHeight = builder.anchor.context.getLandScreenSize().height + + + val popupWindowLocation = getShowLocation(anchorViewLocationInScreen, popoverWidth, popoverHeight, anchorWidth, anchorHeight, popoverView) + adjustPopupWindowLayoutParams(popupWindowLocation, popoverWidth, popoverHeight, screenWidth, screenHeight, popoverView) + + val arrowPosition = when (builder.position) { + Position.BOTTOM, + Position.TOP, + -> + (anchorViewLocationInScreen[0] + anchorWidth / 2 - popupWindowLocation[0] - popoverView.paddingLeft) / (popoverWidth - popoverView.paddingLeft * 2).toFloat() + else -> + (anchorViewLocationInScreen[1] + anchorHeight / 2 - popupWindowLocation[1] - popoverView.paddingTop) / (popoverHeight - popoverView.paddingTop * 2).toFloat() + } + + popoverView.setArrowOffset(arrowPosition) + + return popupWindowLocation + } + + /** + * 创建popupwindow的内容 + */ + private fun createPopoverView(): PopoverView { + isTextContent = false + + val arrowPosition = when (builder.position) { + Position.LEFT -> PopoverView.ArrowPosition.RIGHT + Position.RIGHT -> PopoverView.ArrowPosition.LEFT + Position.TOP -> PopoverView.ArrowPosition.BOTTOM + Position.BOTTOM -> PopoverView.ArrowPosition.TOP + } + + val popoverView = PopoverView(builder.anchor.context, + popoverBackgroundColor = builder.backgroundColor, + arrowColor = builder.arrowColor, + showArrow = builder.showArrow, + arrowPosition = arrowPosition, + borderRadius = builder.anchor.resources.getDimension(R.dimen.uxsdk_4_dp)) + + if (builder.customView != null) { + popoverView.setContentView(builder.customView!!, builder.layoutParams) + } else if (builder.customLayoutRes != 0) { + val view = LayoutInflater.from(builder.anchor.context).inflate(builder.customLayoutRes, popoverView, false) + popoverView.setContentView(view, view.layoutParams) + } else if (builder.content != null) { + // 纯文本提示的Popover + isTextContent = true + val textView = TextView(builder.anchor.context) + textView.text = builder.content + textView.setTextColor(builder.anchor.resources.getColor(builder.textColor)) + textView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, 12F) + textView.setTypeface(textView.typeface, Typeface.BOLD) + val padding = builder.anchor.resources.getDimension(R.dimen.uxsdk_8_dp).toInt() + textView.setPadding(padding, padding, padding, padding) + popoverView.setContentView(textView, builder.layoutParams) + } + + return popoverView + } + + fun show() { + val popupWindowLocation = initPopover() + popupWindow.showAtLocation(builder.anchor, + Gravity.NO_GRAVITY, + popupWindowLocation[0] + builder.xOffset, + popupWindowLocation[1] + builder.yOffset) + + } + + fun show(gravity: Int, x: Int, y: Int) { + initPopover() + popupWindow.showAtLocation(builder.anchor, gravity, x, y) + + } + + fun getContentView(): View? { + return popupWindow.contentView + } + + private fun initPopover(): IntArray { + popoverView = createPopoverView() + configShadow(popoverView) + val popupWindowLocation = configPopupWindow(popoverView) + width = popoverView.measuredWidth + height = popoverView.measuredHeight + + popoverView.addOnLayoutChangeListener { _, left, top, right, bottom, _, _, _, _ -> + val newWidth = right - left + val newHeight = bottom - top + + if (newWidth != width || newHeight != height) { + width = newWidth + height = newHeight + requestLayout() + } + } + + if (popupWindow.isFocusable) { + popupWindow.contentView?.let { + it.isFocusable = true + it.isFocusableInTouchMode = true + it.requestFocus() + it.setOnKeyListener(DispatchViewKeyEventToActivityListener()) + } + } + + return popupWindowLocation + } + + fun dismiss() { + popupWindow.dismiss() + } + + fun isShowing(): Boolean { + return popupWindow.isShowing + } + + fun setOnDismissListener(dismissListener: PopupWindow.OnDismissListener) { + mDismissListener = dismissListener; + } + + fun requestLayout() { + popoverView?.post(requestLayoutRunnable) + } + + /** + * 对齐Anchor View的方式 + */ + enum class Align { + LEFT, + RIGHT, + CENTER, + TOP, + BOTTOM + } + + /** + * Popover相对Anchor View弹出的位置 + */ + enum class Position { + LEFT, + RIGHT, + TOP, + BOTTOM + } + + + class Builder(var anchor: View) { + var content: CharSequence? = null + var customView: View? = null + var customLayoutRes: Int = 0 + var layoutParams: ViewGroup.LayoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT) + var align: Align = Align.CENTER + var position: Position = Position.BOTTOM + var enableShadow: Boolean = true + var showArrow: Boolean = true + var focusable: Boolean = true + var backgroundColor: Int = Color.parseColor("#FFCC00") + var dropShadow: DropShadow + var dismissListener: PopupWindow.OnDismissListener? = null + var xOffset: Int = 0 + var yOffset: Int = 0 + var leftScreenMargin: Int = 0 + var rightScreenMargin: Int = 0 + var topScreenMargin: Int = 0 + var bottomScreenMargin: Int = 0 + var arrowColor: Int = backgroundColor + var textColor: Int = R.color.uxsdk_black + + init { + dropShadow = DropShadow( + color = anchor.resources.getColor(R.color.uxsdk_black_20_percent), + dx = 0F, + dy = anchor.resources.getDimension(R.dimen.uxsdk_4_dp), + blurRadius = anchor.resources.getDimension(R.dimen.uxsdk_16_dp) + ) + + } + + /** + * 显示的文本 + */ + fun content(content: CharSequence?): Builder { + this.content = content + return this + } + + fun content(@StringRes contentRes: Int): Builder { + this.content = anchor.context.getString(contentRes) + return this + } + + /** + * 设置自定义的view + */ + fun customView(view: View?): Builder { + this.customView = view + return this + } + + fun customView(@LayoutRes layoutRes: Int): Builder { + this.customLayoutRes = layoutRes + return this + } + + /** + * 自定义view添加到popover里的layout参数 + * 默认是wrap_content + */ + fun layoutParams(layoutParams: ViewGroup.LayoutParams): Builder { + this.layoutParams = layoutParams + return this + } + + /** + * 自定义view的尺寸 + */ + fun size(width: Int, height: Int): Builder { + this.layoutParams = ViewGroup.LayoutParams(width, height) + return this + } + + /** + * 对齐anchor的方式 + */ + fun align(align: Align): Builder { + this.align = align + return this + } + + /** + * 显示在anchor的哪个位置上 + */ + fun position(position: Position): Builder { + this.position = position + return this + } + + /** + * 是否使用阴影 + */ + fun enableShadow(enableShadow: Boolean): Builder { + this.enableShadow = enableShadow + return this + } + + /** + * 是否显示小箭头 + */ + fun showArrow(showArrow: Boolean): Builder { + this.showArrow = showArrow + return this + } + + /** + * focusable设置为true时,popupwindow会处理返回键等事件,设置为false时,点击事件可以穿透popupwindow传递给下层 + * 默认是true + */ + fun focusable(focusable: Boolean): Builder { + this.focusable = focusable + return this + } + + /** + * 背景颜色 + */ + fun backgroundColor(backgroundColor: Int): Builder { + this.backgroundColor = backgroundColor + return this + } + + /** + * 阴影参数 + * color: 阴影颜色 + * dx: x轴偏移 + * dy: y轴偏移 + * blurRadius: 模糊范围,数值越大模糊范围越大 + */ + fun dropShadow(dropShadow: DropShadow): Builder { + this.dropShadow = dropShadow + return this + } + + /** + * popover消失时的回调 + */ + fun onDismiss(dismissListener: PopupWindow.OnDismissListener): Builder { + this.dismissListener = dismissListener + return this + } + + /** + * 显示坐标x轴偏移 + * 默认0 + */ + fun xOffset(xOffset: Int): Builder { + this.xOffset = xOffset + return this + } + + /** + * 显示坐标y轴偏移 + * 默认是0 + */ + fun yOffset(yOffset: Int): Builder { + this.yOffset = yOffset + return this + } + + /** + * 距离屏幕边缘的边距 + */ + fun allScreenMargin(margin: Int): Builder { + this.topScreenMargin = margin + this.rightScreenMargin = margin + this.bottomScreenMargin = margin + this.leftScreenMargin = margin + return this + } + + /** + * 距离右边屏幕边距 + */ + fun rightScreenMargin(margin: Int): Builder { + this.rightScreenMargin = margin + return this + } + + /** + * 距离下边屏幕的边距 + */ + fun bottomScreenMargin(margin: Int): Builder { + this.bottomScreenMargin = margin + return this + } + + /** + * 距离左边屏幕的边距 + */ + fun leftScreenMargin(margin: Int): Builder { + this.leftScreenMargin = margin + return this + } + + /** + * 距离上边屏幕的边距 + */ + fun topScreenMargin(margin: Int): Builder { + this.topScreenMargin = margin + return this + } + + /** + * 指定箭头颜色 + */ + fun arrowColor(color: Int): Builder { + this.arrowColor = color + return this + } + + + fun build(): Popover { + return Popover(this) + } + + fun textColor(color: Int): Builder { + this.textColor = color + return this + } + } + + /** + * 阴影配置 + */ + class DropShadow( + var color: Int = 0, + var dx: Float = 0F, + var dy: Float = 0F, + var blurRadius: Float = 0F, + ) + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/popover/PopoverHelper.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/popover/PopoverHelper.kt new file mode 100644 index 00000000..37850179 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/popover/PopoverHelper.kt @@ -0,0 +1,48 @@ +package dji.v5.ux.core.popover + +import android.view.View +import android.view.ViewGroup +import androidx.annotation.LayoutRes +import dji.v5.ux.R +import dji.v5.utils.common.AndUtil + + +object PopoverHelper { + + fun showPopover( + anchor: View, + @LayoutRes layoutRes: Int, + width: Int = ViewGroup.LayoutParams.WRAP_CONTENT, + height: Int = ViewGroup.LayoutParams.WRAP_CONTENT, + ): Popover { + val popover = baseBuilder(anchor) + .customView(layoutRes) + .size(width, height) + .build() + popover.show() + return popover + } + + fun showPopover( + anchor: View, + layout: View, + width: Int = ViewGroup.LayoutParams.WRAP_CONTENT, + height: Int = ViewGroup.LayoutParams.WRAP_CONTENT, + ): Popover { + val popover = baseBuilder(anchor) + .customView(layout) + .size(width, height) + .build() + popover.show() + return popover + } + + fun baseBuilder(anchor: View): Popover.Builder { + return Popover.Builder(anchor) + .arrowColor(AndUtil.getResColor(R.color.uxsdk_fpv_popover_title_background_color)) + .yOffset(AndUtil.getDimension(R.dimen.uxsdk_2_dp).toInt()) + .backgroundColor(AndUtil.getResColor(R.color.uxsdk_white_0_percent)) + .allScreenMargin(AndUtil.getDimension(R.dimen.uxsdk_32_dp).toInt()) + .enableShadow(false) + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/popover/PopoverView.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/popover/PopoverView.kt new file mode 100644 index 00000000..cc4381f3 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/popover/PopoverView.kt @@ -0,0 +1,214 @@ +package dji.v5.ux.core.popover + +import android.content.Context +import android.graphics.* +import android.graphics.drawable.Drawable +import android.os.Build +import android.view.Gravity +import android.view.View +import android.view.View.MeasureSpec.UNSPECIFIED +import android.view.ViewGroup +import android.widget.FrameLayout +import android.widget.ImageView +import androidx.cardview.widget.CardView +import com.dji.industry.pandora.pilot2.uikit.popover.TintedBitmapDrawable +import dji.v5.ux.R + + +class PopoverView(context: Context, + private var popoverBackgroundColor: Int = Color.parseColor("#FFCC00"), + private var arrowColor: Int = popoverBackgroundColor, + private var borderRadius: Float = 0F, + private var showArrow: Boolean = true, + private var arrowOffset: Float = 0.5F, + private var arrowPosition: ArrowPosition = ArrowPosition.TOP +): FrameLayout(context) { + + // 箭头位置 + enum class ArrowPosition { + TOP, + RIGHT, + BOTTOM, + LEFT + } + // 箭头旋转的角度 + private var arrowAngle = 270F + + lateinit var arrowImageView: ImageView + lateinit var contentLayout: CardView + + // 阴影 + var shadowPaint = Paint() + var shadowDx: Float = 0F + var shadowDy: Float = 0F + var shadowRectF = RectF() + var enableDropShadow = false + + + init { + arrowAngle = when(arrowPosition) { + ArrowPosition.TOP ->270F + ArrowPosition.RIGHT ->0F + ArrowPosition.BOTTOM ->90F + ArrowPosition.LEFT ->180F + } + + initViews() + } + + private fun getArrowDrawable(): Drawable { + val arrowRes: Int = R.drawable.uxsdk_ic_themedark_popover_arrow_left + val source = BitmapFactory.decodeResource(this.resources, arrowRes) + + val rotateBitmap = rotateBitmap(source, arrowAngle) + + return TintedBitmapDrawable(resources, rotateBitmap, arrowColor) + } + + private fun initViews() { + + contentLayout = CardView(context) + contentLayout.radius = borderRadius + contentLayout.cardElevation = 0F + contentLayout.isClickable = true + + contentLayout.id = View.generateViewId() + contentLayout.setCardBackgroundColor(popoverBackgroundColor) + + val contentLayoutParams = LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT) + + arrowImageView = ImageView(context) + arrowImageView.id = View.generateViewId() + arrowImageView.setImageDrawable(getArrowDrawable()) + + val arrowLayoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT) + + arrowImageView.measure(UNSPECIFIED, UNSPECIFIED) + + if (showArrow) { + when (arrowPosition) { + ArrowPosition.TOP -> { + arrowLayoutParams.gravity = Gravity.TOP + contentLayoutParams.topMargin = arrowImageView.measuredHeight + } + ArrowPosition.RIGHT -> { + arrowLayoutParams.gravity = Gravity.RIGHT + contentLayoutParams.rightMargin = arrowImageView.measuredWidth + } + ArrowPosition.BOTTOM -> { + arrowLayoutParams.gravity = Gravity.BOTTOM + contentLayoutParams.bottomMargin = arrowImageView.measuredHeight + } + ArrowPosition.LEFT -> { + arrowLayoutParams.gravity = Gravity.LEFT + contentLayoutParams.leftMargin = arrowImageView.measuredWidth + } + } + } + + addView(arrowImageView, arrowLayoutParams) + addView(contentLayout, contentLayoutParams) + + post(this::updateArrow) + } + + override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { + super.onSizeChanged(w, h, oldw, oldh) + post(this::updateArrow) + } + + fun rotateBitmap(source: Bitmap, angle: Float): Bitmap { + val matrix = Matrix() + matrix.postRotate(angle) + return Bitmap.createBitmap(source, 0, 0, source.width, source.height, matrix, true) + } + + + private fun updateArrow() { + if (!showArrow) { + arrowImageView.visibility = GONE + return + } + val layoutParams = arrowImageView.layoutParams as LayoutParams + when(arrowPosition) { + ArrowPosition.TOP, + ArrowPosition.BOTTOM + -> { + val x = contentLayout.width * arrowOffset - arrowImageView.width/2 + layoutParams.leftMargin = x.toInt() + } + ArrowPosition.LEFT, + ArrowPosition.RIGHT + -> { + val y = contentLayout.height * arrowOffset - arrowImageView.height/2 + layoutParams.topMargin = y.toInt() + } + } + arrowImageView.layoutParams = layoutParams + } + + fun setArrowOffset(arrowOffset: Float): PopoverView { + this.arrowOffset = arrowOffset + updateArrow() + return this + } + + fun setContentView(view: View): PopoverView { + if (view.parent != null && view.parent is ViewGroup) { + (view.parent as ViewGroup).removeView(view) + } + this.contentLayout.addView(view) + return this + } + + fun setContentView(view: View, layoutParams: ViewGroup.LayoutParams): PopoverView { + if (view.parent != null && view.parent is ViewGroup) { + (view.parent as ViewGroup).removeView(view) + } + this.contentLayout.addView(view, layoutParams) + return this + } + + fun setDropShadow(blurRadius: Float, dx: Float, dy: Float, color: Int) { + // Android 10以下系统不能用硬件加速,否则BlurMaskFilter不生效 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { + setLayerType(View.LAYER_TYPE_SOFTWARE, null) + } + enableDropShadow = true + shadowDx = dx + shadowDy = dy + val blurMaskFilter = BlurMaskFilter(blurRadius, BlurMaskFilter.Blur.NORMAL) + + shadowPaint.run { + style = Paint.Style.FILL + isAntiAlias = true + shadowPaint.color = color + maskFilter = blurMaskFilter + } + + val padding = (blurRadius * 2).toInt() + setPadding(padding, padding, padding, padding) + setWillNotDraw(false) + postInvalidate() + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + + if (!enableDropShadow) { + return + } + + shadowRectF.set(contentLayout.left + shadowDx, + contentLayout.top + shadowDy, + contentLayout.right + shadowDx, + contentLayout.bottom + shadowDy) + + canvas?.save() + + canvas?.drawRoundRect(shadowRectF, contentLayout.radius, contentLayout.radius, shadowPaint) + + canvas?.restore() + + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/popover/TintedBitmapDrawable.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/popover/TintedBitmapDrawable.kt new file mode 100644 index 00000000..62797844 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/popover/TintedBitmapDrawable.kt @@ -0,0 +1,27 @@ +package com.dji.industry.pandora.pilot2.uikit.popover + +import android.content.res.Resources +import android.graphics.* +import android.graphics.drawable.BitmapDrawable + +class TintedBitmapDrawable(res: Resources?, bitmap: Bitmap?, private var tint: Int) : BitmapDrawable(res, bitmap) { + private var tintAlpha = 0 + + init { + tintAlpha = Color.alpha(tint) + } + + override fun setTint(tint: Int) { + this.tint = tint + tintAlpha = Color.alpha(tint) + } + + override fun draw(canvas: Canvas) { + val paint = paint + if (paint.colorFilter == null) { + paint.colorFilter = LightingColorFilter(tint, 0) + paint.alpha = tintAlpha + } + super.draw(canvas) + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/BaseFrameLayout.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/BaseFrameLayout.java new file mode 100644 index 00000000..2c515bb3 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/BaseFrameLayout.java @@ -0,0 +1,70 @@ +package dji.v5.ux.core.ui; + +import android.content.Context; +import android.os.Looper; +import android.util.AttributeSet; +import android.view.View; +import android.widget.FrameLayout; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.BuildConfig; + + +public class BaseFrameLayout extends FrameLayout { + + protected final String TAG = this.getClass().getSimpleName(); + + public BaseFrameLayout(@NonNull Context context) { + super(context); + } + + public BaseFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public BaseFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public BaseFrameLayout(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + /** + * 接管处理下可能存在的异步invalidate + * https://cloud.tencent.com/developer/article/1846821 + */ + @Override + public void invalidate() { + if (Looper.myLooper() == Looper.getMainLooper()) { + super.invalidate(); + } else { + recordInvalidateCallStack(this); + } + } + + public static void recordInvalidateCallStack(View view) { + view.postInvalidate(); + if (BuildConfig.DEBUG) { + throw new NonMainThreadInvalidateException(); + } else { + StringBuilder stringBuilder = new StringBuilder(); + for (StackTraceElement stackTraceElement : Thread.currentThread().getStackTrace()) { + stringBuilder.append(stackTraceElement); + stringBuilder.append("\n"); + } + LogUtils.e("View", " async call invalidate \n" + stringBuilder); + } + } + + public static class NonMainThreadInvalidateException extends RuntimeException { + public NonMainThreadInvalidateException() { + super("Dji Only the original thread that created a view hierarchy can touch its views."); + } + + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/BaseView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/BaseView.java new file mode 100644 index 00000000..a31966fd --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/BaseView.java @@ -0,0 +1,40 @@ +package dji.v5.ux.core.ui; + +import android.content.Context; +import android.os.Looper; +import android.util.AttributeSet; +import android.view.View; + +import androidx.annotation.Nullable; + +public class BaseView extends View { + protected final String TAG = getClass().getSimpleName(); + public BaseView(Context context) { + super(context); + } + + public BaseView(Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public BaseView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public BaseView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } + + /** + * 接管处理下可能存在的异步invalidate + * https://cloud.tencent.com/developer/article/1846821 + */ + @Override + public void invalidate() { + if (Looper.myLooper() == Looper.getMainLooper()) { + super.invalidate(); + } else { + BaseFrameLayout.recordInvalidateCallStack(this); + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/CenterPointView.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/CenterPointView.kt new file mode 100644 index 00000000..22e68eaa --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/CenterPointView.kt @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +package dji.v5.ux.core.ui + +import android.content.Context +import android.graphics.Color +import android.util.AttributeSet +import android.view.View +import androidx.annotation.ColorInt +import androidx.annotation.DrawableRes +import androidx.appcompat.widget.AppCompatImageView +import dji.v5.ux.R +import dji.v5.ux.core.communication.GlobalPreferencesManager +import dji.v5.ux.core.ui.CenterPointView.CenterPointType +import dji.v5.ux.core.util.ViewUtil + +/** + * Displays an icon based on the given [CenterPointType]. + */ +class CenterPointView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : AppCompatImageView(context, attrs, defStyleAttr) { + + //region Fields + /** + * The color of the center point + */ + @get:ColorInt + var color: Int + get() { + return if (GlobalPreferencesManager.getInstance() != null) { + GlobalPreferencesManager.getInstance().centerPointColor + } else { + Color.WHITE + } + } + set(@ColorInt color) { + if (this.color != color && GlobalPreferencesManager.getInstance() != null) { + GlobalPreferencesManager.getInstance().centerPointColor = color + ViewUtil.tintImage(this, color) + } + } + + /** + * The type of center point + */ + var type: CenterPointType + get() { + return if (GlobalPreferencesManager.getInstance() != null) { + GlobalPreferencesManager.getInstance().centerPointType + } else { + CenterPointType.NONE + } + } + set(type) { + if (this.type != type && GlobalPreferencesManager.getInstance() != null) { + GlobalPreferencesManager.getInstance().centerPointType = type + initView() + } + } + //endregion + + //region Constructor + init { + initView() + } + + private fun initView() { + if (type == CenterPointType.NONE) { + visibility = View.GONE + } else { + visibility = View.VISIBLE + setImageResource(type.drawableId) + ViewUtil.tintImage(this, color) + } + } + //endregion + + //region Classes + /** + * Represents the types of center points that can be set. + * + * @property value Identifier for the item + * @property drawableId ID of the drawable resource + */ + enum class CenterPointType(@get:JvmName("value") val value: Int, + @DrawableRes var drawableId: Int) { + /** + * The center point is hidden. + */ + NONE(0, -1), + + /** + * The center point is a standard shape. + */ + STANDARD(1, R.drawable.uxsdk_ic_centerpoint_standard), + + /** + * The center point is a cross shape. + */ + CROSS(2, R.drawable.uxsdk_ic_centerpoint_cross), + + /** + * The center point is a narrow cross shape. + */ + NARROW_CROSS(3, R.drawable.uxsdk_ic_centerpoint_narrow_cross), + + /** + * The center point is a frame shape. + */ + FRAME(4, R.drawable.uxsdk_ic_centerpoint_frame), + + /** + * The center point is a frame shape with a cross inside. + */ + FRAME_AND_CROSS(5, R.drawable.uxsdk_ic_centerpoint_frame_and_cross), + + /** + * The center point is a square shape. + */ + SQUARE(6, R.drawable.uxsdk_ic_centerpoint_square), + + /** + * The center point is a square shape with a cross inside. + */ + SQUARE_AND_CROSS(7, R.drawable.uxsdk_ic_centerpoint_square_and_cross), + + /** + * The center point is an unknown shape. + */ + UNKNOWN(8, -1); + + companion object { + @JvmStatic + val values = values() + + @JvmStatic + fun find(value: Int): CenterPointType { + return values.find { it.value == value } ?: UNKNOWN + } + } + + } + //endregion + + companion object { + /** + * Sets a new drawable to display when the center point is set to the given type. + * + * @param type The type of center point + * @param drawableId The drawable that will be displayed + */ + @JvmStatic + fun setImageForType(type: CenterPointType, @DrawableRes drawableId: Int) { + type.drawableId = drawableId + } + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/GridLineView.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/GridLineView.kt new file mode 100644 index 00000000..e0b1dfbe --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/GridLineView.kt @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +package dji.v5.ux.core.ui + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.util.AttributeSet +import android.view.View +import androidx.annotation.ColorInt +import dji.v5.ux.R +import dji.v5.ux.core.communication.GlobalPreferencesManager +import dji.v5.ux.core.extension.getColor + +private const val DISABLED = 0 +private const val DEFAULT_NUM_LINES = 4 +private const val DEFAULT_LINE_WIDTH = 1 + +/** + * Displays a grid centered in the view. + */ +class GridLineView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : View(context, attrs, defStyleAttr) { + //region Fields + private val paint: Paint = Paint() + private var gridWidth = DISABLED + private var gridHeight = DISABLED + + /** + * The color of the grid lines + */ + @get:ColorInt + var lineColor = getColor(R.color.uxsdk_white_80_percent) + set(@ColorInt color) { + field = color + if (!isInEditMode) { + paint.color = lineColor + } + invalidate() + } + + /** + * The type of grid line. + */ + var type: GridLineType + get() { + return if (GlobalPreferencesManager.getInstance() != null) { + GlobalPreferencesManager.getInstance().gridLineType + } else { + GridLineType.NONE + } + } + set(type) { + if (this.type != type && GlobalPreferencesManager.getInstance() != null) { + GlobalPreferencesManager.getInstance().gridLineType = type + invalidate() + } + } + + /** + * The width of the grid lines + * + * @return The width of the grid lines + */ + var lineWidth: Float = DEFAULT_LINE_WIDTH.toFloat() + set(lineWidth) { + field = lineWidth + if (!isInEditMode) { + paint.strokeWidth = lineWidth + } + invalidate() + } + + /** + * The number of lines drawn both horizontally and vertically on the screen, including the + * two border lines. + */ + var numberOfLines: Int = DEFAULT_NUM_LINES + set(numLines) { + field = numLines + invalidate() + } + + //endregion + + //region Constructor + init { + if (!isInEditMode) { + setWillNotDraw(false) + paint.isAntiAlias = true + paint.color = lineColor + paint.strokeWidth = lineWidth + } + } + //endregion + + //region Customization + /** + * Adjust the width and height of the grid lines. The grid will be centered within the view. + * + * @param width The new width of the grid lines. + * @param height The new height of the grid lines. + */ + fun adjustDimensions(width: Int, height: Int) { + if (width > 0 && height > 0) { + gridWidth = width + gridHeight = height + } else { + gridWidth = DISABLED + gridHeight = DISABLED + } + invalidate() + } + //endregion + + //region Lifecycle + override fun onDraw(canvas: Canvas) { + if (gridHeight == DISABLED || gridWidth == DISABLED) { + return + } + var measureWidth = measuredWidth.toFloat() + var measureHeight = measuredHeight.toFloat() + + // Offset by 1 because canvas origin is at 0 + measureHeight -= 1f + measureWidth -= 1f + + // Calculate offset for different aspect ratios + var widthOffset = ((measureWidth - gridWidth) / 2).toInt() + if (widthOffset < 0) { + widthOffset = 0 + } + var heightOffset = ((measureHeight - gridHeight) / 2).toInt() + if (heightOffset < 0) { + heightOffset = 0 + } + if (type != GridLineType.NONE) { + // Draw horizontal lines + val horizontalOffset = (measureHeight - heightOffset - heightOffset) / (numberOfLines - 1) + var y = heightOffset.toFloat() + while (y <= measureHeight - heightOffset) { + canvas.drawLine(widthOffset.toFloat(), y, measureWidth - widthOffset, y, paint) + y += horizontalOffset + } + + // Draw vertical lines + val verticalOffset = (measureWidth - widthOffset - widthOffset) / (numberOfLines - 1) + var x = widthOffset.toFloat() + while (x <= measureWidth - widthOffset) { + canvas.drawLine(x, heightOffset.toFloat(), x, measureHeight - heightOffset, paint) + x += verticalOffset + } + + // Draw diagonal lines + if (type == GridLineType.PARALLEL_DIAGONAL) { + canvas.drawLine(widthOffset.toFloat(), heightOffset.toFloat(), measureWidth - widthOffset, measureHeight - heightOffset, paint) + canvas.drawLine(widthOffset.toFloat(), measureHeight - heightOffset, measureWidth - widthOffset, heightOffset.toFloat(), paint) + } + } + } + //endregion + + //region Classes + /** + * Represents the types of grid lines that can be set. + * + * @property value Identifier for the item + */ + enum class GridLineType(@get:JvmName("value") val value: Int) { + /** + * No grid lines are visible. + */ + NONE(0), + + /** + * Horizontal and vertical grid lines are visible using a NxN grid. + */ + PARALLEL(1), + + /** + * Same as PARALLEL with the addition of 2 diagonal lines running through the center. + */ + PARALLEL_DIAGONAL(2), + + /** + * The type of grid is unknown. + */ + UNKNOWN(3); + + companion object { + @JvmStatic + val values = values() + + @JvmStatic + fun find(value: Int): GridLineType { + return values.find { it.value == value } ?: UNKNOWN + } + } + + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/HorizontalSeekBar.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/HorizontalSeekBar.java new file mode 100644 index 00000000..75b5c85f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/HorizontalSeekBar.java @@ -0,0 +1,1109 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.ui; + +import android.content.Context; +import android.content.res.ColorStateList; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; +import android.widget.ImageView; +import android.widget.TextView; + +import java.util.LinkedList; +import java.util.List; + +import androidx.annotation.ColorInt; +import androidx.annotation.Dimension; +import androidx.annotation.DrawableRes; +import androidx.annotation.IntRange; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StyleRes; +import androidx.constraintlayout.widget.ConstraintLayout; +import dji.v5.ux.R; + +/** + * Displays a customized seek bar that displays a value positioned above the thumb image. There are + * also options for displaying either minimum and maximum values or plus and minus buttons to the + * start and end of the seek bar, as well as a bar showing a baseline as a recommended value. + */ +public class HorizontalSeekBar extends ConstraintLayout implements View.OnTouchListener, View.OnClickListener { + + //region Properties + private ImageView seekBarTrackImage; + private TextView seekBarValueText; + private List onSeekBarChangeListeners; + private int progressMax; + private int currentProgress; + // Null status will be used + private int previousProgress; + + private float boundaryLeft; + private float boundaryRight; + private float xThumbStartCenter; + private float xMoveStart; + private ImageView seekBarThumbImage; + + //Min and Max + private boolean minValueVisibility = false; + private boolean maxValueVisibility = false; + private TextView seekBarMinText; + private TextView seekBarMaxText; + + //Plus and minus + private boolean minusVisibility = false; + private boolean plusVisibility = false; + private ImageView seekBarMinus; + private ImageView seekBarPlus; + + // Baseline + private boolean baselineVisibility = false; + private int baselineProgress = -1; + private View seekBarBaseline; + private int seekBarBaselineColor; + //endregion + + //region Life Cycle + public HorizontalSeekBar(@NonNull Context context) { + super(context); + initView(context); + } + + public HorizontalSeekBar(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + initView(context); + initAttributes(context, attrs); + } + + public HorizontalSeekBar(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initView(context); + initAttributes(context, attrs); + } + + public void initView(@NonNull Context context) { + inflate(context, R.layout.uxsdk_view_seek_bar, this); + seekBarTrackImage = findViewById(R.id.imageview_track); + seekBarThumbImage = findViewById(R.id.imageview_thumb); + seekBarValueText = findViewById(R.id.textview_value); + seekBarMinText = findViewById(R.id.textview_min_value); + seekBarMaxText = findViewById(R.id.textview_max_value); + seekBarBaseline = findViewById(R.id.imageview_baseline); + seekBarMinus = findViewById(R.id.imageview_minus); + seekBarPlus = findViewById(R.id.imageview_plus); + + seekBarBaselineColor = getResources().getColor(R.color.uxsdk_green); + } + + private void initAttributes(@NonNull Context context, @Nullable AttributeSet attrs) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.SeekBarView); + + setMinValueVisibility(typedArray.getBoolean(R.styleable.SeekBarView_uxsdk_minValueVisible, false)); + setMaxValueVisibility(typedArray.getBoolean(R.styleable.SeekBarView_uxsdk_maxValueVisible, false)); + setMinusVisibility(typedArray.getBoolean(R.styleable.SeekBarView_uxsdk_minusVisible, false)); + setPlusVisibility(typedArray.getBoolean(R.styleable.SeekBarView_uxsdk_plusVisible, false)); + setBaselineVisibility(typedArray.getBoolean(R.styleable.SeekBarView_uxsdk_baselineVisible, false)); + + typedArray.recycle(); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + super.onLayout(changed, left, top, right, bottom); + boundaryLeft = seekBarTrackImage.getLeft(); + boundaryRight = seekBarTrackImage.getRight(); + updateTextAndThumbInProgress(currentProgress); + } + //endregion + + // region Public Methods + + /** + * Get the maximum value + * + * @return the maximum value + */ + public int getMax() { + synchronized (this) { + return progressMax; + } + } + + /** + * Set the maximum value + * + * @param max the maximum value + */ + public void setMax(@IntRange(from = 0) int max) { + synchronized (this) { + progressMax = max; + } + } + + /** + * Set whether the seek bar is enabled + * + * @param status True to enable, false to disable + */ + public void enable(boolean status) { + seekBarValueText.setEnabled(status); + //seekBarValueText.requestLayout(); + seekBarThumbImage.setEnabled(status); + //seekBarThumbImage.requestLayout(); + + if (status) { + setOnTouchListener(this); + seekBarMinus.setOnClickListener(this); + seekBarPlus.setOnClickListener(this); + } else { + setOnTouchListener(null); + seekBarMinus.setOnClickListener(null); + seekBarPlus.setOnClickListener(null); + } + } + + /** + * Add a listener to react when the seek bar has changed. + * + * @param listener The listener to add. + */ + public void addOnSeekBarChangeListener(@NonNull OnSeekBarChangeListener listener) { + if (onSeekBarChangeListeners == null) { + onSeekBarChangeListeners = new LinkedList<>(); + } + onSeekBarChangeListeners.add(listener); + } + + /** + * Remove a listener from the seek bar. + * + * @param listener The listener to remove. + */ + public void removeOnSeekBarChangeListener(@NonNull OnSeekBarChangeListener listener) { + if (onSeekBarChangeListeners != null) { + onSeekBarChangeListeners.remove(listener); + } + } + + /** + * Remove all listeners from the seek bar. + */ + public void removeAllOnSeekBarChangeListeners() { + if (onSeekBarChangeListeners != null) { + onSeekBarChangeListeners.clear(); + } + } + + /** + * Set the text above the seek bar progress indicator + * + * @param text The text to display above the progress indicator + */ + public void setText(@Nullable String text) { + seekBarValueText.setText(text); + } + + /** + * Get the text above the seek bar progress indicator + */ + public String getText() { + return seekBarValueText.getText().toString(); + } + + /** + * Set the minimum value text + * + * @param text The minimum value text + */ + public void setMinValueText(@Nullable String text) { + seekBarMinText.setText(text); + } + + /** + * Set the maximum value text + * + * @param text The maximum value text + */ + public void setMaxValueText(@Nullable String text) { + seekBarMaxText.setText(text); + } + + /** + * Get the progress of the seek bar. This will be in the range 0..max where max was set by + * {@link #setMax(int)}. + * + * @return The progress of the seek bar + */ + public int getProgress() { + return currentProgress; + } + + /** + * Set the progress of the seek bar. This should be in the range 0..max where max was set by + * {@link #setMax(int)}. + * + * @param progress The progress to set the seek bar to + */ + public void setProgress(@IntRange(from = 0) int progress) { + updateSeekBarProgress(progress, false); + } + + /** + * Set the progress of the seek bar to the value it was at before it was interacted with. + */ + public void restorePreviousProgress() { + setProgress(previousProgress); + updateTextAndThumbInProgress(previousProgress); + } + //endregion + + //region Seek Bar Internal Methods + + private void updateSeekBarProgress(int progress, boolean isFromUI) { + synchronized (this) { + if (progress >= progressMax) { + currentProgress = progressMax; + } else if (progress < 0) { + currentProgress = 0; + } else { + currentProgress = progress; + } + + if (onSeekBarChangeListeners != null) { + for (int i = 0; i < onSeekBarChangeListeners.size(); i++) { + onSeekBarChangeListeners.get(i).onProgressChanged(this, currentProgress, isFromUI); + } + } + updateTextAndThumbInProgress(currentProgress); + } + } + + private void updateTextAndThumbInProgress(int progress) { + float newX = boundaryLeft + getIncrement() * progress; + updateTextAndThumbPosition(newX); + } + + private void updateTextAndThumbPosition(float newX) { + float xPosition; + if (newX < boundaryLeft) { + xPosition = boundaryLeft; + } else if (newX > boundaryRight) { + xPosition = boundaryRight; + } else { + xPosition = newX; + } + + setSeekbarTextPosition(xPosition); + setSeekbarThumbPosition(xPosition); + } + + private void setSeekbarTextPosition(float newX) { + seekBarValueText.setX(newX - seekBarValueText.getWidth() / 2f); + } + + private void setSeekbarThumbPosition(float newX) { + seekBarThumbImage.setX(newX - seekBarThumbImage.getWidth() / 2f); + } + + /** + * Make the unit smaller to make the room for the last item. + */ + private float getIncrement() { + return (boundaryRight - boundaryLeft) / progressMax; + } + + //endregion + + //region OnTouchListener + @Override + public boolean onTouch(View v, MotionEvent event) { + switch (event.getAction()) { + + case MotionEvent.ACTION_DOWN: + onStartTracking(event); + break; + + case MotionEvent.ACTION_CANCEL: + case MotionEvent.ACTION_UP: + onEndTracking(); + break; + + case MotionEvent.ACTION_MOVE: + // perform scrolling + onTrackMoving(event); + break; + + default: + break; + + } + + return true; + } + + private void onStartTracking(@NonNull MotionEvent event) { + xMoveStart = event.getX(); + xThumbStartCenter = seekBarThumbImage.getX() + seekBarThumbImage.getWidth() / 2f; + + previousProgress = currentProgress; + if (onSeekBarChangeListeners != null) { + for (int i = 0; i < onSeekBarChangeListeners.size(); i++) { + onSeekBarChangeListeners.get(i).onStartTrackingTouch(this, currentProgress); + } + } + } + //endregion + + //region OnDragListener + private void onTrackMoving(@NonNull MotionEvent event) { + float xDelta = event.getX() - xMoveStart; + float newX = xThumbStartCenter + xDelta; + updateSeekBarProgress((int) ((newX - boundaryLeft) / getIncrement()), true); + } + + private void onEndTracking() { + if (onSeekBarChangeListeners != null) { + for (int i = 0; i < onSeekBarChangeListeners.size(); i++) { + onSeekBarChangeListeners.get(i).onStopTrackingTouch(this, currentProgress); + } + } + } + //endregion + + //region OnClickListener + @Override + public void onClick(View v) { + if (onSeekBarChangeListeners != null) { + if (v.equals(seekBarMinus)) { + for (int i = 0; i < onSeekBarChangeListeners.size(); i++) { + onSeekBarChangeListeners.get(i).onMinusClicked(this); + } + } else if (v.equals(seekBarPlus)) { + for (int i = 0; i < onSeekBarChangeListeners.size(); i++) { + onSeekBarChangeListeners.get(i).onPlusClicked(this); + } + } + } + } + //endregion + + /** + * Get the visibility of the minimum value + * + * @return True if the minimum value is visible, false otherwise. + */ + public boolean isMinValueVisible() { + return minValueVisibility; + } + + /** + * Set the visibility of the minimum value + * + * @param minValueVisibility True to show the minimum value, false to hide it. + */ + public void setMinValueVisibility(boolean minValueVisibility) { + this.minValueVisibility = minValueVisibility; + seekBarMinText.setVisibility(minValueVisibility ? VISIBLE : GONE); + } + + /** + * Get the visibility of the maximum value + * + * @return True if the maximum value is visible, false otherwise. + */ + public boolean isMaxValueVisible() { + return maxValueVisibility; + } + + /** + * Set the visibility of the maximum value + * + * @param maxValueVisibility True to show the maximum value, false to hide it. + */ + public void setMaxValueVisibility(boolean maxValueVisibility) { + this.maxValueVisibility = maxValueVisibility; + seekBarMaxText.setVisibility(maxValueVisibility ? VISIBLE : GONE); + } + + /** + * Get the visibility of the minus button + * + * @return True if the minus button is visible, false otherwise. + */ + public boolean isMinusVisible() { + return minusVisibility; + } + + /** + * Set the visibility of the minus button + * + * @param minusVisibility True to show the minus button, false to hide it. + */ + public void setMinusVisibility(boolean minusVisibility) { + this.minusVisibility = minusVisibility; + seekBarMinus.setVisibility(minusVisibility ? VISIBLE : GONE); + } + + /** + * Get the visibility of the plus button + * + * @return True if the plus button is visible, false otherwise. + */ + public boolean isPlusVisible() { + return plusVisibility; + } + + /** + * Set the visibility of the plus button + * + * @param plusVisibility True to show the plus button, false to hide it. + */ + public void setPlusVisibility(boolean plusVisibility) { + this.plusVisibility = plusVisibility; + seekBarPlus.setVisibility(plusVisibility ? VISIBLE : GONE); + } + + /** + * Get the visibility of the baseline + * + * @return True if the baseline is visible, false otherwise. + */ + public boolean isBaselineVisibility() { + return baselineVisibility; + } + + /** + * Set the visibility of the baseline + * + * @param baselineVisibility True to show the baseline, false to hide it. + */ + public void setBaselineVisibility(boolean baselineVisibility) { + this.baselineVisibility = baselineVisibility; + seekBarBaseline.setVisibility(baselineVisibility ? VISIBLE : GONE); + } + + /** + * Get the progress of the baseline + * + * @return The progress of the baseline + */ + public int getBaselineProgress() { + return baselineProgress; + } + + /** + * Set the baseline progress + * + * @param baselineProgress The progress to set the baseline to + */ + public void setBaselineProgress(int baselineProgress) { + this.baselineProgress = baselineProgress; + float newX = boundaryLeft + getIncrement() * baselineProgress; + seekBarBaseline.setX(newX - seekBarBaseline.getWidth() / 2f); + } + + /** + * Get the drawable resource for the track icon + * + * @return Drawable resource for the icon + */ + @Nullable + public Drawable getTrackIcon() { + return seekBarTrackImage.getDrawable(); + } + + /** + * Set the resource ID for the track icon + * + * @param resourceId Integer ID of the drawable resource + */ + public void setTrackIcon(@DrawableRes int resourceId) { + setTrackIcon(getResources().getDrawable(resourceId)); + } + + /** + * Set the drawable resource for the track icon + * + * @param icon Drawable resource for the icon + */ + public void setTrackIcon(@Nullable Drawable icon) { + seekBarTrackImage.setImageDrawable(icon); + } + + /** + * Get the drawable resource for the track icon's background + * + * @return Drawable resource for the icon's background + */ + @Nullable + public Drawable getTrackIconBackground() { + return seekBarTrackImage.getBackground(); + } + + /** + * Set the resource ID for the track icon's background + * + * @param resourceId Integer ID of the background resource + */ + public void setTrackIconBackground(@DrawableRes int resourceId) { + seekBarTrackImage.setBackgroundResource(resourceId); + } + + /** + * Set the drawable resource for the track icon's background + * + * @param icon Drawable resource for the icon's background + */ + public void setTrackIconBackground(@Nullable Drawable icon) { + seekBarTrackImage.setBackground(icon); + } + + /** + * Get the drawable resource for the thumb icon + * + * @return Drawable resource for the icon + */ + @Nullable + public Drawable getThumbIcon() { + return seekBarThumbImage.getDrawable(); + } + + /** + * Set the resource ID for the thumb icon + * + * @param resourceId Integer ID of the drawable resource + */ + public void setThumbIcon(@DrawableRes int resourceId) { + setThumbIcon(getResources().getDrawable(resourceId)); + } + + /** + * Set the drawable resource for the thumb icon + * + * @param icon Drawable resource for the icon + */ + public void setThumbIcon(@Nullable Drawable icon) { + seekBarThumbImage.setImageDrawable(icon); + } + + /** + * Get the drawable resource for the thumb icon's background + * + * @return Drawable resource for the icon's background + */ + @Nullable + public Drawable getThumbIconBackground() { + return seekBarThumbImage.getBackground(); + } + + /** + * Set the resource ID for the thumb icon's background + * + * @param resourceId Integer ID of the background resource + */ + public void setThumbIconBackground(@DrawableRes int resourceId) { + seekBarThumbImage.setBackgroundResource(resourceId); + } + + /** + * Set the drawable resource for the thumb icon's background + * + * @param icon Drawable resource for the icon's background + */ + public void setThumbIconBackground(@Nullable Drawable icon) { + seekBarThumbImage.setBackground(icon); + } + + /** + * Get the drawable resource for the minus icon + * + * @return Drawable resource for the icon + */ + @Nullable + public Drawable getMinusIcon() { + return seekBarMinus.getDrawable(); + } + + /** + * Set the resource ID for the minus icon + * + * @param resourceId Integer ID of the drawable resource + */ + public void setMinusIcon(@DrawableRes int resourceId) { + setMinusIcon(getResources().getDrawable(resourceId)); + } + + /** + * Set the drawable resource for the minus icon + * + * @param icon Drawable resource for the icon + */ + public void setMinusIcon(@Nullable Drawable icon) { + seekBarMinus.setImageDrawable(icon); + } + + /** + * Get the drawable resource for the minus icon's background + * + * @return Drawable resource for the icon's background + */ + @Nullable + public Drawable getMinusIconBackground() { + return seekBarMinus.getBackground(); + } + + /** + * Set the resource ID for the minus icon's background + * + * @param resourceId Integer ID of the background resource + */ + public void setMinusIconBackground(@DrawableRes int resourceId) { + seekBarMinus.setBackgroundResource(resourceId); + } + + /** + * Set the drawable resource for the minus icon's background + * + * @param icon Drawable resource for the icon's background + */ + public void setMinusIconBackground(@Nullable Drawable icon) { + seekBarMinus.setBackground(icon); + } + + /** + * Get the drawable resource for the plus icon + * + * @return Drawable resource for the icon + */ + @Nullable + public Drawable getPlusIcon() { + return seekBarPlus.getDrawable(); + } + + /** + * Set the resource ID for the plus icon + * + * @param resourceId Integer ID of the drawable resource + */ + public void setPlusIcon(@DrawableRes int resourceId) { + setPlusIcon(getResources().getDrawable(resourceId)); + } + + /** + * Set the drawable resource for the plus icon + * + * @param icon Drawable resource for the icon + */ + public void setPlusIcon(@Nullable Drawable icon) { + seekBarPlus.setImageDrawable(icon); + } + + /** + * Get the drawable resource for the plus icon's background + * + * @return Drawable resource for the icon's background + */ + @Nullable + public Drawable getPlusIconBackground() { + return seekBarPlus.getBackground(); + } + + /** + * Set the resource ID for the plus icon's background + * + * @param resourceId Integer ID of the background resource + */ + public void setPlusIconBackground(@DrawableRes int resourceId) { + seekBarPlus.setBackgroundResource(resourceId); + } + + /** + * Set the drawable resource for the plus icon's background + * + * @param icon Drawable resource for the icon's background + */ + public void setPlusIconBackground(@Nullable Drawable icon) { + seekBarPlus.setBackground(icon); + } + + /** + * Set text appearance of the value text view + * + * @param textAppearanceResId Style resource for text appearance + */ + public void setValueTextAppearance(@StyleRes int textAppearanceResId) { + seekBarValueText.setTextAppearance(getContext(), textAppearanceResId); + } + + /** + * Get current text color of the value text view + * + * @return color integer resource + */ + @ColorInt + public int getValueTextColor() { + return seekBarValueText.getCurrentTextColor(); + } + + /** + * Set text color for the value text view + * + * @param color color integer resource + */ + public void setValueTextColor(@ColorInt int color) { + seekBarValueText.setTextColor(color); + } + + /** + * Set text color state list for the value text view + * + * @param colorStateList ColorStateList resource + */ + public void setValueTextColor(@NonNull ColorStateList colorStateList) { + seekBarValueText.setTextColor(colorStateList); + } + + /** + * Get current color state list of the value text view + * + * @return ColorStateList resource + */ + @NonNull + public ColorStateList getValueTextColors() { + return seekBarValueText.getTextColors(); + } + + /** + * Get current background of the value text view + * + * @return Drawable resource of the background + */ + @Nullable + public Drawable getValueTextBackground() { + return seekBarValueText.getBackground(); + } + + /** + * Set the resource ID for the background of the value text view + * + * @param resourceId Integer ID of the drawable resource for the background + */ + public void setValueTextBackground(@DrawableRes int resourceId) { + seekBarValueText.setBackgroundResource(resourceId); + } + + /** + * Set the background of the value text view + * + * @param background Drawable resource for the background + */ + public void setValueTextBackground(@Nullable Drawable background) { + seekBarValueText.setBackground(background); + } + + /** + * Get current text size of the value text view + * + * @return text size of the text view + */ + @Dimension + public float getValueTextSize() { + return seekBarValueText.getTextSize(); + } + + /** + * Set the text size of the value text view + * + * @param textSize text size float value + */ + public void setValueTextSize(@Dimension float textSize) { + seekBarValueText.setTextSize(textSize); + } + + /** + * Set text appearance of the min value text view + * + * @param textAppearanceResId Style resource for text appearance + */ + public void setMinValueTextAppearance(@StyleRes int textAppearanceResId) { + seekBarMinText.setTextAppearance(getContext(), textAppearanceResId); + } + + /** + * Get current text color of the min value text view + * + * @return color integer resource + */ + @ColorInt + public int getMinValueTextColor() { + return seekBarMinText.getCurrentTextColor(); + } + + /** + * Set text color for the min value text view + * + * @param color color integer resource + */ + public void setMinValueTextColor(@ColorInt int color) { + seekBarMinText.setTextColor(color); + } + + /** + * Set text color state list for the min value text view + * + * @param colorStateList ColorStateList resource + */ + public void setMinValueTextColor(@NonNull ColorStateList colorStateList) { + seekBarMinText.setTextColor(colorStateList); + } + + /** + * Get current color state list of the min value text view + * + * @return ColorStateList resource + */ + @NonNull + public ColorStateList getMinValueTextColors() { + return seekBarMinText.getTextColors(); + } + + /** + * Get current background of the min value text view + * + * @return Drawable resource of the background + */ + @Nullable + public Drawable getMinValueTextBackground() { + return seekBarMinText.getBackground(); + } + + /** + * Set the resource ID for the background of the min value text view + * + * @param resourceId Integer ID of the drawable resource for the background + */ + public void setMinValueTextBackground(@DrawableRes int resourceId) { + seekBarMinText.setBackgroundResource(resourceId); + } + + /** + * Set the background of the min value text view + * + * @param background Drawable resource for the background + */ + public void setMinValueTextBackground(@Nullable Drawable background) { + seekBarMinText.setBackground(background); + } + + /** + * Get current text size of the min value text view + * + * @return text size of the text view + */ + @Dimension + public float getMinValueTextSize() { + return seekBarMinText.getTextSize(); + } + + /** + * Set the text size of the min value text view + * + * @param textSize text size float value + */ + public void setMinValueTextSize(@Dimension float textSize) { + seekBarMinText.setTextSize(textSize); + } + + /** + * Set text appearance of the max value text view + * + * @param textAppearanceResId Style resource for text appearance + */ + public void setMaxValueTextAppearance(@StyleRes int textAppearanceResId) { + seekBarMaxText.setTextAppearance(getContext(), textAppearanceResId); + } + + /** + * Get current text color of the max value text view + * + * @return color integer resource + */ + @ColorInt + public int getMaxValueTextColor() { + return seekBarMaxText.getCurrentTextColor(); + } + + /** + * Set text color for the max value text view + * + * @param color color integer resource + */ + public void setMaxValueTextColor(@ColorInt int color) { + seekBarMaxText.setTextColor(color); + } + + /** + * Set text color state list for the max value text view + * + * @param colorStateList ColorStateList resource + */ + public void setMaxValueTextColor(@NonNull ColorStateList colorStateList) { + seekBarMaxText.setTextColor(colorStateList); + } + + /** + * Get current color state list of the max value text view + * + * @return ColorStateList resource + */ + @NonNull + public ColorStateList getMaxValueTextColors() { + return seekBarMaxText.getTextColors(); + } + + /** + * Get current background of the max value text view + * + * @return Drawable resource of the background + */ + @Nullable + public Drawable getMaxValueTextBackground() { + return seekBarMaxText.getBackground(); + } + + /** + * Set the resource ID for the background of the max value text view + * + * @param resourceId Integer ID of the drawable resource for the background + */ + public void setMaxValueTextBackground(@DrawableRes int resourceId) { + seekBarMaxText.setBackgroundResource(resourceId); + } + + /** + * Set the background of the max value text view + * + * @param background Drawable resource for the background + */ + public void setMaxValueTextBackground(@Nullable Drawable background) { + seekBarMaxText.setBackground(background); + } + + /** + * Get current text size of the max value text view + * + * @return text size of the text view + */ + @Dimension + public float getMaxValueTextSize() { + return seekBarMaxText.getTextSize(); + } + + /** + * Set the text size of the max value text view + * + * @param textSize text size float value + */ + public void setMaxValueTextSize(@Dimension float textSize) { + seekBarMaxText.setTextSize(textSize); + } + + /** + * Get the color of the baseline + * + * @return color integer resource + */ + @ColorInt + public int getBaselineColor() { + return seekBarBaselineColor; + } + + /** + * Set the color of the baseline + * + * @param color color integer resource + */ + public void setBaselineColor(@ColorInt int color) { + seekBarBaselineColor = color; + seekBarBaseline.setBackgroundColor(color); + } + + /** + * A callback that notifies clients when the progress level has been + * changed. This includes changes that were initiated by the user through a + * touch gesture or arrow key/trackball as well as changes that were initiated + * programmatically. + */ + public interface OnSeekBarChangeListener { + + /** + * Notification that the progress level has changed. Clients can use the fromUser parameter + * to distinguish user-initiated changes from those that occurred programmatically. + * + * @param object The SeekBarView whose progress changed. + * @param progress The current progress level. This will be in the range 0..max where max + * was set by {@link #setMax(int)}. + */ + void onProgressChanged(@NonNull HorizontalSeekBar object, @IntRange(from = 0) int progress, boolean isFromUI); + + /** + * Notification that the user has started a touch gesture. Clients may want to use this + * to disable advancing the seek bar. + * + * @param object The SeekBarView that was touched. + * @param progress The current progress level. This will be in the range 0..max where max + * was set by {@link #setMax(int)}. + */ + void onStartTrackingTouch(@NonNull HorizontalSeekBar object, @IntRange(from = 0) int progress); + + /** + * Notification that the user has finished a touch gesture. Clients may want to use this + * to re-enable advancing the seek bar. + * + * @param object The SeekBarView that was touched. + * @param progress The current progress level. This will be in the range 0..max where max + * was set by {@link #setMax(int)}. + */ + void onStopTrackingTouch(@NonNull HorizontalSeekBar object, @IntRange(from = 0) int progress); + + /** + * Notification that the user has clicked the plus symbol. Clients should use this + * to increment the value and update the seek bar. + * + * @param object The SeekBarView whose plus symbol was clicked. + */ + void onPlusClicked(@NonNull HorizontalSeekBar object); + + /** + * Notification that the user has clicked the minus symbol. Clients should use this + * to decrement the value and update the seek bar. + * + * @param object The SeekBarView whose minus symbol was clicked. + */ + void onMinusClicked(@NonNull HorizontalSeekBar object); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/OffsetVerticalSeekBar.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/OffsetVerticalSeekBar.java new file mode 100644 index 00000000..02cb9caf --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/OffsetVerticalSeekBar.java @@ -0,0 +1,132 @@ +package dji.v5.ux.core.ui; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import dji.v5.utils.common.DisplayUtil; +import dji.v5.ux.R; + + +public class OffsetVerticalSeekBar extends VerticalSeekBar { + + private Rect mRect; + private Paint mPaint; + private int mSeekBarHeight; + private int mRectColor; + private boolean mIsOnlyDragSupported = false; + private boolean mIsDragging = false; + + public OffsetVerticalSeekBar(Context context, AttributeSet attrs) { + super(context, attrs); + initViews(context); + } + + private void initViews(Context context) { + mRect = new Rect(); + mPaint = new Paint(); + mSeekBarHeight = DisplayUtil.dip2px(getContext(), 4); + mRectColor = context.getResources().getColor(R.color.uxsdk_white_0_percent); + } + + @Override + public void setProgressDrawable(Drawable d) { + super.setProgressDrawable(d); + updateProgressDrawableBounds(); + } + + @Override + public void setThumb(Drawable thumb) { + super.setThumb(thumb); + updateProgressDrawableBounds(); + } + + @Override + protected synchronized void onDraw(Canvas canvas) { + mRect.set(0, + (getHeight() / 2) - (mSeekBarHeight / 2), + getWidth(), + (getHeight() / 2) + (mSeekBarHeight / 2)); + + mPaint.setColor(Color.TRANSPARENT); + + canvas.drawRect(mRect, mPaint); + + if (getProgress() < getMax() / 2) { + mRect.set(getWidth() / 2 - mSeekBarHeight / 2, + (getHeight() / 2), + getWidth() / 2 + mSeekBarHeight / 2, + getThumb().getBounds().top); + + mPaint.setColor(mRectColor); + canvas.drawRect(mRect, mPaint); + + } + + if (getProgress() > getMax() / 2) { + mRect.set(getWidth() / 2 - mSeekBarHeight / 2, + (getThumb().getBounds().bottom), + getWidth() / 2 + mSeekBarHeight / 2, + getHeight() / 2); + + mPaint.setColor(mRectColor); + canvas.drawRect(mRect, mPaint); + } + + super.onDraw(canvas); + } + + @Override + protected void updateDrawableBounds(int w, int h) { + updateProgressDrawableBounds(); + Drawable thumb = this.mThumb; + + int max = this.mMax; + float scale = max > 0 ? (float) this.mProgress / (float) max : 0.0F; + if (thumb != null) { + this.setDrawableBounds(w, h, thumb, scale); + } + } + + public void updateProgressDrawableBounds() { + Drawable d = this.mProgressDrawable; + Drawable thumb = this.mThumb; + + int trackWidth = this.mProgressWidth; + int thumbWidth = thumb == null ? 0 : thumb.getIntrinsicWidth(); + int thumbHeight = thumb == null ? 0 : thumb.getIntrinsicHeight(); + int gapForCenteringTrack = (thumbWidth - trackWidth) / 2; + int top = thumbHeight / 2 + this.getPaddingTop(); + int bottom = this.getHeight() - this.getPaddingBottom() - thumbHeight / 2; + + if (d != null) { + d.setBounds(gapForCenteringTrack, top, gapForCenteringTrack + trackWidth, bottom); + } + } + + public void setIsOnlyDrag(boolean isOnlyDragSupported) { + this.mIsOnlyDragSupported = isOnlyDragSupported; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (event.getAction() == MotionEvent.ACTION_DOWN && mIsOnlyDragSupported + && (event.getY() < mThumb.getBounds().top || event.getY() > mThumb.getBounds().bottom)) { + mIsDragging = true; + return true; + } + + if (mIsOnlyDragSupported && mIsDragging + && (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL)) { + mIsDragging = false; + return true; + } + + return super.onTouchEvent(event); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/RangeSeekBar.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/RangeSeekBar.java new file mode 100644 index 00000000..d5105861 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/RangeSeekBar.java @@ -0,0 +1,365 @@ +package dji.v5.ux.core.ui; + +import android.animation.ValueAnimator; +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.View; + +import androidx.annotation.Nullable; +import androidx.interpolator.view.animation.FastOutSlowInInterpolator; +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.R; + +/** + * Range SeekBar + * @author eleven + */ +public class RangeSeekBar extends View { + + + protected Drawable mLeftThumb; + protected Drawable mRightThumb; + protected Drawable mBackgroundDrawable; + protected Drawable mProgressDrawable; + protected int mThumbSize; + + protected int mMax = 100; + protected int mMin = 0; + /** + * mMax和mMin的当前值,如果有动画的话 + */ + protected float mDrawMax = mMax; + protected float mDrawMin = mMin; + protected int mLeftValue = 0; + protected int mRightValue = mMax; + protected int mMaxHeight; + + protected float mDownX; + protected float mDownY; + + protected float mLastTouchX; + + protected Drawable mTouchThumb; + protected Rect mTouchRect = new Rect(); + + protected OnChangedListener mOnChangedListener; + + public RangeSeekBar(Context context) { + this(context, null); + } + + public RangeSeekBar(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public RangeSeekBar(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + + TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.RangeSeekBar); + mLeftThumb = ta.getDrawable(R.styleable.RangeSeekBar_uxsdk_range_leftThumbDrawable); + if (mLeftThumb == null) { + mLeftThumb = getResources().getDrawable(R.drawable.uxsdk_ic_temp_cold); + } + mRightThumb = ta.getDrawable(R.styleable.RangeSeekBar_uxsdk_range_rightThumbDrawable); + if (mRightThumb == null) { + mRightThumb = getResources().getDrawable(R.drawable.uxsdk_ic_temp_hot); + } + mBackgroundDrawable = ta.getDrawable(R.styleable.RangeSeekBar_uxsdk_range_backgroundDrawable); + if (mBackgroundDrawable == null) { + mBackgroundDrawable = getResources().getDrawable(R.drawable.uxsdk_range_seekbar_bg); + } + mProgressDrawable = ta.getDrawable(R.styleable.RangeSeekBar_uxsdk_range_progressDrawable); + if (mProgressDrawable == null) { + mProgressDrawable = getResources().getDrawable(R.drawable.uxsdk_ic_isotherm_seekbar); + } + mThumbSize = ta.getDimensionPixelSize(R.styleable.RangeSeekBar_uxsdk_range_thumbSize, 0); + if (mThumbSize == 0) { + mLeftThumb.getIntrinsicWidth(); + } + mMaxHeight = ta.getDimensionPixelSize(R.styleable.RangeSeekBar_uxsdk_range_progressHeight, AndUtil.dip2px(context, 3)); + ta.recycle(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + + // 高度 + int heightNeeded = mThumbSize; + + int heightSize = MeasureSpec.getSize(heightMeasureSpec); + int heightMode = MeasureSpec.getMode(heightMeasureSpec); + + if (heightMode == MeasureSpec.EXACTLY) { + heightMeasureSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY); + } else if (heightMode == MeasureSpec.AT_MOST) { + heightMeasureSpec = MeasureSpec.makeMeasureSpec( + heightSize < heightNeeded ? heightSize : heightNeeded, MeasureSpec.EXACTLY); + } else { + heightMeasureSpec = MeasureSpec.makeMeasureSpec( + heightNeeded, MeasureSpec.EXACTLY); + } + + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + // 背景 + drawBackground(canvas); + // 进度 + drawProgress(canvas); + + // thumb + drawLeftThumb(canvas); + drawRightThumb(canvas); + } + + protected void drawBackground(Canvas canvas) { + // 背景 + int paddingLeft = getPaddingLeft() + mThumbSize/2; + int paddingRight = getPaddingRight() + mThumbSize/2; + mBackgroundDrawable.setBounds(paddingLeft, getHeight()/2 - mMaxHeight/2, getWidth() - paddingRight, getHeight()/2 + mMaxHeight/2); + mBackgroundDrawable.draw(canvas); + } + + protected void drawProgress(Canvas canvas) { + int leftX = getThumbPosition(mLeftValue); + int rightX = getThumbPosition(mRightValue); + + mProgressDrawable.setBounds(leftX, mBackgroundDrawable.getBounds().top, rightX, mBackgroundDrawable.getBounds().bottom); + mProgressDrawable.draw(canvas); + } + + protected void drawLeftThumb(Canvas canvas) { + mLeftThumb.setBounds(getThumbPosition(mLeftValue) - mThumbSize/2, 0, getThumbPosition(mLeftValue) + mThumbSize/2, mThumbSize); + mLeftThumb.draw(canvas); + } + + protected void drawRightThumb(Canvas canvas) { + mRightThumb.setBounds(getThumbPosition(mRightValue) - mThumbSize/2, 0, getThumbPosition(mRightValue) + mThumbSize/2, mThumbSize); + mRightThumb.draw(canvas); + } + + /** + * 获取thumb的x轴坐标 + * @param value + * @return + */ + protected int getThumbPosition(int value) { + // progress的总长度 + float width = getWidth() - getPaddingRight() - (float)mThumbSize/2 - getPaddingLeft() - (float)mThumbSize/2; + float range = mDrawMax - mDrawMin; + float v = value - mDrawMin; + return Math.round((v / range) * width) + getPaddingLeft() + mThumbSize/2; + } + + protected int getValueByDelta(float delta) { + int width = getWidth() - getPaddingRight() - getPaddingLeft() - mThumbSize; + int range = mMax - mMin; + return Math.round(delta / width * range); + } + + + public int getMax() { + return mMax; + } + + public void setMax(int max) { + if (max == mMax) { + return; + } + mMax = max; + mDrawMax = mMax; + postInvalidate(); + } + + public int getMin() { + return mMin; + } + + public void setMin(int min) { + if (min == mMin) { + return; + } + mMin = min; + mDrawMin = mMin; + postInvalidate(); + } + + public int getLeftValue() { + return mLeftValue; + } + + public void setLeftValue(int leftValue) { + if (leftValue < mMin) { + leftValue = mMin; + } + if (mLeftValue == leftValue) { + return; + } + mLeftValue = leftValue; + postInvalidate(); + } + + public int getRightValue() { + return mRightValue; + } + + public void setRightValue(int rightValue) { + if (rightValue > mMax) { + rightValue = mMax; + } + if (mRightValue == rightValue) { + return; + } + mRightValue = rightValue; + postInvalidate(); + } + + public void animateMax(int max) { + if (max == mMax || max <= mMin) { + return; + } + ValueAnimator objectAnimator = ValueAnimator.ofFloat(mMax, max); + objectAnimator.setDuration(200); + objectAnimator.setInterpolator(new FastOutSlowInInterpolator()); + objectAnimator.addUpdateListener(animation -> { + mDrawMax = (Float) animation.getAnimatedValue(); + postInvalidate(); + }); + objectAnimator.start(); + mMax = max; + } + + public void animateMin(int min) { + if (min == mMin || min >= mMax) { + return; + } + ValueAnimator objectAnimator = ValueAnimator.ofFloat(mMin, min); + objectAnimator.setDuration(200); + objectAnimator.setInterpolator(new FastOutSlowInInterpolator()); + objectAnimator.addUpdateListener(animation -> { + mDrawMin = (Float) animation.getAnimatedValue(); + postInvalidate(); + }); + objectAnimator.start(); + mMin = min; + } + + public OnChangedListener getOnChangedListener() { + return mOnChangedListener; + } + + public void setOnChangedListener(OnChangedListener onChangedListener) { + mOnChangedListener = onChangedListener; + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (!isEnabled()) { + return false; + } + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + if (handleTouchDown(event)) return false; + break; + case MotionEvent.ACTION_MOVE: + handleTouchMove(event); + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + mTouchThumb = null; + onSeekEnd(); + break; + default: + break; + } + + return true; + } + + private void handleTouchMove(MotionEvent event) { + float x = event.getX(); + float delta = x - mLastTouchX; + mLastTouchX = x; + int value =getValueByDelta(Math.abs(delta)); + if (delta < 0) { + value = -value; + } + if (mTouchThumb == mLeftThumb) { + int newValue = mLeftValue + value; + if (newValue < mMin) { + newValue = mMin; + } + if (newValue >= mRightValue) { + newValue = mRightValue - 1; + } + mLeftValue = newValue; + onValueChanged(true); + } else if (mTouchThumb == mRightThumb) { + int newValue = mRightValue + value; + if (newValue <= mLeftValue) { + newValue = mLeftValue + 1; + } + if (newValue > mMax) { + newValue = mMax; + } + mRightValue = newValue; + onValueChanged(true); + } + postInvalidate(); + } + + private boolean handleTouchDown(MotionEvent event) { + mDownX = event.getX(); + mDownY = event.getY(); + mLastTouchX = event.getX(); + + if (getTouchRect(mLeftThumb).contains((int)mDownX, (int)mDownY)) { + mTouchThumb = mLeftThumb; + onSeekStart(); + } else if (getTouchRect(mRightThumb).contains((int)mDownX, (int)mDownY)) { + mTouchThumb = mRightThumb; + onSeekStart(); + } + if (mTouchThumb == null) { + return true; + } + return false; + } + + protected Rect getTouchRect(Drawable thumb) { + mTouchRect.set(thumb.getBounds().left - mThumbSize/2, thumb.getBounds().top, thumb.getBounds().right + mThumbSize/2, thumb.getBounds().bottom); + return mTouchRect; + } + + private void onSeekStart() { + if (mOnChangedListener != null) { + mOnChangedListener.onSeekStart(this); + } + } + + private void onValueChanged(boolean fromUser) { + if (mOnChangedListener != null) { + mOnChangedListener.onValueChanged(this, mLeftValue, mRightValue, fromUser); + } + } + + private void onSeekEnd() { + if (mOnChangedListener != null) { + mOnChangedListener.onSeekEnd(this); + } + } + + public interface OnChangedListener { + void onSeekStart(RangeSeekBar seekBar); + void onValueChanged(RangeSeekBar seekBar, int leftValue, int rightValue, boolean fromUser); + void onSeekEnd(RangeSeekBar seekBar); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/RulerView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/RulerView.java new file mode 100644 index 00000000..f125de37 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/RulerView.java @@ -0,0 +1,611 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.ui; + +import android.content.Context; +import android.content.res.Resources; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.MotionEvent; +import android.view.VelocityTracker; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewParent; +import android.widget.Scroller; + +import androidx.annotation.ColorInt; +import dji.v5.ux.R; + +/** + * + * A custom view used to display a scale with increase and decrease buttons + * + */ +public class RulerView extends View { + + + protected final static int DEFAULT_INTERVAL = 10; // Default scale interval value + protected final static int DEFAULT_NUMBER = 13; + + protected int width = 0; + protected int height = 0; + protected Paint drawPaint = null; + + protected Drawable selectDrawable = null; + protected int scaleColor = 0; + protected int scalePadding = 0; + + protected float density = 0; + protected int minVelocity = 0; + protected int maxVelocity = 0; + protected Scroller scroller = null; + protected VelocityTracker velocityTracker = null; + protected int offsetY = 0; + protected int lastTouchY = 0; + protected final RectF tmpRect = new RectF(); + + protected int maxSize = 2000; + protected int curSize = 0; + protected int interval = DEFAULT_INTERVAL; + + protected OnRulerScrollListener onScrollListener = null; + protected OnRulerChangeListener onChangeListener = null; + protected boolean isRulerEnabled = true; + + public RulerView(Context context, AttributeSet attrs) { + super(context, attrs); + + initDatas(context); + + if (isInEditMode()) { + return; + } + initDefaultAttrs(); + } + + /** + * Set ruler scroll listener + * + * @param listener instance of {@link OnRulerScrollListener} + */ + public void setOnScrollListener(final OnRulerScrollListener listener) { + onScrollListener = listener; + } + + /** + * Set ruler change listener + * + * @param listener instance of {@link OnRulerChangeListener} + */ + public void setOnChangeListener(final OnRulerChangeListener listener) { + onChangeListener = listener; + } + + /** + * Set the max size of the ruler + * + * @param max integer value + */ + public void setMaxSize(final int max) { + if (max != maxSize) { + maxSize = max; + if (curSize > max) { + final int beforeSize = curSize; + curSize = max; + if (null != onChangeListener) { + onChangeListener.onChanged(this, max, beforeSize, false); + } + offsetY = (int) ((max + 1) * density); + } + postInvalidate(); + } + } + + /** + * Get the max size of the ruler + * + * @return integer value + */ + public int getMaxSize() { + return maxSize; + } + + /** + * Check if the ruler cursor is at minimum position + * + * @return boolean value true - cursor at minimum false - cursor more than minimum + */ + public boolean isAtMin() { + return (curSize == 0); + } + + /** + * Check if the ruler cursor is at maximum position + * + * @return boolean value true - cursor at maximum false - cursor less than maximum + */ + public boolean isAtMax() { + return (curSize == maxSize); + } + + /** + * Sets the new value and updates to the new state immediately. + * + * @param size integer value + */ + public void setCurSizeNow(final int size) { + final int beforeSize = curSize; + curSize = size; + if (null != onChangeListener) { + onChangeListener.onChanged(this, size, beforeSize, false); + } + offsetY = (int) (size * density); + postInvalidate(); + } + + /** + * Sets the new value and uses a scrolling animation to update the new state. + * + * @param size integer value + */ + public void setCurSize(int size) { + if (size != curSize) { + if (size > maxSize) { + size = maxSize; + } else if (size < 0) { + size = 0; + } + final int step = (int) (Math.abs(curSize - size) * 1.0f / 8 + 1); + post(new ScrollRunnable(curSize, size, step)); + } + } + + /** + * Get the cursor position of the ruler + * + * @return integer value + */ + public int getCurSize() { + return curSize; + } + + /** + * Increase the value by the given step + * + * @param step integer delta to increase + * @return updated integer value + */ + public int stepUp(final int step) { + int size = curSize; + if (curSize < maxSize) { + size = (curSize + step); + if (size > maxSize) { + size = maxSize; + } + post(new ScrollRunnable(curSize, size)); + } + return size; + } + + /** + * Reduce the value by the given step + * + * @param step integer delta to decrease + * @return updated integer value + */ + public int stepDown(final int step) { + int size = curSize; + if (curSize > 0) { + size = (curSize - step); + if (size < 0) { + size = 0; + } + post(new ScrollRunnable(curSize, size)); + } + return size; + } + + /** + * Increase the value by the + * default interval size {@link #DEFAULT_INTERVAL}. + */ + public void stepNext() { + if (curSize < maxSize) { + int size = (curSize + interval); + if (size > maxSize) { + size = maxSize; + } + post(new ScrollRunnable(curSize, size)); + } + } + + /** + * Decrease the value by the + * default interval size {@link #DEFAULT_INTERVAL} + */ + public void stepPrev() { + if (curSize > 0) { + int size = (curSize - interval); + if (size < 0) { + size = 0; + } + post(new ScrollRunnable(curSize, size)); + } + } + + protected void initDefaultAttrs() { + final Resources res = getResources(); + scaleColor = res.getColor(R.color.uxsdk_white); + scalePadding = res.getDimensionPixelSize(R.dimen.uxsdk_gen_corner_radius); + drawPaint.setColor(scaleColor); + } + + protected void initDatas(final Context context) { + scroller = new Scroller(context); + + drawPaint = new Paint(); + drawPaint.setAntiAlias(true); + drawPaint.setStyle(Paint.Style.FILL); + + final ViewConfiguration configuration = ViewConfiguration.get(context); + minVelocity = configuration.getScaledMinimumFlingVelocity(); + maxVelocity = configuration.getScaledMaximumFlingVelocity(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + final int heightSize = MeasureSpec.getSize(heightMeasureSpec); + final int widthSize = MeasureSpec.getSize(widthMeasureSpec); + setMeasuredDimension(widthSize, heightSize); + + float targetDensity = getResources().getDisplayMetrics().density * 2; + if (targetDensity < 4.0f) { + targetDensity = 4.0f; + } + + int number = DEFAULT_NUMBER - 1; + final float fHeight = heightSize * 1.0f; + density = fHeight / (number * interval + 1); + while (density > targetDensity) { + number += 2; + density = fHeight / (number * interval + 1); + } + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + width = w; + height = h; + if (selectDrawable != null) { + final int selectHeight = selectDrawable.getIntrinsicHeight(); + final int selectWidth = selectDrawable.getIntrinsicWidth(); + selectDrawable.setBounds((w - selectWidth) / 2, (h - selectHeight) / 2, (w + selectWidth) / 2, (h + selectHeight) / 2); + } + } + + private void obtainTracker() { + if (null == velocityTracker) { + velocityTracker = VelocityTracker.obtain(); + } + } + + private void recycleTracker() { + if (null != velocityTracker) { + velocityTracker.clear(); + velocityTracker.recycle(); + velocityTracker = null; + } + } + + private void requestInterceptEvent() { + final ViewParent parent = getParent(); + if (parent != null) { + parent.requestDisallowInterceptTouchEvent(true); + } + } + + private void onOffsetChanged(final int offset) { + final int size = (int) (offset / density); + if (size != curSize) { + final int beforeSize = curSize; + curSize = size; + if (null != onChangeListener) { + onChangeListener.onChanged(this, size, beforeSize, true); + } + } + } + + private void scrollOverY(final int deltaY) { + final int maxOffset = (int) ((maxSize + 1) * density); + offsetY += deltaY; + if (offsetY < 0) { + offsetY = 0; + } else if (offsetY > maxOffset) { + offsetY = maxOffset; + } + onOffsetChanged(offsetY); + postInvalidate(); + } + + @Override + public void computeScroll() { + if (scroller.computeScrollOffset()) { + offsetY = scroller.getCurrY(); + onOffsetChanged(offsetY); + if (scroller.isFinished() && null != onScrollListener) { + onScrollListener.onScrollingFinished(this); + } + postInvalidateOnAnimation(); + } + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (isRulerEnabled) { + obtainTracker(); + velocityTracker.addMovement(event); + + int action = event.getAction(); + switch (action) { + case MotionEvent.ACTION_DOWN: + requestInterceptEvent(); + if (!scroller.isFinished()) { + scroller.abortAnimation(); + } + lastTouchY = (int) event.getY(); + if (null != onScrollListener) { + onScrollListener.onScrollingStarted(this); + } + break; + case MotionEvent.ACTION_MOVE: + final int y = (int) event.getY(); + int deltaY = lastTouchY - y; + lastTouchY = y; + scrollOverY(deltaY); + break; + case MotionEvent.ACTION_UP: + case MotionEvent.ACTION_CANCEL: + velocityTracker.computeCurrentVelocity(1000, maxVelocity); + int initialVelocity = (int) velocityTracker.getYVelocity(); + if ((Math.abs(initialVelocity) > minVelocity)) { + final int maxOffset = (int) ((maxSize + 1) * density); + scroller.fling(0, offsetY, 0, -initialVelocity, 0, 0, 0, maxOffset); + } else if (null != onScrollListener) { + onScrollListener.onScrollingFinished(this); + } + recycleTracker(); + break; + default: + break; + } + } + return true; + } + + @Override + protected void onDraw(Canvas canvas) { + if (selectDrawable != null) { + selectDrawable.draw(canvas); + } + + final float offset = offsetY; + final float maxOffset = (maxSize + 1) * density; + final float halfH = height * 1.0f / 2; + int offDensity = (int) ((offset / density) % interval); + if (offDensity != 0) { + offDensity = interval - offDensity; + } + + final float left = scalePadding; + final float right = (float) width - scalePadding; + final float radius = density / 2; + + float top = offDensity * density; + final float halfDensity = density / 2; + + while (top < height) { + if ((halfH <= (top + offset + density)) && ((top + offset + halfDensity) <= (maxOffset + halfH))) { + tmpRect.set(left, top, right, top + density); + drawPaint.setAlpha(recalAlpha(top, halfH)); + canvas.drawRoundRect(tmpRect, radius, radius, drawPaint); + } + top += interval * density; + } + } + + private int recalAlpha(final float top, final float halfH) { + final float pos = (top + density * 1.0f / 2); + final float factor = Math.abs(pos - halfH) * 1.0f / halfH; + return (int) (((1 - factor) * (1 - factor) * 0.95f + 0.05f) * 255); + } + + private final class ScrollRunnable implements Runnable { + private int mStartSize; + private int mEndSize; + private int mStep; + private boolean mbAdd = false; + + private ScrollRunnable(final int start, final int end) { + this(start, end, 2); + } + + private ScrollRunnable(final int start, final int end, final int step) { + mStartSize = start; + mEndSize = end; + mStep = step; + if (start < end) { + mbAdd = true; + } + } + + private void doAdd(){ + if (mEndSize <= mStartSize + mStep + 1) { + final int beforeSize = curSize; + curSize = mEndSize; + if (null != onChangeListener) { + onChangeListener.onChanged(RulerView.this, mEndSize, beforeSize, true); + } + + offsetY = (int) (mEndSize * density); + postInvalidate(); + } else { + curSize += mStep; + if (curSize >= mEndSize) { + final int beforeSize = curSize; + curSize = mEndSize; + if (null != onChangeListener) { + onChangeListener.onChanged(RulerView.this, mEndSize, beforeSize, true); + } + + offsetY = (int) (mEndSize * density); + postInvalidate(); + } else { + offsetY = (int) (curSize * density); + invalidate(); + postDelayed(this, 10); + } + } + } + + @Override + public void run() { + if (mbAdd) { + doAdd(); + } else { + if (mEndSize + mStep + 1 >= mStartSize) { + final int beforeSize = curSize; + curSize = mEndSize; + if (null != onChangeListener) { + onChangeListener.onChanged(RulerView.this, mEndSize, beforeSize, true); + } + + offsetY = (int) (mEndSize * density); + postInvalidate(); + } else { + performListenerChange(); + } + } + } + + private void performListenerChange(){ + curSize -= mStep; + if (curSize <= mEndSize) { + final int beforeSize = curSize; + curSize = mEndSize; + if (null != onChangeListener) { + onChangeListener.onChanged(RulerView.this, mEndSize, beforeSize, true); + } + + offsetY = (int) (mEndSize * density); + postInvalidate(); + } else { + offsetY = (int) (curSize * density); + invalidate(); + postDelayed(this, 10); + } + } + } + + /** + * Interface to track updates of the ruler srcoll + */ + public interface OnRulerScrollListener { + /** + * Indicate start of scroll action + * + * @param rulerView current instance of {@link RulerView} + */ + void onScrollingStarted(final RulerView rulerView); + + /** + * Indicate stop of scroll action + * + * @param rulerView current instance of {@link RulerView} + */ + void onScrollingFinished(final RulerView rulerView); + } + + + /** + * Interface to track changes in ruler + * + */ + public interface OnRulerChangeListener { + + /** + * Indicate ruler changed + * + * @param rulerView current instance of {@link RulerView} + * @param newSize update size + * @param oldSize old size + * @param fromUser is the update from user interaction + */ + void onChanged(final RulerView rulerView, final int newSize, final int oldSize, final boolean fromUser); + } + + /** + * Enable or disable the scroll + * + * @param isEnabled true- scroll enabled false - scroll disabled + */ + public void setRulerEnabled(boolean isEnabled) { + isRulerEnabled = isEnabled; + } + + /** + * Check if ruler scrolling is enabled + * + * @return boolean value true- enabled false - disabled + */ + public boolean isRulerEnabled() { + return isRulerEnabled; + } + + + /** + * Set the ruler scale color + * + * @param scaleColor integer value representing color + */ + public void setScaleColor(@ColorInt int scaleColor) { + this.scaleColor = scaleColor; + drawPaint.setColor(scaleColor); + invalidate(); + } + + /** + * Get the ruler scale color + * + * @return integer value representing color + */ + @ColorInt + public int getScaleColor() { + return scaleColor; + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/SlideAndFillSeekBar.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/SlideAndFillSeekBar.kt new file mode 100644 index 00000000..401408c4 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/SlideAndFillSeekBar.kt @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.ui + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.util.AttributeSet +import android.widget.SeekBar +import androidx.appcompat.widget.AppCompatSeekBar +import dji.v5.ux.R +import dji.v5.ux.core.extension.getColor + +/** + * A SeekBar that features a progress color + */ +class SlideAndFillSeekBar @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : AppCompatSeekBar(context, attrs, defStyleAttr) { + // Paint of the progress + private var reachedPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG) + + // Paint of the thumb + private var thumbPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG) + + // Paint that always stays at the start to make it circular + // Because progress alone has a square corner + private var startPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG) + + private var outerListener: OnSeekBarChangeListener? = null + private var currentProgress = 0 + + /** + * The color of the thumb when selected + */ + var thumbSelectedColor = getColor(R.color.uxsdk_slider_thumb_selected) + + /** + * The color of the thumb when unselected + */ + var thumbNormalColor = getColor(R.color.uxsdk_white) + + /** + * The color of the filled section of the SeekBar + */ + var progressColor = getColor(R.color.uxsdk_slider_filled) + set(value) { + field = value + initPaints() + } + + private fun initListener() { + val innerListener: OnSeekBarChangeListener = object : OnSeekBarChangeListener { + override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { + currentProgress = progress + outerListener?.onProgressChanged(this@SlideAndFillSeekBar, progress, fromUser) + } + + override fun onStartTrackingTouch(seekBar: SeekBar) { + outerListener?.onStartTrackingTouch(this@SlideAndFillSeekBar) + } + + override fun onStopTrackingTouch(seekBar: SeekBar) { + outerListener?.onStopTrackingTouch(this@SlideAndFillSeekBar) + } + } + super.setOnSeekBarChangeListener(innerListener) + } + + override fun setOnSeekBarChangeListener(l: OnSeekBarChangeListener) { + outerListener = l + } + + private fun initPaints() { + reachedPaint.color = progressColor + reachedPaint.style = Paint.Style.STROKE + reachedPaint.strokeWidth = measuredHeight.toFloat() + reachedPaint.strokeCap = Paint.Cap.ROUND + startPaint.color = progressColor + startPaint.style = Paint.Style.STROKE + startPaint.strokeWidth = measuredHeight.toFloat() + startPaint.strokeCap = Paint.Cap.ROUND + thumbPaint.color = thumbNormalColor + thumbPaint.style = Paint.Style.STROKE + thumbPaint.strokeWidth = measuredHeight.toFloat() + thumbPaint.strokeCap = Paint.Cap.ROUND + } + + @Synchronized + override fun onDraw(canvas: Canvas) { + val thumb = thumb + val thumbRect = thumb.bounds + reachedPaint.strokeWidth = thumb.intrinsicHeight.toFloat() + startPaint.strokeWidth = thumb.intrinsicHeight.toFloat() + thumbPaint.strokeWidth = thumb.intrinsicHeight.toFloat() + if (currentProgress > 0) { + canvas.drawLine(thumb.intrinsicWidth / 2.toFloat(), + thumbRect.centerY().toFloat(), + thumbRect.centerX().toFloat(), + thumbRect.centerY().toFloat(), + reachedPaint) + canvas.drawPoint(thumb.intrinsicWidth / 2.toFloat(), thumbRect.centerY().toFloat(), startPaint) + } + if (currentProgress == 0 || currentProgress == 100) { + thumbPaint.color = thumbNormalColor + } else { + thumbPaint.color = thumbSelectedColor + } + canvas.drawPoint(thumbRect.centerX().toFloat(), thumbRect.centerY().toFloat(), thumbPaint) + } + + init { + initListener() + initPaints() + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/SlidingDialog.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/SlidingDialog.kt new file mode 100644 index 00000000..2e5fd6d5 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/SlidingDialog.kt @@ -0,0 +1,742 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.ui + +import android.app.Dialog +import android.content.Context +import android.content.DialogInterface +import android.content.res.ColorStateList +import android.graphics.drawable.Drawable +import android.os.Bundle +import android.view.Gravity +import android.view.View +import android.view.Window +import android.view.WindowManager +import android.widget.* +import androidx.annotation.* +import androidx.constraintlayout.widget.ConstraintLayout +import dji.v5.ux.R +import dji.v5.ux.core.extension.textColor +import dji.v5.ux.core.extension.textColorStateList +import dji.v5.ux.core.util.ViewUtil + +private const val SLIDE_MAX_THRESHOLD = 100 +private const val SLIDE_COMPLETE_THRESHOLD = 95 +private const val SLIDE_START_THRESHOLD = 0 + +/** + * A dialog where the positive action is represented by a [SlideAndFillSeekBar]. The negative + * action is represented by a button at the bottom of the dialog. The dialog contains a title, + * a message, and a checkbox. + */ +class SlidingDialog @JvmOverloads constructor( + context: Context, + @StyleRes styleId: Int, + @param:DimenRes private val widthId: Int = R.dimen.uxsdk_sliding_dialog_width +) : Dialog(context, styleId), View.OnClickListener, SeekBar.OnSeekBarChangeListener, + CompoundButton.OnCheckedChangeListener { + //region Fields + private var container: ConstraintLayout + private var iconImageView: ImageView + private var cancelTextView: TextView + private var actionTextView: TextView + private var titleTextView: TextView + private var messageTextView: TextView + private var checkbox: CheckBox + private var seekBar: SlideAndFillSeekBar + private var onEventListener: OnEventListener? = null + + /** + * The size of the dialog title text + */ + var dialogTitleTextSize: Float + @Dimension + get() = titleTextView.textSize + set(@Dimension textSize) { + titleTextView.textSize = textSize + } + + /** + * The color of the dialog title text + */ + var dialogTitleTextColor: Int + @ColorInt + get() = titleTextView.textColor + set(@ColorInt color) { + titleTextView.textColor = color + } + + /** + * The background of the dialog title + */ + var dialogTitleBackground: Drawable? + get() = titleTextView.background + set(value) { + titleTextView.background = value + } + + /** + * The size of the dialog message text + */ + var dialogMessageTextSize: Float + @Dimension + get() = messageTextView.textSize + set(@Dimension textSize) { + messageTextView.textSize = textSize + } + + /** + * The color of the dialog message text + */ + var dialogMessageTextColor: Int + @ColorInt + get() = messageTextView.textColor + set(@ColorInt color) { + messageTextView.textColor = color + } + + /** + * The background of the dialog message + */ + var dialogMessageBackground: Drawable? + get() = messageTextView.background + set(value) { + messageTextView.background = value + } + + /** + * The size of the check box message text + */ + var checkBoxMessageTextSize: Float + @Dimension + get() = checkbox.textSize + set(@Dimension textSize) { + checkbox.textSize = textSize + } + + /** + * The color of the check box message text + */ + var checkBoxMessageTextColor: Int + @ColorInt + get() = checkbox.textColor + set(@ColorInt color) { + checkbox.textColor = color + } + + /** + * The background of the check box message + */ + var checkBoxMessageBackground: Drawable? + get() = checkbox.background + set(value) { + checkbox.background = value + } + + /** + * Whether the check box is checked + */ + var checkBoxChecked: Boolean + get() = checkbox.isChecked + set(value) { + checkbox.isChecked = value + } + + /** + * The size of the cancel button text + */ + var cancelTextSize: Float + @Dimension + get() = cancelTextView.textSize + set(@Dimension textSize) { + cancelTextView.textSize = textSize + } + + /** + * The color of the cancel button text + */ + var cancelTextColor: Int + @ColorInt + get() = cancelTextView.textColor + set(@ColorInt color) { + cancelTextView.textColor = color + } + + /** + * The colors of the cancel button text + */ + var cancelTextColors: ColorStateList? + get() = cancelTextView.textColorStateList + set(colors) { + cancelTextView.textColorStateList = colors + } + + /** + * The background of the cancel button + */ + var cancelBackground: Drawable? + get() = cancelTextView.background + set(value) { + cancelTextView.background = value + } + + /** + * The size of the action message text + */ + var actionMessageTextSize: Float + @Dimension + get() = actionTextView.textSize + set(@Dimension textSize) { + actionTextView.textSize = textSize + } + + /** + * The color of the action message text + */ + var actionMessageTextColor: Int + @ColorInt + get() = actionTextView.textColor + set(@ColorInt color) { + actionTextView.textColor = color + } + + /** + * The background of the action message + */ + var actionMessageBackground: Drawable? + get() = actionTextView.background + set(value) { + actionTextView.background = value + } + + /** + * The icon to the right of the action message + */ + var actionIcon: Drawable? + get() = actionTextView.compoundDrawables[2] + set(icon) { + actionTextView.setCompoundDrawablesWithIntrinsicBounds(null, null, icon, null) + } + + /** + * The color of the slider thumb + */ + var actionSliderThumbColor: Int + @ColorInt + get() = seekBar.thumbNormalColor + set(@ColorInt color) { + seekBar.thumbNormalColor = color + } + + /** + * The color of the slider thumb when selected + */ + var actionSliderThumbSelectedColor: Int + @ColorInt + get() = seekBar.thumbSelectedColor + set(@ColorInt color) { + seekBar.thumbSelectedColor = color + } + + /** + * The fill color of the slider + */ + var actionSliderFillColor: Int + @ColorInt + get() = seekBar.progressColor + set(@ColorInt color) { + seekBar.progressColor = color + } + + /** + * The background of the dialog + */ + var background: Drawable? + get() = container.background + set(value) { + container.background = value + } + //endregion + + /** + * The listener that handles slider, button, and check box interaction + */ + interface OnEventListener { + /** + * Event when the cancel button is clicked + * + * @param dialog The dialog that was interacted with + */ + fun onCancelClick(dialog: DialogInterface?) + + /** + * Event when the [SlideAndFillSeekBar] has been filled + * + * @param dialog The dialog that was interacted with + * @param checked `true` if the [SlideAndFillSeekBar] is filled + */ + fun onSlideChecked(dialog: DialogInterface?, checked: Boolean) + + /** + * Event when the check box is checked + * + * @param dialog The dialog that was interacted with + * @param checked `true` if the check box is checked + */ + fun onCheckBoxChecked(dialog: DialogInterface?, checked: Boolean) + } + + //region Lifecycle + init { + requestWindowFeature(Window.FEATURE_NO_TITLE) + setContentView(R.layout.uxsdk_dialog_sliding_action) + container = findViewById(R.id.container) + iconImageView = findViewById(R.id.image_view_dialog_icon) + cancelTextView = findViewById(R.id.text_view_cancel) + actionTextView = findViewById(R.id.text_view_action) + titleTextView = findViewById(R.id.text_view_dialog_title) + messageTextView = findViewById(R.id.text_view_dialog_description) + checkbox = findViewById(R.id.checkbox) + checkbox.setOnCheckedChangeListener(this) + seekBar = findViewById(R.id.slide_seek_bar) + seekBar.setOnSeekBarChangeListener(this) + cancelTextView.setOnClickListener(this) + seekBar.setPadding(0, 0, 0, 0) + } + + override fun onCreate(savedInstanceState: Bundle?) { + adjustAttrs(context.resources.getDimension(widthId).toInt(), + WindowManager.LayoutParams.WRAP_CONTENT, 0, + Gravity.CENTER, + cancelable = true, + cancelTouchOutside = false) + } + + override fun onClick(v: View) { + val id = v.id + if (id == R.id.text_view_cancel) { + onEventListener?.onCancelClick(this) + } + } + + override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) { + onEventListener?.onCheckBoxChecked(this, isChecked) + } + //endregion + + //region private methods + private fun handleSbStopTrack() { + val progress = seekBar.progress + if (progress >= SLIDE_COMPLETE_THRESHOLD) { + seekBar.progress = SLIDE_MAX_THRESHOLD + setSlideChecked(true) + } else { + seekBar.progress = SLIDE_START_THRESHOLD + setSlideChecked(false) + } + } + + private fun setSlideChecked(checked: Boolean) { + onEventListener?.onSlideChecked(this, checked) + } + //endregion + + //region public methods + /** + * Set the listener for the slider, button, and check box interaction + * + * @param listener The listener for this dialog + */ + fun setOnEventListener(listener: OnEventListener?) { + onEventListener = listener + } + + /** + * Configure the dialog + * + * @param width The width of the dialog + * @param height The height of the dialog + * @param yOffset The y offset of the dialog + * @param gravity The gravity of the dialog + * @param cancelable Whether the dialog can be canceled + * @param cancelTouchOutside Whether the dialog is canceled when a touch occurs outside + */ + fun adjustAttrs(width: Int, + height: Int, + yOffset: Int, + gravity: Int, + cancelable: Boolean, + cancelTouchOutside: Boolean) { + val attrs = window?.attributes + attrs?.width = width + attrs?.height = height + attrs?.y = yOffset + attrs?.flags = (attrs?.flags ?: 0).and(WindowManager.LayoutParams.FLAG_DIM_BEHIND.inv()) + attrs?.gravity = gravity + window?.attributes = attrs + window?.setWindowAnimations(R.style.UXSDKDialogWindowAnim) + setCancelable(cancelable) + setCanceledOnTouchOutside(cancelTouchOutside) + } + + override fun show() { + window?.setFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE, + WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE) + seekBar.progress = SLIDE_START_THRESHOLD + super.show() + } + + override fun onProgressChanged(seekBar: SeekBar, progress: Int, fromUser: Boolean) { + //方法暂时未实现 + } + + override fun onStartTrackingTouch(seekBar: SeekBar) { + //方法暂时未实现 + } + + override fun onStopTrackingTouch(seekBar: SeekBar) { + handleSbStopTrack() + } + + /** + * Set the dialog title + * + * @param titleId The resource ID of the dialog title + */ + fun setDialogTitleRes(@StringRes titleId: Int): SlidingDialog { + titleTextView.setText(titleId) + return this + } + + /** + * Set the dialog title + * + * @param title The dialog title + */ + fun setDialogTitle(title: String): SlidingDialog { + titleTextView.text = title + return this + } + + /** + * Set the dialog message + * + * @param messageId The resource ID of the dialog message + */ + fun setDialogMessageRes(@StringRes messageId: Int): SlidingDialog { + messageTextView.setText(messageId) + return this + } + + /** + * Set the dialog message + * + * @param message The dialog message + */ + fun setDialogMessage(message: String): SlidingDialog { + messageTextView.text = message + return this + } + + /** + * Set the color of the dialog title + * + * @param color The color of the dialog title + */ + fun setDialogTitleTextColor(@ColorInt color: Int): SlidingDialog { + titleTextView.setTextColor(color) + return this + } + + /** + * Set the color of the dialog message + * + * @param color The color of the dialog message + */ + fun setDialogMessageTextColor(@ColorInt color: Int): SlidingDialog { + messageTextView.setTextColor(color) + return this + } + + /** + * Set the size of the dialog title + * + * @param textSize The size of the dialog title + */ + fun setDialogTitleTextSize(@Dimension textSize: Float): SlidingDialog { + titleTextView.textSize = textSize + return this + } + + /** + * Set the size of the dialog message + * + * @param textSize The size of the dialog message + */ + fun setDialogMessageTextSize(@Dimension textSize: Float): SlidingDialog { + messageTextView.textSize = textSize + return this + } + + /** + * Set the background of the dialog title + * + * @param drawable The background of the dialog title + */ + fun setDialogTitleBackground(drawable: Drawable?): SlidingDialog { + titleTextView.background = drawable + return this + } + + /** + * Set the background of the dialog message + * + * @param drawable The background of the dialog message + */ + fun setDialogMessageBackground(drawable: Drawable?): SlidingDialog { + messageTextView.background = drawable + return this + } + + /** + * Set the text appearance of the dialog title + * + * @param textAppearance The text appearance of the dialog title + */ + fun setDialogTitleTextAppearance(@StyleRes textAppearance: Int): SlidingDialog { + titleTextView.setTextAppearance(context, textAppearance) + return this + } + + /** + * Set the text appearance of the dialog message + * + * @param textAppearance The text appearance of the dialog message + */ + fun setDialogMessageTextAppearance(@StyleRes textAppearance: Int): SlidingDialog { + messageTextView.setTextAppearance(context, textAppearance) + return this + } + + /** + * Set the visibility of the check box + * + * @param visible Whether the check box is visible + */ + fun setCheckBoxVisibility(visible: Boolean): SlidingDialog { + checkbox.visibility = if (visible) View.VISIBLE else View.GONE + return this + } + + /** + * Set the check box message + * + * @param messageId The resource ID of the check box message + */ + fun setCheckBoxMessageRes(@StringRes messageId: Int): SlidingDialog { + checkbox.setText(messageId) + return this + } + + /** + * Set the check box message + * + * @param message The check box message + */ + fun setCheckBoxMessage(message: String): SlidingDialog { + checkbox.text = message + return this + } + + /** + * Set whether the check box is checked + * + * @param isChecked Whether the check box is checked + */ + fun setCheckBoxChecked(isChecked: Boolean): SlidingDialog { + checkbox.isChecked = isChecked + return this + } + + /** + * Set the color of the check box message + * + * @param color The color of the check box message + */ + fun setCheckBoxMessageTextColor(@ColorInt color: Int): SlidingDialog { + checkbox.setTextColor(color) + return this + } + + /** + * Set the size of the check box message + * + * @param textSize The size of the check box message + */ + fun setCheckBoxMessageTextSize(@Dimension textSize: Float): SlidingDialog { + checkbox.textSize = textSize + return this + } + + /** + * Set the background of the check box message + * + * @param drawable The background of the check box message + */ + fun setCheckBoxMessageBackground(drawable: Drawable?): SlidingDialog { + checkbox.background = drawable + return this + } + + /** + * Set the text appearance of the check box message + * + * @param textAppearance The text appearance of the check box message + */ + fun setCheckBoxMessageTextAppearance(@StyleRes textAppearance: Int): SlidingDialog { + checkbox.setTextAppearance(context, textAppearance) + return this + } + + /** + * Set the action message + * + * @param actionId The resource ID of the action message + */ + fun setActionMessageRes(@StringRes actionId: Int): SlidingDialog { + actionTextView.setText(actionId) + return this + } + + /** + * Set the action message + * + * @param action The action message + */ + fun setActionMessage(action: String): SlidingDialog { + actionTextView.text = action + return this + } + + /** + * Set the color of the action message + * + * @param color The color of the action message + */ + fun setActionMessageTextColor(@ColorInt color: Int): SlidingDialog { + actionTextView.setTextColor(color) + return this + } + + /** + * Set the size of the action message + * + * @param textSize The size of the action message + */ + fun setActionMessageTextSize(@Dimension textSize: Float): SlidingDialog { + actionTextView.textSize = textSize + return this + } + + /** + * Set the background of the action message + * + * @param drawable The background of the action message + */ + fun setActionMessageBackground(drawable: Drawable?): SlidingDialog { + actionTextView.background = drawable + return this + } + + /** + * Set the text appearance of the action message + * + * @param textAppearance The text appearance of the action message + */ + fun setActionMessageTextAppearance(@StyleRes textAppearance: Int): SlidingDialog { + actionTextView.setTextAppearance(context, textAppearance) + return this + } + + /** + * Set the icon next to the dialog title + * + * @param drawable The icon next to the dialog title + */ + fun setDialogIcon(drawable: Drawable?): SlidingDialog { + iconImageView.setImageDrawable(drawable) + return this + } + + /** + * Set the tint of the icon next to the dialog title + * + * @param color The tint of the icon + */ + fun setDialogIconTint(@ColorInt color: Int): SlidingDialog { + ViewUtil.tintImage(iconImageView, color) + return this + } + + /** + * Set the color of the cancel button text + * + * @param color The color of the cancel text + */ + fun setCancelTextColor(@ColorInt color: Int): SlidingDialog { + cancelTextView.setTextColor(color) + return this + } + + /** + * Set the size of the cancel button text + * + * @param textSize The size of the cancel text + */ + fun setCancelTextSize(@Dimension textSize: Float): SlidingDialog { + cancelTextView.textSize = textSize + return this + } + + /** + * Set the background of the cancel button + * + * @param drawable The background of the cancel button + */ + fun setCancelBackground(drawable: Drawable?): SlidingDialog { + cancelTextView.background = drawable + return this + } + + /** + * Set the text appearance of the cancel button + * + * @param textAppearance The text appearance of the cancel button + */ + fun setCancelTextAppearance(@StyleRes textAppearance: Int): SlidingDialog { + cancelTextView.setTextAppearance(context, textAppearance) + return this + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/VerticalSeekBar.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/VerticalSeekBar.java new file mode 100644 index 00000000..f91384ec --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/VerticalSeekBar.java @@ -0,0 +1,527 @@ +/** + * @filename : DJIVSeekBar.java + * @package : dji.pilot.publics.widget + * @date : 2015-10-30 下午12:18:20 + * @author : gashion.fang + *

+ * Copyright (c) 2015, DJI All Rights Reserved. + */ + +package dji.v5.ux.core.ui; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.BitmapShader; +import android.graphics.Canvas; +import android.graphics.Rect; +import android.graphics.Shader; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.ClipDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.LayerDrawable; +import android.graphics.drawable.ShapeDrawable; +import android.graphics.drawable.shapes.RoundRectShape; +import android.graphics.drawable.shapes.Shape; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.MotionEvent; +import android.view.View; +import android.view.ViewConfiguration; +import android.view.ViewGroup; +import android.view.ViewParent; + +import dji.v5.utils.common.DisplayUtil; +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.R; + + +public class VerticalSeekBar extends View { + + public interface OnVSBChangeListener { + void onProgressChanged(VerticalSeekBar seekBar, int progress, boolean fromUser); + + void onStartTrackingTouch(VerticalSeekBar seekBar); + + void onStopTrackingTouch(VerticalSeekBar seekBar); + } + + private static final int MAX_LEVEL = 10000; + protected final String logTag = LogUtils.getTag(this); + + protected Drawable mProgressDrawable = null; + protected int mProgressWidth = 0; + protected Drawable mThumb = null; + protected int mMax = 1; + protected int mProgress = 0; + protected int mSecondaryProgress = 0; + // 宽度必须比Thumb的宽度要小,如果有需要,请重写或者修改该控件 + protected Drawable mSecondaryThumb = null; + + private int mScaledTouchSlop = 0; + private float mTouchDownY = 0.0f; + private boolean mIsDragging = false; + + private OnVSBChangeListener mOnChangedListener = null; + + public VerticalSeekBar(Context context, AttributeSet attrs) { + super(context, attrs); + + initAttrs(context); + + final TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.VerticalSeekBar, 0, 0); + mProgressWidth = ta.getDimensionPixelSize(R.styleable.VerticalSeekBar_uxsdk_progressHeight, mProgressWidth); + Drawable drawable = ta.getDrawable(R.styleable.VerticalSeekBar_uxsdk_progressDrawable); + if (null != drawable) { + setProgressDrawable(drawable); + } + setMax(ta.getInt(R.styleable.VerticalSeekBar_uxsdk_max, mMax)); + setProgress(ta.getInt(R.styleable.VerticalSeekBar_uxsdk_progress, mProgress)); + setSecondaryProgress(ta.getInt(R.styleable.VerticalSeekBar_uxsdk_secondaryProgress, mSecondaryProgress)); + Drawable thumb = ta.getDrawable(R.styleable.VerticalSeekBar_uxsdk_thumb); + if (null != thumb) { + setThumb(thumb); + } + + Drawable sThumb = ta.getDrawable(R.styleable.VerticalSeekBar_uxsdk_secondaryThumb); + if (null != sThumb) { + setSecondaryThumb(sThumb); + } + ta.recycle(); + } + + public VerticalSeekBar(Context context, AttributeSet attrs, int defStyleAttr) { + this(context, attrs); + } + + public VerticalSeekBar(Context context) { + this(context, null); + } + + public void setOnChangeListener(final OnVSBChangeListener listener) { + mOnChangedListener = listener; + } + + public void setProgressDrawable(Drawable d) { + if (!isInEditMode()){ + d = tileify(d, false, 0); + } + boolean needUpdate; + if (mProgressDrawable != null && d != mProgressDrawable) { + mProgressDrawable.setCallback(null); + needUpdate = true; + } else { + needUpdate = false; + } + + if (d != null) { + d.setCallback(this); + } + + mProgressDrawable = d; + postInvalidate(); + if (needUpdate) { + updateDrawableBounds(getWidth(), getHeight()); + doRefreshProgress(android.R.id.progress, mProgress, false, false); + doRefreshProgress(android.R.id.secondaryProgress, mSecondaryProgress, false, false); + } + } + + public void setThumb(Drawable thumb) { + boolean needUpdate = false; + if (mThumb != null && thumb != mThumb) { + needUpdate = true; + } + if (thumb != null && needUpdate + && (thumb.getIntrinsicWidth() != mThumb.getIntrinsicWidth() || thumb.getIntrinsicHeight() != mThumb.getIntrinsicHeight())) { + requestLayout(); + } + mThumb = thumb; + invalidate(); + if (needUpdate) { + updateDrawableBounds(getWidth(), getHeight()); + } + } + + public void setSecondaryThumb(final Drawable thumb) { + mSecondaryThumb = thumb; + setDrawableBounds(getWidth(), getHeight(), mSecondaryThumb, (mMax == 0 ? 0.0f : (float) mSecondaryProgress / mMax)); + invalidate(); + } + + public int getMax() { + return mMax; + } + + public void setMax(int max) { + if (max < 0) { + max = 0; + } + if (max != mMax) { + mMax = max; + + if (mProgress > max) { + mProgress = max; + } + setDrawableBounds(getWidth(), getHeight(), mThumb, (mMax == 0 ? 0.0f : (float) mProgress / mMax)); + postInvalidate(); + doRefreshProgress(android.R.id.progress, mProgress, false, false); + doRefreshProgress(android.R.id.secondaryProgress, mSecondaryProgress, false, false); + } + } + + public int getProgress() { + return mProgress; + } + + public void setProgress(int progress) { + setProgress(progress, false); + } + + private void setProgress(int progress, final boolean fromUser) { + if (progress < 0) { + progress = 0; + } + + if (progress > mMax) { + progress = mMax; + } + + if (progress != mProgress) { + mProgress = progress; + doRefreshProgress(android.R.id.progress, mProgress, fromUser, true); + } + } + + public int getSecondaryProgress() { + return mSecondaryProgress; + } + + public void setSecondaryProgress(int secondProgress) { + if (secondProgress < 0) { + secondProgress = 0; + } + + if (secondProgress > mMax) { + secondProgress = mMax; + } + + if (secondProgress != mSecondaryProgress) { + mSecondaryProgress = secondProgress; + doRefreshProgress(android.R.id.secondaryProgress, mSecondaryProgress, false, false); + } + } + + protected void updateDrawableBounds(int w, int h) { + Drawable d = mProgressDrawable; + Drawable thumb = mThumb; + final int thumbWidth = thumb == null ? 0 : thumb.getIntrinsicWidth(); + final int trackWidth = mProgressWidth; + + int max = mMax; + float scale = max > 0 ? (float) mProgress / (float) max : 0; + + setDrawableBounds(w, h, thumb, scale); + + int gapForCenteringTrack = (thumbWidth - trackWidth) / 2; + int bottom = h - getPaddingTop() - getPaddingBottom(); + if (d != null) { + d.setBounds(gapForCenteringTrack, 0, gapForCenteringTrack + trackWidth, bottom); + } + } + + protected void setDrawableBounds(final int w, final int h, final Drawable thumb, final float scale) { + if (thumb == null) { + return; + } + int available = h - getPaddingTop() - getPaddingBottom(); + int thumbWidth = thumb.getIntrinsicWidth(); + int thumbHeight = thumb.getIntrinsicHeight(); + available -= thumbHeight; + + int thumbLeft = (w - thumbWidth) / 2; + int thumbPos = available + getPaddingTop() - (int) (scale * available); + thumb.setBounds(thumbLeft, thumbPos, thumbLeft + thumbWidth, thumbPos + thumbHeight); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + if (!isEnabled()) { + return false; + } + + switch (event.getAction()) { + case MotionEvent.ACTION_DOWN: + onTouchDown(event); + break; + case MotionEvent.ACTION_MOVE: + onTouchMove(event); + break; + case MotionEvent.ACTION_UP: + onTouchUp(event); + break; + case MotionEvent.ACTION_CANCEL: + onTouchCancel(); + break; + default: + break; + } + return true; + } + + private void onTouchDown(MotionEvent event) { + if (isInScrollingContainer()) { + mTouchDownY = event.getY(); + } else { + setPressed(true); + if (mThumb != null) { + invalidate(mThumb.getBounds()); + } + onStartTrackingTouch(); + trackTouchEvent(event); + attemptClaimDrag(); + } + } + + private void onTouchMove(MotionEvent event) { + if (mIsDragging) { + trackTouchEvent(event); + } else { + final float y = event.getY(); + if (Math.abs(y - mTouchDownY) > mScaledTouchSlop) { + setPressed(true); + if (mThumb != null) { + invalidate(mThumb.getBounds()); + } + onStartTrackingTouch(); + trackTouchEvent(event); + attemptClaimDrag(); + } + } + } + + private void onTouchUp(MotionEvent event) { + if (mIsDragging) { + trackTouchEvent(event); + onStopTrackingTouch(); + setPressed(false); + } else { + onStartTrackingTouch(); + trackTouchEvent(event); + onStopTrackingTouch(); + } + invalidate(); + } + + private void onTouchCancel() { + if (mIsDragging) { + onStopTrackingTouch(); + setPressed(false); + } + invalidate(); + } + + private void trackTouchEvent(MotionEvent event) { + final int height = getHeight(); + final int paddingTop = getPaddingTop(); + final int paddingBottom = getPaddingBottom(); + + final int available = height - paddingTop - paddingBottom; + int y = (int) event.getY(); + float scale; + float progress = 0; + + if (y > height - paddingBottom) { + scale = 0.0f; + } else if (y < paddingTop) { + scale = 1.0f; + } else { + scale = (float) (available - y + paddingTop) / (float) available; + progress = 0.0f; + } + + final int max = getMax(); + progress += scale * max; + + setProgress((int) progress, true); + // doRefreshProgress(android.R.id.progress, (int) progress, true, true); + } + + private void attemptClaimDrag() { + ViewParent vp = getParent(); + if (null != vp) { + vp.requestDisallowInterceptTouchEvent(true); + } + } + + void onStartTrackingTouch() { + mIsDragging = true; + if (null != mOnChangedListener) { + mOnChangedListener.onStartTrackingTouch(this); + } + } + + void onStopTrackingTouch() { + mIsDragging = false; + if (null != mOnChangedListener) { + mOnChangedListener.onStopTrackingTouch(this); + } + } + + protected boolean isInScrollingContainer() { + ViewParent vp = getParent(); + while (vp instanceof ViewGroup) { + if (((ViewGroup) vp).shouldDelayChildPressedState()) { + return true; + } + vp = vp.getParent(); + } + return false; + } + + public Drawable getThumb() { + return mThumb; + } + + @Override + protected boolean verifyDrawable(Drawable who) { + return who == mProgressDrawable || who == mThumb || who == mSecondaryThumb || super.verifyDrawable(who); + } + + @Override + public void invalidateDrawable(Drawable drawable) { + if (verifyDrawable(drawable)) { + final Rect dirty = drawable.getBounds(); + final int scrollX = getScrollX() + getPaddingLeft(); + final int scrollY = getScrollY() + getPaddingRight(); + + invalidate(dirty.left + scrollX, dirty.top + scrollY, dirty.right + scrollX, dirty.bottom + scrollY); + } else { + super.invalidateDrawable(drawable); + } + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + updateDrawableBounds(w, h); + setDrawableBounds(w, h, mSecondaryThumb, (mMax == 0 ? 0.0f : (float) mSecondaryProgress / mMax)); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int thumbWidth = mThumb == null ? 0 : mThumb.getIntrinsicWidth(); + int dw = mProgressWidth; // MeasureSpec.getSize(widthMeasureSpec); + int dh = MeasureSpec.getSize(heightMeasureSpec); + dw = Math.max(thumbWidth, dw); + dw += getPaddingLeft() + getPaddingRight(); + dh += getPaddingTop() + getPaddingBottom(); + LogUtils.i(logTag, "onMeasure", dw, dh); + setMeasuredDimension(dw, dh); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + final Drawable d = mProgressDrawable; + if (null != d) { + canvas.save(); + canvas.translate(getPaddingLeft(), getPaddingTop()); + d.draw(canvas); + canvas.restore(); + } + + if (null != mSecondaryThumb) { + canvas.save(); + canvas.translate(getPaddingLeft(), getPaddingTop()); + mSecondaryThumb.draw(canvas); + canvas.restore(); + } + + if (null != mThumb) { + canvas.save(); + canvas.translate(getPaddingLeft(), getPaddingTop()); + mThumb.draw(canvas); + canvas.restore(); + } + } + + private synchronized void doRefreshProgress(int id, int progress, final boolean fromUser, final boolean callToApp) { + float scale = mMax > 0 ? (float) progress / (float) mMax : 0; + final Drawable d = mProgressDrawable; + if (d != null) { + Drawable progressDrawable = null; + + if (d instanceof LayerDrawable) { + progressDrawable = ((LayerDrawable) d).findDrawableByLayerId(id); + } + + final int level = (int) (scale * MAX_LEVEL); + (progressDrawable != null ? progressDrawable : d).setLevel(level); + } else { + invalidate(); + } + + if (id == android.R.id.progress) { + setDrawableBounds(getWidth(), getHeight(), mThumb, scale); + invalidate(); + if (callToApp && null != mOnChangedListener) { + mOnChangedListener.onProgressChanged(this, progress, fromUser); + } + } else if (id == android.R.id.secondaryProgress) { + setDrawableBounds(getWidth(), getHeight(), mSecondaryThumb, scale); + invalidate(); + } + } + + protected void initAttrs(final Context context) { + mProgressWidth = DisplayUtil.dip2px(context, 4); + mMax = 100; + mProgress = 0; + mSecondaryProgress = 0; + mScaledTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); + } + + private Shape getDrawableShape() { + final float[] roundedCorners = new float[]{ + 5, 5, 5, 5, 5, 5, 5, 5 + }; + return new RoundRectShape(roundedCorners, null, null); + } + + private Drawable tileify(Drawable drawable, final boolean clip, final int drawableId) { + if (drawable instanceof LayerDrawable) { + LayerDrawable background = (LayerDrawable) drawable; + final int N = background.getNumberOfLayers(); + Drawable[] outDrawables = new Drawable[N]; + + for (int i = 0; i < N; i++) { + int id = background.getId(i); + outDrawables[i] = tileify(background.getDrawable(i), (id == android.R.id.progress || id == android.R.id.secondaryProgress), + id); + } + + LayerDrawable newBg = new LayerDrawable(outDrawables); + + for (int i = 0; i < N; i++) { + newBg.setId(i, background.getId(i)); + } + + return newBg; + } else if (drawable instanceof BitmapDrawable) { + final Bitmap tileBitmap = ((BitmapDrawable) drawable).getBitmap(); + + final ShapeDrawable shapeDrawable = new ShapeDrawable(getDrawableShape()); + + final BitmapShader bitmapShader = new BitmapShader(tileBitmap, Shader.TileMode.REPEAT, Shader.TileMode.CLAMP); + shapeDrawable.getPaint().setShader(bitmapShader); + + if (android.R.id.background == drawableId) { + mProgressWidth = tileBitmap.getWidth(); + } + + return (clip) ? new ClipDrawable(shapeDrawable, Gravity.BOTTOM, ClipDrawable.VERTICAL) : shapeDrawable; + } + return drawable; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/IsothermRangeSeekbar.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/IsothermRangeSeekbar.kt new file mode 100644 index 00000000..4684afda --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/IsothermRangeSeekbar.kt @@ -0,0 +1,167 @@ +package dji.v5.ux.core.ui.component + +import android.content.Context +import android.graphics.* +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import dji.v5.utils.common.AndUtil +import dji.v5.ux.R +import dji.v5.ux.core.ui.RangeSeekBar + +/** + * 等温线范围条件控件 + */ +open class IsothermRangeSeekbar @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null +) : RangeSeekBar(context, attrs) { + private val DEBUG_TOUCH_RECT = false + private val paint = Paint() + val textPaint = Paint() + val textBounds = Rect() + val thumbWidth = AndUtil.getDimension(R.dimen.uxsdk_11_dp).toInt() + val thumbHeight = AndUtil.getDimension(R.dimen.uxsdk_18_dp).toInt() + + var textFormatCallback: TextFormatCallback? = null + + init { + paint.color = Color.RED + paint.isAntiAlias = true + paint.style = Paint.Style.STROKE + paint.strokeWidth = 2F + + textPaint.run { + isDither = true + isAntiAlias = true + color = Color.WHITE + typeface = Typeface.DEFAULT_BOLD + textSize = resources.getDimension(R.dimen.uxsdk_10_dp) + } + + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + if (DEBUG_TOUCH_RECT) { + canvas?.drawRect(getTouchRect(mLeftThumb), paint) + canvas?.drawRect(getTouchRect(mRightThumb), paint) + } + } + + override fun getTouchRect(thumb: Drawable?): Rect { + mTouchRect = super.getTouchRect(thumb) + if (thumb == mLeftThumb) { + mTouchRect.left -= thumbWidth + } else { + mTouchRect.right += thumbWidth + } + mTouchRect.top -= thumbHeight/2 + mTouchRect.bottom += thumbHeight/2 + return mTouchRect + } + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + // 高度 + var heightMeasureSpec = heightMeasureSpec + val heightNeeded: Int = resources.getDimension(R.dimen.uxsdk_42_dp).toInt() + paddingTop + paddingBottom + var heightSize: Int = MeasureSpec.getSize(heightMeasureSpec) + val heightMode: Int = MeasureSpec.getMode(heightMeasureSpec) + heightMeasureSpec = if (heightMode == MeasureSpec.EXACTLY) { + MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY) + } else if (heightMode == MeasureSpec.AT_MOST) { + MeasureSpec.makeMeasureSpec( + if (heightSize < heightNeeded) heightSize else heightNeeded, MeasureSpec.EXACTLY + ) + } else { + MeasureSpec.makeMeasureSpec( + heightNeeded, MeasureSpec.EXACTLY + ) + } + val widthSize = MeasureSpec.getSize(widthMeasureSpec) + heightSize = MeasureSpec.getSize(heightMeasureSpec) + setMeasuredDimension(widthSize, heightSize) + } + + override fun drawLeftThumb(canvas: Canvas) { + + val leftTop = height / 2 - thumbHeight/2 + val leftX = getThumbPosition(mLeftValue) - thumbWidth + mLeftThumb.setBounds(leftX, leftTop, leftX + thumbWidth, leftTop + thumbHeight) + if (isEnabled) { + mLeftThumb.draw(canvas) + } + + // 绘制文字 + val text = textFormatCallback?.format(mLeftValue)?:mLeftValue.toString() + textPaint.getTextBounds(text, 0, text.length, textBounds) + val textRight = leftX + textBounds.width() + // 超出显示范围,画在左边 + if (textRight > width) { + textPaint.textAlign = Paint.Align.RIGHT + } else { + textPaint.textAlign = Paint.Align.LEFT + } + val textTop = mLeftThumb.bounds.bottom + resources.getDimension(R.dimen.uxsdk_4_dp) + val textLeft = mLeftThumb.bounds.left.toFloat() + canvas.drawText(text, textLeft, textTop + textBounds.height(), textPaint) + + } + + override fun drawRightThumb(canvas: Canvas) { + val rightX = getThumbPosition(mRightValue) + val rightTop = height / 2 - thumbHeight/2 + mRightThumb.setBounds(rightX, rightTop, rightX + thumbWidth, rightTop + thumbHeight) + if (isEnabled) { + mRightThumb.draw(canvas) + } + + // 绘制文字 + val text = textFormatCallback?.format(mRightValue)?:mRightValue.toString() + textPaint.getTextBounds(text, 0, text.length, textBounds) + val textRight = rightX - textBounds.width() + // 超出显示范围,画在左边 + if (textRight < 0) { + textPaint.textAlign = Paint.Align.LEFT + } else { + textPaint.textAlign = Paint.Align.RIGHT + } + val textTop = mRightThumb.bounds.top + resources.getDimension(R.dimen.uxsdk_4_dp) + val textLeft = mRightThumb.bounds.right.toFloat() + canvas.drawText(text, textLeft, textTop - textBounds.height(), textPaint) + } + + override fun drawProgress(canvas: Canvas) { + val leftX = getThumbPosition(mLeftValue) - thumbWidth + val rightX = getThumbPosition(mRightValue) + thumbWidth + + mProgressDrawable.setBounds( + leftX, + mBackgroundDrawable.bounds.top, + rightX, + mBackgroundDrawable.bounds.bottom + ) + mProgressDrawable.draw(canvas) + } + + fun setProgressDrawable(drawable: Drawable) { + mProgressDrawable = drawable + postInvalidate() + } + + override fun getThumbPosition(value: Int): Int { + // progress的总长度 + val width = (width - paddingRight - paddingLeft).toFloat() + val range = mDrawMax - mDrawMin + val v = value - mDrawMin + return Math.round(v / range * width) + paddingLeft + } + + override fun getValueByDelta(delta: Float): Int { + val width = (width - paddingRight - thumbWidth / 2 - paddingLeft - thumbWidth / 2).toFloat() + val range = (mMax - mMin).toFloat() + return Math.round(delta / width * range) + } + + fun interface TextFormatCallback { + fun format(value: Int): String + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/MarqueeTextView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/MarqueeTextView.java new file mode 100644 index 00000000..ae08c6d3 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/MarqueeTextView.java @@ -0,0 +1,51 @@ +/** + * @filename : DJIMarqueeTextView.java + * @package : dji.pilot.publics.widget + * @date : 2014年12月16日下午4:12:23 + * @author : gashion.fang + * @description : + * + * Copyright (c) 2014, DJI All Rights Reserved. + * + */ + +package dji.v5.ux.core.ui.component; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.widget.TextView; + +import java.util.Objects; + +@SuppressLint("AppCompatCustomView") +public class MarqueeTextView extends TextView { + + public MarqueeTextView(Context context, AttributeSet attrs) { + super(context, attrs); + setEllipsize(TextUtils.TruncateAt.MARQUEE); + setMarqueeRepeatLimit(-1); + setSingleLine(); + setFocusable(true); + } + + @Override + public boolean isFocused() { + return true; + } + + @Override + public void setText(CharSequence text, BufferType type) { + //这里text会为null,导致SmartController遥控器必现出现空指针问题:(其他遥控器没有问题,猜测跟Android版本有关) + // Android NullPointerException at android.text.BoringLayout.isBoring,必须加上该过滤逻辑。 + if (TextUtils.isEmpty(text)) { + super.setText("", type); + return; + } + if (!Objects.equals(text, getText())) { + super.setText(text, type); + requestFocus(); + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/MaxHeightScrollView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/MaxHeightScrollView.java new file mode 100644 index 00000000..3be37c8a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/MaxHeightScrollView.java @@ -0,0 +1,53 @@ +package dji.v5.ux.core.ui.component; + +import android.app.Activity; +import android.content.Context; +import android.util.AttributeSet; +import android.util.DisplayMetrics; +import android.view.Display; +import android.widget.ScrollView; + +import dji.v5.ux.R; + +public class MaxHeightScrollView extends ScrollView { + + private Context mContext; + private final DisplayMetrics d = new DisplayMetrics(); + + public MaxHeightScrollView(Context context) { + super(context); + init(context); + } + + public MaxHeightScrollView(Context context, AttributeSet attrs) { + super(context, attrs); + init(context); + + } + + public MaxHeightScrollView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context); + } + + private void init(Context context) { + mContext = context; + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + try { + //最大高度显示为屏幕内容高度的一半 + Display display = ((Activity) mContext).getWindowManager().getDefaultDisplay(); + display.getMetrics(d); + //此处是关键,设置控件高度不能超过屏幕高度一半(d.heightPixels / 2)(在此替换成自己需要的高度) + int maxHeight = (int) mContext.getResources().getDimension(R.dimen.uxsdk_186_dp); + heightMeasureSpec = MeasureSpec.makeMeasureSpec(maxHeight, MeasureSpec.AT_MOST); + + } catch (Exception e) { +// e.printStackTrace(); + } + //重新计算控件高、宽 + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/PaletteItemDecoration.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/PaletteItemDecoration.kt new file mode 100644 index 00000000..54e16ea5 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/PaletteItemDecoration.kt @@ -0,0 +1,47 @@ +package dji.v5.ux.core.ui.component + +import android.graphics.Rect +import android.view.View +import androidx.recyclerview.widget.RecyclerView + +class PaletteItemDecoration(val spanCount: Int, + val leftEdgeSpacing: Int, + val rightEdgeSpacing: Int, + val topEdgeSpacing: Int, + val hSpacing: Int, + val vSpacing: Int) : RecyclerView.ItemDecoration() { + + override fun getItemOffsets(outRect: Rect, itemPosition: Int, parent: RecyclerView) { + when (itemPosition % spanCount) { + 0 -> { + outRect.left = leftEdgeSpacing + outRect.right = hSpacing / 2 + } + spanCount - 1 -> { + outRect.left = hSpacing / 2 + outRect.right = rightEdgeSpacing + } + else -> { + outRect.left = hSpacing / 2 + outRect.right = hSpacing / 2 + } + } + + val row = itemPosition / spanCount + val maxRow = (parent.adapter?.itemCount?:0) / spanCount + + when (row) { + maxRow-> { + outRect.top = vSpacing / 2 + outRect.bottom = vSpacing + } + else-> { + outRect.top = vSpacing / 2 + outRect.bottom = vSpacing / 2 + } + } + + + + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/SegmentedButtonGroup.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/SegmentedButtonGroup.kt new file mode 100644 index 00000000..84a46a81 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/SegmentedButtonGroup.kt @@ -0,0 +1,130 @@ +package dji.v5.ux.core.ui.component + +import android.animation.ValueAnimator +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.RectF +import android.util.AttributeSet +import android.view.Gravity +import android.view.View +import android.widget.LinearLayout +import androidx.annotation.IdRes +import androidx.appcompat.view.ContextThemeWrapper +import androidx.interpolator.view.animation.FastOutSlowInInterpolator +import kotlin.math.roundToInt +import dji.v5.ux.R +/** + * 类似iOS的分段控件 + */ +class SegmentedButtonGroup @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null +) : LinearLayout(ContextThemeWrapper(context, R.style.SegmentedButtonGroup), attrs) { + + private val NOT_SET = Float.MAX_VALUE + + var checkedItemBgColor = Color.TRANSPARENT + + var checkedItemRect = RectF() + + var checkedItemLeft: Float = NOT_SET + // 动画 + var animator: ValueAnimator? = null + + var paint = Paint() + private var radius = 0F + + private var checkedItemView: View? = null + + var onCheckedChangedListener: OnCheckedListener? = null + + init { + val themeContext = getContext() + val ta = themeContext.obtainStyledAttributes(attrs, R.styleable.SegmentedButtonGroup) + checkedItemBgColor = ta.getColor(R.styleable.SegmentedButtonGroup_uxsdk_checkedItemBackgroundColor, Color.TRANSPARENT) + ta.recycle() + + setBackgroundResource(R.drawable.uxsdk_segmented_button_group_bg) + clipToOutline = true + + orientation = HORIZONTAL + val padding = resources.getDimension(R.dimen.uxsdk_2_dp).roundToInt() + setPadding(padding, padding, padding, padding) + setWillNotDraw(false) + gravity = Gravity.CENTER_VERTICAL + + radius = resources.getDimension(R.dimen.uxsdk_3_dp) + + paint.isAntiAlias = true + paint.style = Paint.Style.FILL + } + + override fun onFinishInflate() { + super.onFinishInflate() + for (i in 0 until childCount) { + val child = getChildAt(i) + child.setOnClickListener { + onClickItem(it) + } + } + + if (checkedItemView == null && childCount > 0) { + checkedItemView = getChildAt(0) + checkedItemView?.isSelected = true + } + } + + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + + checkedItemView?.let { child-> + if (checkedItemLeft == NOT_SET) { + checkedItemLeft = child.left.toFloat() + } + child.background = null + checkedItemRect.set(checkedItemLeft, child.top.toFloat(), checkedItemLeft + child.width, child.bottom.toFloat()) + paint.color = checkedItemBgColor + canvas?.drawRoundRect(checkedItemRect, radius, radius, paint) + } + } + + private fun onClickItem(view: View) { + // 取消上次选中的view的selection + checkedItemView?.let { + it.isSelected = false + } + checkedItemView = view + view.isSelected = true + onCheckedChangedListener?.onChecked(view.id) + + if (view.width > 0) { + animator?.cancel() + animator = ValueAnimator.ofFloat(checkedItemRect.left, view.left.toFloat()) + .apply { + duration = 200 + interpolator = FastOutSlowInInterpolator() + addUpdateListener { + checkedItemLeft = it.animatedValue as Float + postInvalidate() + } + start() + } + } else { + checkedItemLeft = NOT_SET + postInvalidate() + } + } + + fun check(@IdRes id: Int) { + findViewById(id)?.let { + if (checkedItemView != it) { + onClickItem(it) + } + } + } + + fun interface OnCheckedListener { + fun onChecked(@IdRes id: Int) + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/StreamPaletteRangeSeekbar.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/StreamPaletteRangeSeekbar.kt new file mode 100644 index 00000000..47e9ddad --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/StreamPaletteRangeSeekbar.kt @@ -0,0 +1,72 @@ +package dji.v5.ux.core.ui.component + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.Rect +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import dji.v5.ux.R +import java.text.DecimalFormat +/** + * 码流调试融合强度调整 + */ +class StreamPaletteRangeSeekbar(context: Context, attrs: AttributeSet? = null) : IsothermRangeSeekbar(context, attrs) { + var zoomMultiple = 1.0 + var df: DecimalFormat = DecimalFormat("#.#") + + override fun drawLeftThumb(canvas: Canvas) { + val leftTop = height / 2 - thumbHeight/2 + val leftX = getThumbPosition(mLeftValue) - thumbWidth + mLeftThumb.setBounds(leftX, leftTop, leftX + thumbWidth, leftTop + thumbHeight) + if (isEnabled) { + mLeftThumb.draw(canvas) + } + + // 绘制文字 + val text = if (zoomMultiple == 1.0) leftValue.toString() else (df.format(leftValue * zoomMultiple)).toString() + textPaint.getTextBounds(text, 0, text.length, textBounds) + val textRight = leftX + textBounds.width() + // 超出显示范围,画在左边 + if (textRight > width) { + textPaint.textAlign = Paint.Align.RIGHT + } else { + textPaint.textAlign = Paint.Align.LEFT + } + val textTop = mLeftThumb.bounds.bottom + resources.getDimension(R.dimen.uxsdk_4_dp) + val textLeft = mLeftThumb.bounds.left.toFloat() + canvas.drawText(text, textLeft, textTop + textBounds.height(), textPaint) + } + + override fun drawRightThumb(canvas: Canvas) { + val rightX = getThumbPosition(mRightValue) + val rightTop = height / 2 - thumbHeight/2 + mRightThumb.setBounds(rightX, rightTop, rightX + thumbWidth, rightTop + thumbHeight) + if (isEnabled) { + mRightThumb.draw(canvas) + } + + // 绘制文字 + val text = if (zoomMultiple == 1.0) rightValue.toString() else (df.format(rightValue * zoomMultiple)).toString() + textPaint.getTextBounds(text, 0, text.length, textBounds) + val textRight = rightX - textBounds.width() + // 超出显示范围,画在左边 + if (textRight < 0) { + textPaint.textAlign = Paint.Align.LEFT + } else { + textPaint.textAlign = Paint.Align.RIGHT + } + val textTop = mRightThumb.bounds.top + resources.getDimension(R.dimen.uxsdk_4_dp) + val textLeft = mRightThumb.bounds.right.toFloat() + canvas.drawText(text, textLeft, textTop - textBounds.height(), textPaint) + } + + override fun getTouchRect(thumb: Drawable?): Rect { + mTouchRect = super.getTouchRect(thumb) + mTouchRect.left -= thumbWidth + mTouchRect.right += thumbWidth + mTouchRect.top -= thumbHeight/2 + mTouchRect.bottom += thumbHeight/2 + return mTouchRect + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/StrokeTextView.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/StrokeTextView.kt new file mode 100644 index 00000000..afe185a3 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/StrokeTextView.kt @@ -0,0 +1,63 @@ +package dji.v5.ux.core.ui.component + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.util.AttributeSet +import android.widget.TextView +import androidx.appcompat.view.ContextThemeWrapper +import androidx.appcompat.widget.AppCompatTextView +import dji.v5.ux.R + +/** + * 支持描边的TextView + */ +open class StrokeTextView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 +) : AppCompatTextView(ContextThemeWrapper(context, R.style.Widget_StrokeTextView), attrs, defStyleAttr) { + + var strokeWidth: Float = 0F + var strokeColor: Int = 0 + + var onDrawingFlag = false + + init { + val newContext = getContext() + val ta = newContext.obtainStyledAttributes(attrs, R.styleable.StrokeTextView) + strokeWidth = ta.getDimension(R.styleable.StrokeTextView_uxsdk_textStrokeWidth, 0F) + strokeColor = ta.getColor(R.styleable.StrokeTextView_uxsdk_textStrokeColor, 0) + ta.recycle() + + + try { + val field = TextView::class.java.getDeclaredField("mShadowRadius") + field.isAccessible = true + field.setFloat(this, strokeWidth) + field.isAccessible = false + } catch (exception: Exception) { + // 如果上面的方法失败了,使用下面这个备用方式 + setShadowLayer(strokeWidth, 0F, 0F, Color.TRANSPARENT) + } + } + + override fun invalidate() { + if (!onDrawingFlag) { + super.invalidate() + } + } + + override fun onDraw(canvas: Canvas) { + onDrawingFlag = true + val lastColor = textColors + setTextColor(strokeColor) + paint.style = Paint.Style.STROKE + paint.strokeWidth = strokeWidth + super.onDraw(canvas) + + setTextColor(lastColor) + paint.style = Paint.Style.FILL + super.onDraw(canvas) + onDrawingFlag = false + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/UXRecyclerView.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/UXRecyclerView.kt new file mode 100644 index 00000000..570a92a4 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/component/UXRecyclerView.kt @@ -0,0 +1,27 @@ +package dji.v5.ux.core.ui.component + +import android.content.Context +import android.util.AttributeSet +import androidx.recyclerview.widget.RecyclerView +import dji.v5.ux.R + +open class UXRecyclerView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 +) : RecyclerView(context, attrs, defStyleAttr) { + + var fadingEdgeColor: Int = 0 + + init { + val ta = context.obtainStyledAttributes(attrs, R.styleable.UXRecyclerView) + fadingEdgeColor = ta.getColor(R.styleable.UXRecyclerView_uxsdk_fadingEdgeColor, 0) + ta.recycle() + } + + override fun getSolidColor(): Int { + return fadingEdgeColor + } + + override fun getTopFadingEdgeStrength(): Float { + return 0F + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/exposure/ExposeVSeekBar.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/exposure/ExposeVSeekBar.kt new file mode 100644 index 00000000..de072ad3 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/exposure/ExposeVSeekBar.kt @@ -0,0 +1,93 @@ +package dji.v5.ux.core.ui.exposure + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.Rect +import android.util.AttributeSet +import android.view.MotionEvent +import androidx.core.content.ContextCompat +import dji.v5.ux.R +import dji.v5.ux.core.ui.VerticalSeekBar +import dji.v5.utils.common.AndUtil +import kotlin.math.max + +class ExposeVSeekBar @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null +) : VerticalSeekBar(context, attrs) { + + var isShowSeekBar = false + private val sunSize = getContext().resources.getDimensionPixelSize(R.dimen.uxsdk_14_dp) + private val rectWidth = getContext().resources.getDimensionPixelSize(R.dimen.uxsdk_1_dp) + private val sunMargin = getContext().resources.getDimensionPixelSize(R.dimen.uxsdk_2_dp) + private val rectStrokeWidth = AndUtil.dip2px(context, 0.5f) + private val halfSunSize = sunSize shr 1 + + private val rect = Rect() + private val paint = Paint() + + private val rectSolidColor = ContextCompat.getColor(context, R.color.uxsdk_yellow_500) + private val rectStrokeColor = ContextCompat.getColor(context, R.color.uxsdk_black_30_percent) + + override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { + val thumbWidth = if (mThumb == null) 0 else mThumb.intrinsicWidth + var dw = mProgressWidth + var dh = MeasureSpec.getSize(heightMeasureSpec) + dw = max(thumbWidth shl 1, dw) + dw += paddingLeft + paddingRight + dh += paddingTop + paddingBottom + setMeasuredDimension(dw, dh) + } + + override fun onTouchEvent(event: MotionEvent?): Boolean { + if ((event != null && event.action == MotionEvent.ACTION_DOWN && mThumb != null) + && (event.y < mThumb.bounds.top - mThumb.intrinsicWidth + || event.y > mThumb.bounds.bottom + mThumb.intrinsicWidth) + ) { + //只有点击小太阳图标时才有效,否则不处理点击事件 + return false + } + return super.onTouchEvent(event) + } + + override fun onDraw(canvas: Canvas) { + canvas.takeIf { isShowSeekBar }?.let { + drawRect(it) + } + super.onDraw(canvas) + } + + private fun drawRect(canvas: Canvas) { + val thumbRect = mThumb.bounds + + val startOffX = (thumbRect.left + thumbRect.right - rectWidth) shr 1 + val topEndOffY = thumbRect.top - sunMargin + + if (topEndOffY.toFloat() > halfSunSize) { + rect.set(startOffX, halfSunSize, startOffX + rectWidth, topEndOffY) + onDrawRect(canvas) + } + val bottomStartOffY = thumbRect.bottom + sunMargin + val bottomEndOffY = layoutParams.height - halfSunSize + if (bottomEndOffY > bottomStartOffY) { + rect.set(startOffX, bottomStartOffY, startOffX + rectWidth, bottomEndOffY) + onDrawRect(canvas) + } + } + + private fun onDrawRect(canvas: Canvas) { + //绘制实体线 + paint.color = rectSolidColor + paint.style = Paint.Style.FILL + canvas.drawRect(rect, paint) + //绘制黑色描边 + paint.color = rectStrokeColor + paint.style = Paint.Style.STROKE + paint.strokeWidth = rectStrokeWidth.toFloat() + with(rect) { + right += rectStrokeWidth + bottom += rectStrokeWidth + } + canvas.drawRect(rect, paint) + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/AircraftAttitudeView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/AircraftAttitudeView.java new file mode 100644 index 00000000..9a27f7d5 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/AircraftAttitudeView.java @@ -0,0 +1,559 @@ +package dji.v5.ux.core.ui.hsi; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.util.AttributeSet; +import android.view.View; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.ui.hsi.fpv.IFPVParams; +import dji.v5.ux.core.util.MatrixUtils; +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.disposables.CompositeDisposable; +import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.subjects.PublishSubject; + +public class AircraftAttitudeView extends View { + + private static final String TAG = "AircraftAttitudeView"; + + private static final int VIEW_DRAW_FRAME_RATE = 60; + + private static final int DATA_RECEIVED_FRAME_RATE = 10; + + @NonNull + private static final float[] EMPTY_FLOAT_ARRAYS = new float[0]; + + /** + * 机头"+"相对于父布局的百分比 + */ + private static final float AIRCRAFT_NOSE_PERCENTAGE_OF_PARENT = 16f / 252; + + /** + * 速度矢量球相对于父布局的百分比 + */ + private static final float AIRCRAFT_HEADING_VIEW_PERCENTAGE_OF_PARENT = 24f / 252; + + /** + * 矢量球圆形占矢量球大小比例 + */ + private static final float AIRCRAFT_HEADING_CIRCLE_PERCENTAGE = 5f / 12; + + private static final float[] C2I_MATRIX = new float[]{0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f}; + + @NonNull + private final Paint mPaint; + + private int mVideoViewWidth; + + private int mVideoViewHeight; + + private int mActualWidthBack; + + private int mActualHeightBack; + + private int mActualWidth; + + private int mActualHeight; + + private final int mLineStrokeWidth; + + private float mYaw; + private float mRoll; + private float mPitch; + + private float mSpeedX; + private float mSpeedY; + private float mSpeedZ; + + @NonNull + private final List mParameters = new ArrayList<>(); + + @NonNull + private final PublishSubject mAircraftAttitudePublisher = PublishSubject.create(); + + @Nullable + private ViewModel mViewModel; + + @Nullable + private CompositeDisposable mDisposable; + private IFPVParams mFpvParams; + + public AircraftAttitudeView(Context context) { + this(context, null); + } + + public AircraftAttitudeView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public AircraftAttitudeView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AircraftAttitudeView); + mActualWidth = typedArray.getDimensionPixelSize(R.styleable.AircraftAttitudeView_uxsdk_actual_width, -1); + mActualHeight = typedArray.getDimensionPixelSize(R.styleable.AircraftAttitudeView_uxsdk_actual_height, -1); + mActualWidthBack = mActualWidth; + mActualHeightBack = mActualHeight; + typedArray.recycle(); + + mLineStrokeWidth = context.getResources().getDimensionPixelSize(R.dimen.uxsdk_1_dp); + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG | Paint.DITHER_FLAG); + mPaint.setColor(getResources().getColor(R.color.uxsdk_green_in_dark)); + mPaint.setStrokeWidth(mLineStrokeWidth); + } + + /** + * 镜头焦距,以像素为单位 + */ + public float getFpvFocusX() { + return mFpvParams.getFocusX(); + } + + /** + * 镜头焦距,以像素为单位 + */ + public float getFpvFocusY() { + return mFpvParams.getFocusY(); + } + + /** + * 视频原始宽度的1/2 + */ + public float getVideoCenterX() { + return mFpvParams.getCenterX(); + } + + /** + * 视频原始高度的1/2 + */ + public float getVideoCenterY() { + return mFpvParams.getCenterY(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mFpvParams = IFPVParams.Companion.getCurrent(); + mDisposable = new CompositeDisposable(); + + processAircraftAttitude(); + processHorizontalLineAndSpeedVectorMark(); + } + + private void processHorizontalLineAndSpeedVectorMark() { + mDisposable.add(Observable.interval(1000 / VIEW_DRAW_FRAME_RATE, TimeUnit.MILLISECONDS) + .observeOn(Schedulers.single()) + .map(aLong -> getParameters()) + .distinctUntilChanged() + .observeOn(Schedulers.computation()) + .map(floats -> { + ViewModel viewModel = new ViewModel(); + if (floats.length > 0) { + SpeedVectorData speedVectorData = new SpeedVectorData(); + speedVectorData.setPitch(floats[2]); + speedVectorData.setYaw(floats[3]); + speedVectorData.setRoll(floats[4]); + updateHorizontalLine(viewModel, (int) floats[0], (int) floats[1], speedVectorData); + + updateSpeedVectorMark(viewModel, (int) floats[0], (int) floats[1], speedVectorData, floats[5], floats[6], floats[7]); + } + return viewModel; + }) + .onErrorReturn(throwable -> { + LogUtils.e(TAG, throwable.getMessage()); + return new ViewModel(); + }) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(viewModel -> { + if (!viewModel.isValidate()) { + return; + } + mViewModel = viewModel; + invalidate(); + })); + } + + private float[] getParameters() { + if (mParameters.isEmpty()) { + return EMPTY_FLOAT_ARRAYS; + } else { + if (mParameters.get(0) == null) { + mParameters.remove(0); + return EMPTY_FLOAT_ARRAYS; + } else { + if (mParameters.size() > 1) { + return mParameters.remove(0); + } else { + return mParameters.get(0); + } + } + } + } + + private void processAircraftAttitude() { + // 屏幕刷新率是60Hz,协议推送频率是10Hz,对数据进行两帧线性内插,提高平滑度 + mDisposable.add(mAircraftAttitudePublisher + .debounce(10, TimeUnit.MILLISECONDS, Schedulers.newThread()) + .observeOn(Schedulers.single()) + .map(floats -> new float[][]{ + mParameters.isEmpty() ? null : mParameters.get(mParameters.size() - 1), + floats + }) + .observeOn(Schedulers.computation()) + .map(params -> { + if (params[0] == null) { + mParameters.add(params[1]); + } else { + float[] startElement = params[0]; + float[] floats = params[1]; + int interval = VIEW_DRAW_FRAME_RATE / DATA_RECEIVED_FRAME_RATE; + //若pitch yaw roll前后角度相反,采用线性插值会导致速度矢量球有剧烈的变化。这里用等量的前参数+后参数进行插值可以解决此问题 + boolean isDrasticChange = + floats[2] * startElement[2] < 0 || floats[3] * startElement[3] < 0 || floats[4] * startElement[4] < 0; + float pitchOffset = (floats[2] - startElement[2]) / interval; + float yawOffset = (floats[3] - startElement[3]) / interval; + float rollOffset = (floats[4] - startElement[4]) / interval; + float speedXOffset = (floats[5] - startElement[5]) / interval; + float speedYOffset = (floats[6] - startElement[6]) / interval; + float speedZOffset = (floats[7] - startElement[7]) / interval; + for (int i = 1; i < interval; i++) { + float[] offset = !isDrasticChange ? new float[]{floats[0], floats[1], + startElement[2] + pitchOffset * i, startElement[3] + yawOffset * i, startElement[4] + rollOffset * i, + startElement[5] + speedXOffset * i, + startElement[6] + speedYOffset * i, startElement[7] + speedZOffset * i + } : getOffset(i, interval, startElement, floats); + mParameters.add(offset); + } + mParameters.add(floats); + } + return true; + }) + .onErrorReturn(throwable -> { + LogUtils.e(TAG, throwable.getMessage()); + return false; + }) + .subscribe()); + } + + private float[] getOffset(int i, int interval, float[] startElement, float[] floats) { + return i < interval / 2 ? startElement : floats; + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (mDisposable != null && !mDisposable.isDisposed()) { + mDisposable.dispose(); + } + } + + public void setYaw(float yaw) { + mYaw = yaw; + recalculateAndInvalidate(); + } + + public void setRoll(float roll) { + mRoll = roll; + recalculateAndInvalidate(); + } + + public void setPitch(float pitch) { + mPitch = pitch; + recalculateAndInvalidate(); + } + + public void setSpeedX(float speedX) { + mSpeedX = speedX; + recalculateAndInvalidate(); + } + + public void setSpeedY(float speedY) { + mSpeedY = speedY; + recalculateAndInvalidate(); + } + + public void setSpeedZ(float speedZ) { + mSpeedZ = speedZ; + recalculateAndInvalidate(); + } + + public void setVideoViewSize(int videoViewWidth, int videoViewHeight) { + mVideoViewWidth = videoViewWidth; + mVideoViewHeight = videoViewHeight; + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (mActualHeight == -1) { + mActualHeight = getHeight(); + } + if (mActualWidth == -1) { + mActualWidth = getWidth(); + } + // "+"的大小取两者的最小值 + int aircraftNoseSize = Math.min((int) (mActualWidth * AIRCRAFT_NOSE_PERCENTAGE_OF_PARENT), + (int) (mActualHeight * AIRCRAFT_NOSE_PERCENTAGE_OF_PARENT)); + + drawAircraftNose(canvas, aircraftNoseSize); + if (mViewModel != null) { + drawAircraftHorizon(canvas, aircraftNoseSize, mViewModel.aircraftHorizonRotate, mViewModel.aircraftHorizonOffsetY); + drawAircraftHeading(canvas, mViewModel.aircraftHeadingOffsetX, mViewModel.aircraftHeadingOffsetY); + return; + } + drawAircraftHorizon(canvas, aircraftNoseSize, 0, 0); + drawAircraftHeading(canvas, 0, 0); + } + + public void setSize(int width, int height) { + mActualWidth = width; + mActualHeight = height; + invalidate(); + } + + public void resetSize() { + setSize(mActualWidthBack, mActualHeightBack); + } + + /** + * 画出飞机机头,始终在图传正中央,用"+"表示 + * + * @param canvas + * @param aircraftNoseSize 机头"+"的大小 + */ + private void drawAircraftNose(Canvas canvas, int aircraftNoseSize) { + // 画横线 + canvas.drawLine( + (float) (getWidth() - aircraftNoseSize) / 2, + (float) getHeight() / 2, + (float) (getWidth() + aircraftNoseSize) / 2, + (float) getHeight() / 2, + mPaint + ); + + // 画竖线 + canvas.drawLine( + (float) getWidth() / 2, + (float) (getHeight() + aircraftNoseSize) / 2, + (float) getWidth() / 2, + (float) (getHeight() - aircraftNoseSize) / 2, + mPaint + ); + } + + /** + * 画出速度矢量球,表示飞机即将飞去的位置,飞机往后飞的时候不显示 + * 要有一条线连接矢量球跟机头 + * + * @param canvas + * @param offsetX + * @param offsetY + */ + private void drawAircraftHeading(Canvas canvas, float offsetX, float offsetY) { + float middleHeight = (float) getHeight() / 2; + float middleWidth = (float) getWidth() / 2; + // 计算速度矢量球的大小 + float aircraftHeadingSize = Math.min(mActualWidth * AIRCRAFT_HEADING_VIEW_PERCENTAGE_OF_PARENT, + mActualHeight * AIRCRAFT_HEADING_VIEW_PERCENTAGE_OF_PARENT); + + // 画连接机头与矢量球的线段,矢量球内不绘制 + canvas.save(); + canvas.translate(middleWidth, middleHeight); + float radius = aircraftHeadingSize / 2 * AIRCRAFT_HEADING_CIRCLE_PERCENTAGE; + float length = (float) Math.sqrt(offsetX * offsetX + offsetY * offsetY); + float drawRate = (length - radius) / length; + canvas.drawLine(0, 0, offsetX * drawRate, offsetY * drawRate, mPaint); + canvas.translate(offsetX, offsetY); + // 画矢量球 + mPaint.setStyle(Paint.Style.STROKE); + canvas.drawCircle(0, 0, radius, mPaint); + // 画矢量球左上右的线段 + canvas.drawLine(-aircraftHeadingSize / 2, 0, -radius, 0, mPaint); + canvas.drawLine(radius, 0, aircraftHeadingSize / 2, 0, mPaint); + canvas.drawLine(0, -radius, 0, -radius * 2, mPaint); + canvas.restore(); + } + + /** + * 画出地平线,反应飞行器的姿态,与飞行器倾斜角度相反 + * + * @param canvas + * @param aircraftNoseSize 机头"+"的大小 + * @param rotate 倾斜角 + * @param offsetY 垂直方向上的偏移量 + */ + private void drawAircraftHorizon(Canvas canvas, int aircraftNoseSize, float rotate, float offsetY) { + float middleHeight = (float) getHeight() / 2; + float middleWidth = (float) getWidth() / 2; + canvas.save(); + canvas.translate(middleWidth, middleHeight); + canvas.rotate(rotate); + canvas.translate(0, -offsetY); + // 画左边的线段 + canvas.drawLine(-(float) mActualWidth / 2, + 0, + -aircraftNoseSize / 4f * 3, + 0, + mPaint); + // 画右边的线段 + canvas.drawLine(aircraftNoseSize / 4f * 3, + 0, + (float) mActualWidth / 2, + 0, + mPaint); + canvas.restore(); + + } + + /** + * 计算地平线在VideoView中的位置,原始位置是视频中间 + * + * @param viewModel + * @param displayWidth + * @param displayHeight + */ + private void updateHorizontalLine(ViewModel viewModel, int displayWidth, int displayHeight, + SpeedVectorData speedVectorData) { + float[] i2gMat = MatrixUtils.createRotationMatrix(speedVectorData.yaw, speedVectorData.pitch, speedVectorData.roll); + float[] bl2gMat = MatrixUtils.createRotationMatrix(speedVectorData.yaw, 0, 0); + + float[] g2blMat = MatrixUtils.transposeMatrix(bl2gMat); + float[] i2blMat = MatrixUtils.productMatrix(g2blMat, i2gMat); + + float[] c2blMat = MatrixUtils.productMatrix(i2blMat, C2I_MATRIX); + float[] bl2cMat = MatrixUtils.transposeMatrix(c2blMat); + + float[] kMat = MatrixUtils.createIntrinsicMatrix(getFpvFocusX(), getFpvFocusY(), getVideoCenterX(), getVideoCenterY()); + + float[] v1 = {bl2cMat[0] / bl2cMat[6], bl2cMat[3] / bl2cMat[6], 1.0f}; + float[] v2 = {(bl2cMat[0] + bl2cMat[1]) / (bl2cMat[6] + bl2cMat[7]), (bl2cMat[3] + bl2cMat[4]) / (bl2cMat[6] + bl2cMat[7]), 1.0f}; + v1 = MatrixUtils.rotateVector(v1, kMat); + v2 = MatrixUtils.rotateVector(v2, kMat); + + float a = (v2[1] - v1[1]) / (v2[0] - v1[0]); + float angrad = (float) Math.atan(a); + float rotate = (float) Math.toDegrees(angrad); + float c = v1[1] - a * v1[0]; + float offsetY = (float) displayHeight / 2 - (float) displayWidth / 2 * a - c * displayHeight / (getVideoCenterY() * 2); + + viewModel.aircraftHorizonRotate = rotate; + viewModel.aircraftHorizonOffsetY = offsetY; + } + + /** + * 计算速度矢量球在VideoView中的位置,原始位置是视频中间 + */ + private void updateSpeedVectorMark(ViewModel viewModel, int displayWidth, int displayHeight, + SpeedVectorData speedVectorData, + float speedX, float speedY, float speedZ) { + + float[] i2gMat = MatrixUtils.createRotationMatrix(speedVectorData.yaw, speedVectorData.pitch, speedVectorData.roll); + float[] g2iMat = MatrixUtils.transposeMatrix(i2gMat); + + float[] speedVector = new float[]{speedX, speedY, speedZ}; + + float[] vi = MatrixUtils.rotateVector(speedVector, g2iMat); + + if (vi[0] >= 0) { + float[] c2gMat = MatrixUtils.productMatrix(i2gMat, C2I_MATRIX); + float[] g2cMat = MatrixUtils.transposeMatrix(c2gMat); + float[] kMat = MatrixUtils.createIntrinsicMatrix(getFpvFocusX(), getFpvFocusY(), getVideoCenterX(), getVideoCenterY()); + float[] mMat = MatrixUtils.productMatrix(kMat, g2cMat); + + speedVector = MatrixUtils.rotateVector(speedVector, mMat); + speedVector[0] = speedVector[0] / speedVector[2]; + speedVector[1] = speedVector[1] / speedVector[2]; + + float vectorX = (speedVector[0] - getVideoCenterX()) * displayWidth / (getVideoCenterX() * 2); + float vectorY = (speedVector[1] - getVideoCenterY()) * displayHeight / (getVideoCenterY() * 2); + + //检查边界值 + if (vectorX < -(float) displayWidth / 2 || vectorX > (float) displayWidth / 2) { + float checkedX; + checkedX = Math.max(vectorX, (float) -displayWidth / 2); + checkedX = vectorX > (float) displayWidth / 2 ? (float) displayWidth / 2 : checkedX; + + float checkedY = checkedX / vectorX * vectorY; + + vectorX = checkedX; + vectorY = checkedY; + } + + if (vectorY < -(float) displayHeight / 2 || vectorY > (float) displayHeight / 2) { + float checkedY; + checkedY = Math.max(vectorY, (float) -displayHeight / 2); + checkedY = vectorY > (float) displayHeight / 2 ? (float) displayHeight / 2 : checkedY; + + vectorX = vectorX / vectorY * checkedY; + vectorY = checkedY; + } + + viewModel.aircraftHeadingOffsetX = vectorX; + viewModel.aircraftHeadingOffsetY = vectorY; + + } + } + + private class SpeedVectorData { + private float pitch; + private float yaw; + private float roll; + + public float getPitch() { + return pitch; + } + + public void setPitch(float pitch) { + this.pitch = pitch; + } + + public float getYaw() { + return yaw; + } + + public void setYaw(float yaw) { + this.yaw = yaw; + } + + public float getRoll() { + return roll; + } + + public void setRoll(float roll) { + this.roll = roll; + } + } + + private void recalculateAndInvalidate() { + mAircraftAttitudePublisher.onNext(new float[]{ + mVideoViewWidth, mVideoViewHeight, + mPitch, mYaw, mRoll, + mSpeedX, mSpeedY, mSpeedZ + }); + } + + private static final class ViewModel { + float aircraftHorizonRotate = Float.NaN; + float aircraftHorizonOffsetY = Float.NaN; + float aircraftHeadingOffsetX = Float.NaN; + float aircraftHeadingOffsetY = Float.NaN; + + boolean isValidate() { + return !Float.isNaN(aircraftHorizonRotate) + || !Float.isNaN(aircraftHorizonOffsetY) + || !Float.isNaN(aircraftHeadingOffsetX) + || !Float.isNaN(aircraftHeadingOffsetY); + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/FlashTimer.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/FlashTimer.kt new file mode 100644 index 00000000..f77dad3e --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/FlashTimer.kt @@ -0,0 +1,57 @@ +package dji.v5.ux.core.ui.hsi + +import androidx.annotation.MainThread +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers +import io.reactivex.rxjava3.core.Observable +import io.reactivex.rxjava3.disposables.CompositeDisposable + +import java.util.concurrent.TimeUnit + +object FlashTimer { + + private val compositeDisposable = CompositeDisposable() + + private val listenerList: MutableList = mutableListOf() + + private var started = false + + @MainThread + fun addListener(listener: Listener?) { + listener?.let { + if (!listenerList.contains(it)) { + listenerList.add(it) + } + if (listenerList.size > 0 && !started) { + started = true + startFlash() + } + } + } + + @MainThread + fun removeListener(listener: Listener?) { + listener?.let { + listenerList.remove(it) + if (listenerList.isEmpty() && started) { + started = false + compositeDisposable.clear() + } + } + + } + + private fun startFlash() { + val valueObservable = Observable.fromArray(false, true) + val intervalObservable = Observable.interval(250, TimeUnit.MILLISECONDS) + + compositeDisposable.add(Observable.zip(valueObservable, intervalObservable) { value, _ -> + value + }.repeat().observeOn(AndroidSchedulers.mainThread()).subscribe { value -> + listenerList.forEach { it.onValue(value) } + }) + } + + fun interface Listener { + fun onValue(show: Boolean) + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/HSICompassProcesser.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/HSICompassProcesser.kt new file mode 100644 index 00000000..c0fa6484 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/HSICompassProcesser.kt @@ -0,0 +1,194 @@ +package dji.v5.ux.core.ui.hsi + +import android.content.Context +import android.hardware.Sensor +import android.hardware.SensorEvent +import android.hardware.SensorEventListener +import android.hardware.SensorManager +import android.os.Handler +import android.view.Display +import android.view.OrientationEventListener +import android.view.WindowManager +import dji.v5.utils.common.DJIExecutor +import dji.v5.utils.common.LogUtils + +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers +import io.reactivex.rxjava3.disposables.Disposable +import java.lang.ref.WeakReference + +internal class HSICompassProcesser(context: Context, listener: CompassListener) { + private val mSensorMgr: SensorManager = context.applicationContext.getSystemService(Context.SENSOR_SERVICE) as SensorManager + private var mAccelerometerStatus: Int = SensorManager.SENSOR_STATUS_NO_CONTACT + private var mMagneticStatus: Int = SensorManager.SENSOR_STATUS_NO_CONTACT + private val mDefaultDisplay: Display + private val mRegisterManager: RegisterManager + private var mAccelerometerData: FloatArray? = null + private var mMagneticValues: FloatArray? = null + var mListener: CompassListener + + private val sampleTimeInMs = 100L + private var lastUpdateTime = 0L + + private fun calcOrientation() { + if (mAccelerometerData == null || mMagneticValues == null) { + return + } + val values = FloatArray(3) + val matrix = FloatArray(9) + SensorManager.getRotationMatrix(matrix, null, mAccelerometerData, mMagneticValues) + SensorManager.getOrientation(matrix, values) + values[0] = Math.toDegrees(values[0].toDouble()).toFloat() + var orientation = values[0] + if (orientation < 0) { + orientation += 360 + } + orientation += screenOrientation.toFloat() + if (orientation > 360) { + orientation -= 360f + } + + val strength = mAccelerometerStatus.coerceAtMost(mMagneticStatus) + notifyDisposable?.dispose() + notifyDisposable = AndroidSchedulers.mainThread().scheduleDirect { + mListener.onOrientationChange(strength, orientation) + } + } + + @Volatile + private var screenOrientation: Int = 0 + + + private var notifyDisposable: Disposable? = null + + fun start() { + mRegisterManager.registerSensorListener() + updateScreenOrientation() + } + + + fun stop() { + mRegisterManager.unRegisterSensorListener() + notifyDisposable?.dispose() + } + + fun updateScreenOrientation() { + screenOrientation = mDefaultDisplay.rotation * 90 + } + + fun onSensorChanged(event: SensorEvent?) { + if (event?.sensor?.type == Sensor.TYPE_ACCELEROMETER) { + mAccelerometerData = event.values + } + if (event?.sensor?.type == Sensor.TYPE_MAGNETIC_FIELD) { + mMagneticValues = event.values + } + val now = System.currentTimeMillis() + if (now - lastUpdateTime >= sampleTimeInMs) { + lastUpdateTime = now + calcOrientation() + } + } + + fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { + LogUtils.d(TAG, "onAccuracyChanged: type: ${sensor?.type}, accuracy: $accuracy") + when (sensor?.type) { + Sensor.TYPE_ACCELEROMETER -> mAccelerometerStatus = accuracy + Sensor.TYPE_MAGNETIC_FIELD -> mMagneticStatus = accuracy + } + } + + /** + * 监测设备朝向 + */ + internal interface CompassListener { + /** + * @param strength 信号强度,one of SensorManager.SENSOR_STATUS_* + * @param degree 朝向 + */ + fun onOrientationChange(strength: Int, degree: Float) + } + + init { + val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager + mDefaultDisplay = wm.defaultDisplay + val mAccelerometerSensor: Sensor? = mSensorMgr.getDefaultSensor(Sensor.TYPE_ACCELEROMETER) + val mMagneticSensor: Sensor? = mSensorMgr.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD) + mRegisterManager = RegisterManager( + mSensorMgr, + mAccelerometerSensor, + mMagneticSensor, + HSICompassSensorEventListener(WeakReference(this)), + HSICompassSensorOrientationEventListener(WeakReference(this), context.applicationContext), + ) + mListener = listener + } + + private class RegisterManager( + private val sensorManager: SensorManager, + private val mAccelerometerSensor: Sensor?, + private val mMagneticSensor: Sensor?, + private val mRcOriListener: SensorEventListener, + private val orientationEventListener: OrientationEventListener, + ) { + // 在自己的线程上进行计算 + private val handler: Handler = Handler(DJIExecutor.getLooper()) + + fun registerSensorListener() { + mAccelerometerSensor?.let { + mMagneticSensor?.let { + handler.post { + //耗时操作,需要放在子线程处理 + sensorManager.registerListener(mRcOriListener, + mAccelerometerSensor, + SAMPLING_PERIOD_US, + SensorManager.SENSOR_DELAY_NORMAL, + handler) + sensorManager.registerListener(mRcOriListener, + mMagneticSensor, + SAMPLING_PERIOD_US, + SensorManager.SENSOR_DELAY_NORMAL, + handler) + if (orientationEventListener.canDetectOrientation()) { + orientationEventListener.enable() + } + } + } + } + } + + fun unRegisterSensorListener() { + handler.post { + sensorManager.unregisterListener(mRcOriListener) + if (orientationEventListener.canDetectOrientation()) { + orientationEventListener.disable() + } + } + } + } + + private class HSICompassSensorEventListener(private val weakRefHSICompassProcesser: WeakReference) : SensorEventListener { + + override fun onSensorChanged(event: SensorEvent?) { + weakRefHSICompassProcesser.get()?.onSensorChanged(event) + } + + override fun onAccuracyChanged(sensor: Sensor?, accuracy: Int) { + weakRefHSICompassProcesser.get()?.onAccuracyChanged(sensor, accuracy) + } + } + + private class HSICompassSensorOrientationEventListener( + private val weakRefHSICompassProcesser: WeakReference, + context: Context, + ) : OrientationEventListener(context) { + override fun onOrientationChanged(orientation: Int) { + weakRefHSICompassProcesser.get()?.updateScreenOrientation() + } + + } + + companion object { + private const val SAMPLING_PERIOD_US = SensorManager.SENSOR_DELAY_NORMAL + private const val TAG = "HSICompassProcesser" + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/HSIContract.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/HSIContract.java new file mode 100644 index 00000000..3e171d2a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/HSIContract.java @@ -0,0 +1,49 @@ +package dji.v5.ux.core.ui.hsi; + +import android.graphics.Canvas; +import android.graphics.Paint; +import android.view.View; + +public interface HSIContract { + + public interface HSIContainer { + int getWidth(); + + int getHeight(); + + float getCurrentDegree(); + + int getAircraftSize(); + + int getVisibleDistanceInHsiInMeters(); + + float getCalibrationAreaWidth(); + + float getDegreeIndicatorHeight(); + + float getCompassBitmapOffset(); + + //void addDJIKey(DJIKey key); + + void updateWidget(); + + View getView(); + } + + public interface HSILayer { + void onStart(); + + void onStop(); + + void draw(Canvas canvas, Paint paint, int compassSize); + + /** + * 飞机当前模式 + * @param fpv true: fpv ,false: liveview + */ + default void enterFpvMode(boolean fpv){} + + //boolean transformValue(DJIKey key, Object value); + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/HSIMarkerLayer.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/HSIMarkerLayer.java new file mode 100644 index 00000000..7c8347b2 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/HSIMarkerLayer.java @@ -0,0 +1,1212 @@ +package dji.v5.ux.core.ui.hsi; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Point; +import android.graphics.PointF; +import android.graphics.Rect; +import android.hardware.SensorManager; +import android.location.Location; +import android.text.TextPaint; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.Size; +import android.view.ViewDebug; + +import java.util.concurrent.CopyOnWriteArrayList; + +import androidx.annotation.IntDef; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + + + +import dji.sdk.keyvalue.value.common.LocationCoordinate3D; +import dji.sdk.keyvalue.value.common.LocationCoordinate2D; +import dji.v5.utils.common.LocationUtil; +import dji.v5.ux.R; +import dji.v5.ux.core.ui.hsi.dashboard.FpvStrokeConfig; +import dji.v5.utils.common.AndUtil; +import dji.v5.common.utils.UnitUtils; +import dji.v5.ux.core.util.DrawUtils; +import dji.v5.ux.mapkit.core.utils.DJIGpsUtils; +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.disposables.CompositeDisposable; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.schedulers.Schedulers; +import io.reactivex.rxjava3.subjects.BehaviorSubject; + +public class HSIMarkerLayer implements HSIContract.HSILayer { + + @NonNull + private static final Path PATH = new Path(); + +// @NonNull +// private static final int WAYPOINT_HEIGHT_THRESHOLD_FPV = 1; +// private static final int WAYPOINT_HEIGHT_THRESHOLD_LIVEVIEW = 5; + private static final int MAX_DISPLAY_DISTANCE_NUMBER = 999; + private static final float FLOAT_THRESHOLD = 0.000001f; + private static final int HSI_HOME_RC_MERGE_THRESHOLD = 5; + + @NonNull + private HSIContract.HSIContainer mHSIContainer; + + @NonNull + private final float[] mFloats = new float[2]; + +// @NonNull +// private static final BearingDistance INVALID_BEARING_DISTANCE = new BearingDistance(); + + @NonNull + private final Bitmap mHomePointBitmap; + private final Bitmap mHomePointCornerBitmap; + + private final int mHomePointMarkerSize; + + @NonNull + private final Bitmap mWayPointBitmap; +// private final Bitmap mBreakBitmap; + +// private int mWaypointThrosholdInMeter = WAYPOINT_HEIGHT_THRESHOLD_FPV; + +// private Bitmap mWayPointDownBitmap; + +// private Bitmap mWayPointUpBitmap; + + @ViewDebug.ExportedProperty(category = HSIView.VIEW_DEBUG_CATEGORY_DJI) + private final int mMarkerIndicatorTextSize; + + private float mMarkerIndicatorTextMaxWidth; + +// @NonNull +// private Bitmap mPinPointBitmap; + + // private final int mPinPointMarkerSize; + + @NonNull + private final Bitmap mRngPointBitmap; + + @NonNull + private final Bitmap mSmartTrackPointBitmap; + private final Bitmap mRemoteControlPointBitmap; + private final Bitmap mRemoteControlDirectionNormalBitmap; + private final Bitmap mRemoteControlDirectionMergeBitmap; +// private final boolean mShowSmartTrack; + + @NonNull + private Bitmap mAdsbRedBitmap; + + @NonNull + private Bitmap mAdsbYellowBitmap; + + private final int mAdsbMarkerSize; + + private final int mMarkerMarginVertical; + + private final int mMarkerMarginHorizontal; + + private int mMarkerNameInset; + private float mMarkerNameTriangleWidth; + private float mMarkerNameTriangleHeight; + + @NonNull + private final BehaviorSubject mSubject = BehaviorSubject.create(); + + @Nullable + private LocationCoordinate3D mAircraftLocation; + + @Nullable + private LocationCoordinate2D mHomeLocation; + + @NonNull + private IndicatorInfo mHomeInfo = new IndicatorInfo(); + @NonNull + private IndicatorInfo mRngInfo = new IndicatorInfo(); + +// @NonNull +// private final List mPinPointsDistances = new ArrayList<>(); + + private IndicatorInfo mSelectPinInfo = new IndicatorInfo(true); + +// @Nullable +// private BearingDistance mSmartTrackDistance; + + @NonNull + private IndicatorInfo mSmartTrackInfo = new IndicatorInfo(); + + @NonNull + private IndicatorInfo mWayPointInfo = new IndicatorInfo(); + + @NonNull + private IndicatorInfo mRemoteControlInfo = new IndicatorInfo(); + private IndicatorInfo mRemoteControlDirectionInfo = new IndicatorInfo(); + + HSICompassProcesser mCompassProcesser; + + @NonNull + private final CopyOnWriteArrayList mAdsbYellowDistances = new CopyOnWriteArrayList<>(); + + @NonNull + private final CopyOnWriteArrayList mAdsbRedDistances = new CopyOnWriteArrayList<>(); + + private Paint mStrokePaint = new Paint(Paint.DITHER_FLAG | Paint.ANTI_ALIAS_FLAG); + + @Nullable + private CompositeDisposable mCompositeDisposable = new CompositeDisposable(); + private Location mLastLocation; + private float mRcDegree; +// private boolean mAdsbShow; +// private FlashTimer.Listener mFlashListener; + FpvStrokeConfig mStrokeConfig; + @NonNull + private HSIWidgetModel widgetModel; + + public HSIMarkerLayer(@NonNull Context context, @Nullable AttributeSet attrs, @NonNull HSIContract.HSIContainer container, + HSIWidgetModel widgetModel) { + mHSIContainer = container; + mStrokeConfig = new FpvStrokeConfig(context); + this.widgetModel = widgetModel; + + + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HSIView); + mHomePointMarkerSize = typedArray.getDimensionPixelSize(R.styleable.HSIView_uxsdk_hsi_home_point_marker_size, 0); + mHomePointBitmap = DrawUtils.drawableRes2Bitmap(typedArray.getResourceId(R.styleable.HSIView_uxsdk_hsi_home_point_marker, + R.drawable.uxsdk_fpv_pfd_hsi_home_point)); + mHomePointCornerBitmap = DrawUtils.drawableRes2Bitmap(typedArray.getResourceId(R.styleable.HSIView_uxsdk_hsi_home_point_marker, + R.drawable.uxsdk_fpv_hsi_compass_home_point)); + mWayPointBitmap = DrawUtils.drawableRes2Bitmap(typedArray.getResourceId(R.styleable.HSIView_uxsdk_hsi_waypoint_marker, + R.drawable.uxsdk_fpv_hsi_waypoint)); +// mBreakBitmap = DrawUtils.drawableRes2Bitmap(typedArray.getResourceId(R.styleable.HSIView_uxsdk_hsi_break_marker, +// R.drawable.uxsdk_ic_fpv_hsi_ar_waypoint_break)); + + // mPinPointMarkerSize = typedArray.getDimensionPixelSize(R.styleable.HSIView_hsi_pin_point_marker_size, + // context.getResources().getDimensionPixelSize(R.dimen.dp_9_in_sw640)); + // mPinPointBitmap = DrawUtils.drawableRes2Bitmap(typedArray.getResourceId(R.styleable.HSIView_hsi_pin_point_marker, R.drawable + // .fpv_hsi_pin_point_blue)); + + int remoteControlRes = typedArray.getResourceId(R.styleable.HSIView_uxsdk_hsi_remote_control_point_marker, R.drawable.uxsdk_fpv_hsi_rc); + mRemoteControlPointBitmap = DrawUtils.drawableRes2Bitmap(remoteControlRes); +// mShowSmartTrack = typedArray.getBoolean(R.styleable.HSIView_uxsdk_hsi_smart_track_enable, false); + mSmartTrackPointBitmap = DrawUtils.drawableRes2Bitmap(typedArray.getResourceId(R.styleable.HSIView_uxsdk_hsi_smart_track_point_marker, + R.drawable.uxsdk_fpv_hsi_smart_track_point)); + + mRngPointBitmap = DrawUtils.drawableRes2Bitmap(typedArray.getResourceId(R.styleable.HSIView_uxsdk_hsi_rng_point_marker, + R.drawable.uxsdk_fpv_hsi_rng_point)); + + mAdsbMarkerSize = context.getResources().getDimensionPixelSize(R.dimen.uxsdk_10_dp); + mAdsbRedBitmap = DrawUtils.drawableRes2Bitmap(R.drawable.uxsdk_fpv_hsi_plane_danger); + mAdsbYellowBitmap = DrawUtils.drawableRes2Bitmap(R.drawable.uxsdk_fpv_hsi_plane_caution); + + + mMarkerMarginHorizontal = typedArray.getDimensionPixelSize(R.styleable.HSIView_uxsdk_hsi_marker_margin_horizontal, + context.getResources().getDimensionPixelSize(R.dimen.uxsdk_2_dp)); + mMarkerNameInset = typedArray.getDimensionPixelSize(R.styleable.HSIView_uxsdk_hsi_marker_name_inset, + context.getResources().getDimensionPixelSize(R.dimen.uxsdk_4_dp)); + mMarkerMarginVertical = typedArray.getDimensionPixelSize(R.styleable.HSIView_uxsdk_hsi_marker_margin_vertical, + 0); + mMarkerIndicatorTextSize = typedArray.getDimensionPixelSize(R.styleable.HSIView_uxsdk_hsi_marker_indicator_text_size, + context.getResources().getDimensionPixelSize(R.dimen.uxsdk_8_dp)); + mMarkerIndicatorTextMaxWidth = typedArray.getDimensionPixelSize(R.styleable.HSIView_uxsdk_hsi_marker_indicator_text_max_width, + context.getResources().getDimensionPixelSize(R.dimen.uxsdk_60_dp)); + typedArray.recycle(); + + mStrokePaint.setStrokeWidth(mStrokeConfig.getStrokeBoldWidth()); + mStrokePaint.setStyle(Paint.Style.STROKE); + mStrokePaint.setColor(mStrokeConfig.getStrokeDeepColor()); + + mMarkerNameTriangleWidth = context.getResources().getDimension(R.dimen.uxsdk_4_dp); + mMarkerNameTriangleHeight = context.getResources().getDimension(R.dimen.uxsdk_6_dp); + + mSelectPinInfo.textSize = mMarkerIndicatorTextSize; + mSelectPinInfo.horizontalAlign = INDICATOR_ALIGN_LEFT; + mSelectPinInfo.verticalAlign = INDICATOR_ALIGN_BOTTOM; + mSelectPinInfo.textOffset.set(0, (int) mHSIContainer.getDegreeIndicatorHeight()); + + mHomeInfo.textSize = mMarkerIndicatorTextSize; + mHomeInfo.horizontalAlign = INDICATOR_ALIGN_RIGHT; + mHomeInfo.verticalAlign = INDICATOR_ALIGN_BOTTOM; + mHomeInfo.marker = mHomePointBitmap; + mHomeInfo.cornerMarker = mHomePointCornerBitmap; + mHomeInfo.markSize = mHomePointMarkerSize; + mHomeInfo.textOffset.set(0, (int) mHSIContainer.getDegreeIndicatorHeight()); + + mRngInfo.textSize = mMarkerIndicatorTextSize; + mRngInfo.horizontalAlign = INDICATOR_ALIGN_RIGHT; + mRngInfo.verticalAlign = INDICATOR_ALIGN_TOP; + mRngInfo.marker = mRngPointBitmap; + mRngInfo.showInHsi = false; + mRngInfo.textOffset.set(0, (int) -mHSIContainer.getDegreeIndicatorHeight()); + + mSmartTrackInfo.textSize = mMarkerIndicatorTextSize; + mSmartTrackInfo.horizontalAlign = INDICATOR_ALIGN_RIGHT; + mSmartTrackInfo.verticalAlign = INDICATOR_ALIGN_TOP; + mSmartTrackInfo.marker = mSmartTrackPointBitmap; + mSmartTrackInfo.showInHsi = false; + mSmartTrackInfo.textOffset.set(0, (int) -mHSIContainer.getDegreeIndicatorHeight()); + + mWayPointInfo.textColor = context.getResources().getColor(R.color.uxsdk_blue_highlight); + mWayPointInfo.textSize = mMarkerIndicatorTextSize; + mWayPointInfo.horizontalAlign = INDICATOR_ALIGN_LEFT; + mWayPointInfo.verticalAlign = INDICATOR_ALIGN_TOP; + mWayPointInfo.marker = mWayPointBitmap; + mWayPointInfo.textOffset.set(0, (int) -mHSIContainer.getDegreeIndicatorHeight()); + + mRemoteControlInfo.textSize = mMarkerIndicatorTextSize; + mRemoteControlInfo.marker = mRemoteControlPointBitmap; + mRemoteControlInfo.showOnCorner = false; + + mRemoteControlDirectionNormalBitmap = DrawUtils.drawableRes2Bitmap(R.drawable.uxsdk_fpv_hsi_rc_arrow); + mRemoteControlDirectionMergeBitmap = DrawUtils.drawableRes2Bitmap(R.drawable.uxsdk_fpv_hsi_home_arrow); + mRemoteControlDirectionInfo.showOnCorner = false; + + mCompassProcesser = new HSICompassProcesser(context, this::onRcDegreeChanged); + } + + public void onRcDegreeChanged(int strength, float degree) { + mRemoteControlDirectionInfo.showInHsi = strength > SensorManager.SENSOR_STATUS_ACCURACY_LOW; + mRcDegree = degree; + } + + // private void airSenseSystemInformationHandler(AirSenseSystemInformation info) { + // + // mAdsbYellowDistances.clear(); + // mAdsbRedDistances.clear(); + // if (info.getWarningLevel().value() < AirSenseWarningLevel.LEVEL_2.value()) { + // if (mFlashListener != null) { + // FlashTimer.INSTANCE.removeListener(mFlashListener); + // } + // return; + // } + // List airSenseAirplaneStates = info.getAirplaneStates(); + // if (mFlashListener == null) { + // mFlashListener = show -> { + // mAdsbShow = show; + // mHSIContainer.updateWidget(); + // }; + // } + // //添加计时器,用于控制 adsb hsi小飞机闪烁时间 + // FlashTimer.INSTANCE.addListener(mFlashListener); + // for (AirSenseAirplaneState airplaneState : airSenseAirplaneStates) { + // BearingDistance bearingDistance = computeRelativeLocation(airplaneState.getLatitude(), airplaneState.getLongitude()); + // if (airplaneState.getWarningLevel() == AirSenseWarningLevel.LEVEL_2) { + // mAdsbYellowDistances.add(bearingDistance); + // } else if (airplaneState.getWarningLevel() == AirSenseWarningLevel.LEVEL_3 + // || airplaneState.getWarningLevel() == AirSenseWarningLevel.LEVEL_4) { + // mAdsbRedDistances.add(bearingDistance); + // } + // } + // } + + @Override + public void onStart() { + mCompositeDisposable = new CompositeDisposable(); + + // HSI 中元素信息 + startListenAircraftLocation(); + startListenHomeLocation(); + // startListenAirSenseSystem(); + // startListenSelectPinPoints(); +// startListenRngPoints(); + startListenSmartTrackIfNeed(); + startListenRc(); + mCompassProcesser.start(); + } + + private void startListenAircraftLocation() { + addDisposable(widgetModel.getAircraftLocationDataProcessor().toFlowable().subscribe(location -> { + if (location != null) { + mAircraftLocation = location; + if (mHomeLocation != null) { + updateLocation(mHomeInfo.distance, mHomeLocation.getLatitude(), mHomeLocation.getLongitude()); + } + mSubject.onNext(mAircraftLocation); + } + })); + } + + private void startListenHomeLocation() { + addDisposable(widgetModel.getHomeLocationDataProcessor().toFlowable().subscribe(locationCoordinate2D -> { + mHomeLocation = locationCoordinate2D; + if (mHomeLocation == null) { + return; + } + if (mLastLocation == null) { + mLastLocation = new Location("HomeLocation"); + mLastLocation.setLongitude(mHomeLocation.getLongitude()); + mLastLocation.setLatitude(mHomeLocation.getLatitude()); + if (!mRemoteControlInfo.distance.isValidate()) { + updateLocation(mRemoteControlInfo.distance, mLastLocation.getLatitude(), mLastLocation.getLongitude()); + } + } + mHomeInfo.distance.mLatitude = mHomeLocation.getLatitude(); + mHomeInfo.distance.mLongitude = mHomeLocation.getLongitude(); + updateLocation(mHomeInfo.distance, mHomeLocation.getLatitude(), mHomeLocation.getLongitude()); + })); + } + +// private void startListenAirSenseSystem() { + // addDisposable(Observable.combineLatest(mSubject.hide(), + // Pilot2Repo.FlightController().AirSenseSystemInformation().observable(mHSIContainer.getView()) + // .filter(info -> info.getWarningLevel() != AirSenseWarningLevel.UNKNOWN) + // .distinctUntilChanged(), + // ((locationCoordinate3D, airSenseSystemInformation) -> airSenseSystemInformation)) + // .sample(300, TimeUnit.MILLISECONDS) + // .subscribe(this::airSenseSystemInformationHandler)); +// } + +// private void startListenSelectPinPoints() { + // PinPoint,只显示选中的PIN点 + // addDisposable(Observable.combineLatest(mSubject, PinPointService.getInstance().getSelectPinPoints(), + // (locationCoordinate3D, pinSelectData) -> { + // + // if (pinSelectData == PinSelectData.NONE) { + // mSelectPinInfo.distance.setInvalid(); + // return mSelectPinInfo.distance; + // } + // + // PinPoint pinPoint = pinSelectData.getPinPoint(); + // Location3D location = pinPoint.getLocation(); + // BearingDistance distance = computeRelativeLocation(location.latitude, location.longitude); + // updateLocation(mSelectPinInfo.distance, location.latitude, location.longitude); + // if (distance.isValidate()) { + // if (pinPoint.getColor() != mSelectPinInfo.distance.mColor) { + // mSelectPinInfo.distance.mColor = pinPoint.getColor(); + // mSelectPinInfo.textColor = pinPoint.getColor(); + // } + // mSelectPinInfo.distance.mName = pinPoint.getName(); + // } else { + // mSelectPinInfo.distance.setInvalid(); + // } + // return mSelectPinInfo.distance; + // }) + // .observeOn(AndroidSchedulers.mainThread()) + // .subscribeOn(Schedulers.computation()) + // .subscribe(distance -> { + // mPinPointsDistances.clear(); + // if (distance.isValidate()) { + // mPinPointsDistances.add(distance); + // } + // mHSIContainer.updateWidget(); + // })); +// } + +// private void startListenRngPoints() { + // RNG Point + // addDisposable(Observable.combineLatest(mSubject, PinPointService.getInstance().getRNGPoint(), + // (locationCoordinate3D, location3D) -> { + // if (!location3D.isAvailable()) { + // mRngInfo.distance.setInvalid(); + // } else { + // updateLocation(mRngInfo.distance, location3D.latitude, location3D.longitude); + // } + // return mRngInfo.distance; + // }) + // .observeOn(AndroidSchedulers.mainThread()) + // .subscribeOn(Schedulers.computation()) + // .subscribe(bearingDistance -> mHSIContainer.updateWidget())); +// } + + private void startListenRc() { + mLastLocation = LocationUtil.getLastLocation(); + addDisposable(mSubject + .doOnNext(myLocation -> { + Location location = mLastLocation; + if (location != null && DJIGpsUtils.isAvailable(location.getLatitude(), location.getLongitude())) { + updateLocation(mRemoteControlInfo.distance, location.getLatitude(), location.getLongitude()); + } + }) + .observeOn(AndroidSchedulers.mainThread()) + .subscribeOn(Schedulers.computation()) + .subscribe() + ); + + mCompositeDisposable.add(widgetModel.getLocationDataProcessor().toFlowable().subscribe(location -> { + mLastLocation = location; + updateLocation(mRemoteControlInfo.distance, location.getLatitude(), location.getLongitude()); + })); + // LocationClient.getInstance().addLocationChangedListener(mOnLocationChangedListener); + } + + private void startListenSmartTrackIfNeed() { + // Smart Track Point + // if (mShowSmartTrack) { + // addDisposable(Observable.combineLatest(mSubject, SmartTrackService.getInstance().getTrackTargetPostion(), + // (locationCoordinate3D, location3D) -> { + // if (!location3D.isAvailable()) { + // mSmartTrackInfo.distance.setInvalid(); + // } else { + // updateLocation(mSmartTrackInfo.distance, location3D.latitude, location3D.longitude); + // } + // return mSmartTrackInfo.distance; + // }) + // .observeOn(AndroidSchedulers.mainThread()) + // .subscribeOn(Schedulers.computation()) + // .subscribe(bearingDistance -> mHSIContainer.updateWidget())); + // } + } + + @Override + public void onStop() { +// if (mFlashListener != null) { +// FlashTimer.INSTANCE.removeListener(mFlashListener); +// } + mCompassProcesser.stop(); + if (mCompositeDisposable != null && !mCompositeDisposable.isDisposed()) { + mCompositeDisposable.dispose(); + mCompositeDisposable = null; + } + } + + @Override + public void enterFpvMode(boolean fpv) { +// mWaypointThrosholdInMeter = fpv ? WAYPOINT_HEIGHT_THRESHOLD_FPV : WAYPOINT_HEIGHT_THRESHOLD_LIVEVIEW; + } + + /** + * 按顺序绘制 HSI 中图标 + */ + @Override + public void draw(Canvas canvas, Paint paint, int compassSize) { + canvas.save(); + canvas.translate(0, compassSize / 2f); + paint.setStyle(Paint.Style.FILL); + paint.setColor(Color.WHITE); + // canvas 中心位于罗盘水平中间,垂直上方 + + if (isAircraftLocationAvailable()) { + // drawPinPoint(canvas, paint, compassSize); + // drawRngPoint(canvas, paint, compassSize); + // drawSmartTrackPoint(canvas, paint, compassSize); + // drawWayPoint(canvas, paint, compassSize); + boolean mergeRc = mergeRcAndHome(); + if (!mergeRc) { + drawRemoteControlPoint(canvas, paint, compassSize); + } + // 绘制遥控器方向 + drawRemoteControlDirection(canvas, paint, compassSize, mergeRc); + drawHomePoint(canvas, paint, compassSize); + drawAdsbPoint(canvas, paint, compassSize); + } + canvas.restore(); + } + + private void drawRemoteControlDirection(Canvas canvas, Paint paint, int compassSize, boolean mergeRc) { + IndicatorInfo draw = mRemoteControlDirectionInfo; + IndicatorInfo from = mergeRc ? mHomeInfo : mRemoteControlInfo; + draw.marker = mergeRc ? mRemoteControlDirectionMergeBitmap : mRemoteControlDirectionNormalBitmap; + draw.distance.mDistance = from.distance.mDistance; + draw.distance.mInitialBearing = from.distance.mInitialBearing; + draw.markerRotate = mRcDegree - mHSIContainer.getCurrentDegree(); + + drawIndicatorInfo(canvas, paint, compassSize, draw); + } + + + private boolean mergeRcAndHome() { + if (mHomeInfo.distance.isValidate() && mRemoteControlInfo.distance.isValidate()) { + float[] results = new float[1]; + Location.distanceBetween(mLastLocation.getLatitude(), mLastLocation.getLongitude(), mHomeInfo.distance.mLatitude, + mHomeInfo.distance.mLongitude, results); + return results[0] < HSI_HOME_RC_MERGE_THRESHOLD; + } + + return false; + } + + private void addDisposable(Disposable disposable) { + if (disposable == null) { + return; + } + if (mCompositeDisposable != null && !mCompositeDisposable.isDisposed()) { + mCompositeDisposable.add(disposable); + } + } + + private void updateLocation(BearingDistance target, double latitude, double longitude) { + if (!isAircraftLocationAvailable() || !isAvailable(latitude, longitude)) { + target.setInvalid(); + return; + } + if (mAircraftLocation == null) { + return; + } + Location.distanceBetween(mAircraftLocation.getLatitude(), mAircraftLocation.getLongitude(), latitude, longitude, mFloats); + target.mDistance = mFloats[0]; + target.mInitialBearing = mFloats[1]; + + } + // + // @NonNull + // private BearingDistance computeRelativeLocation(double latitude, double longitude) { + // if (!isAircraftLocationAvailable() || !isAvailable(latitude, longitude)) { + // return INVALID_BEARING_DISTANCE; + // } + // Location.distanceBetween(mAircraftLocation.getLatitude(), mAircraftLocation.getLongitude(), latitude, longitude, mFloats); + // BearingDistance distance = new BearingDistance(); + // distance.mDistance = mFloats[0]; + // distance.mInitialBearing = mFloats[1]; + // return distance; + // } + + private boolean isAircraftLocationAvailable() { + return mAircraftLocation != null + && isAvailable(mAircraftLocation.getLatitude(), mAircraftLocation.getLongitude()); + } + + /** + * 绘制出Pin Point点位置 + * + * @param canvas + * @param compassSize + */ + // private void drawPinPoint(Canvas canvas, Paint paint, int compassSize) { + // for (BearingDistance pinPointDistance : mPinPointsDistances) { + // if (pinPointDistance != null) { + // paint.setColor(pinPointDistance.mColor); + // mPinPointBitmap = getPinDrawableFromColor(pinPointDistance.mColor); + // canvas.save(); + // drawMarkerOnHsi(canvas, compassSize, pinPointDistance, false); + // drawMarker(canvas, mPinPointBitmap, getScaleBitmapSize(mPinPointBitmap, mPinPointMarkerSize), new PointF(0, 0), paint, false); + // canvas.restore(); + // } + // } + // + // if (mSelectPinInfo.distance.isValidate()) { + // mPinPointBitmap = getPinDrawableFromColor(mSelectPinInfo.distance.mColor); + // drawMarkerIndicator(canvas, + // compassSize, + // mSelectPinInfo.textOffset, + // mPinPointBitmap, + // mSelectPinInfo, + // paint); + // } + // } + + /** + * 根据原始位图,返回缩放后的图标尺寸 + * + * @param pinPointBitmap 图标原尺寸 + * @param markerSize 罗盘中图标大小,用来限制较长的一边 + */ + @NonNull + private Size getScaleBitmapSize(Bitmap pinPointBitmap, int markerSize) { + int width = pinPointBitmap.getWidth(); + int height = pinPointBitmap.getHeight(); + if (markerSize == 0) { + return new Size(width, height); + } + if (height > width) { + return new Size(Math.round((float) width * markerSize / height), markerSize); + } else { + return new Size(markerSize, Math.round((float) height * markerSize / width)); + } + } + + // @NonNull + // private Bitmap getPinDrawableFromColor(int color) { + // int resId; + // if (color == DrawingElementColor.BLUE.getColor()) { + // resId = R.drawable.fpv_hsi_pin_point_blue; + // } else if (color == DrawingElementColor.RED.getColor()) { + // resId = R.drawable.fpv_hsi_pin_point_red; + // } else if (color == DrawingElementColor.GREEN.getColor()) { + // resId = R.drawable.fpv_hsi_pin_point_green; + // } else if (color == DrawingElementColor.ORANGE.getColor()) { + // resId = R.drawable.fpv_hsi_pin_point_peach; + // } else if (color == DrawingElementColor.YELLOW.getColor()) { + // resId = R.drawable.fpv_hsi_pin_point_yellow; + // } else { + // resId = R.drawable.fpv_hsi_pin_point_blue; + // } + // return DrawUtils.drawableRes2Bitmap(resId); + // } + + /** + * 绘制出Rng点位置 + * + * @param canvas + * @param compassSize + */ + // private void drawRngPoint(Canvas canvas, Paint paint, int compassSize) { + // // 仅RNG开启时才显示,优先显示SmartTrack + // if (mShowSmartTrack && mSmartTrackInfo.distance.isValidate()) { + // return; + // } + // drawIndicatorInfo(canvas, paint, compassSize, mRngInfo); + // } + + /** + * 绘制出Smart Track点位置 + * + * @param canvas + * @param compassSize + */ + // private void drawSmartTrackPoint(Canvas canvas, Paint paint, int compassSize) { + // drawIndicatorInfo(canvas, paint, compassSize, mSmartTrackInfo); + // } + + /** + * 绘制出遥控位置 + */ + private void drawRemoteControlPoint(Canvas canvas, Paint paint, int compassSize) { + BearingDistance distance = mRemoteControlInfo.distance; + if (distance == null || !distance.isValidate()) { + return; + } + Bitmap bitmap = mRemoteControlPointBitmap; + if (bitmap == null) { + return; + } + drawIndicatorInfo(canvas, paint, compassSize, mRemoteControlInfo); + } + + /** + * 绘制出Home点位置 + * + * @param canvas + * @param compassSize + */ + private void drawHomePoint(Canvas canvas, Paint paint, int compassSize) { + IndicatorInfo indicatorInfo = mHomeInfo; + drawIndicatorInfo(canvas, paint, compassSize, indicatorInfo); + } + + private void drawIndicatorInfo(Canvas canvas, Paint paint, int compassSize, IndicatorInfo indicatorInfo) { + if (!indicatorInfo.distance.isValidate()) { + return; + } + if (indicatorInfo.showInHsi) { + canvas.save(); + // 当前 canvas 中心位于罗盘中间上方 + drawMarkerOnHsi(canvas, compassSize, indicatorInfo.distance, false); + drawMarker(canvas, indicatorInfo.markerRotate, indicatorInfo.marker, getScaleBitmapSize(indicatorInfo.marker, indicatorInfo.markSize), + indicatorInfo.markerOffset, paint, false); + canvas.restore(); + } + if (indicatorInfo.showOnCorner) { + drawMarkerIndicator(canvas, + compassSize, + indicatorInfo.textOffset, + indicatorInfo.cornerMarker != null ? indicatorInfo.cornerMarker : indicatorInfo.marker, + indicatorInfo, + paint); + } + } + + /** + * 绘制Waypoint + * + * @param canvas + * @param paint + * @param compassSize + */ +// private void drawWayPoint(Canvas canvas, Paint paint, int compassSize) { + // List arPoints = MissionManagerDelegate.INSTANCE.getArPoints(); + // if (arPoints.size() == 0) { + // return; + // } + // MissionManagerDelegate.WaypointLocation waypointLocation = arPoints.get(0); + // String name; + // int idx = waypointLocation.getIdx(); + // if (idx <= 0) { + // name = null; + // } else if (idx > 9) { + // name = String.valueOf(idx); + // } else { + // name = "0" + idx; + // } + // + // Bitmap marker; + // if (waypointLocation.getType() == MissionManagerDelegate.WaypointLocation.TYPE_BREAK) { + // marker = mBreakBitmap; + // name = null; + // } else { + // marker = mWayPointBitmap; + // } + // mWayPointInfo.distance.mName = name; + // mWayPointInfo.marker = marker; + // Location3D location3d = waypointLocation.getLoc(); + // mWayPointInfo.cornerMarkerSecondary = getWaypointIndicator(location3d); + // updateLocation(mWayPointInfo.distance, location3d.getLatitude(), location3d.getLongitude()); + // drawIndicatorInfo(canvas, paint, compassSize, mWayPointInfo); +// } + // + // private Bitmap getWaypointIndicator(Location3D location3d) { + // if (mAircraftLocation != null && isAircraftLocationAvailable()) { + // double heightDelta = location3d.getAltitude() - mAircraftLocation.getAltitude(); + // if (heightDelta > mWaypointThrosholdInMeter) { + // if (mWayPointUpBitmap == null) { + // mWayPointUpBitmap = DrawUtils.drawableRes2Bitmap(R.drawable.fpv_hsi_waypoint_up); + // } + // return mWayPointUpBitmap; + // } else if (heightDelta < -mWaypointThrosholdInMeter) { + // if (mWayPointDownBitmap == null) { + // mWayPointDownBitmap = DrawUtils.drawableRes2Bitmap(R.drawable.fpv_hsi_waypoint_down); + // } + // return mWayPointDownBitmap; + // } else { + // return null; + // } + // } + // return null; + // } + + /** + * 绘制Adsb Point + */ + private void drawAdsbPoint(Canvas canvas, Paint paint, int compassSize) { + //绘制黄色小飞机(长显) + for (BearingDistance adsbDistance : mAdsbYellowDistances) { + canvas.save(); + drawMarkerOnHsi(canvas, compassSize, adsbDistance, true); + drawMarker(canvas, mAdsbYellowBitmap, new Size(mAdsbMarkerSize, mAdsbMarkerSize), new PointF(0, 0), paint, true); + canvas.restore(); + } + +// if (mAdsbShow) { +// //绘制红色小飞机 +// for (BearingDistance adsbDistance : mAdsbRedDistances) { +// canvas.save(); +// drawMarkerOnHsi(canvas, compassSize, adsbDistance, true); +// drawMarker(canvas, mAdsbRedBitmap, new Size(mAdsbMarkerSize, mAdsbMarkerSize), new PointF(0, 0), paint, true); +// canvas.restore(); +// } +// } + } + + /** + * 将图标朝上的方向转向HSI罗盘中心所需的度数(如将载人飞机图标飞机头方向朝向HSI罗盘中心) + * + * @param initialBearing 原位置与无人机夹角 + * @return 转向HSI罗盘中心所需的度数 + */ + private float transformDegreePointToDrone(float initialBearing) { + float degree = -mHSIContainer.getCurrentDegree() + initialBearing; + if (degree > 180) { + degree = degree - 360; + } + return 180 + degree; + } + + private void drawMarkerOnHsi(Canvas canvas, int compassSize, BearingDistance distance, boolean isPointToDrone) { + if (distance == null || !distance.isValidate()) { + return; + } + + canvas.rotate(-mHSIContainer.getCurrentDegree() + distance.mInitialBearing); + float ratio = distance.mDistance / mHSIContainer.getVisibleDistanceInHsiInMeters(); + //超过16米或者adsb小飞机需要显示在罗盘边缘 + if (ratio > 1 || isPointToDrone) { + ratio = 1; + } + canvas.translate(0, -((float) compassSize / 2 - mHSIContainer.getCalibrationAreaWidth() - mHSIContainer.getCompassBitmapOffset()) * ratio); + canvas.rotate(-(-mHSIContainer.getCurrentDegree() + distance.mInitialBearing)); + if (isPointToDrone) { + //图标朝上的方向指向HSI罗盘中心(如载人飞机图标飞机头方向) + canvas.rotate(transformDegreePointToDrone(distance.mInitialBearing)); + } + } + + private void drawMarker(Canvas canvas, Bitmap marker, Size size, PointF position, Paint paint, boolean isPointToDrone) { + drawMarker(canvas, 0, marker, size, position, paint, isPointToDrone); + } + + /** + * 绘制 HSI 中图标 + * + * @param canvas 画布 + * @param marker 图片信息 + * @param size 绘制大小 + * @param position 图标绘制起始点偏移 + * @param isPointToDrone 是否为 ADSB + */ + private void drawMarker(Canvas canvas, float rotate, Bitmap marker, Size size, PointF position, Paint paint, boolean isPointToDrone) { + int flag = paint.getFlags(); + paint.setFlags(flag | Paint.FILTER_BITMAP_FLAG); + canvas.save(); + //ADSB 飞机头位置需要在罗盘边缘 + int offsetX = size.getWidth() / 2; + int offsetY = isPointToDrone ? 0 : size.getHeight() / 2; + canvas.translate(position.x, position.y); + HSIView.RECT.set(0, 0, marker.getWidth(), marker.getHeight()); + HSIView.RECT2.set(-offsetX, -offsetY, -offsetX + size.getWidth(), -offsetY + size.getHeight()); + if (needRotateCanvas(rotate)) { + canvas.rotate(rotate); + } + canvas.drawBitmap(marker, HSIView.RECT, HSIView.RECT2, paint); + canvas.restore(); + paint.setFlags(flag); + } + + private boolean needRotateCanvas(float rotate) { + return rotate > FLOAT_THRESHOLD || rotate < -FLOAT_THRESHOLD; + } + + /** + * 绘制HSI四个角的Pin/Home/ST/Rng数据 + */ + private void drawMarkerIndicator(Canvas canvas, int compassSize, Point position, + Bitmap marker, IndicatorInfo indicatorInfo, Paint paint) { + if (indicatorInfo.distance == null || !indicatorInfo.distance.isValidate()) { + return; + } + canvas.save(); + float radius = compassSize / 2f; + canvas.translate( + position.x + (indicatorInfo.horizontalAlign == INDICATOR_ALIGN_LEFT ? -radius : radius), + position.y + (indicatorInfo.verticalAlign == INDICATOR_ALIGN_TOP ? -radius : radius) + ); + drawMarkerIndicatorContent(canvas, marker, indicatorInfo, paint); + canvas.restore(); + } + + private void drawMarkerIndicatorContent(Canvas canvas, + Bitmap marker, + IndicatorInfo indicatorInfo, + Paint paint) { + int textSize = indicatorInfo.textSize; + BearingDistance distance = indicatorInfo.distance; + canvas.save(); + String text = getText(distance.mDistance); + paint.setColor(Color.WHITE); + paint.setStyle(Paint.Style.FILL); + paint.setTextSize(textSize); + Paint.FontMetrics fontMetrics = paint.getFontMetrics(); + int horizontalAlign = indicatorInfo.horizontalAlign; + int verticalAlign = indicatorInfo.verticalAlign; + canvas.translate(horizontalAlign == INDICATOR_ALIGN_LEFT ? -mMarkerMarginHorizontal : mMarkerMarginHorizontal, + verticalAlign == INDICATOR_ALIGN_TOP ? mMarkerMarginVertical : -mMarkerMarginVertical); + + // 绘制文字 + paint.setTextAlign(horizontalAlign == INDICATOR_ALIGN_LEFT ? Paint.Align.LEFT : Paint.Align.RIGHT); + if (verticalAlign == INDICATOR_ALIGN_TOP) { + canvas.translate(0, -fontMetrics.ascent); + drawTextWithStroke(canvas, 0, 0, text, paint); + canvas.translate(0, fontMetrics.descent); + } else { + canvas.translate(0, -fontMetrics.descent); + drawTextWithStroke(canvas, 0, 0, text, paint); + canvas.translate(0, fontMetrics.ascent - marker.getHeight()); + } + + int flag = paint.getFlags(); + paint.setFlags(flag | Paint.FILTER_BITMAP_FLAG); + canvas.drawBitmap(marker, horizontalAlign == INDICATOR_ALIGN_LEFT ? 0 : -marker.getWidth(), 0, paint); + Bitmap markerSecondary = indicatorInfo.cornerMarkerSecondary; + if (markerSecondary != null) { + canvas.drawBitmap(markerSecondary, horizontalAlign == INDICATOR_ALIGN_LEFT ? marker.getWidth() : + -marker.getWidth() - markerSecondary.getWidth(), (marker.getHeight() - markerSecondary.getHeight()) / 2f, paint); + } + paint.setFlags(flag); + canvas.restore(); + + // 画name + float offsetY = fontMetrics.descent - fontMetrics.ascent + marker.getHeight() / 2f - mMarkerMarginVertical; + drawName(canvas, indicatorInfo, paint, distance, offsetY); + } + + private void drawName(Canvas canvas, IndicatorInfo indicatorInfo, Paint paint, BearingDistance distance, float centerY) { + String name = distance.mName; + if (!TextUtils.isEmpty(name)) { + paint.setTextAlign(Paint.Align.LEFT); + TextPaint textPaint = new TextPaint(paint); + int firstLineCount = textPaint.breakText(name, true, mMarkerIndicatorTextMaxWidth, null); + String firstLine = name.substring(0, firstLineCount); + String secondLine = null; + if (firstLineCount != name.length()) { + secondLine = + TextUtils.ellipsize(name.substring(firstLineCount), textPaint, mMarkerIndicatorTextMaxWidth, TextUtils.TruncateAt.END).toString(); + } + boolean multiLine = secondLine != null; + Paint.FontMetrics fontMetrics = textPaint.getFontMetrics(); + float height = fontMetrics.descent - fontMetrics.ascent; + float baselineOffset = height / 2 - fontMetrics.descent; + float textHeight; + float textWidth; + Rect rect = HSIView.RECT; + if (multiLine) { + textHeight = height * 2; + rect.set(0, 0, Math.round(mMarkerIndicatorTextMaxWidth), Math.round(textHeight)); + textWidth = mMarkerIndicatorTextMaxWidth; + } else { + textHeight = height; + textWidth = paint.measureText(name); + rect.set(0, 0, Math.round(textWidth), Math.round(textHeight)); + } + int textColor = indicatorInfo.textColor; + paint.setColor(textColor); + Rect bgRect = HSIView.RECT2; + bgRect.set(rect); + bgRect.inset(-mMarkerNameInset, -mMarkerNameInset); + + float bgOffset = getNameBgOffset(distance); + int horizontalAlign = indicatorInfo.horizontalAlign; + float dx = getNameOffsetX(textWidth, bgOffset, horizontalAlign); + float dy = getNameOffsetY(indicatorInfo, centerY, textHeight); + canvas.translate(dx, dy); + + if (distance.mDrawBg) { + drawNameBg(canvas, bgRect, paint, horizontalAlign == INDICATOR_ALIGN_LEFT); + } + float baseline; + if (multiLine) { + baseline = (rect.top * 3 + rect.bottom) / 4f + baselineOffset; + drawTextWithStroke(canvas, 0, baseline, firstLine, paint); + baseline += rect.height() / 2f; + drawTextWithStroke(canvas, 0, baseline, secondLine, paint); + } else { + baseline = rect.centerY() + baselineOffset; + drawTextWithStroke(canvas, 0, baseline, name, paint); + } + } + } + + private float getNameBgOffset(BearingDistance distance) { + return distance.mDrawBg ? mMarkerNameTriangleWidth + mMarkerNameInset + mMarkerMarginHorizontal : 0; + } + + private float getNameOffsetX(float textWidth, float bgOffset, int horizontalAlign) { + float dx; + if (horizontalAlign == INDICATOR_ALIGN_LEFT) { + dx = -mMarkerMarginHorizontal - textWidth - bgOffset; + } else { + dx = mMarkerMarginHorizontal + bgOffset; + } + return dx; + } + + private float getNameOffsetY(IndicatorInfo indicatorInfo, float centerY, float textHeight) { + float dy; + int verticalAlign = indicatorInfo.verticalAlign; + if (verticalAlign == INDICATOR_ALIGN_TOP) { + dy = Math.max(centerY - textHeight / 2f, 0); + } else { + dy = Math.min(-centerY - textHeight / 2f, -textHeight); + } + return dy; + } + + private void drawNameBg(Canvas canvas, Rect bgRect, Paint paint, boolean alignLeft) { + Paint.Style style = paint.getStyle(); + int color = paint.getColor(); + // 绘制圆角矩形 + paint.setStyle(Paint.Style.FILL); + paint.setColor(AndUtil.getResColor(R.color.uxsdk_black_60_percent)); + canvas.drawRoundRect(bgRect.left, bgRect.top, bgRect.right, bgRect.bottom, 5, 5, paint); + + // 绘制三角形 + Path path = PATH; + path.reset(); + float offset = mMarkerNameTriangleHeight / 2f; + int lineX = alignLeft ? bgRect.right : bgRect.left; + float pointX = alignLeft ? bgRect.right + mMarkerNameTriangleWidth : bgRect.left - mMarkerNameTriangleWidth; + path.moveTo(lineX, bgRect.centerY() + offset); + path.lineTo(pointX, bgRect.centerY()); + path.lineTo(lineX, bgRect.centerY() - offset); + path.close(); + canvas.drawPath(path, paint); + + paint.setStyle(style); + paint.setColor(color); + } + + private void drawTextWithStroke(Canvas canvas, int x, float baseline, String text, Paint paint) { + mStrokePaint.setTypeface(paint.getTypeface()); + mStrokePaint.setTextSize(paint.getTextSize()); + mStrokePaint.setTextAlign(paint.getTextAlign()); + canvas.drawText(text, x, baseline, mStrokePaint); + canvas.drawText(text, x, baseline, paint); + } + + private String getText(float value) { + String unit; + String extra = ""; + boolean hasDecimals = false; + if (!UnitUtils.isMetricUnits()) { + value = UnitUtils.getValueFromMetricByLength(value, UnitUtils.UnitType.IMPERIAL); + unit = UnitUtils.getUintStrByLength(UnitUtils.UnitType.IMPERIAL); + // 加 0.5f 是为了避免出现 999.5m 出现 1000m 这样的场景 + if (UnitUtils.moreThanMile(value + 0.5f)) { + unit = "mi"; + value = UnitUtils.footToMile(value); + hasDecimals = value < 99.5f; + if (value > MAX_DISPLAY_DISTANCE_NUMBER) { + extra = "+"; + value = MAX_DISPLAY_DISTANCE_NUMBER; + } + } + } else { + unit = UnitUtils.getUintStrByLength(UnitUtils.UnitType.METRIC); + if (value + 0.5f >= 1000) { + value /= 1000; + extra = "k"; + // 不能直接使用 100,99.95 显示一位小数是 100.0 共 5 字符 + hasDecimals = value < 99.95f; + if (value > MAX_DISPLAY_DISTANCE_NUMBER) { + value = MAX_DISPLAY_DISTANCE_NUMBER; + extra = "+k"; + } + } + } + + /** + * 原来代码format字符串会比较耗CPU时间 + * String format = hasDecimals ? "%.1f%s%s" : "%.0f%s%s"; + * return String.format(Locale.getDefault(), format, value, extra, unit); + */ + if (hasDecimals) { + return "" + (float) Math.round(value * 10) / 10 + extra + unit; + } else { + return "" + Math.round(value) + extra + unit; + } + } + + private static final int INDICATOR_ALIGN_LEFT = 0; + private static final int INDICATOR_ALIGN_RIGHT = 1; + private static final int INDICATOR_ALIGN_TOP = 2; + private static final int INDICATOR_ALIGN_BOTTOM = 3; + + @IntDef({INDICATOR_ALIGN_LEFT, INDICATOR_ALIGN_RIGHT, INDICATOR_ALIGN_TOP, INDICATOR_ALIGN_BOTTOM}) + @interface IndicatorAlign { + } + + /** + * HSI 绘制元素的指示信息 + */ + private static class IndicatorInfo { + /** + * 文字颜色,航点和 Pin 点 + */ + int textColor; + /** + * 文字大小 + */ + int textSize; + /** + * 距离和朝向信息 + */ + BearingDistance distance; + /** + * HSI 中图标大小 + */ + int markSize; + + /** + * HSI 中图标绘制时画布偏移量,相对中心 + */ + PointF markerOffset = new PointF(); + + /** + * HSI 边上文字偏移量,罗盘角 + */ + Point textOffset = new Point(); + + /** + * 元素图标 + */ + Bitmap marker; + + /** + * 罗盘周边使用图标,为空默认使用元素图标 + */ + Bitmap cornerMarker; + + /** + * 紧挨罗盘周边图标,航点相对位置指示 + */ + Bitmap cornerMarkerSecondary; + + /** + * 图标旋转角度 + */ + float markerRotate; + + /** + * 显示在 HSI 里面 + */ + boolean showInHsi = true; + /** + * 显示在 HSI 边上 + */ + boolean showOnCorner = true; + + /** + * 角落绘制的水平朝向 + */ + @IndicatorAlign + int horizontalAlign; + /** + * 角落绘制的垂直朝向 + */ + @IndicatorAlign + int verticalAlign; + + private IndicatorInfo() { + this(false); + } + + private IndicatorInfo(boolean drawNameBg) { + this.distance = new BearingDistance(); + distance.mDrawBg = drawNameBg; + } + } + + private static class BearingDistance { + private static final float INVALID_DISTANCE = -1; + + /** + * 距离 + */ + private float mDistance = INVALID_DISTANCE; + /** + * 朝向 + */ + private float mInitialBearing = 0.0f; + + /** + * 纬度 + * 经纬度信息在计算 Home 点和遥控距离时需要使用 + */ + private double mLatitude; + /** + * 经度 + */ + private double mLongitude; + + /** + * 名称背景 + */ + private boolean mDrawBg = false; + + /** + * 名称 + */ + private String mName; + + boolean isValidate() { + return mDistance >= 0 && !Float.isNaN(mDistance); + } + + void setInvalid() { + mDistance = INVALID_DISTANCE; + } + } + + + + /** + * 实测发现飞机刚获取GPS信号时坐标值有可能在 1E-8 ~ 1E-7 之间 + */ + public boolean isAvailable(double latitude, double longitude) { + return Math.abs(latitude) > 1.0E-7D + && Math.abs(longitude) > 1.0E-7D + && Math.abs(latitude) <= 90.0D + && Math.abs(longitude) <= 180.0D; + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/HSIPerceptionLayer.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/HSIPerceptionLayer.java new file mode 100644 index 00000000..a915fef4 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/HSIPerceptionLayer.java @@ -0,0 +1,888 @@ +package dji.v5.ux.core.ui.hsi; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.RectF; +import android.graphics.Shader; +import android.graphics.drawable.GradientDrawable; +import android.util.AttributeSet; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.graphics.ColorUtils; + +import dji.sdk.keyvalue.value.flightcontroller.FCFlightMode; +import dji.sdk.keyvalue.value.product.ProductType; +import dji.v5.manager.aircraft.perception.data.ObstacleAvoidanceType; +import dji.v5.manager.aircraft.perception.data.PerceptionInfo; +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.ui.hsi.config.IOmniAbility; +import dji.v5.ux.core.ui.hsi.dashboard.FpvStrokeConfig; +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.disposables.CompositeDisposable; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.functions.Consumer; +import io.reactivex.rxjava3.schedulers.Schedulers; + +public class HSIPerceptionLayer implements HSIContract.HSILayer { + + private static final String TAG = HSIPerceptionLayer.class.getSimpleName(); + + private static final String PERCEPTION_DISABLED = "NA"; + + private static final String PERCEPTION_TOF_ONLY = "TOF"; + private static final String PERCEPTION_USER_DISABLE = "OFF"; + + /** + * 雷达路径操作超时 + */ + private static final int RADAR_PATH_OP_TIMEOUT = 500; + + private static final int DEFAULT_PERCEPTION_BLIND_AREA_COUNT = 4; + + private static final int DEFAULT_PERCEPTION_AREA_COUNT = 4; + + private static final int DEFAULT_RADAR_START_ANGLE_OFFSET = -15; + + public static final int WARN_COLOR_ALPHA_CENTER = 0x14; + public static final int WARN_COLOR_ALPHA_OUTER = 0x40; + + /** + * 分多少个区块 + */ + private static final int PERCEPTION_GROUP_SIZE = 5; + + @NonNull + private final Path mPath = new Path(); + + @NonNull + private final RectF mRect = new RectF(); + + private final int[] mPerceptionLevelColor = new int[3]; + + private final int[] mRadarLevelColor = new int[3]; + private final FpvStrokeConfig mStrokeConfig; + + private List mRadarHorizontalDistances = new ArrayList<>(); + + + @NonNull + private final GradientDrawable mPerceptionAreaDrawable; + @NonNull + private final GradientDrawable mTofDrawable; + private final GradientDrawable mNaDrawable; + + + private final int mPerceptionDisabledTextSize; + + private final int mMaxPerceptionStrokeWidth; + private final int mRadarMaxPerceptionStrokeWidth; + + + private HSIContract.HSIContainer mHSIContainer; + + private float mHorizontalBarrierAvoidanceDistance; + + private float mHorizontalPerceptionDistance; + + private int mCompassSize; + + private boolean mShowVisualPerceptionInfo; + + private boolean mShowRadarPerceptionInfo; + + private boolean mPerceptionNotWorkMode = false; + + private boolean isHidePerceptionBg = false; + + private FCFlightMode mFlightMode = FCFlightMode.UNKNOWN; + + private boolean mIsMultiModeOpen = false; + + @NonNull + private final List mShapeList = new ArrayList<>(); + + @NonNull + private final List mRadarShapeList = new ArrayList<>(); + + @Nullable + private CompositeDisposable mDisposable; + + IOmniAbility mOmniAbility; + + /** + * 前、右、后、左四个方向的视觉感知是否正常工作 + */ + @NonNull + private final boolean[] mVisionPerceptionEnableState = new boolean[4]; + + /** + * 前、右、后、左四个方向的ToF感知是否正常工作,目前认定ToF几乎不可能不工作,所以默认为True + */ + @NonNull + private final boolean[] mToFPerceptionEnableState = new boolean[]{true, true, true, true}; + + /** + * 机型不支持 TOF,如:M3E系列 + */ + private boolean mSupportTof = true; + private final static PathPool mPathPool = new PathPool(128); + private final static PathPool mRadarPathPool = new PathPool(128); + private Shader mTofShader; + private Shader mNaShader; + private final int mWarnColor; + private final int mDangerColor; + @NonNull + private HSIWidgetModel widgetModel; + + + public HSIPerceptionLayer(@NonNull Context context, @Nullable AttributeSet attrs, HSIContract.HSIContainer container, + HSIWidgetModel widgetModel) { + mHSIContainer = container; + this.widgetModel = widgetModel; + + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AttitudeDashBoard); + mPerceptionLevelColor[2] = typedArray.getColor(R.styleable.HSIView_uxsdk_hsi_avoidance_setting_area_color, + context.getResources().getColor(R.color.uxsdk_pfd_hsi_barrier_color)); + mPerceptionLevelColor[1] = typedArray.getColor(R.styleable.HSIView_uxsdk_hsi_perception_setting_area_color, + context.getResources().getColor(R.color.uxsdk_pfd_hsi_avoidance_color)); + mPerceptionLevelColor[0] = typedArray.getColor(R.styleable.HSIView_uxsdk_hsi_max_perception_area_color, + context.getResources().getColor(R.color.uxsdk_pfd_hsi_main_color)); + mMaxPerceptionStrokeWidth = typedArray.getDimensionPixelSize(R.styleable.HSIView_uxsdk_hsi_max_perception_stroke_width, + context.getResources().getDimensionPixelSize(R.dimen.uxsdk_2_dp)); + + mRadarLevelColor[2] = typedArray.getColor(R.styleable.HSIView_uxsdk_hsi_radar_avoidance_setting_area_color, + context.getResources().getColor(R.color.uxsdk_pfd_hsi_radar_barrier_color)); + mRadarLevelColor[1] = typedArray.getColor(R.styleable.HSIView_uxsdk_hsi_radar_perception_setting_area_color, + context.getResources().getColor(R.color.uxsdk_pfd_hsi_radar_avoidance_color)); + mRadarLevelColor[0] = typedArray.getColor(R.styleable.HSIView_uxsdk_hsi_radar_max_perception_area_color, + context.getResources().getColor(R.color.uxsdk_pfd_hsi_radar_main_color)); + mRadarMaxPerceptionStrokeWidth = typedArray.getDimensionPixelSize(R.styleable.HSIView_uxsdk_hsi_radar_max_perception_stroke_width, + context.getResources().getDimensionPixelSize(R.dimen.uxsdk_4_dp)); + typedArray.recycle(); + + mPerceptionDisabledTextSize = context.getResources().getDimensionPixelSize(R.dimen.uxsdk_6_dp); + + mPerceptionAreaDrawable = new GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, + new int[]{ + Color.parseColor("#29FFFFFF"), + Color.parseColor("#0CFFFFFF") + }); + mPerceptionAreaDrawable.setGradientType(GradientDrawable.LINEAR_GRADIENT); + mPerceptionAreaDrawable.setShape(GradientDrawable.RECTANGLE); + + mWarnColor = context.getResources().getColor(R.color.uxsdk_pfd_avoidance_color); + mDangerColor = context.getResources().getColor(R.color.uxsdk_pfd_barrier_color); + mTofDrawable = new GradientDrawable( + GradientDrawable.Orientation.BOTTOM_TOP, + new int[]{ + ColorUtils.setAlphaComponent(mWarnColor, WARN_COLOR_ALPHA_OUTER), + ColorUtils.setAlphaComponent(mWarnColor, WARN_COLOR_ALPHA_CENTER) + } + ); + mTofDrawable.setGradientType(GradientDrawable.LINEAR_GRADIENT); + mTofDrawable.setShape(GradientDrawable.RECTANGLE); + + mNaDrawable = new GradientDrawable( + GradientDrawable.Orientation.BOTTOM_TOP, + new int[]{ + ColorUtils.setAlphaComponent(mDangerColor, WARN_COLOR_ALPHA_OUTER), + ColorUtils.setAlphaComponent(mDangerColor, WARN_COLOR_ALPHA_CENTER) + } + ); + mNaDrawable.setGradientType(GradientDrawable.LINEAR_GRADIENT); + mNaDrawable.setShape(GradientDrawable.RECTANGLE); + + mStrokeConfig = new FpvStrokeConfig(context); + + mOmniAbility = IOmniAbility.Companion.getCurrent(); + + } + + @Override + public void onStart() { + mDisposable = new CompositeDisposable(); + + mDisposable.add(widgetModel.getProductTypeDataProcessor().toFlowable() + .subscribe(productType -> { + boolean isSupportTof = productType == ProductType.DJI_MAVIC_3_ENTERPRISE_SERIES || productType == ProductType.DJI_MINI_3 || productType == ProductType.DJI_MINI_3_PRO; + isHidePerceptionBg = isSupportTof; + mSupportTof = !isSupportTof; + })); + + mDisposable.add(widgetModel.getPerceptionInformationDataProcessor().toFlowable().subscribe(new Consumer() { + @Override + public void accept(PerceptionInfo perceptionInfo) throws Throwable { + mShowVisualPerceptionInfo = + perceptionInfo.isHorizontalObstacleAvoidanceEnabled() || perceptionInfo.getObstacleAvoidanceType() == ObstacleAvoidanceType.BYPASS; + mHorizontalBarrierAvoidanceDistance = (float) perceptionInfo.getHorizontalObstacleAvoidanceBrakingDistance(); + mHorizontalPerceptionDistance = (float) perceptionInfo.getHorizontalObstacleAvoidanceWarningDistance(); + + mVisionPerceptionEnableState[0] = perceptionInfo.getForwardObstacleAvoidanceWorking() == Boolean.TRUE; + mVisionPerceptionEnableState[1] = perceptionInfo.getRightSideObstacleAvoidanceWorking() == Boolean.TRUE; + mVisionPerceptionEnableState[2] = perceptionInfo.getBackwardObstacleAvoidanceWorking() == Boolean.TRUE; + mVisionPerceptionEnableState[3] = perceptionInfo.getLeftSideObstacleAvoidanceWorking() == Boolean.TRUE; + } + })); + + mDisposable.add(widgetModel.getRadarInformationDataProcessor().toFlowable().subscribe(information -> { + mShowRadarPerceptionInfo = information.isHorizontalObstacleAvoidanceEnabled(); + })); + mDisposable.add(widgetModel.getPerceptionObstacleDataProcessor().toFlowable() + .throttleLast(200, TimeUnit.MILLISECONDS) + .subscribeOn(AndroidSchedulers.mainThread()) //shape 计算要在mainthread,不然有可能会导致native内存使用错误 + .observeOn(AndroidSchedulers.mainThread()) + .map(data -> updatePerceptionDrawShape(getOptimizationDataIfNeed(data.getHorizontalObstacleDistance()))) + .subscribe(list -> { + mShapeList.clear(); + mShapeList.addAll(list); + if (mHSIContainer != null) { + mHSIContainer.updateWidget(); + } + })); + + mDisposable.add(widgetModel.getRadarObstacleDataProcessor().toFlowable().subscribe(data -> mRadarHorizontalDistances = + data.getHorizontalObstacleDistance())); + + + mDisposable.add(Flowable.combineLatest( + widgetModel.getFlightModeProcessor().toFlowable(), + widgetModel.getMultipleFlightModeEnabledProcessor().toFlowable(), + (fcFlightMode, isMultiModeOpen) -> { + mFlightMode = fcFlightMode; + mIsMultiModeOpen = isMultiModeOpen; + mPerceptionNotWorkMode = mIsMultiModeOpen && (mFlightMode == FCFlightMode.GPS_SPORT || mFlightMode == FCFlightMode.ATTI); + Arrays.fill(mToFPerceptionEnableState, !mPerceptionNotWorkMode); + return true; + }).subscribe() + ); + + mDisposable.add(getRadarDisposable()); + } + + + /** + * 针对数据进行分组,每组使用其中最小值 + * 数据分组可避免显示非常细的障碍图 + */ + @NonNull + private List getOptimizationDataIfNeed(List data) { + int size = data.size(); + if (size == 0) { + return data; + } + int sectorLength = PERCEPTION_GROUP_SIZE; + int sectorCount = size / sectorLength; + float singleDataAngle = 360f / size; + for (int i = 0; i < sectorCount; i++) { + int srcPos = sectorLength * i; + if (posInBlind(srcPos, sectorLength, singleDataAngle)) { + continue; + } + int result = minInList(data, srcPos, sectorLength); + fillList(data, srcPos, sectorLength, result); + } + return data; + } + + /** + * 判断数据起止位置是否落在盲区 + */ + private boolean posInBlind(int srcPos, int sectorLength, float singleDataAngle) { + float startAngle = srcPos * singleDataAngle; + float sweepAngle = sectorLength * singleDataAngle; + return posInBlind(startAngle) || posInBlind(startAngle + sweepAngle); + } + + /** + * 数据是否落在盲区 + */ + private boolean posInBlind(float angle) { + return Math.abs(angle % 90 - 45) < mOmniAbility.getPerceptionBlindAreaAngle() / 2f; + } + + /** + * @param data 数据集 + * @param offset 数据开始的索引 + * @param size 需要计算的数据量 + * @return + * @throws IndexOutOfBoundsException offset 必须小于 date 大小 + */ + private int minInList(List data, int offset, int size) { + if (offset >= data.size() || offset < 0) { + throw new IndexOutOfBoundsException(); + } + int last = Math.min(offset + size, data.size()); + int result = data.get(last - 1); + for (int i = last - 2; i >= offset; i--) { + result = Math.min(result, data.get(i)); + } + return result; + } + + /** + * @param data 数据集 + * @param offset 数据开始的索引 + * @param size 需要填充的大小 + * @return + * @throws IndexOutOfBoundsException offset 必须小于 date 大小 + */ + private void fillList(List data, int offset, int size, int value) { + if (offset >= data.size() || offset < 0) { + throw new IndexOutOfBoundsException(); + } + int last = Math.min(offset + size, data.size()); + for (int i = last - 1; i >= offset; i--) { + data.set(i, value); + } + } + + @Override + public void onStop() { + if (mDisposable != null) { + mDisposable.dispose(); + } + + mHSIContainer = null; + } + + private Disposable getRadarDisposable() { + return Observable.interval(HSIView.INVALIDATE_INTERVAL_TIME, TimeUnit.MILLISECONDS) + .map(aLong -> mRadarHorizontalDistances) + .observeOn(Schedulers.newThread()) + .map(this::updateRadarDrawShape) + .timeout(RADAR_PATH_OP_TIMEOUT, TimeUnit.MILLISECONDS) + .retry() + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(list -> { + synchronized (mRadarShapeList) { + mRadarShapeList.clear(); + mRadarShapeList.addAll(list); + } + if (mHSIContainer != null) { + mHSIContainer.updateWidget(); + } + }); + } + + @Override + public void draw(Canvas canvas, Paint paint, int compassSize) { + mCompassSize = compassSize; + canvas.save(); + canvas.translate(0, (float) compassSize / 2); + drawRadarBarrier(canvas, paint, compassSize); + drawBarrier(canvas, paint, compassSize); + drawPerception(canvas, paint, compassSize); + canvas.restore(); + } + + boolean isUserDisable() { + return !mShowVisualPerceptionInfo && !mShowRadarPerceptionInfo; + } + + /** + * 绘制 HSI 中障碍检测范围背景 + * + * @param compassSize 罗盘半径 + */ + private void drawPerception(Canvas canvas, Paint paint, int compassSize) { + if (mHSIContainer == null) { + return; + } + fixAlpha(paint); + canvas.save(); + + int perceptionAngleTotal = 360 - DEFAULT_PERCEPTION_BLIND_AREA_COUNT * mOmniAbility.getPerceptionBlindAreaAngle(); + int perceptionAngleEach = perceptionAngleTotal / DEFAULT_PERCEPTION_AREA_COUNT; + + paint.setStyle(Paint.Style.FILL); + float radius = (float) compassSize / 2 - mHSIContainer.getCalibrationAreaWidth() - mHSIContainer.getCompassBitmapOffset(); + mRect.set(-radius, -radius, radius, radius); + + mPerceptionAreaDrawable.setSize((int) radius * 2, (int) radius * 2); + float offsetX = (float) (Math.sin(Math.PI * perceptionAngleEach / 2 / 180) * radius); + float offsetY = (float) (Math.cos(Math.PI * perceptionAngleEach / 2 / 180) * radius); + mPath.reset(); + mPath.lineTo(offsetX, -offsetY); + offsetX = (float) (Math.sin(Math.PI * (360 - (float) perceptionAngleEach / 2) / 180) * radius); + offsetY = (float) (Math.cos(Math.PI * (360 - (float) perceptionAngleEach / 2) / 180) * radius); + mPath.lineTo(offsetX, -offsetY); + mPath.close(); + mPath.addArc(mRect, 270 - (float) perceptionAngleEach / 2, perceptionAngleEach); + // 按照前、右、后、左的顺序绘制 + for (int i = 0; i < DEFAULT_PERCEPTION_AREA_COUNT; i++) { + canvas.save(); + boolean visionEnable = mVisionPerceptionEnableState[i]; + if (!isHidePerceptionBg) { + drawPerceptionBg(canvas, paint, i, visionEnable, radius, perceptionAngleEach); + } + if (isUserDisable() || mPerceptionNotWorkMode || (!visionEnable && mShowVisualPerceptionInfo)) { + boolean isTof = mToFPerceptionEnableState[i]; + // 绘制文字 + paint.setTextSize(mPerceptionDisabledTextSize); + paint.setTextAlign(Paint.Align.CENTER); + String text = getPerceptionStatusText(isTof); + paint.getTextBounds(text, 0, text.length(), HSIView.RECT); + Paint.FontMetrics fontMetrics = paint.getFontMetrics(); + float baselineOffsetY = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom; + canvas.save(); + canvas.translate(0, -(radius + mHSIContainer.getAircraftSize()) / 2); + canvas.rotate(-90f * i); + int textColor = getPerceptionTextColor(isTof); + drawTextWithStroke(canvas, text, baselineOffsetY, mStrokeConfig.getStrokeBoldWidth(), mStrokeConfig.getStrokeDeepColor(), textColor + , paint); + canvas.restore(); + } + canvas.restore(); + canvas.rotate(perceptionAngleEach + mOmniAbility.getPerceptionBlindAreaAngle() * 1f); + } + + canvas.restore(); + } + + private void drawPerceptionBg(Canvas canvas, Paint paint, int index, boolean visionEnable, float radius, int perceptionAngleEach) { + if (isUserDisable() || (!mPerceptionNotWorkMode && (visionEnable || !mShowVisualPerceptionInfo))) { + canvas.clipPath(mPath); + mPerceptionAreaDrawable.setBounds((int) -radius, (int) -radius, (int) radius, 0); + mPerceptionAreaDrawable.draw(canvas); + } else { + // 用户关闭开关 + boolean isTof = mToFPerceptionEnableState[index]; + paint.setStyle(Paint.Style.FILL); + paint.setShader(getPerceptionDisabledShader(radius, isTof)); + canvas.drawArc(mRect, 270 - (float) perceptionAngleEach / 2, perceptionAngleEach, true, paint); + paint.setStyle(Paint.Style.FILL); + paint.setShader(null); + } + } + + /** + * 画笔设置透明度颜色之后,画笔透明度需要修复 + */ + private void fixAlpha(Paint paint) { + paint.setAlpha(255); + } + + private int getPerceptionTextColor(boolean isTof) { + if (!isUserDisable() && isTof && mSupportTof) { + return mWarnColor; + } else { + return mDangerColor; + } + } + + @NonNull + private String getPerceptionStatusText(boolean isTof) { + if (isUserDisable()) { + return PERCEPTION_USER_DISABLE; + } else if (isTof && mSupportTof) { + return PERCEPTION_TOF_ONLY; + } else { + return PERCEPTION_DISABLED; + } + } + + protected void drawTextWithStroke(Canvas canvas, String text, float baseline, float strokeWidth, int strokeColor, int textColor, Paint paint) { + paint.setStrokeWidth(strokeWidth); + paint.setColor(strokeColor); + paint.setStyle(Paint.Style.STROKE); + canvas.drawText(text, 0, baseline, paint); + + paint.setColor(textColor); + paint.setStyle(Paint.Style.FILL); + canvas.drawText(text, 0, baseline, paint); + } + + public Shader getPerceptionDisabledShader(float radius, boolean isTof) { + Shader result; + if (isTof && mSupportTof) { + if (mTofShader == null) { + mTofShader = createLinearShader(radius, mWarnColor); + } + result = mTofShader; + } else { + if (mNaShader == null) { + mNaShader = createLinearShader(radius, mDangerColor); + } + result = mNaShader; + } + return result; + } + + @NonNull + private LinearGradient createLinearShader(float radius, int warnColor) { + int centerColor = ColorUtils.setAlphaComponent(warnColor, WARN_COLOR_ALPHA_CENTER); + int outerColor = ColorUtils.setAlphaComponent(warnColor, WARN_COLOR_ALPHA_OUTER); + return new LinearGradient(0, 0, 0, -radius, centerColor, outerColor, Shader.TileMode.CLAMP); + } + + private void drawBarrier(Canvas canvas, Paint paint, int compassSize) { + if (mHSIContainer == null) { + return; + } + + if (mShapeList.isEmpty()) { + return; + } + + float calibrationAreaWidth = mHSIContainer.getCalibrationAreaWidth(); + float radius = (float) compassSize / 2 - calibrationAreaWidth - mHSIContainer.getCompassBitmapOffset(); + // 这里把盲区也考虑上,从盲区中间算起,算起来比较简单 + int perceptionAngleEach = 360 / DEFAULT_PERCEPTION_AREA_COUNT; + + for (Shape shape : mShapeList) { + canvas.save(); + // 判断该方向的感知系统是否正常工作 + int fromAngle = shape.mFromAngle; + boolean skip = mPerceptionNotWorkMode; + if (!skip) { + skip = calcSkip(perceptionAngleEach, fromAngle); + } + if (!skip) { + if (shape instanceof PathShape) { + canvas.rotate(shape.mFromAngle); + paint.setStyle(Paint.Style.FILL); + paint.setColor(shape.mColor); + canvas.drawPath(((PathShape) shape).mPath, paint); + mPathPool.recycle(((PathShape) shape).mPath); + } else if (shape instanceof ArcShape) { + canvas.rotate(shape.mFromAngle); + paint.setColor(shape.mColor); + paint.setStyle(Paint.Style.STROKE); + float lastStrokeWidth = paint.getStrokeWidth(); + paint.setStrokeWidth(mMaxPerceptionStrokeWidth); + float arcRadius = radius - (float) mMaxPerceptionStrokeWidth / 2; + canvas.drawArc(-arcRadius, -arcRadius, arcRadius, arcRadius, 270f, + ((ArcShape) shape).mToAngle * 1f - shape.mFromAngle * 1f, false, paint); + paint.setStrokeWidth(lastStrokeWidth); + } + } + canvas.restore(); + } + } + + private boolean calcSkip(int perceptionAngleEach, int fromAngle) { + boolean skip = false; + if (fromAngle > perceptionAngleEach * 7 / 2 || fromAngle < perceptionAngleEach / 2) { + skip = !mVisionPerceptionEnableState[0] && !mToFPerceptionEnableState[0]; + } else if (fromAngle > perceptionAngleEach / 2 && fromAngle < perceptionAngleEach * 3 / 2) { + skip = !mVisionPerceptionEnableState[1] && !mToFPerceptionEnableState[1]; + } else if (fromAngle > perceptionAngleEach * 3 / 2 && fromAngle < perceptionAngleEach * 5 / 2) { + skip = !mVisionPerceptionEnableState[2] && !mToFPerceptionEnableState[2]; + } else if (fromAngle > perceptionAngleEach * 5 / 2 && fromAngle < perceptionAngleEach * 7 / 2) { + skip = !mVisionPerceptionEnableState[3] && !mToFPerceptionEnableState[3]; + } + return skip; + } + + private void drawRadarBarrier(Canvas canvas, Paint paint, int compassSize) { + if (mHSIContainer == null) { + return; + } + + if (mRadarShapeList.isEmpty()) { + return; + } + + float calibrationAreaWidth = mHSIContainer.getCalibrationAreaWidth(); + float radius = (float) compassSize / 2 - calibrationAreaWidth - mHSIContainer.getCompassBitmapOffset(); + + synchronized (mRadarShapeList) { + for (Shape shape : mRadarShapeList) { + canvas.save(); + if (shape instanceof PathShape) { + canvas.rotate(shape.mFromAngle + DEFAULT_RADAR_START_ANGLE_OFFSET * 1f); + paint.setStyle(Paint.Style.FILL); + paint.setColor(shape.mColor); + canvas.drawPath(((PathShape) shape).mPath, paint); + mRadarPathPool.recycle(((PathShape) shape).mPath); + } else if (shape instanceof ArcShape) { + canvas.rotate(shape.mFromAngle + DEFAULT_RADAR_START_ANGLE_OFFSET * 1f); + paint.setColor(shape.mColor); + paint.setStyle(Paint.Style.STROKE); + float lastStrokeWidth = paint.getStrokeWidth(); + paint.setStrokeWidth(mRadarMaxPerceptionStrokeWidth); + float arcRadius = radius - (float) mRadarMaxPerceptionStrokeWidth / 2; + canvas.drawArc(-arcRadius, -arcRadius, arcRadius, arcRadius, 270f, + ((ArcShape) shape).mToAngle - shape.mFromAngle * 1f, false, paint); + paint.setStrokeWidth(lastStrokeWidth); + } + canvas.restore(); + } + } + } + + private List updatePerceptionDrawShape(List horizontalBarrierDistance) { + if (horizontalBarrierDistance.size() == 0) { + return new ArrayList<>(); + } + int perceptionAngleTotal = 360 - DEFAULT_PERCEPTION_BLIND_AREA_COUNT * mOmniAbility.getPerceptionBlindAreaAngle(); + int perceptionAngleEach = perceptionAngleTotal / DEFAULT_PERCEPTION_AREA_COUNT; + int rotationOffset = 360 / horizontalBarrierDistance.size(); + int startOffset = -perceptionAngleEach / rotationOffset / 2; + + return updateDrawShape(horizontalBarrierDistance, startOffset, mPerceptionLevelColor); + } + + private List updateRadarDrawShape(List horizontalBarrierDistance) { + if (horizontalBarrierDistance == null || horizontalBarrierDistance.size() == 0) { + return new ArrayList<>(); + } + Thread currentThread = Thread.currentThread(); + LogUtils.d(TAG, + "updateRadarDrawShape " + horizontalBarrierDistance.get(0) + ". Current thread is " + currentThread.getName() + " " + currentThread.getId()); + long preTime = System.currentTimeMillis(); + List result = updateDrawShape2(horizontalBarrierDistance, 0, mRadarLevelColor); + LogUtils.d(TAG, "updateRadarDrawShape take " + (System.currentTimeMillis() - preTime)); + return result; + } + + private List updateDrawShape2(List horizontalBarrierDistance, int startOffset, int[] levelColor) { + + List shapeList = new ArrayList<>(); + if (mHSIContainer == null) { + return shapeList; + } + + + int rotationOffset = 360 / horizontalBarrierDistance.size(); + int offset = mHSIContainer.getAircraftSize() / 2; + int visibleDistanceInHsi = mHSIContainer.getVisibleDistanceInHsiInMeters(); + float calibrationAreaWidth = mHSIContainer.getCalibrationAreaWidth(); + float radius = (float) mCompassSize / 2 - calibrationAreaWidth - mHSIContainer.getCompassBitmapOffset(); + + float minDistanceInMeter = Integer.MAX_VALUE; + + PathShape lastShape = null; + float barrierRotation = 0; + Path path1 = mRadarPathPool.acquire(), path2; + path1.reset(); + + for (int i = 0; i < horizontalBarrierDistance.size(); i++) { + int angle = i + startOffset; + angle = angle < 0 ? angle + horizontalBarrierDistance.size() : angle; + float distanceInMeter = (float) horizontalBarrierDistance.get(angle) / 1000; + if (distanceInMeter >= visibleDistanceInHsi) { + if (distanceInMeter <= mOmniAbility.getHorizontalDetectionCapability()) { + int color; + if (distanceInMeter > mHorizontalPerceptionDistance) { + color = levelColor[0]; + } else { + color = levelColor[1]; + } + ArcShape shape = new ArcShape(angle * rotationOffset); + shape.mColor = color; + shape.mToAngle += rotationOffset; + shapeList.add(shape); + } + } else { + float c = offset + distanceInMeter / visibleDistanceInHsi * (radius - offset); + if (barrierRotation == 0) { + lastShape = new PathShape(angle * rotationOffset); + path1.reset(); + path1.lineTo(0, -c); + } + barrierRotation += rotationOffset; + double sin = Math.sin(Math.PI * barrierRotation / 180); + double cos = Math.cos(Math.PI * barrierRotation / 180); + float offsetX = (float) (sin * c); + float offsetY = (float) (cos * c); + path1.lineTo(offsetX, -offsetY); + if (distanceInMeter < minDistanceInMeter) { + minDistanceInMeter = distanceInMeter; + } + } + if ((distanceInMeter >= visibleDistanceInHsi || i == horizontalBarrierDistance.size() - 1) + && !path1.isEmpty() && lastShape != null) { + path1.close(); + path2 = mRadarPathPool.acquire(); + path2.reset(); + path2.addArc(-radius, -radius, radius, radius, 270, barrierRotation); + path2.lineTo(0, 0); + path2.close(); + LogUtils.d(TAG, "updateRadar2 op 1 size=" + shapeList.size() + " " + minDistanceInMeter); + //todo:必须重构path的布尔操作算法,怀疑是雷达传递数据有问题,导致方法卡死 + path2.op(path1, Path.Op.DIFFERENCE); + LogUtils.d(TAG, "updateRadar2 op 2"); + + int areaColor; + if (minDistanceInMeter > mHorizontalPerceptionDistance) { + areaColor = levelColor[0];// + } else if (minDistanceInMeter > mHorizontalBarrierAvoidanceDistance + 2) { + // feature HYAPP-10551 避障变红由【刹停距离】改为【刹停距离+2m】 + areaColor = levelColor[1]; + } else { + areaColor = levelColor[2]; + } + PathShape pathShape = lastShape; + pathShape.mColor = areaColor; + pathShape.mPath = path2; + barrierRotation = 0; + shapeList.add(pathShape); + path1.reset(); + lastShape = null; + minDistanceInMeter = Integer.MAX_VALUE; + } + } + mRadarPathPool.recycle(path1); + return shapeList; + } + + private List updateDrawShape(List horizontalBarrierDistance, int startOffset, int[] levelColor) { + List shapeList = new ArrayList<>(); + + if (mHSIContainer == null) { + return shapeList; + } + + + int rotationOffset = 360 / horizontalBarrierDistance.size(); + int offset = mHSIContainer.getAircraftSize() / 2; + int visibleDistanceInHsi = mHSIContainer.getVisibleDistanceInHsiInMeters(); + float calibrationAreaWidth = mHSIContainer.getCalibrationAreaWidth(); + float radius = (float) mCompassSize / 2 - calibrationAreaWidth - mHSIContainer.getCompassBitmapOffset(); + + float minDistanceInMeter = Integer.MAX_VALUE; + + Shape lastShape = null; + float barrierRotation = 0; + Path path1 = mPathPool.acquire(), path2; + path1.reset(); + + for (int i = 0; i < horizontalBarrierDistance.size(); i++) { + int angle = i + startOffset; + angle = angle < 0 ? angle + horizontalBarrierDistance.size() : angle; + float distanceInMeter = (float) horizontalBarrierDistance.get(angle) / 1000; + if (distanceInMeter >= visibleDistanceInHsi) { + if (distanceInMeter <= mOmniAbility.getHorizontalDetectionCapability()) { + int color; + if (distanceInMeter > mHorizontalPerceptionDistance) { + color = levelColor[0]; + } else { + color = levelColor[1]; + } + ArcShape shape = new ArcShape(angle * rotationOffset); + shape.mColor = color; + shape.mToAngle += rotationOffset; + shapeList.add(shape); + } + } else { + float c = offset + distanceInMeter / visibleDistanceInHsi * (radius - offset); + if (barrierRotation == 0) { + lastShape = new PathShape(angle * rotationOffset); + path1.reset(); + path1.lineTo(0, -c); + } + barrierRotation += rotationOffset; + double sin = Math.sin(Math.PI * barrierRotation / 180); + double cos = Math.cos(Math.PI * barrierRotation / 180); + float offsetX = (float) (sin * c); + float offsetY = (float) (cos * c); + path1.lineTo(offsetX, -offsetY); + if (distanceInMeter < minDistanceInMeter) { + minDistanceInMeter = distanceInMeter; + } + } + if ((distanceInMeter >= visibleDistanceInHsi || i == horizontalBarrierDistance.size() - 1) + && !path1.isEmpty() && lastShape instanceof PathShape) { + path1.close(); + path2 = mPathPool.acquire(); + path2.reset(); + path2.addArc(-radius, -radius, radius, radius, 270, barrierRotation); + path2.lineTo(0, 0); + path2.close(); + // LogUtils.d(TAG, "updateRadar op 1 size=" + shapeList.size() + " " + minDistanceInMeter); + // sendRadarMsg(); + path2.op(path1, Path.Op.DIFFERENCE); + // LogUtils.d(TAG, "updateRadar op 2"); + // removeRadarMsg(); + int areaColor; + if (minDistanceInMeter > mHorizontalPerceptionDistance) { + areaColor = levelColor[0];// + } else if (minDistanceInMeter > mHorizontalBarrierAvoidanceDistance + 2) { + // feature HYAPP-10551 避障变红由【刹停距离】改为【刹停距离+2m】 + areaColor = levelColor[1]; + } else { + areaColor = levelColor[2]; + } + PathShape pathShape = (PathShape) lastShape; + pathShape.mColor = areaColor; + pathShape.mPath = path2; + barrierRotation = 0; + shapeList.add(pathShape); + path1.reset(); + lastShape = null; + minDistanceInMeter = Integer.MAX_VALUE; + } + } + mPathPool.recycle(path1); + return shapeList; + } + + private static class Shape { + int mFromAngle; + int mColor; + + public Shape(int fromAngle) { + mFromAngle = fromAngle; + } + } + + private static class PathShape extends Shape { + Path mPath; + + public PathShape(int fromAngle) { + super(fromAngle); + } + + @Override + public String toString() { + return "PathShape{" + + "mFromAngle=" + mFromAngle + + '}'; + } + } + + private static class ArcShape extends Shape { + int mToAngle; + + public ArcShape(int fromAngle) { + super(fromAngle); + mToAngle = fromAngle; + } + + @Override + public String toString() { + return "ArcShape{" + + "mFromAngle=" + mFromAngle + + ", mToAngle=" + mToAngle + + '}'; + } + } + + private static class PathPool extends RecyclerPool { + + public PathPool(int maxPoolSize) { + super(maxPoolSize); + } + + @NonNull + @Override + protected Path create() { + return new Path(); + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/HSIView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/HSIView.java new file mode 100644 index 00000000..9f1f94a5 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/HSIView.java @@ -0,0 +1,733 @@ +package dji.v5.ux.core.ui.hsi; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Rect; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.GradientDrawable; +import android.os.Handler; +import android.os.Looper; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewDebug; + +import java.lang.ref.WeakReference; +import java.util.Locale; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import dji.sdk.keyvalue.value.product.ProductType; +import dji.v5.manager.aircraft.perception.data.ObstacleAvoidanceType; +import dji.v5.manager.aircraft.perception.data.PerceptionInfo; +import dji.v5.utils.common.DisplayUtil; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.ui.hsi.dashboard.FpvStrokeConfig; +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.core.util.DrawUtils; +import dji.v5.ux.core.util.MatrixUtils; +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.core.ObservableEmitter; +import io.reactivex.rxjava3.core.ObservableOnSubscribe; +import io.reactivex.rxjava3.disposables.CompositeDisposable; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.functions.Consumer; +import io.reactivex.rxjava3.schedulers.Schedulers; + +public class HSIView extends View implements HSIContract.HSIContainer { + + public static final Rect RECT = new Rect(); + + public static final Rect RECT2 = new Rect(); + + public static final Path mPath = new Path(); + + /** + * HSI 固定可视化半径为16m + */ + public static final int HSI_VISIBLE_DISTANCE_IN_METERS = 16; + + /** + * 最大云台数量 + */ + private static final int MAX_GIMBAL_COUNT = 3; + + /** + * 性能原因,绘制间隔调整为:100ms + */ + public static final int INVALIDATE_INTERVAL_TIME = 200; + private static final int MSG_INVALIDATE = 0x01; + public static final String VIEW_DEBUG_CATEGORY_DJI = "dji"; + public static final String VIEW_DEBUG_PREFIX_MARKER = "hsi_marker_"; + public static final String VIEW_DEBUG_PREFIX_PERCEPTION = "hsi_perception_"; + + private final static String APAS_TEXT = "APAS"; + + @NonNull + private final Handler.Callback mCallback = msg -> { + if (msg.what == MSG_INVALIDATE) { + // invalidate(); + postInvalidate(); + return true; + } + return false; + }; + + @Nullable + private Handler mHandler; + + /** + * 当前飞机罗盘的角度 + */ + @ViewDebug.ExportedProperty(category = "hsi") + private float mCurrentDegree; + private String mCurrentDegreeText; + + private boolean[] mGimbalConnected = new boolean[3]; + private float[] mGimbalCurrentDegree = new float[3]; + + private boolean mIsRadarConnected; + + private boolean mIsRadarAvailable; + + private boolean isHideGimbalDrawable = false; + + private float mAircraftHeadingOffsetDistanceX; + + private float mAircraftHeadingOffsetDistanceY; + + /** + * 云台指示器圆环最大宽度,内部为避障区域 + */ + @ViewDebug.ExportedProperty(category = "hsi") + private final int mGimbalIndicatorMaxScope; + @ViewDebug.ExportedProperty(category = "hsi") + private final int mAircraftIndicatorSize; + @ViewDebug.ExportedProperty(category = "hsi") + private final int mDegreeIndicatorTextSize; + @ViewDebug.ExportedProperty(category = "hsi") + private final int mDegreeIndicatorTextHeight; + @ViewDebug.ExportedProperty(category = "hsi") + private final int mCompassMargin; + + /** + * 角度指示 + */ + @ViewDebug.ExportedProperty(category = "hsi") + private final int mDegreeIndicatorHeight; + @ViewDebug.ExportedProperty(category = "hsi") + private final float mDegreeIndicatorHeightInCompass; + @ViewDebug.ExportedProperty(category = "hsi") + private final float mDegreeIndicatorWidth; + @ViewDebug.ExportedProperty(category = "hsi", formatToHexString = true) + private final int mDegreeIndicatorColor; + @ViewDebug.ExportedProperty(category = "hsi") + private final int mHeadingLineWidth; + + + @ViewDebug.ExportedProperty(category = "hsi") + private float mYaw; + @ViewDebug.ExportedProperty(category = "hsi", formatToHexString = true) + private float mRoll; + @ViewDebug.ExportedProperty(category = "hsi", formatToHexString = true) + private float mPitch; + + @ViewDebug.ExportedProperty(category = "hsi", formatToHexString = true) + private float mSpeedX; + @ViewDebug.ExportedProperty(category = "hsi", formatToHexString = true) + private float mSpeedY; + @ViewDebug.ExportedProperty(category = "hsi", formatToHexString = true) + private float mSpeedZ; + + /** + * 罗盘的image边上有空隙,在计算的时候需要考虑到 + */ + private final int mBitmapOffset; + + @NonNull + private final Paint mPaint; + + @Nullable + private final Bitmap mCompassBitmap; + + @NonNull + private final Bitmap mAircraftBitmap; + + @NonNull + private final Bitmap mRadarAvailableBitmap; + + @NonNull + private final Bitmap mRadarUnavailableBitmap; + + @NonNull + private final GradientDrawable mAircraftHeadingLineDrawable; + + @NonNull + @ViewDebug.ExportedProperty(category = VIEW_DEBUG_CATEGORY_DJI, prefix = VIEW_DEBUG_PREFIX_MARKER, deepExport = true) + private final HSIContract.HSILayer mMarkerLayer; + + @NonNull + @ViewDebug.ExportedProperty(category = VIEW_DEBUG_CATEGORY_DJI, prefix = VIEW_DEBUG_PREFIX_PERCEPTION, deepExport = true) + private final HSIContract.HSILayer mPerceptionLayer; + + FpvStrokeConfig mStrokeConfig; + + private boolean isApasMode = false; + private float mApasTextLength = 0; + private float mApasTextHeight = 0; + private float mApasTextSize = AndUtil.getDimension(R.dimen.uxsdk_6_dp); + private float mApasTextStrokeWith = AndUtil.getDimension(R.dimen.uxsdk_1_dp); + private int mApasTextColor = AndUtil.getResColor(R.color.uxsdk_white); + private int mApasTextStrokeColor = AndUtil.getResColor(R.color.uxsdk_black_60_percent); + + + @Nullable + private Disposable mDisposable; + + private HSIWidgetModel widgetModel; + + + @Nullable + private OnAircraftAttitudeChangeListener mListener; + + + + private CompositeDisposable mCompositeDisposable = new CompositeDisposable(); + + + public HSIView(Context context) { + this(context, null); + } + + public HSIView(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public HSIView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + if (!isInEditMode()) { + widgetModel = new HSIWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + } + + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.HSIView); + mBitmapOffset = typedArray.getDimensionPixelSize(R.styleable.HSIView_uxsdk_hsi_bitmap_offset, 0); + mAircraftIndicatorSize = typedArray.getDimensionPixelSize(R.styleable.HSIView_uxsdk_hsi_aircraft_indicator_size, + getResources().getDimensionPixelSize(R.dimen.uxsdk_10_dp)); + mGimbalIndicatorMaxScope = typedArray.getDimensionPixelSize(R.styleable.HSIView_uxsdk_hsi_gimbal_indicator_max_scope, + getResources().getDimensionPixelSize(R.dimen.uxsdk_10_dp)); + mDegreeIndicatorHeight = typedArray.getDimensionPixelSize(R.styleable.HSIView_uxsdk_hsi_degree_indicator_width, + getResources().getDimensionPixelSize(R.dimen.uxsdk_5_dp)); + mDegreeIndicatorTextSize = typedArray.getDimensionPixelSize(R.styleable.HSIView_uxsdk_hsi_degree_indicator_text_size, + getResources().getDimensionPixelSize(R.dimen.uxsdk_text_size_normal)); + mDegreeIndicatorTextHeight = typedArray.getDimensionPixelSize(R.styleable.HSIView_uxsdk_hsi_degree_indicator_height, + getResources().getDimensionPixelSize(R.dimen.uxsdk_11_dp)); + mCompassMargin = typedArray.getDimensionPixelSize(R.styleable.HSIView_uxsdk_hsi_compass_margin, + getResources().getDimensionPixelSize(R.dimen.uxsdk_5_dp)); + mDegreeIndicatorColor = typedArray.getColor(R.styleable.HSIView_uxsdk_hsi_degree_indicator_color, + getResources().getColor(R.color.uxsdk_green_in_dark)); + mAircraftHeadingOffsetDistanceX = typedArray.getDimensionPixelSize(R.styleable.HSIView_uxsdk_hsi_aircraft_heading_offset_x, 0); + mAircraftHeadingOffsetDistanceY = typedArray.getDimensionPixelSize(R.styleable.HSIView_uxsdk_hsi_aircraft_heading_offset_y, 0); + mHeadingLineWidth = typedArray.getDimensionPixelSize(R.styleable.HSIView_uxsdk_hsi_heading_line_width, + getResources().getDimensionPixelSize(R.dimen.uxsdk_1_dp)); + typedArray.recycle(); + mDegreeIndicatorHeightInCompass = getResources().getDimension(R.dimen.uxsdk_1_dp); + mDegreeIndicatorWidth = DisplayUtil.dip2px(context, 1.4f); + + mPaint = new Paint(Paint.DITHER_FLAG | Paint.ANTI_ALIAS_FLAG); + mPaint.setStrokeWidth(getResources().getDimensionPixelSize(R.dimen.uxsdk_1_dp)); + Typeface typeface = Typeface.create("sans-serif-condensed", Typeface.BOLD); + mPaint.setTypeface(typeface); + // 屏幕相比视觉稿放大 1.2 倍,使用 3 倍图尺寸最后会导致模糊 + mCompassBitmap = getBitmap(R.drawable.uxsdk_fpv_hsi_compass_list); + mAircraftBitmap = getBitmap(R.drawable.uxsdk_fpv_hsi_aircraft); + mRadarAvailableBitmap = getBitmap(R.drawable.uxsdk_hsi_aircraft_radar_normal); + mRadarUnavailableBitmap = getBitmap(R.drawable.uxsdk_hsi_aircraft_radar_disable); + mAircraftHeadingLineDrawable = new GradientDrawable(GradientDrawable.Orientation.BOTTOM_TOP, + new int[]{ + getResources().getColor(R.color.uxsdk_white_30_percent), + getResources().getColor(R.color.uxsdk_white) + }); + mAircraftHeadingLineDrawable.setGradientType(GradientDrawable.LINEAR_GRADIENT); + mAircraftHeadingLineDrawable.setShape(GradientDrawable.RECTANGLE); + mAircraftHeadingLineDrawable.setCornerRadius(getResources().getDimensionPixelSize(R.dimen.uxsdk_1_dp)); + + mMarkerLayer = new HSIMarkerLayer(context, attrs, this, widgetModel); + mPerceptionLayer = new HSIPerceptionLayer(context, attrs, this, widgetModel); + + mStrokeConfig = new FpvStrokeConfig(getContext()); + initApasParam(); + } + + private void initApasParam() { + mPaint.setTextSize(getContext().getResources().getDimension(R.dimen.uxsdk_6_dp)); + mApasTextLength = mPaint.measureText(APAS_TEXT); + Paint.FontMetrics fontMetrics = mPaint.getFontMetrics(); + mApasTextHeight = fontMetrics.bottom - fontMetrics.top; + } + + private Bitmap getBitmap(int resId) { + if (isInEditMode()) { + return Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888); + } else { + return DrawUtils.drawableRes2Bitmap(resId); + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (isInEditMode()) { + return; + } + widgetModel.setup(); + + mHandler = new Handler(Looper.getMainLooper(), mCallback); + + mMarkerLayer.onStart(); + mPerceptionLayer.onStart(); + + mCompositeDisposable.add(widgetModel.getProductTypeDataProcessor().toFlowable() + .subscribe(productType -> isHideGimbalDrawable = productType == ProductType.DJI_MAVIC_3_ENTERPRISE_SERIES)); + + mCompositeDisposable.add(widgetModel.getRadarInformationDataProcessor().toFlowable().subscribe(info -> { + mIsRadarConnected = info.isConnected(); + mIsRadarAvailable = info.isHorizontalObstacleAvoidanceEnabled(); + updateWidget(); + })); + + mCompositeDisposable.add(widgetModel.getPerceptionInformationDataProcessor().toFlowable().subscribe(new Consumer() { + @Override + public void accept(PerceptionInfo info) throws Throwable { + isApasMode = info.getObstacleAvoidanceType() == ObstacleAvoidanceType.BYPASS; + } + })); + + mDisposable = Observable.create(new ObservableSource(this)) + .observeOn(Schedulers.computation()) + .map(data -> updateSpeedVectorMark(data[0], data[1], data[2], data[3], data[4], data[5])) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(p -> { + mAircraftHeadingOffsetDistanceX = p[0]; + mAircraftHeadingOffsetDistanceY = p[1]; + updateWidget(); + }); + + + mCompositeDisposable.add(widgetModel.getVelocityProcessor().toFlowable().subscribe(velocity3D -> { + mSpeedX = velocity3D.getX().floatValue(); + mSpeedY = velocity3D.getY().floatValue(); + mSpeedZ = velocity3D.getZ().floatValue(); + recalculateAndInvalidate(); + })); + + //获取飞机角度 + mCompositeDisposable.add(widgetModel.getAircraftAttitudeProcessor().toFlowable().subscribe(attitude -> { + mYaw = attitude.getYaw().floatValue(); + mCurrentDegree = mYaw + (mYaw < 0 ? 359f : 0); + mCurrentDegreeText = String.format(Locale.ENGLISH, "%03.0f", mCurrentDegree); + mRoll = attitude.getRoll().floatValue(); + mPitch = attitude.getPitch().floatValue(); + recalculateAndInvalidate(); + })); + + //云台Yaw夹角 + mCompositeDisposable.add(Flowable.fromArray(new Integer[]{0, 1, 2}) + .flatMap(cameraIndex -> Flowable.combineLatest( + //云台连接状态 + widgetModel.getGimbalConnectionProcessorList().get(cameraIndex).toFlowable(), + //云台相对机身的Yaw夹角 + widgetModel.getGimbalYawInDegreesProcessorList().get(cameraIndex).toFlowable(), + ((isConnected, yaw) -> { + mGimbalConnected[cameraIndex] = isConnected; + mGimbalCurrentDegree[cameraIndex] = yaw.floatValue(); + return true; + }) + )) + .subscribeOn(AndroidSchedulers.mainThread()) + .subscribe(aBoolean -> updateWidget())); + + + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mMarkerLayer.onStop(); + mPerceptionLayer.onStop(); + if (mHandler != null) { + mHandler.removeCallbacksAndMessages(null); + mHandler = null; + } + if (mDisposable != null && !mDisposable.isDisposed()) { + mDisposable.dispose(); + } + mCompositeDisposable.dispose(); + widgetModel.cleanup(); + } + + public void enterFpvMode(boolean fpv) { + mMarkerLayer.enterFpvMode(fpv); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + // 画布中心移动到 HSI (0.5, 0) 位置 + canvas.translate(getWidth() / 2f, 0); + + // 计算罗盘尺寸 + int textHeight = mDegreeIndicatorTextHeight; + int compassHeight = getHeight() - textHeight - mCompassMargin * 2; + int compassWidth = getWidth() - mCompassMargin * 2; + int compassSize = Math.min(compassWidth, compassHeight); + + drawDegreeIndicator(canvas); + + int compassStartY = textHeight + mCompassMargin; + // 画布中心移动到罗盘(0.5, 0)位置 + canvas.translate(0, compassStartY); + drawCompass(canvas, compassSize); + drawDegreeLine(canvas); + drawGimbalIndicators(canvas, compassSize); + + drawAircraftHeadingLine(canvas, compassSize, + mAircraftHeadingOffsetDistanceX, mAircraftHeadingOffsetDistanceY); + drawAircraftIndicator(canvas, compassSize); + drawApasModeText(canvas, compassSize); + + mPerceptionLayer.draw(canvas, mPaint, compassSize); + mMarkerLayer.draw(canvas, mPaint, compassSize); + } + + private void drawDegreeLine(Canvas canvas) { + mPaint.setColor(getResources().getColor(R.color.uxsdk_green_in_dark)); + float width = mDegreeIndicatorWidth; + mPaint.setStrokeWidth(width); + mPaint.setStyle(Paint.Style.FILL); + float top = -mDegreeIndicatorHeight + mDegreeIndicatorHeightInCompass; + canvas.drawLine(0, top, 0, mDegreeIndicatorHeight + top, mPaint); + + + float strokeWidth = mStrokeConfig.getStrokeThinWidth(); + mPaint.setStrokeWidth(strokeWidth); + mPaint.setColor(mStrokeConfig.getStrokeShallowColor()); + mPaint.setStyle(Paint.Style.STROKE); + float halfWidth = width / 2; + float halfStrokeWidth = strokeWidth / 2; + float bottom = top + mDegreeIndicatorHeight + halfStrokeWidth; + canvas.drawRect(-halfWidth - halfStrokeWidth, top - halfStrokeWidth, halfStrokeWidth + halfWidth, bottom, mPaint); + } + + /** + * 绘制当前飞机朝向的度数 + * + * @param canvas + * @return + */ + private void drawDegreeIndicator(Canvas canvas) { + if (mCurrentDegreeText == null) { + return; + } + canvas.save(); + mPaint.setTextSize(mDegreeIndicatorTextSize); + String degree = mCurrentDegreeText; + mPaint.getTextBounds(degree, 0, degree.length(), RECT); + Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt(); + float baseline = (mDegreeIndicatorTextHeight - fontMetrics.bottom + fontMetrics.top) / 2f - fontMetrics.top; + mPaint.setTextAlign(Paint.Align.LEFT); + drawTextWithStroke(canvas, degree, -(float) RECT.width() / 2, baseline, mStrokeConfig.getStrokeBoldWidth(), + mStrokeConfig.getStrokeDeepColor(), mDegreeIndicatorColor); + canvas.restore(); + } + + /** + * 绘制罗盘 + * + * @param canvas + * @param compassSize + */ + private void drawCompass(Canvas canvas, int compassSize) { + if (mCompassBitmap == null) { + return; + } + int flag = mPaint.getFlags(); + mPaint.setFlags(flag | Paint.FILTER_BITMAP_FLAG); + // save 1 + canvas.save(); + canvas.translate(-compassSize / 2f, 0); + RECT.set(0, 0, mCompassBitmap.getWidth(), mCompassBitmap.getHeight()); + RECT2.set(0, 0, compassSize, compassSize); + // save 2 + canvas.save(); + canvas.translate(compassSize / 2f, compassSize / 2f); + canvas.rotate(-mCurrentDegree); + canvas.translate(-compassSize / 2f, -compassSize / 2f); + canvas.drawBitmap(mCompassBitmap, RECT, RECT2, mPaint); + // restore 2 + canvas.restore(); + mPaint.setFlags(flag); + // restore 1 + canvas.restore(); + } + + /** + * 绘制飞行器的指示图标 + * + * @param canvas + * @param compassSize + */ + private void drawAircraftIndicator(Canvas canvas, int compassSize) { + canvas.save(); + canvas.translate(-(float) compassSize / 2, 0); + Bitmap marker = mAircraftBitmap; + if (mIsRadarConnected) { + if (mIsRadarAvailable) { + marker = mRadarAvailableBitmap; + } else { + marker = mRadarUnavailableBitmap; + } + } + drawMarker(canvas, marker, mAircraftIndicatorSize, mAircraftIndicatorSize, + (float) compassSize / 2, (float) compassSize / 2, mPaint); + canvas.restore(); + } + + private void drawApasModeText(Canvas canvas, int compassSize) { + if (!isApasMode) { + return; + } + + mPaint.setColor(mApasTextStrokeColor); + mPaint.setTextSize(mApasTextSize); + mPaint.setStrokeWidth(mApasTextStrokeWith); + + float offX = -mApasTextLength / 2; + float offY = compassSize / 2f + mAircraftIndicatorSize / 2f + mApasTextHeight; + + mPaint.setStyle(Paint.Style.STROKE); + canvas.drawText(APAS_TEXT, offX, offY, mPaint); + + mPaint.setColor(mApasTextColor); + mPaint.setStyle(Paint.Style.FILL); + canvas.drawText(APAS_TEXT, offX, offY, mPaint); + } + + /** + * 绘制各个云台的指示图 + * + * @param canvas + * @param compassSize + */ + private void drawGimbalIndicators(Canvas canvas, int compassSize) { + if (isHideGimbalDrawable) { + return; + } + canvas.save(); + canvas.translate(0, 0); + Drawable drawable = DrawUtils.getDrawable(R.drawable.uxsdk_fpv_hsi_outer_guide_gimbal_3); + float gimbalPadding = (float) (mGimbalIndicatorMaxScope - drawable.getMinimumHeight()) / (MAX_GIMBAL_COUNT - 1); + drawEachGimbalIndicator(canvas, getGimbalYawDegreeWithAircraft(mGimbalCurrentDegree[0], mYaw), + mGimbalConnected[0], compassSize / 2f, mBitmapOffset, R.drawable.uxsdk_fpv_hsi_outer_guide_gimbal_3); + drawEachGimbalIndicator(canvas, getGimbalYawDegreeWithAircraft(mGimbalCurrentDegree[1], mYaw), + mGimbalConnected[1], compassSize / 2f, + mBitmapOffset + gimbalPadding, R.drawable.uxsdk_fpv_hsi_outer_guide_gimbal_1); + drawEachGimbalIndicator(canvas, getGimbalYawDegreeWithAircraft(mGimbalCurrentDegree[2], mYaw), + mGimbalConnected[2], compassSize / 2f, + mBitmapOffset + gimbalPadding * 2, R.drawable.uxsdk_fpv_hsi_outer_guide_gimbal_2); + canvas.restore(); + } + + private float getGimbalYawDegreeWithAircraft(float gimbalYaw, float aircraftYaw) { + return gimbalYaw - aircraftYaw; + } + + + /** + * 绘制单个云台的指示图 + * + * @param canvas + * @param yawDegree + * @param isConnected + * @param centerY + * @param offsetY + */ + private void drawEachGimbalIndicator(Canvas canvas, float yawDegree, + boolean isConnected, float centerY, float offsetY, int gimbalDrawable) { + if (isInEditMode() || isConnected) { + canvas.save(); + canvas.translate(0, centerY); + canvas.rotate(yawDegree); + Drawable drawable = DrawUtils.getDrawable(gimbalDrawable); + int width = drawable.getMinimumWidth(); + int height = drawable.getMinimumHeight(); + float halfWidth = width / 2f; + canvas.translate(-halfWidth, offsetY - centerY); + drawable.setBounds(0, 0, width, height); + drawable.draw(canvas); + canvas.restore(); + } + } + + /** + * 绘制速度矢量球的线段 + * + * @param canvas + * @param compassSize + * @param distanceX + * @param distanceY + */ + private void drawAircraftHeadingLine(Canvas canvas, int compassSize, + float distanceX, float distanceY) { + // distanceX,distanceY 实际分别对应Y轴和X轴 + canvas.save(); + int radius = (int) (compassSize / 2 - mGimbalIndicatorMaxScope - mBitmapOffset); + float offsetX = distanceX / HSI_VISIBLE_DISTANCE_IN_METERS * radius; + float offsetY = distanceY / HSI_VISIBLE_DISTANCE_IN_METERS * radius; + int lineHeight = (int) Math.sqrt(Math.pow(offsetX, 2) + Math.pow(offsetY, 2)); + if (lineHeight > radius) { + lineHeight = radius; + } + double atan = Math.atan(offsetY / offsetX); + float angle = (float) (atan * 180 / Math.PI); + if (!Float.isNaN(angle) && distanceX < 0) { + angle += 180; + } + canvas.translate(0, compassSize / 2f); + canvas.rotate(angle); + mPaint.setColor(Color.WHITE); + mPaint.setStrokeWidth(mHeadingLineWidth); + canvas.drawLine(0, -lineHeight, 0, 0, mPaint); + canvas.restore(); + } + + private void drawMarker(Canvas canvas, Bitmap marker, int markerWidth, int markerHeight, + float offsetMiddleX, float offsetMiddleY, Paint paint) { + int flag = paint.getFlags(); + paint.setFlags(flag | Paint.FILTER_BITMAP_FLAG); + canvas.save(); + canvas.translate(offsetMiddleX - (float) markerWidth / 2, offsetMiddleY - (float) markerHeight / 2); + RECT.set(0, 0, marker.getWidth(), marker.getHeight()); + RECT2.set(0, 0, markerWidth, markerHeight); + canvas.drawBitmap(marker, RECT, RECT2, paint); + canvas.restore(); + paint.setFlags(flag); + } + + protected void drawTextWithStroke(Canvas canvas, String currentValueString, float textOffset, float baseline, float strokeWidth, + int strokeColor, int textColor) { + mPaint.setStrokeWidth(strokeWidth); + mPaint.setColor(strokeColor); + mPaint.setStyle(Paint.Style.STROKE); + canvas.drawText(currentValueString, textOffset, baseline, mPaint); + + mPaint.setColor(textColor); + mPaint.setStyle(Paint.Style.FILL); + canvas.drawText(currentValueString, textOffset, baseline, mPaint); + } + + private void setListener(@Nullable OnAircraftAttitudeChangeListener listener) { + mListener = listener; + } + + private void recalculateAndInvalidate() { + if (mListener != null) { + mListener.onAttitudeChanged(mPitch, mYaw, mRoll, mSpeedX, mSpeedY, mSpeedZ); + } + } + + @Override + public float getCurrentDegree() { + return mCurrentDegree; + } + + @Override + public int getAircraftSize() { + return mAircraftIndicatorSize; + } + + @Override + public int getVisibleDistanceInHsiInMeters() { + return HSI_VISIBLE_DISTANCE_IN_METERS; + } + + @Override + public float getCalibrationAreaWidth() { + return mGimbalIndicatorMaxScope; + } + + @Override + public float getDegreeIndicatorHeight() { + return mDegreeIndicatorHeight; + } + + @Override + public float getCompassBitmapOffset() { + return mBitmapOffset; + } + + @Override + public void updateWidget() { + if (mHandler != null && !mHandler.hasMessages(MSG_INVALIDATE)) { + mHandler.sendEmptyMessageDelayed(MSG_INVALIDATE, INVALIDATE_INTERVAL_TIME); + } + } + + @Override + public View getView() { + return this; + } + + + private static final class ObservableSource implements ObservableOnSubscribe { + + private final WeakReference mReference; + + public ObservableSource(HSIView view) { + mReference = new WeakReference<>(view); + } + + @Override + public void subscribe(ObservableEmitter e) throws Exception { + final HSIView view = mReference.get(); + if (view == null) { + return; + } + OnAircraftAttitudeChangeListener listener = + (pitch, yaw, roll, speedX, speedY, speedZ) -> { + if (!e.isDisposed()) { + e.onNext(new float[]{pitch, yaw, roll, speedX, speedY, speedZ}); + } + }; + e.setCancellable(() -> view.setListener(null)); + view.setListener(listener); + } + + } + + @NonNull + private static float[] updateSpeedVectorMark(float pitch, float yaw, float roll, + float speedX, float speedY, float speedZ) { + float[] i2gMat = MatrixUtils.createRotationMatrix(yaw, pitch, roll); + float[] g2iMat = MatrixUtils.transposeMatrix(i2gMat); + + float[] speedVector = new float[]{speedX, speedY, speedZ}; + + float[] vi = MatrixUtils.rotateVector(speedVector, g2iMat); + + return MatrixUtils.multiple(vi, 2); + } + + private interface OnAircraftAttitudeChangeListener { + void onAttitudeChanged(float pitch, float yaw, float roll, + float speedX, float speedY, float speedZ); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/HSIWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/HSIWidgetModel.java new file mode 100644 index 00000000..976541b6 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/HSIWidgetModel.java @@ -0,0 +1,221 @@ +package dji.v5.ux.core.ui.hsi; + +import android.location.Location; +import android.location.LocationListener; +import android.os.Bundle; + +import java.util.ArrayList; +import java.util.List; + +import androidx.annotation.NonNull; + +import dji.sdk.keyvalue.key.FlightControllerKey; +import dji.sdk.keyvalue.key.GimbalKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.key.ProductKey; +import dji.sdk.keyvalue.value.common.Attitude; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.sdk.keyvalue.value.common.LocationCoordinate2D; +import dji.sdk.keyvalue.value.common.LocationCoordinate3D; +import dji.sdk.keyvalue.value.common.Velocity3D; +import dji.sdk.keyvalue.value.flightcontroller.FCFlightMode; +import dji.sdk.keyvalue.value.product.ProductType; +import dji.v5.common.utils.RxUtil; +import dji.v5.manager.aircraft.perception.PerceptionManager; +import dji.v5.manager.aircraft.perception.data.ObstacleData; +import dji.v5.manager.aircraft.perception.data.PerceptionInfo; +import dji.v5.manager.aircraft.perception.listener.ObstacleDataListener; +import dji.v5.manager.aircraft.perception.listener.PerceptionInformationListener; +import dji.v5.manager.aircraft.perception.radar.RadarInformation; +import dji.v5.manager.aircraft.perception.radar.RadarInformationListener; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.DataProcessor; +import dji.v5.ux.core.util.MobileGPSLocationUtil; +import io.reactivex.rxjava3.core.Flowable; + +public class HSIWidgetModel extends WidgetModel implements LocationListener { + private final DataProcessor aircraftLocationDataProcessor = DataProcessor.create(new LocationCoordinate3D(Double.NaN, + Double.NaN, Double.NaN)); + private final DataProcessor homeLocationDataProcessor = DataProcessor.create(new LocationCoordinate2D(Double.NaN, + Double.NaN)); + private final DataProcessor flightModeProcessor = DataProcessor.create(FCFlightMode.UNKNOWN); + private final DataProcessor multipleFlightModeEnabledProcessor = DataProcessor.create(false); + private final DataProcessor velocityProcessor = DataProcessor.create(new Velocity3D()); + private final DataProcessor aircraftAttitudeProcessor = DataProcessor.create(new Attitude()); + private final DataProcessor productTypeDataProcessor = DataProcessor.create(ProductType.UNKNOWN); + private final List> gimbalConnectionProcessorList = new ArrayList<>(); + private final DataProcessor gimbalConnection0Processor = DataProcessor.create(false); + private final DataProcessor gimbalConnection1Processor = DataProcessor.create(false); + private final DataProcessor gimbalConnection2Processor = DataProcessor.create(false); + private final List> gimbalYawInDegreesProcessorList = new ArrayList<>(); + private final DataProcessor gimbalYawInDegrees0Processor = DataProcessor.create(0.0); + private final DataProcessor gimbalYawInDegrees1Processor = DataProcessor.create(0.0); + private final DataProcessor gimbalYawInDegrees2Processor = DataProcessor.create(0.0); + + /** + * 新增 + */ + // 180 / PI = 57.295779513082321 + private static final Double RAD_TO_DEG = 57.295779513082321; + + private final DataProcessor radarInformationDataProcessor = DataProcessor.create(new RadarInformation()); + private final DataProcessor perceptionInformationDataProcessor = DataProcessor.create(new PerceptionInfo()); + + + private final DataProcessor radarObstacleDataProcessor = DataProcessor.create(new ObstacleData()); + private final DataProcessor perceptionObstacleDataProcessor = DataProcessor.create(new ObstacleData()); + + private RadarInformationListener radarInformationListener = radarInformation -> radarInformationDataProcessor.onNext(radarInformation); + private PerceptionInformationListener perceptionInformationListener = perceptionInfo -> perceptionInformationDataProcessor.onNext(perceptionInfo); + + + private ObstacleDataListener radarObstacleDataListener = data -> radarObstacleDataProcessor.onNext(data); + private ObstacleDataListener perceptionObstacleDataListener = data -> perceptionObstacleDataProcessor.onNext(data); + private final DataProcessor locationDataProcessor = DataProcessor.create(new Location("HSIWidgetModel")); + + public HSIWidgetModel(@NonNull DJISDKModel djiSdkModel, @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + } + + @Override + protected void inSetup() { + // HSIMarkerLayer + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyAircraftLocation3D), aircraftLocationDataProcessor); + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyHomeLocation), homeLocationDataProcessor); + + /*kGimbalAttitude 获取的云台YAW 角度 和 飞机的YAW 不是一个坐标系的,需要加上 kImuCoordinateTran 的值来修正*/ + Flowable.combineLatest(RxUtil.addListener(KeyTools.createKey(GimbalKey.KeyGimbalAttitude, ComponentIndexType.LEFT_OR_MAIN), this), + RxUtil.addListener(KeyTools.createKey(FlightControllerKey.KeyImuCoordinateTran), this), + (attitude, aDouble) -> attitude.getYaw() + aDouble * RAD_TO_DEG).subscribe(gimbalYawInDegrees0Processor::onNext); + + Flowable.combineLatest(RxUtil.addListener(KeyTools.createKey(GimbalKey.KeyGimbalAttitude, ComponentIndexType.RIGHT), this), + RxUtil.addListener(KeyTools.createKey(FlightControllerKey.KeyImuCoordinateTran), this), + (attitude, aDouble) -> attitude.getYaw() + aDouble * RAD_TO_DEG).subscribe(gimbalYawInDegrees1Processor::onNext); + + Flowable.combineLatest(RxUtil.addListener(KeyTools.createKey(GimbalKey.KeyGimbalAttitude, ComponentIndexType.UP), this), + RxUtil.addListener(KeyTools.createKey(FlightControllerKey.KeyImuCoordinateTran), this), + (attitude, aDouble) -> attitude.getYaw() + aDouble * RAD_TO_DEG).subscribe(gimbalYawInDegrees2Processor::onNext); + + gimbalYawInDegreesProcessorList.add(gimbalYawInDegrees0Processor); + gimbalYawInDegreesProcessorList.add(gimbalYawInDegrees1Processor); + gimbalYawInDegreesProcessorList.add(gimbalYawInDegrees2Processor); + MobileGPSLocationUtil.getInstance().addLocationListener(this); + MobileGPSLocationUtil.getInstance().startUpdateLocation(); + + //HSIPerceptionLayer + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyFCFlightMode), flightModeProcessor); + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyMultipleFlightModeEnabled), multipleFlightModeEnabledProcessor); + + //HSIView + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyAircraftVelocity), velocityProcessor); + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyAircraftAttitude), aircraftAttitudeProcessor); + bindDataProcessor(KeyTools.createKey(ProductKey.KeyProductType), productTypeDataProcessor); + + bindDataProcessor(KeyTools.createKey(GimbalKey.KeyConnection, ComponentIndexType.LEFT_OR_MAIN), gimbalConnection0Processor); + bindDataProcessor(KeyTools.createKey(GimbalKey.KeyConnection, ComponentIndexType.RIGHT), gimbalConnection1Processor); + bindDataProcessor(KeyTools.createKey(GimbalKey.KeyConnection, ComponentIndexType.UP), gimbalConnection2Processor); + gimbalConnectionProcessorList.add(gimbalConnection0Processor); + gimbalConnectionProcessorList.add(gimbalConnection1Processor); + gimbalConnectionProcessorList.add(gimbalConnection2Processor); + + PerceptionManager.getInstance().getRadarManager().addObstacleDataListener(radarObstacleDataListener); + PerceptionManager.getInstance().getRadarManager().addRadarInformationListener(radarInformationListener); + PerceptionManager.getInstance().addPerceptionInformationListener(perceptionInformationListener); + PerceptionManager.getInstance().addObstacleDataListener(perceptionObstacleDataListener); + } + + @Override + protected void inCleanup() { + gimbalConnectionProcessorList.clear(); + gimbalYawInDegreesProcessorList.clear(); + + PerceptionManager.getInstance().getRadarManager().removeRadarInformationListener(radarInformationListener); + PerceptionManager.getInstance().getRadarManager().removeObstacleDataListener(radarObstacleDataListener); + PerceptionManager.getInstance().removePerceptionInformationListener(perceptionInformationListener); + PerceptionManager.getInstance().removeObstacleDataListener(perceptionObstacleDataListener); + MobileGPSLocationUtil.getInstance().removeLocationListener(this); + } + + public DataProcessor getAircraftLocationDataProcessor() { + return aircraftLocationDataProcessor; + } + + public DataProcessor getHomeLocationDataProcessor() { + return homeLocationDataProcessor; + } + + + public DataProcessor getFlightModeProcessor() { + return flightModeProcessor; + } + + public DataProcessor getMultipleFlightModeEnabledProcessor() { + return multipleFlightModeEnabledProcessor; + } + + public DataProcessor getVelocityProcessor() { + return velocityProcessor; + } + + public DataProcessor getAircraftAttitudeProcessor() { + return aircraftAttitudeProcessor; + } + + public List> getGimbalConnectionProcessorList() { + return gimbalConnectionProcessorList; + } + + + public List> getGimbalYawInDegreesProcessorList() { + return gimbalYawInDegreesProcessorList; + } + + + public DataProcessor getRadarInformationDataProcessor() { + return radarInformationDataProcessor; + } + + public DataProcessor getProductTypeDataProcessor() { + return productTypeDataProcessor; + } + + public DataProcessor getPerceptionInformationDataProcessor() { + return perceptionInformationDataProcessor; + } + + public DataProcessor getLocationDataProcessor() { + return locationDataProcessor; + } + + @Override + public void onLocationChanged(Location location) { + locationDataProcessor.onNext(location); + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) { + // Do nothing + } + + @Override + public void onProviderEnabled(String provider) { + // Do nothing + } + + @Override + public void onProviderDisabled(String provider) { + // Do nothing + } + + public DataProcessor getRadarObstacleDataProcessor() { + return radarObstacleDataProcessor; + } + + public DataProcessor getPerceptionObstacleDataProcessor() { + return perceptionObstacleDataProcessor; + } +} + + diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/RecyclerPool.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/RecyclerPool.kt new file mode 100644 index 00000000..ab012827 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/RecyclerPool.kt @@ -0,0 +1,37 @@ +package dji.v5.ux.core.ui.hsi +import java.util.* + +abstract class RecyclerPool(poolSize: Int) { + private val mPoolSize: Int + private val mList: MutableList + + init { + mList = LinkedList() + mPoolSize = poolSize + } + + @Synchronized + fun acquire(): T { + val n = mList.size + return if (n == 0) { + create() + } else { + mList.removeAt(0) + } + } + + protected abstract fun create(): T + @Synchronized + fun recycle(t: T): Boolean { + if (mList.size < mPoolSize) { + mList.add(t) + return true + } + return false + } + + @Synchronized + fun clear() { + mList.clear() + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/config/IOmniAbility.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/config/IOmniAbility.kt new file mode 100644 index 00000000..f5ee2966 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/config/IOmniAbility.kt @@ -0,0 +1,62 @@ +package dji.v5.ux.core.ui.hsi.config; + + +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.key.ProductKey +import dji.sdk.keyvalue.value.product.ProductType +import dji.v5.manager.KeyManager +import dji.v5.utils.dpad.DpadProductManager + +interface IOmniAbility { + /** + * 视觉避障-上方探测距离 + */ + fun getUpDetectionCapability(): Int + + /** + * 上方避障刹停距离设置范围 + */ + fun getUpAvoidanceDistanceRange(): Pair + + /** + * 视觉避障-下方探测距离 + */ + fun getDownDetectionCapability(): Int + + /** + * 下方避障刹停距离设置范围 + */ + fun getDownAvoidanceDistanceRange(): Pair + + /** + * 视觉避障-水平探测距离 + */ + fun getHorizontalDetectionCapability(): Int + + /** + * 水平避障刹停距离设置范围 + */ + fun getHorizontalAvoidanceDistanceRange(): Pair + + /** + * 视觉避障-每方向盲区大小 + */ + fun getPerceptionBlindAreaAngle(): Int + + companion object { + /** + * 当前未考虑遥控器连接不同飞机,未观察连接飞机的变化,当出现遥控支持不同飞机时,需要观察飞机状态变化。 + */ + fun getCurrent(): IOmniAbility { + val type = KeyManager.getInstance().getValue( + KeyTools.createKey( + ProductKey.KeyProductType), ProductType.UNKNOWN) + return when { + DpadProductManager.getInstance().isSmartController || type == ProductType.M300_RTK || type == ProductType.M350_RTK|| type == ProductType.DJI_MATRICE_400 -> M300OmniAbility + DpadProductManager.getInstance().isDjiRcPlus || type == ProductType.M30_SERIES -> M30OmniAbility + DpadProductManager.getInstance().isDjiRcPro || type == ProductType.DJI_MAVIC_3_ENTERPRISE_SERIES -> M3EOmniAbility + else -> M300OmniAbility + } + } + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/config/M300OmniAbility.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/config/M300OmniAbility.kt new file mode 100644 index 00000000..28b6c623 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/config/M300OmniAbility.kt @@ -0,0 +1,33 @@ +package dji.v5.ux.core.ui.hsi.config; + +object M300OmniAbility : IOmniAbility { + const val MAX_PERCEPTION_DISTANCE_HORIZONTAL_IN_METER = 40 + const val MAX_PERCEPTION_DISTANCE_VERTICAL_IN_METER = 30 + + private val MAX_HORIZONTAL_AVOIDANCE_DISTANCE_IN_METER = Pair(1f, 10f) + private val MAX_DOWN_AVOIDANCE_DISTANCE_IN_METER = Pair(0.5f, 3f) + + const val PERCEPTION_BLIND_AREA_ANGLE = 16 + + override fun getUpDetectionCapability(): Int { + return MAX_PERCEPTION_DISTANCE_VERTICAL_IN_METER + } + + override fun getUpAvoidanceDistanceRange() = MAX_HORIZONTAL_AVOIDANCE_DISTANCE_IN_METER + + override fun getDownDetectionCapability(): Int { + return MAX_PERCEPTION_DISTANCE_VERTICAL_IN_METER + } + + override fun getDownAvoidanceDistanceRange() = MAX_DOWN_AVOIDANCE_DISTANCE_IN_METER + + override fun getHorizontalDetectionCapability(): Int { + return MAX_PERCEPTION_DISTANCE_HORIZONTAL_IN_METER + } + + override fun getHorizontalAvoidanceDistanceRange() = MAX_HORIZONTAL_AVOIDANCE_DISTANCE_IN_METER + + override fun getPerceptionBlindAreaAngle(): Int { + return PERCEPTION_BLIND_AREA_ANGLE + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/config/M30OmniAbility.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/config/M30OmniAbility.kt new file mode 100644 index 00000000..467d0c5d --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/config/M30OmniAbility.kt @@ -0,0 +1,39 @@ +package dji.v5.ux.core.ui.hsi.config; + +/** + * M30 避障参数 + * + */ +object M30OmniAbility : IOmniAbility { + private const val MAX_PERCEPTION_DISTANCE_IN_METER = 33 + + private val MAX_HORIZONTAL_AVOIDANCE_DISTANCE_IN_METER = Pair(1f, 10f) + private val MAX_DOWN_AVOIDANCE_DISTANCE_IN_METER = Pair(0.5f, 3f) + + /** + * 实际可视角度65,和 M300 原本逻辑一致,为方便计算,取偶数 + */ + private const val PERCEPTION_BLIND_AREA_ANGLE = 26 + + override fun getUpDetectionCapability(): Int { + return MAX_PERCEPTION_DISTANCE_IN_METER + } + + override fun getUpAvoidanceDistanceRange() = MAX_HORIZONTAL_AVOIDANCE_DISTANCE_IN_METER + + override fun getDownDetectionCapability(): Int { + return MAX_PERCEPTION_DISTANCE_IN_METER + } + + override fun getDownAvoidanceDistanceRange() = MAX_DOWN_AVOIDANCE_DISTANCE_IN_METER + + override fun getHorizontalDetectionCapability(): Int { + return MAX_PERCEPTION_DISTANCE_IN_METER + } + + override fun getHorizontalAvoidanceDistanceRange() = MAX_HORIZONTAL_AVOIDANCE_DISTANCE_IN_METER + + override fun getPerceptionBlindAreaAngle(): Int { + return PERCEPTION_BLIND_AREA_ANGLE + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/config/M3EOmniAbility.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/config/M3EOmniAbility.kt new file mode 100644 index 00000000..b8b28e4b --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/config/M3EOmniAbility.kt @@ -0,0 +1,28 @@ +package dji.v5.ux.core.ui.hsi.config; + +object M3EOmniAbility : IOmniAbility { + + const val MAX_PERCEPTION_DISTANCE_HORIZONTAL_IN_METER = 16 + const val MAX_PERCEPTION_DISTANCE_VERTICAL_IN_METER = 10 + + private val MAX_HORIZONTAL_AVOIDANCE_DISTANCE_IN_METER = Pair(1f, 10f) + private val MAX_UP_AVOIDANCE_DISTANCE_IN_METER = Pair(1f, 9.9f) + private val MAX_DOWN_AVOIDANCE_DISTANCE_IN_METER = Pair(0.5f, 2f) + + private const val PERCEPTION_BLIND_AREA_ANGLE = 0 + + override fun getUpDetectionCapability() = MAX_PERCEPTION_DISTANCE_VERTICAL_IN_METER + + override fun getUpAvoidanceDistanceRange() = MAX_UP_AVOIDANCE_DISTANCE_IN_METER + + override fun getDownDetectionCapability() = MAX_PERCEPTION_DISTANCE_VERTICAL_IN_METER + + override fun getDownAvoidanceDistanceRange() = MAX_DOWN_AVOIDANCE_DISTANCE_IN_METER + + override fun getHorizontalDetectionCapability() = MAX_PERCEPTION_DISTANCE_HORIZONTAL_IN_METER + + override fun getHorizontalAvoidanceDistanceRange() = MAX_HORIZONTAL_AVOIDANCE_DISTANCE_IN_METER + + override fun getPerceptionBlindAreaAngle() = PERCEPTION_BLIND_AREA_ANGLE + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/dashboard/AttitudeDashBoard.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/dashboard/AttitudeDashBoard.java new file mode 100644 index 00000000..5d07326f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/dashboard/AttitudeDashBoard.java @@ -0,0 +1,1038 @@ +package dji.v5.ux.core.ui.hsi.dashboard; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; + +import dji.sdk.keyvalue.utils.ProductUtil; +import dji.v5.manager.aircraft.perception.data.ObstacleAvoidanceType; +import dji.v5.manager.aircraft.perception.data.ObstacleData; +import dji.v5.manager.aircraft.perception.radar.RadarInformation; +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.R; +import dji.v5.common.utils.UnitUtils; +import dji.v5.ux.core.ui.hsi.config.IOmniAbility; +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.core.util.DrawUtils; +import dji.v5.ux.core.util.FontUtils; +import dji.v5.ux.core.widget.hsi.AttitudeDisplayModel; +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.disposables.CompositeDisposable; + +public class AttitudeDashBoard extends ScrollableAttributeDashBoard { + + + private static final String TAG = "AttitudeDashBoard"; + + private static final int UPWARD = -1; + private static final int DOWNWARD = 1; + + private static final int PREDICT_TIME_IN_SECONDS = 6; + + /** + * 障碍物最远感知距离 + */ + private int mUpMaxPerceptionDistanceInMeter; + private int mDownMaxPerceptionDistanceInMeter; + private static final float SPEED_THRESHOLD = 0.001f; + private static final int PFD_BARRIER_OFF_TEXT_DISTANCE = 20; + + private final int mAvoidanceMaxHeight; + private final int mBarrierDistanceTextSize; + private final int mBarrierIndicatorColor; + private final int mAvoidanceIndicatorColor; + /** + * 避障条宽度,因描边存在不同粗细,为保证显示宽度一致,此宽度包含描边 + */ + private final int mAvoidanceIndicatorWidth; + private final int mAvoidanceIndicatorStrokeWidth; + private final int mDistancePredictWidth; + private final int mReturnToHomeIndicatorWidth; + + private final CompositeDisposable mCompositeDisposable = new CompositeDisposable(); + + + /** + * 用户设置的上视障碍物避障距离 + */ + private float mUserSetUpBarrierAvoidanceDistance; + /** + * 用户设置的上视障碍物告警距离 + */ + private float mUserSetUpBarrierWarnDistance; + + /** + * 用户设置的下视障碍物避障距离 + */ + private float mUserSetDownBarrierAvoidanceDistance; + /** + * 用户设置的下视障碍物告警距离 + */ + private float mUserSetDownBarrierWarnDistance; + + /** + * 垂直速度 + */ + private float mSpeedZ; + + /** + * 当前飞行高度 + */ + private float mHeight; + + // /** + // * 返航高度 + // */ + // private int mReturnToHomeHeight = Integer.MAX_VALUE; + + // /** + // * 飞控设置中的限飞高度,会处理限飞区,但是不包含解禁证书 + // */ + // private int mLimitHeight = Integer.MAX_VALUE; + + /** + * 视觉感知避障开关 + */ + private boolean mUpwardVisualEnable; + + private boolean mShowDownwardVisualPerceptionInfo; + + /** + * 雷达感知避障开关 + */ + private boolean mUpwardRadarEnable; + private RadarInformation radarInformation = new RadarInformation(); + + private float mUpwardRadarDistance; + + private Bitmap mBarrierUp; + private Bitmap mBarrierDown; + + private float mBarrierOriginLineWidth; + private float mBarrierOriginLineLength; + + /** + * 垂直避障条文字与坐标轴间距 + */ + private float mBarrierTextMargin; + + private IBarrierDistanceStrategy mBarrierDistanceStrategy; + // private float mTextExtraPadding; + /** + * 上下两个方向的视觉感知是否正常工作 + */ + @NonNull + private final boolean[] mVisionPerceptionWorkingState = new boolean[]{false, false}; + + + private AttitudeDisplayModel mWidgetModel; + private ObstacleData mPerceptionObstacleData = new ObstacleData(); + + + public void setModel(AttitudeDisplayModel model) { + mWidgetModel = model; + } + + + public AttitudeDashBoard(Context context) { + this(context, null); + } + + public AttitudeDashBoard(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public AttitudeDashBoard(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.AttitudeDashBoard); + mAvoidanceMaxHeight = typedArray.getDimensionPixelSize(R.styleable.AttitudeDashBoard_uxsdk_avoidance_max_height, + getResources().getDimensionPixelSize(R.dimen.uxsdk_38_dp)); + mBarrierDistanceTextSize = typedArray.getDimensionPixelSize(R.styleable.AttitudeDashBoard_uxsdk_barrier_distance_text_size, + getResources().getDimensionPixelSize(R.dimen.uxsdk_7_dp)); + mAvoidanceIndicatorWidth = typedArray.getDimensionPixelSize(R.styleable.AttitudeDashBoard_uxsdk_avoidance_indicator_width, + getResources().getDimensionPixelSize(R.dimen.uxsdk_3_dp)); + mAvoidanceIndicatorStrokeWidth = typedArray.getDimensionPixelSize(R.styleable.AttitudeDashBoard_uxsdk_avoidance_indicator_stroke_width, + getResources().getDimensionPixelSize(R.dimen.uxsdk_0_5_dp)); + mDistancePredictWidth = typedArray.getDimensionPixelSize(R.styleable.AttitudeDashBoard_uxsdk_distance_predict_line_width, + getResources().getDimensionPixelSize(R.dimen.uxsdk_2_dp)); + mReturnToHomeIndicatorWidth = typedArray.getDimensionPixelSize(R.styleable.AttitudeDashBoard_uxsdk_return_to_home_indicator_width, + getResources().getDimensionPixelSize(R.dimen.uxsdk_22_dp)); + + mBarrierIndicatorColor = typedArray.getColor(R.styleable.AttitudeDashBoard_uxsdk_barrier_indicator_color, + getResources().getColor(R.color.uxsdk_pfd_barrier_color)); + Drawable up = typedArray.getDrawable(R.styleable.AttitudeDashBoard_uxsdk_barrier_drawable_up); + if (up != null) { + mBarrierUp = DrawUtils.drawable2Bitmap(up); + } + Drawable down = typedArray.getDrawable(R.styleable.AttitudeDashBoard_uxsdk_barrier_drawable_down); + if (up != null) { + mBarrierDown = DrawUtils.drawable2Bitmap(down); + } + mAvoidanceIndicatorColor = typedArray.getColor(R.styleable.AttitudeDashBoard_uxsdk_avoidance_indicator_color, + getResources().getColor(R.color.uxsdk_pfd_avoidance_color)); + mUpwardRadarDistance = typedArray.getInt(R.styleable.AttitudeDashBoard_uxsdk_barrier_distance, Integer.MAX_VALUE); + mBarrierOriginLineWidth = getResources().getDimension(R.dimen.uxsdk_1_dp); + mBarrierOriginLineLength = getResources().getDimension(R.dimen.uxsdk_6_dp); + typedArray.recycle(); + + if (!isInEditMode()){ + mUpMaxPerceptionDistanceInMeter = IOmniAbility.Companion.getCurrent().getUpDetectionCapability(); + mDownMaxPerceptionDistanceInMeter = IOmniAbility.Companion.getCurrent().getDownDetectionCapability(); + } + + mBarrierTextMargin = getResources().getDimension(R.dimen.uxsdk_1_dp); + //TODO 临时新增日志。这里很奇怪,获取到的mBarrierDistanceStrategy=HsiBarrierDistanceStrategy,因为拿到的isShowFramework=false + Log.d(TAG, "isShowFramework=" + isShowFramework()); + mBarrierDistanceStrategy = isShowFramework() ? new PfdBarrierDistanceStrategy() : new HsiBarrierDistanceStrategy(); + // mTextExtraPadding = getResources().getDimensionPixelSize(R.dimen.uxsdk_2_dp); + mWaypointIcon = ContextCompat.getDrawable(getContext(), R.drawable.uxsdk_fpv_pfd_waypoint_right); + + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (isInEditMode()) { + return; + } + + //视觉开关信息 + mCompositeDisposable.add(mWidgetModel.getPerceptionInfoProcessor().toFlowable().subscribe(info -> { + boolean isBypass = info.getObstacleAvoidanceType() == ObstacleAvoidanceType.BYPASS; + //用户设置的上视避障开关 + mUpwardVisualEnable = info.isUpwardObstacleAvoidanceEnabled() || isBypass; + //用户设置的上视障碍物避障距离 + mUserSetUpBarrierAvoidanceDistance = (float) info.getUpwardObstacleAvoidanceBrakingDistance(); + //用户设置的上视障碍物告警距离 + mUserSetUpBarrierWarnDistance = (float) info.getUpwardObstacleAvoidanceWarningDistance(); + + //用户设置的下视避障开关 + mShowDownwardVisualPerceptionInfo = info.isDownwardObstacleAvoidanceEnabled() || isBypass; + //用户设置的下视障碍物避障距离 + mUserSetDownBarrierAvoidanceDistance = (float) info.getDownwardObstacleAvoidanceBrakingDistance(); + //用户设置的下视障碍物告警距离 + mUserSetDownBarrierWarnDistance = (float) info.getDownwardObstacleAvoidanceWarningDistance() / 10f; + + //上下避障工作状态 + mVisionPerceptionWorkingState[0] = info.getUpwardObstacleAvoidanceWorking() == Boolean.TRUE; + mVisionPerceptionWorkingState[1] = info.getDownwardObstacleAvoidanceWorking() == Boolean.TRUE; + + updateWidget(); + })); + + //视觉避数据信息 + mCompositeDisposable.add(mWidgetModel.getPerceptionObstacleDataProcessor().toFlowable().subscribe(data -> { + mPerceptionObstacleData = data; + updateWidget(); + })); + + //雷达开关信息 + mCompositeDisposable.add(mWidgetModel.getRadarInfoProcessor().toFlowable().subscribe(info -> { + mUpwardRadarEnable = info.isUpwardObstacleAvoidanceEnabled(); + radarInformation = info; + updateWidget(); + })); + + //雷达避数据信息 + mCompositeDisposable.add(mWidgetModel.getRadarObstacleDataProcessor().toFlowable().subscribe(data -> { + if (radarInformation.isConnected()) { + LogUtils.e(TAG, "雷达已连接"); + //mUpwardRadarDistance 的值分两种情况,针对320这种没有雷达的有一个默认值,而这个默认值在绘制逻辑中会起作用,所以不能覆盖掉,不然会出现问题。只有针对检测到雷达有连接上才使用其真实值 + mUpwardRadarDistance = data.getUpwardObstacleDistance() * 1f / 1000; + updateWidget(); + } + })); + + + mCompositeDisposable.add(mWidgetModel.getVelocityProcessor().toFlowable().subscribe(velocity3D -> { + mSpeedZ = velocity3D.getZ().floatValue(); + updateWidget(); + })); + mCompositeDisposable.add(mWidgetModel.getAltitudeProcessor().toFlowable().subscribeOn(AndroidSchedulers.mainThread()).subscribe(altitude -> { + mHeight = altitude.floatValue(); + setCurrentValue(mHeight); + })); + mCompositeDisposable.add(mWidgetModel.getGoHomeHeightProcessor().toFlowable().subscribe(integer -> { + // mReturnToHomeHeight = integer; + updateWidget(); + })); + mCompositeDisposable.add(mWidgetModel.getLimitMaxFlightHeightInMeterProcessor().toFlowable().subscribe(integer -> { + // mLimitHeight = integer; + updateWidget(); + })); + + } + + + // /** + // * 是否需要显示限高 + // * 存在解禁证书时,获取到的限高值不准确,不显示限高 + // */ + // private void updateLimitVisiable() { + // mCompositeDisposable.add(mFlyZoneRepository.fetchWhiteListLicenseFromAircraft() + // .subscribeOn(Schedulers.io()) + // .map(licenses -> { + // boolean showLim = true; + // for (WhiteListLicense license : licenses) { + // if (license.isEnabled() && license.isValid()) { + // showLim = false; + // break; + // } + // } + // return showLim; + // }) + // .observeOn(AndroidSchedulers.mainThread()) + // .doOnNext(showLim -> { + // mShowLimit = showLim; + // updateWidget(); + // }) + // .subscribe() + // ); + // } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mCompositeDisposable.dispose(); + } + + @Override + protected int getMinHeight() { + return Math.max(getFrameworkHeight(), getAvoidanceHeight()); + } + + private int getAvoidanceHeight() { + return mAvoidanceMaxHeight * 2 + getBarrierUpIndicatorHeight() + getBarrierDownIndicatorHeight(); + } + + private int getBarrierUpIndicatorHeight() { + if (mBarrierUp == null) { + return 0; + } + return mBarrierUp.getHeight(); + } + + private int getBarrierDownIndicatorHeight() { + if (mBarrierDown == null) { + return 0; + } + return mBarrierDown.getHeight(); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + canvas.save(); + + // 为简化 PFD 中障碍物的位置信息,将障碍物右侧定义为 canvas 水平零点 + float barrierRightOffset; + if (isShowFramework()) { + barrierRightOffset = mFrameworkPaddingStart - mFrameworkStrokeWidth / 2f; + } else { + barrierRightOffset = mFrameworkPaddingStart + mBarrierOriginLineLength; + } + canvas.translate(barrierRightOffset, (float) getHeight() / 2); + drawDistancePredict(canvas); + // if (isShowFramework()) { + // drawAttitudeIndicator(canvas); + // } + drawBarrierBackground(canvas); + drawBarrierInfo(canvas); + drawBarrierOriginLine(canvas); + canvas.restore(); + } + + /** + * 绘制刻度上的标识 + * + * @param canvas + */ + // private void drawAttitudeIndicator() { + // 只在航线执行过程中显示 + // boolean hasWp = false; + // float waypointAltitude = 0; + // + // MissionManagerDelegate instance = MissionManagerDelegate.INSTANCE; + // if (instance.isRunningMission()) { + // List targetAndNextPointList = instance.getTargetAndNextPointList(); + // if (!targetAndNextPointList.isEmpty()) { + // hasWp = true; + // waypointAltitude = targetAndNextPointList.get(0).getAltitude(); + // } + // } + // + // int limitHeight = mShowLimit ? mLimitHeight : Integer.MAX_VALUE; + // + // float perHeight = (float) getFrameworkHeight() / mVisibleCalibrationUnitCount / mAttributeOffsetPerUnit; + // + // mPaint.setTextSize(mAttitudeIndicatorTextSize); + // mPaint.getTextBounds(RTH_TEXT, 0, RTH_TEXT.length(), RECT); + // float rthHeight = RECT.height(); + // + // mPaint.getTextBounds(LIM_TEXT, 0, LIM_TEXT.length(), RECT); + // float limWidth = RECT.width(); + // float limHeight = RECT.height(); + // + // int iconWidth = 0; + // int iconHeight = 0; + // + // float deltaHeight; + // float deltaValue; + // float rthExtraOffsetX = 0; + // float limExtraOffsetX = 0; + // if (hasWp) { + // // 计算 LIM 和 waypoint 是否重叠 + // iconWidth = mWaypointIcon.getMinimumWidth(); + // iconHeight = mWaypointIcon.getMinimumHeight(); + // deltaHeight = (iconHeight + limHeight) / 2; + // deltaValue = deltaHeight / perHeight; + // if (deltaValue >= Math.abs(waypointAltitude - limitHeight)) { + // limExtraOffsetX = iconWidth + mTextExtraPadding; + // } + // } + // + // // 计算 RTH 和 LIM 是否重叠 + // deltaHeight = (limHeight + rthHeight) / 2; + // deltaValue = deltaHeight / perHeight; + // if (deltaValue >= Math.abs(limitHeight - mReturnToHomeHeight)) { + // rthExtraOffsetX = limWidth + mTextExtraPadding + limExtraOffsetX; + // } else { + // if (hasWp) { + // // RTH 和 LIM 不重叠,需要再检查 RTH 和 waypoint 重叠 + // deltaHeight = (iconHeight + rthHeight) / 2; + // deltaValue = deltaHeight / perHeight; + // if (deltaValue >= Math.abs(mReturnToHomeHeight - waypointAltitude)) { + // rthExtraOffsetX = iconWidth + mTextExtraPadding; + // } + // } + // } + // + // if (hasWp) { + // drawAttitudeIndicator(canvas, waypointAltitude, mWayPointHeightIndicatorColor, "", 0, mWaypointIcon); + // } + // drawAttitudeIndicator(canvas, mReturnToHomeHeight, mReturnToHomeIndicatorColor, RTH_TEXT, -rthExtraOffsetX, null); + // drawAttitudeIndicator(canvas, limitHeight, mMaxFlightHeightIndicatorColor, LIM_TEXT, -limExtraOffsetX, null); + // } + private void drawBarrierBackground(Canvas canvas) { + drawBarrierBackground(canvas, UPWARD); + drawBarrierBackground(canvas, DOWNWARD); + } + + private void drawBarrierBackground(Canvas canvas, int orientation) { + if (isShowFramework() && !isUserDisable(orientation)) { + return; + } + float top; + float bottom; + float bgHeight; + if (isShowFramework()) { + bgHeight = getViewHeightForDistance(PFD_BARRIER_OFF_TEXT_DISTANCE); + } else { + bgHeight = mAvoidanceMaxHeight; + } + if (orientation == UPWARD) { + top = bgHeight * orientation; + bottom = 0; + } else { + top = 0; + bottom = bgHeight * orientation; + } + mPaint.setStyle(Paint.Style.STROKE); + float strokeWidth = getBarStrokeWidth(); + float halfStrokeWidth = strokeWidth / 2f; + mPaint.setStrokeWidth(strokeWidth); + int strokeColor = getBarStrokeColor(); + mPaint.setColor(strokeColor); + // 为保证不同描边粗细整体宽度一致,左右以描边外位置计算 + float left = -mAvoidanceIndicatorWidth; + float right = 0; + canvas.drawRect(left + halfStrokeWidth, top - halfStrokeWidth * orientation, right - halfStrokeWidth, bottom + halfStrokeWidth, mPaint); + + int bgColor = getBarFillColor(); + mPaint.setColor(bgColor); + mPaint.setStyle(Paint.Style.FILL); + canvas.drawRect(left + strokeWidth, top, right - strokeWidth, bottom, mPaint); + + if (!isShowFramework() && (needBarrierInfo(orientation) || isUserDisable(orientation))) { + float baseline = orientation == UPWARD ? FontUtils.getDigitalBaselineFromTop(mPaint, top) : + FontUtils.getDigitalBaselineFromBottom(mPaint, bottom); + drawBarrierText(canvas, orientation, baseline, (mBarrierUp.getWidth() - mAvoidanceIndicatorWidth) / 2f); + } + } + + private int getBarFillColor() { + return AndUtil.getResColor(R.color.uxsdk_white_20_percent); + } + + private int getBarStrokeColor() { + return mStrokeConfig.getStrokeDeepColor(); + } + + private float getBarStrokeWidth() { + if (isShowFramework()) { + return mStrokeConfig.getStrokeBoldWidth(); + } + return mStrokeConfig.getStrokeThinWidth(); + } + + private String mUpBarrierString; + private final Object mUpBarrierStringLock = new Object(); + private String mDownBarrierString; + private final Object mDownBarrierStringLock = new Object(); + + /** + * 在异步线程计算要显示的BarrierString + * + * @param orientation + */ + private void calcBarrierString(final int orientation) { + mDataHandler.post(() -> { + float barrierDistance; + String newString = ""; + if (orientation == UPWARD) { + barrierDistance = getUpwardBarrierDistance(); + newString = getBarrierString(orientation, barrierDistance); + synchronized (mUpBarrierStringLock) { + if (!newString.equals(mUpBarrierString)) { + mUpBarrierString = newString; + updateWidget(); + } + } + } else { + barrierDistance = getDownVisionDistance(); + newString = getBarrierString(orientation, barrierDistance); + synchronized (mDownBarrierStringLock) { + if (!newString.equals(mDownBarrierString)) { + mDownBarrierString = newString; + updateWidget(); + } + } + } + }); + } + + private String getBarrierString(int orientation, float barrierDistance) { + if (isUserDisable(orientation)) { + return "OFF"; + } else { + float displayValue = getDisplayValue(barrierDistance); + if (displayValue >= 99.95f) { + return String.format("%3.0f", displayValue); + } else { + return String.format("%2.1f", displayValue); + } + } + } + + private void drawBarrierText(Canvas canvas, final int orientation, float baseline, float textOffsetX) { + calcBarrierString(orientation); + String barrierString; + float barrierDistance; + float dangerDistance; + mPaint.setTextSize(mBarrierDistanceTextSize); + + if (orientation == UPWARD) { + barrierDistance = getUpwardBarrierDistance(); + dangerDistance = mUserSetUpBarrierAvoidanceDistance; + synchronized (mUpBarrierStringLock) { + barrierString = mUpBarrierString; + } + } else { + barrierDistance = getDownVisionDistance(); + dangerDistance = mUserSetDownBarrierAvoidanceDistance; + synchronized (mUpBarrierStringLock) { + barrierString = mDownBarrierString; + } + } + + if (barrierString == null) { + return; + } + + if (isShowFramework()) { + textOffsetX -= mPaint.measureText(barrierString); + } + int textColor = getBarrierTextColor(orientation, barrierDistance, dangerDistance); + drawTextWithStroke(canvas, barrierString, textOffsetX, baseline, mStrokeConfig.getStrokeBoldWidth(), mStrokeConfig.getStrokeDeepColor(), + textColor); + } + + private int getBarrierTextColor(int orientation, float barrierDistance, float dangerDistance) { + int result; + if (isUserDisable(orientation) || barrierDistance <= dangerDistance) { + result = mBarrierIndicatorColor; + } else { + result = mAvoidanceIndicatorColor; + } + return result; + } + + /** + * 避障被关闭 + */ + boolean isUserDisable(int orientation) { + return orientation == UPWARD && isUpwardUserDisable() + || (orientation == DOWNWARD && isDownwardUserDisable()); + } + + /** + * 上方避障关闭 + */ + boolean isUpwardUserDisable() { + return !mUpwardVisualEnable && !mUpwardRadarEnable; + } + + /** + * 下方避障关闭 + */ + boolean isDownwardUserDisable() { + return !mShowDownwardVisualPerceptionInfo; + } + + // /** + // * 绘制高度标识和文字 + // */ + // private void drawAttitudeIndicator(Canvas canvas, float height, int color, String text, float extraOffsetX, Drawable icon) { + // float current = getCurrentValue(); + // float offset = height - current; + // float ratio = (float) getFrameworkHeight() / mVisibleCalibrationUnitCount / mAttributeOffsetPerUnit; + // float y = offset * ratio; + // if (Math.abs(y) >= (float) getFrameworkHeight() / 2) { + // return; + // } + // canvas.save(); + // float calibrationHorizontalMargin = (float) (mPointerLineInnerWidth - mDegreeLineShortWidth) / 2; + // + // int lineWidth = mFrameworkStrokeWidth; + // mPaint.setStrokeWidth(lineWidth); + // mPaint.setColor(color); + // mPaint.setStyle(Paint.Style.FILL); + // mPaint.setTextSize(mAttitudeIndicatorTextSize); + // + // mStrokePaint.setColor(getResources().getColor(R.color.uxsdk_black_30_percent)); + // mStrokePaint.setStrokeWidth(getShadowLineStrokeWidth()); + // mStrokePaint.setStyle(Paint.Style.STROKE); + // + // float endX = calibrationHorizontalMargin + mDegreeLineLongWidth; + // float startX = Math.min(0, endX - mReturnToHomeIndicatorWidth); + // canvas.drawLine(startX, -y, endX, -y, mPaint); + // float halfShadowWidth = getShadowLineStrokeWidth() / 2; + // float halfWidth = lineWidth / 2f + halfShadowWidth; + // canvas.drawRect(startX - halfShadowWidth, -y - halfWidth, endX + halfShadowWidth, -y + halfWidth, mStrokePaint); + // + // if (!TextUtils.isEmpty(text)) { + // // 绘制文字 + // mPaint.setTextAlign(Paint.Align.LEFT); + // float textWidth = mPaint.measureText(text); + // float textStart = startX - textWidth - mWaypointIconPadding + extraOffsetX; + // float textY = FontUtils.getDigitalBaselineFromCenter(mPaint, -y, text); + // drawTextWithStroke(canvas, text, textStart, textY, getShadowLineStrokeWidth(), getResources().getColor(R.color + // .uxsdk_black_60_percent), + // color); + // } else if (icon != null) { + // // 绘制 icon + // int iconWidth = icon.getMinimumWidth(); + // int iconHeight = icon.getMinimumHeight(); + // int left = Math.round(startX - 2 - iconWidth + extraOffsetX); + // int top = Math.round(-y - icon.getMinimumHeight() / 2f); + // int right = left + iconWidth; + // int bottom = top + iconHeight; + // icon.setBounds(left, top, right, bottom); + // icon.draw(canvas); + // } + // canvas.restore(); + // } + + /** + * 绘制速度条 + */ + private void drawDistancePredict(Canvas canvas) { + if (Math.abs(mSpeedZ) <= SPEED_THRESHOLD) { + return; + } + canvas.save(); + float predictDistance = PREDICT_TIME_IN_SECONDS * mSpeedZ; + float ratio = (float) mAvoidanceMaxHeight / getMaxPerceptionDistanceInMeter(mSpeedZ > 0 ? UPWARD : DOWNWARD); + float predictArea = Math.abs(predictDistance * ratio); + + mPaint.setColor(Color.WHITE); + if (isShowFramework()) { + canvas.translate((float) mFrameworkStrokeWidth / 2, 0); + } + float halfHeight = mBarrierOriginLineWidth / 2; + float top, bottom; + if (predictDistance < 0) { + top = -(int) predictArea; + bottom = halfHeight; + } else { + bottom = (int) predictArea; + top = -halfHeight; + } + mPaint.setStyle(Paint.Style.FILL); + canvas.drawRect(0, top, mDistancePredictWidth, bottom, mPaint); + canvas.restore(); + } + + /** + * 获取高度在刻度上对应的实际长度 + */ + private float getViewHeightForDistance(float distance) { + if (!isShowFramework()) { + return 0; + } + return distance / mAttributeOffsetPerUnit * getFrameworkHeight() / mVisibleCalibrationUnitCount; + } + + private void drawBarrierOriginLine(Canvas canvas) { + float halfHeight = mBarrierOriginLineWidth / 2; + // 绘制速度原点线条 + if (!isShowFramework()) { + mPaint.setColor(Color.WHITE); + mPaint.setStyle(Paint.Style.FILL); + canvas.drawRect(-mBarrierOriginLineLength, halfHeight, 0, -halfHeight, mPaint); + mPaint.setColor(mStrokeConfig.getStrokeDeepColor()); + mPaint.setStyle(Paint.Style.STROKE); + mPaint.setStrokeWidth(getShadowLineStrokeWidth()); + canvas.drawRect(-mBarrierOriginLineLength, halfHeight, 0, -halfHeight, mPaint); + } + } + + private void drawBarrierInfo(Canvas canvas) { + if (isInEditMode()){ + return; + } + if (getUpVisionDistance() == Integer.MAX_VALUE + && mUpwardRadarDistance == Integer.MAX_VALUE + && getDownVisionDistance() == Integer.MAX_VALUE) { + return; + } + canvas.save(); + // 绘制上视障碍物的信息 + if (ProductUtil.isM300Product() && isUserDisable(UPWARD)) { + if (isShowFramework()) { + drawPfdBarrierUserDisableText(canvas, UPWARD); + } + } else if (needUpwardBarrierInfo()) { + canvas.save(); + drawBarrierInfo(canvas, UPWARD); + canvas.restore(); + } + // 绘制下视障碍物的信息 + if (ProductUtil.isM300Product() && isUserDisable(DOWNWARD)) { + if (isShowFramework()) { + drawPfdBarrierUserDisableText(canvas, DOWNWARD); + } + } else if (needDownwardBarrierInfo()) { + canvas.save(); + drawBarrierInfo(canvas, DOWNWARD); + canvas.restore(); + } + canvas.restore(); + } + + private void drawPfdBarrierUserDisableText(Canvas canvas, int orientation) { + float strokeWidth = mStrokeConfig.getStrokeThinWidth(); + mPaint.setStrokeWidth(strokeWidth); + float textOffsetX = -mAvoidanceIndicatorWidth - mBarrierTextMargin; + float textOffsetY = getViewHeightForDistance(PFD_BARRIER_OFF_TEXT_DISTANCE); + float baseline = orientation == UPWARD ? FontUtils.getDigitalBaselineFromTop(mPaint, -textOffsetY) : + FontUtils.getDigitalBaselineFromBottom(mPaint, textOffsetY); + drawBarrierText(canvas, orientation, baseline, textOffsetX); + } + + public int getMaxPerceptionDistanceInMeter(int orientation) { + return orientation == UPWARD ? mUpMaxPerceptionDistanceInMeter : mDownMaxPerceptionDistanceInMeter; + } + + boolean needBarrierInfo(int orientation) { + return orientation == UPWARD && needUpwardBarrierInfo() + || (orientation == DOWNWARD && needDownwardBarrierInfo()); + } + + private boolean needDownwardBarrierInfo() { + return getDownVisionDistance() <= getMaxPerceptionDistanceInMeter(DOWNWARD) + && (!ProductUtil.isM300Product() || mShowDownwardVisualPerceptionInfo); + } + + private boolean needUpwardBarrierInfo() { + int maxPerceptionDistanceInMeter = getMaxPerceptionDistanceInMeter(UPWARD); + return (getUpVisionDistance() <= maxPerceptionDistanceInMeter + && (!ProductUtil.isM300Product() || mUpwardVisualEnable)) + || ((!ProductUtil.isM300Product() || mUpwardRadarEnable) + && mUpwardRadarDistance <= maxPerceptionDistanceInMeter); + } + + private void drawBarrierInfo(Canvas canvas, int orientation) { + // 记录画布移动距离,在绘制障碍物距离时候,需要知道位移 + float[] canvasOffsetY = new float[1]; + // 原点宽度不算在避障高度里面 + float offsetY = isShowFramework() ? 0 : mBarrierOriginLineWidth / 2; + float avoidanceMaxHeight = mAvoidanceMaxHeight; + int maxPerceptionDistanceInMeter = getMaxPerceptionDistanceInMeter(orientation); + if (isShowFramework()) { + // pfd 中不考虑设置的避障条高度,使用实际刻度对应高度 + avoidanceMaxHeight = getViewHeightForDistance(maxPerceptionDistanceInMeter); + } + float barrierIndicatorHeight = avoidanceMaxHeight - offsetY; + float maxPerceptionDistanceBarrierValue = mBarrierDistanceStrategy.getBarrierValue((float) maxPerceptionDistanceInMeter); + if (maxPerceptionDistanceBarrierValue <= 0) { + LogUtils.e(TAG, "mMaxPerceptionDistanceInMeter must large than zero."); + return; + } + + canvas.translate(0, offsetY * orientation); + float ratio = barrierIndicatorHeight / maxPerceptionDistanceBarrierValue; + // 绘制上视障碍物最远感知条 + int restArea = drawMaxPerceptionIndicator(canvas, orientation, (int) barrierIndicatorHeight, ratio, canvasOffsetY); + // 绘制上视障碍物感知条 + if (restArea > 0) { + restArea = drawSettingPerceptionIndicator(canvas, orientation, restArea, ratio, canvasOffsetY); + // 绘制上视障碍物指示条 + drawBarrierIndicator(canvas, orientation, restArea, ratio, canvasOffsetY); + } + // 绘制上视障碍物指示条顶部横线及避障距离 + drawBarrier(canvas, orientation, canvasOffsetY); + + canvas.translate(0, -offsetY * orientation); + } + + private int drawMaxPerceptionIndicator(Canvas canvas, int orientation, int barrierIndicatorHeight, float ratio, float[] canvasOffsetY) { + float barrierDistance = orientation == UPWARD ? getUpwardBarrierDistance() : getDownVisionDistance(); + float perceptionDistance = orientation == UPWARD ? mUserSetUpBarrierWarnDistance : mUserSetDownBarrierWarnDistance; + + float barrierValue = mBarrierDistanceStrategy.getBarrierValue(barrierDistance); + float perceptionValue = mBarrierDistanceStrategy.getBarrierValue(perceptionDistance); + + mPaint.setColor(mAvoidanceIndicatorColor); + int strokeWidth = mAvoidanceIndicatorStrokeWidth; + float halfStrokeWidth = mAvoidanceIndicatorStrokeWidth / 2f; + mPaint.setStrokeWidth(strokeWidth); + mPaint.setStyle(Paint.Style.STROKE); + float outOfPerceptionDistanceRange = barrierValue - perceptionValue; + int restArea = barrierIndicatorHeight; + if (outOfPerceptionDistanceRange > 0) { + float outOfPerceptionArea = outOfPerceptionDistanceRange * ratio; + if (outOfPerceptionArea > restArea) { + outOfPerceptionArea = restArea; + } + if (isShowFramework()) { + float top; + float bottom; + if (orientation == UPWARD) { + top = -(int) outOfPerceptionArea + halfStrokeWidth; + bottom = 0; + } else { + top = 0; + bottom = (int) outOfPerceptionArea - halfStrokeWidth; + } + canvas.drawRect(-mAvoidanceIndicatorWidth + halfStrokeWidth, top, 0 - halfStrokeWidth, bottom, mPaint); + } + + int dy = (int) outOfPerceptionArea * orientation; + canvasOffsetY[0] += dy; + canvas.translate(0, dy); + restArea -= (int) outOfPerceptionArea; + } + return restArea; + } + + private int drawSettingPerceptionIndicator(Canvas canvas, int orientation, int restArea, float ratio, float[] canvasOffsetY) { + float barrierDistance = orientation == UPWARD ? getUpwardBarrierDistance() : getDownVisionDistance(); + float perceptionDistance = orientation == UPWARD ? mUserSetUpBarrierWarnDistance : mUserSetDownBarrierWarnDistance; + float barrierAvoidanceDistance = orientation == UPWARD ? mUserSetUpBarrierAvoidanceDistance : mUserSetDownBarrierAvoidanceDistance; + + float barrierValue = mBarrierDistanceStrategy.getBarrierValue(barrierDistance); + float perceptionValue = mBarrierDistanceStrategy.getBarrierValue(perceptionDistance); + float barrierAvoidanceValue = mBarrierDistanceStrategy.getBarrierValue(barrierAvoidanceDistance); + + mPaint.setColor(mAvoidanceIndicatorColor); + mPaint.setStyle(Paint.Style.FILL); + float upPerceptionArea; + if (perceptionValue > barrierValue) { + upPerceptionArea = (barrierValue - barrierAvoidanceValue) * ratio; + } else { + upPerceptionArea = (perceptionValue - barrierAvoidanceValue) * ratio; + } + if (upPerceptionArea > 0) { + if (upPerceptionArea > restArea) { + upPerceptionArea = restArea; + restArea = 0; + } else { + restArea -= upPerceptionArea; + } + int top; + int bottom; + if (orientation == UPWARD) { + top = -(int) upPerceptionArea; + bottom = 0; + } else { + top = 0; + bottom = (int) upPerceptionArea; + } + RECT.set(-mAvoidanceIndicatorWidth, top, 0, bottom); + canvas.drawRect(RECT, mPaint); + int dy = (int) upPerceptionArea * orientation; + canvasOffsetY[0] += dy; + canvas.translate(0, dy); + } + return restArea; + } + + //TODO 这里是绘制感知条高度的地方 + private int drawBarrierIndicator(Canvas canvas, int orientation, int restArea, float ratio, float[] canvasOffsetY) { + float barrierDistance = orientation == UPWARD ? getUpwardBarrierDistance() : getDownVisionDistance(); + float barrierAvoidanceDistance = orientation == UPWARD ? mUserSetUpBarrierAvoidanceDistance : mUserSetDownBarrierAvoidanceDistance; + + float barrierValue = mBarrierDistanceStrategy.getBarrierValue(barrierDistance); + float barrierAvoidanceValue = mBarrierDistanceStrategy.getBarrierValue(barrierAvoidanceDistance); + + + float upBarrierArea = (Math.min(barrierValue, barrierAvoidanceValue)) * ratio; + + if (upBarrierArea > 0) { + mPaint.setColor(mBarrierIndicatorColor); + if (upBarrierArea > restArea) { + upBarrierArea = restArea; + restArea = 0; + } else { + restArea -= upBarrierArea; + } + int top; + int bottom; + if (orientation == UPWARD) { + top = -(int) upBarrierArea; + bottom = 0; + } else { + top = 0; + bottom = (int) upBarrierArea; + } + + RECT.set(-mAvoidanceIndicatorWidth, top, 0, bottom); + canvas.drawRect(RECT, mPaint); + int dy = (int) upBarrierArea * orientation; + canvasOffsetY[0] += dy; + canvas.translate(0, dy); + } + return restArea; + } + + private void drawBarrier(Canvas canvas, int orientation, float[] canvasOffsetY) { + float canvasOffset = canvasOffsetY[0]; + Bitmap barrier; + if (orientation == UPWARD) { + barrier = mBarrierUp; + } else { + barrier = mBarrierDown; + } + if (barrier == null) { + return; + } + // 绘制上视障碍物指示条顶部横线 + float offsetX = isShowFramework() ? -mAvoidanceIndicatorWidth : -mAvoidanceIndicatorWidth / 2f - barrier.getWidth() / 2f; + float offsetY = orientation == UPWARD ? -barrier.getHeight() : 0; + canvas.drawBitmap(barrier, offsetX, offsetY, mPaint); + + if (isShowFramework()) { + drawPfdBarrierText(canvas, orientation, canvasOffset, barrier, offsetX); + } + } + + private void drawPfdBarrierText(Canvas canvas, int orientation, float canvasOffset, Bitmap barrier, float offsetX) { + float strokeWidth = mStrokeConfig.getStrokeThinWidth(); + mPaint.setStrokeWidth(strokeWidth); + float textOffsetY = (FontUtils.getDigitalTextDrawHeight(mPaint) + mBarrierTextMargin) * orientation; + float baseline; + if (orientation == UPWARD) { + float top = Math.min(textOffsetY - canvasOffset, -barrier.getHeight()); + baseline = FontUtils.getDigitalBaselineFromTop(mPaint, top) - mBarrierTextMargin; + } else { + float bottom = Math.max(textOffsetY - canvasOffset, barrier.getHeight()); + baseline = FontUtils.getDigitalBaselineFromBottom(mPaint, bottom) + mBarrierTextMargin; + } + drawBarrierText(canvas, orientation, baseline, offsetX - mBarrierTextMargin); + } + + @Override + protected String getCurrentValueDisplayFormat(boolean shorthand) { + return shorthand ? "%04.0f" : "%05.1f"; + } + + @Override + protected String getAttributeUnit() { + return UnitUtils.getUintStrByLength(UnitUtils.isMetricUnits() ? UnitUtils.UnitType.METRIC : UnitUtils.UnitType.IMPERIAL); + } + + @Override + protected float getDisplayValue(float value) { + return UnitUtils.getValueFromMetricByLength(value, UnitUtils.isMetricUnits() ? UnitUtils.UnitType.METRIC : UnitUtils.UnitType.IMPERIAL); + } + + @Override + protected int getIndicatorLineLength() { + return mReturnToHomeIndicatorWidth; + } + + private float getUpwardBarrierDistance() { + if (mUpwardVisualEnable && mUpwardRadarEnable) { + return Math.min(mUpwardRadarDistance, getUpVisionDistance()); + } else if (mUpwardRadarEnable) { + return mUpwardRadarDistance; + } else { + return getUpVisionDistance(); + } + } + + + private float getUpVisionDistance() { + return mPerceptionObstacleData.getUpwardObstacleDistance() / 1000f; + } + + private float getDownVisionDistance() { + return mPerceptionObstacleData.getDownwardObstacleDistance() / 1000f; + } + + /** + * 距离转避障条高度的策略以及避障条在 pfd 中起飞/降落时下方避障在 0 点 + */ + interface IBarrierDistanceStrategy { + /** + * 根据距离获取避障条高度比例 + */ + float getBarrierValue(float distance); + } + + private static class HsiBarrierDistanceStrategy implements IBarrierDistanceStrategy { + @Override + public float getBarrierValue(float distance) { + if (distance <= 0) { + return 0; + } else if (distance <= 2) { + return distance / 2; + } else if (distance <= 5) { + return (distance + 1) / 3; + } else { + return (float) (0.3045f + 1.0769f * Math.log(distance)); + } + } + } + + private static class PfdBarrierDistanceStrategy implements IBarrierDistanceStrategy { + @Override + public float getBarrierValue(float distance) { + Log.d(TAG, "PfdBarrierDistanceStrategy getBarrierValue=" + distance); + + return distance; + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/dashboard/FpvStrokeConfig.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/dashboard/FpvStrokeConfig.kt new file mode 100644 index 00000000..79ff2d9c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/dashboard/FpvStrokeConfig.kt @@ -0,0 +1,31 @@ +package dji.v5.ux.core.ui.hsi.dashboard + +import android.content.Context +import android.graphics.Color + +/** + * Pilot UI 2.0 在 FPV 绘制中,需要添加描边 + * 描边不同级别属性在此类中统一配置,方便统一修改 + */ +class FpvStrokeConfig( + context: Context, + boldWidth: Float, + thinWidth: Float, + val strokeDeepColor: Int, + val strokeShallowColor: Int +) { + + constructor(context: Context, boldWidth: Float, thinWidth: Float) + : this(context, boldWidth, thinWidth, Color.argb(0x99, 0, 0, 0), 0x4D000000) + + constructor(context: Context) : this(context, 0.5f, 0.2f) + + val strokeBoldWidth: Float + val strokeThinWidth: Float + + init { + val density = context.resources.displayMetrics.density + strokeBoldWidth = boldWidth * density + strokeThinWidth = thinWidth * density + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/dashboard/ScrollableAttributeDashBoard.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/dashboard/ScrollableAttributeDashBoard.java new file mode 100644 index 00000000..9e3c96d3 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/dashboard/ScrollableAttributeDashBoard.java @@ -0,0 +1,918 @@ +package dji.v5.ux.core.ui.hsi.dashboard; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.Path; +import android.graphics.Rect; +import android.graphics.RectF; +import android.graphics.Region; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Looper; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewDebug; + + +import androidx.annotation.MainThread; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + + +import dji.v5.utils.common.DJIExecutor; +import dji.v5.ux.R; +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.core.util.FontUtils; + +public abstract class ScrollableAttributeDashBoard extends View { + public static final String TAG = "ScrollableAttributeDashBoard"; + protected static final Rect RECT = new Rect(); + + private static final Path PATH = new Path(); + + private static final Float DEFAULT_OFFSET_PER_UNIT = 1f; + + /** + * 最多显示多少个刻度 + */ + private static final int DEFAULT_VISIBLE_CALIBRATION_UNIT_COUNT = 20; + + private static final int SMALL_CALIBRATION_UNIT_COUNT_BETWEEN_TWO_BIG_CALIBRATION_UNIT = 5; + + /** + * 文字在左侧 + */ + private static final int DASH_BOARD_ALIGN_LEFT = 0; + + /** + * 文字在右侧 + */ + private static final int DASH_BOARD_ALIGN_RIGHT = 1; + + private static final int DEFAULT_DASH_BOARD_ALIGN = DASH_BOARD_ALIGN_LEFT; + public static final String VIEW_PROPERTY_CATEGORY_DJI = "dji"; + + /** + * 属性名称 + */ + private final String mAttributeName; + + private float mAttributePadding; + + /** + * 每个小刻度的偏移值 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + protected final float mAttributeOffsetPerUnit; + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + private boolean mShowBorder; + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + private float mBorderRadius; + private int mBorderColor; + private float mBorderWidth; + + /** + * 刻度的字体大小 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + private final int mAttributeCalibrationTextSize; + + /** + * 当前刻度的字体大小 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + private final int mAttributeCurrentCalibrationTextSize; + + /** + * 当前属性单位字体大小 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + private final int mAttributeUnitTextSize; + + /** + * 当前属性名称的字体大小 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + private final int mAttributeNameTextSize; + + /** + * 最大值 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + private final float mAttributeMaxValue; + + /** + * 最小值 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + private final float mAttributeMinValue; + + /** + * 仪表盘的朝向(左/右) + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI, prefix = "hsi_", mapping = { + @ViewDebug.IntToString(from = DASH_BOARD_ALIGN_LEFT, to = "left"), + @ViewDebug.IntToString(from = DASH_BOARD_ALIGN_RIGHT, to = "right") + }) + private final int mAttributeDashBoardAlign; + + /** + * 属性的当前值 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI, prefix = "hsi_") + private float mCurrentValue; + + /** + * 属性当前值颜色 + */ + private int mCurrentValueColor; + + /** + * 属性值内边距 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI, prefix = "hsi_") + private float mCurrentValuePadding; + + private int mAttributePropertyColor; + + + /** + * 仪表盘中可视的刻度数量 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + protected int mVisibleCalibrationUnitCount; + + /** + * dashboard框架线条的宽度 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + protected int mFrameworkStrokeWidth; + + /** + * dashboard框架线条的主色 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI, formatToHexString = true) + protected int mFrameworkPrimaryColor; + + /** + * dashboard框架线条的次要色 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI, formatToHexString = true) + protected int mFrameworkSecondaryColor; + + /** + * dashboard主刻度的颜色 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI, formatToHexString = true) + protected int mFrameworkFrameValueColor; + + /** + * dashboard框架线条的描边色 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI, formatToHexString = true) + protected int mFrameworkStrokeColor; + + /** + * 是否显示dashboard框架 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + private final boolean mShowFramework; + + /** + * dashboard框架的宽度 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + private final int mFrameworkWidth; + + /** + * dashboard框架的高度 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + private final int mFrameworkHeight; + + /** + * dashboard指针的高度 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + private final int mPointerHeight; + + /** + * dashboard指针的宽度 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + private final int mPointerWidth; + + /** + * 框架相对于起始位置的距离 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + protected final int mFrameworkPaddingStart; + + /** + * 框架垂直方向间距,避免刻度文字被截 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + protected int mFrameworkPaddingVercital; + + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + /** + * 1. 当前值指示线,刻度内侧 + * 2. 短刻度线在内侧占据宽度,超过线宽部分左右为 margin + */ + protected final int mPointerLineInnerWidth; + + /** + * 当前值指示线,刻度外侧 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + protected final int mPointerLineOuterWidth; + /** + * 当前值离框架额外边距 + */ + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + protected final int mTextPadding; + + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + protected final int mDegreeLineLongWidth; + + @ViewDebug.ExportedProperty(category = VIEW_PROPERTY_CATEGORY_DJI) + protected final int mDegreeLineShortWidth; + + protected Paint mPaint; + protected Paint mStrokePaint; + + protected Drawable mWaypointIcon; + + private float mCalibrationTextPadding; + + protected float mWaypointIconPadding; + + private final Object mDisplayValueLock = new Object(); + protected DisplayValue mDisplayValue; + + /** + * 100ms,减少性能压力 + */ + private static final int INVALIDATE_INTERVAL_TIME = 100; + private static final int MSG_INVALIDATE = 0x01; + @NonNull + private final Handler.Callback mCallback = msg -> { + if (msg.what == MSG_INVALIDATE) { + invalidate(); + return true; + } + return false; + }; + + @Nullable + private Handler mHandler; + + + // @NonNull + // private final Object mRxObject = new Object() { + // @Subscribe(thread = EventThread.MAIN_THREAD, tags = { + // @Tag(BusAction.TAG_ON_UNIT_CHANGED) + // }) + // @SuppressWarnings("unused") + // public void onEventUnitChanged(Integer unit) { + // // 单位变化后,更新一下显示的值 + // setCurrentValue(mCurrentValue); + // updateWidget(); + // } + // }; + protected FpvStrokeConfig mStrokeConfig; + private Typeface mDefaultTypeface; + private Typeface mCalibrationTextTypeface; + private final int mStrokeColor = AndUtil.getResColor(R.color.uxsdk_black_30_percent); + private final float mCalibrationLineStrokeWidth = (float) getResources().getDimensionPixelSize(R.dimen.uxsdk_1_dp) / 2; + private final int mTextColor = AndUtil.getResColor(R.color.uxsdk_green_in_dark); + + protected Handler mDataHandler; + + protected ScrollableAttributeDashBoard(Context context) { + this(context, null); + } + + protected ScrollableAttributeDashBoard(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + protected ScrollableAttributeDashBoard(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + if (!isInEditMode()) { + mDataHandler = new Handler(DJIExecutor.getLooper()); + } + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.ScrollableAttributeDashBoard); + mAttributeName = typedArray.getString(R.styleable.ScrollableAttributeDashBoard_uxsdk_name); + mAttributeCalibrationTextSize = typedArray.getDimensionPixelSize(R.styleable.ScrollableAttributeDashBoard_uxsdk_calibration_text_size, + getResources().getDimensionPixelOffset(R.dimen.uxsdk_text_size_normal_medium)); + mPointerWidth = typedArray.getDimensionPixelSize(R.styleable.ScrollableAttributeDashBoard_uxsdk_pointer_width, + getResources().getDimensionPixelOffset(R.dimen.uxsdk_65_dp)); + mPointerHeight = typedArray.getDimensionPixelSize(R.styleable.ScrollableAttributeDashBoard_uxsdk_pointer_height, + getResources().getDimensionPixelOffset(R.dimen.uxsdk_21_dp)); + mFrameworkWidth = typedArray.getDimensionPixelSize(R.styleable.ScrollableAttributeDashBoard_uxsdk_framework_width, + getResources().getDimensionPixelOffset(R.dimen.uxsdk_25_dp)); + mFrameworkHeight = typedArray.getDimensionPixelSize(R.styleable.ScrollableAttributeDashBoard_uxsdk_framework_height, + getResources().getDimensionPixelOffset(R.dimen.uxsdk_117_dp)); + mFrameworkStrokeWidth = typedArray.getDimensionPixelSize(R.styleable.ScrollableAttributeDashBoard_uxsdk_framework_stroke_width, + getResources().getDimensionPixelSize(R.dimen.uxsdk_1_dp)); + mFrameworkPrimaryColor = typedArray.getColor(R.styleable.ScrollableAttributeDashBoard_uxsdk_framework_primary_color, + getResources().getColor(R.color.uxsdk_green_in_dark)); + mFrameworkSecondaryColor = typedArray.getColor(R.styleable.ScrollableAttributeDashBoard_uxsdk_framework_secondary_color, + getResources().getColor(R.color.uxsdk_green_in_dark_045)); + mFrameworkStrokeColor = typedArray.getColor(R.styleable.ScrollableAttributeDashBoard_uxsdk_framework_stroke_color, + getResources().getColor(R.color.uxsdk_black_30_percent)); + mPointerLineInnerWidth = typedArray.getDimensionPixelSize(R.styleable.ScrollableAttributeDashBoard_uxsdk_pointer_line_inner_width, 0); + mPointerLineOuterWidth = typedArray.getDimensionPixelSize(R.styleable.ScrollableAttributeDashBoard_uxsdk_pointer_line_outer_width, + getResources().getDimensionPixelOffset(R.dimen.uxsdk_6_dp)); + mTextPadding = typedArray.getDimensionPixelSize(R.styleable.ScrollableAttributeDashBoard_uxsdk_pointer_text_padding, + getResources().getDimensionPixelOffset(R.dimen.uxsdk_2_dp)); + mFrameworkPaddingStart = typedArray.getDimensionPixelSize(R.styleable.ScrollableAttributeDashBoard_uxsdk_calibration_framework_padding_start, + getResources().getDimensionPixelOffset(R.dimen.uxsdk_21_dp)); + mFrameworkPaddingVercital = + typedArray.getDimensionPixelSize(R.styleable.ScrollableAttributeDashBoard_uxsdk_calibration_framework_padding_vertical, + getResources().getDimensionPixelOffset(R.dimen.uxsdk_3_dp)); + mDegreeLineLongWidth = typedArray.getDimensionPixelSize(R.styleable.ScrollableAttributeDashBoard_uxsdk_degree_line_long, + getResources().getDimensionPixelOffset(R.dimen.uxsdk_8_dp)); + mDegreeLineShortWidth = typedArray.getDimensionPixelSize(R.styleable.ScrollableAttributeDashBoard_uxsdk_degree_line_short, + getResources().getDimensionPixelOffset(R.dimen.uxsdk_6_dp)); + mAttributeUnitTextSize = typedArray.getDimensionPixelSize(R.styleable.ScrollableAttributeDashBoard_uxsdk_unit_text_size, + getResources().getDimensionPixelOffset(R.dimen.uxsdk_text_size_small)); + mAttributeNameTextSize = typedArray.getDimensionPixelSize(R.styleable.ScrollableAttributeDashBoard_uxsdk_name_text_size, + getResources().getDimensionPixelOffset(R.dimen.uxsdk_text_size_normal)); + mAttributeCurrentCalibrationTextSize = + typedArray.getDimensionPixelSize(R.styleable.ScrollableAttributeDashBoard_uxsdk_current_calibration_text_size, + getResources().getDimensionPixelOffset(R.dimen.uxsdk_text_size_medium_large)); + mAttributePadding = typedArray.getDimension(R.styleable.ScrollableAttributeDashBoard_uxsdk_padding, + getResources().getDimension(R.dimen.uxsdk_2_dp)); + mAttributeMaxValue = typedArray.getFloat(R.styleable.ScrollableAttributeDashBoard_uxsdk_max_value, Float.MAX_VALUE); + mAttributeMinValue = typedArray.getFloat(R.styleable.ScrollableAttributeDashBoard_uxsdk_min_value, -Float.MAX_VALUE); + mAttributeOffsetPerUnit = typedArray.getFloat(R.styleable.ScrollableAttributeDashBoard_uxsdk_offset_per_unit, DEFAULT_OFFSET_PER_UNIT); + mCalibrationTextPadding = typedArray.getDimension(R.styleable.ScrollableAttributeDashBoard_uxsdk_calibration_text_padding, + getResources().getDimension(R.dimen.uxsdk_2_dp)); + mShowBorder = typedArray.getBoolean(R.styleable.ScrollableAttributeDashBoard_uxsdk_show_border, false); + mBorderColor = typedArray.getColor(R.styleable.ScrollableAttributeDashBoard_uxsdk_border_color, + getResources().getColor(R.color.uxsdk_green_in_dark)); + mBorderWidth = typedArray.getDimension(R.styleable.ScrollableAttributeDashBoard_uxsdk_border_width, + getResources().getDimension(R.dimen.uxsdk_0_6_dp)); + mBorderRadius = typedArray.getDimension(R.styleable.ScrollableAttributeDashBoard_uxsdk_border_radius, + getResources().getDimension(R.dimen.uxsdk_2_dp)); + float currentValue = typedArray.getFloat(R.styleable.ScrollableAttributeDashBoard_uxsdk_current_value, 0); + mCurrentValueColor = typedArray.getColor(R.styleable.ScrollableAttributeDashBoard_uxsdk_current_value_color, Color.WHITE); + mCurrentValuePadding = typedArray.getDimension(R.styleable.ScrollableAttributeDashBoard_uxsdk_current_value_padding, + getResources().getDimension(R.dimen.uxsdk_2_dp)); + mAttributePropertyColor = typedArray.getColor(R.styleable.ScrollableAttributeDashBoard_uxsdk_property_color, Color.WHITE); + mAttributeDashBoardAlign = typedArray.getInt(R.styleable.ScrollableAttributeDashBoard_uxsdk_dash_board_align, DEFAULT_DASH_BOARD_ALIGN); + mVisibleCalibrationUnitCount = typedArray.getInt(R.styleable.ScrollableAttributeDashBoard_uxsdk_visible_calibration_unit_count, + DEFAULT_VISIBLE_CALIBRATION_UNIT_COUNT); + mShowFramework = typedArray.getBoolean(R.styleable.ScrollableAttributeDashBoard_uxsdk_show_calibration_framework, true); + typedArray.recycle(); + + mDefaultTypeface = Typeface.create("sans-serif-condensed", Typeface.BOLD); + mCalibrationTextTypeface = Typeface.create("sans-serif-condensed", Typeface.NORMAL); + mPaint = new Paint(Paint.DITHER_FLAG | Paint.ANTI_ALIAS_FLAG); + mStrokePaint = new Paint(Paint.DITHER_FLAG | Paint.ANTI_ALIAS_FLAG); + restoreTypeface(); + + mWaypointIconPadding = getResources().getDimension(R.dimen.uxsdk_1_dp); + + mFrameworkFrameValueColor = mFrameworkPrimaryColor; + setCurrentValue(currentValue); + + mDisplayValue = new DisplayValue(); + mStrokeConfig = new FpvStrokeConfig(context); + } + + private void restoreTypeface() { + mPaint.setTypeface(mDefaultTypeface); + mStrokePaint.setTypeface(mDefaultTypeface); + } + + private void setCalibrationTypeface() { + mPaint.setTypeface(mCalibrationTextTypeface); + mStrokePaint.setTypeface(mCalibrationTextTypeface); + } + + /** + * 线条描边宽度 + */ + protected float getShadowLineStrokeWidth() { + return mStrokeConfig.getStrokeThinWidth(); + } + + /** + * 文字描边宽度 + */ + protected float getShadowTextStrokeWidth() { + return mStrokeConfig.getStrokeBoldWidth(); + } + + /** + * 线条描边颜色 + */ + protected int getShadowLineStrokeColor() { + return mStrokeConfig.getStrokeShallowColor(); + } + + /** + * 文字描边颜色 + */ + protected int getShadowTextStrokeColor() { + return mStrokeConfig.getStrokeDeepColor(); + } + + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + mHandler = new Handler(Looper.getMainLooper(), mCallback); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (mHandler != null) { + mHandler.removeCallbacksAndMessages(null); + mHandler = null; + } + if (mDataHandler != null) { + mDataHandler.removeCallbacksAndMessages(null); + } + } + + @MainThread + public void setCurrentValue(float currentValue) { + if (isInEditMode()){ + return; + } + if (currentValue > mAttributeMaxValue) { + currentValue = mAttributeMaxValue; + } else if (currentValue < mAttributeMinValue) { + currentValue = mAttributeMinValue; + } + mCurrentValue = currentValue; + final float value = currentValue; + mDataHandler.post(() -> { + calcDisplayValue(value); + updateWidget(); + }); + } + + protected void updateWidget() { + if (mHandler != null && !mHandler.hasMessages(MSG_INVALIDATE)) { + mHandler.sendEmptyMessageDelayed(MSG_INVALIDATE, INVALIDATE_INTERVAL_TIME); + } + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + int widthSpecMode = MeasureSpec.getMode(widthMeasureSpec); + int heightSpecMode = MeasureSpec.getMode(heightMeasureSpec); + int widthSpecSize = MeasureSpec.getSize(widthMeasureSpec); + int heightSpecSize = MeasureSpec.getSize(heightMeasureSpec); + int measuredWidth = getDefaultSize(getSuggestedMinimumWidth(), widthMeasureSpec); + int measuredHeight = getDefaultSize(getSuggestedMinimumHeight(), heightMeasureSpec); + if (widthSpecMode != MeasureSpec.EXACTLY) { + int minWidth = getMinWidth(); + if (widthSpecMode == MeasureSpec.UNSPECIFIED) { + measuredWidth = minWidth; + } else { + measuredWidth = Math.min(minWidth, widthSpecSize); + } + } + if (heightSpecMode != MeasureSpec.EXACTLY) { + int minHeight = getMinHeight(); + if (widthSpecMode == MeasureSpec.UNSPECIFIED) { + measuredHeight = minHeight; + } else { + measuredHeight = Math.min(minHeight, heightSpecSize); + } + } + setMeasuredDimension(measuredWidth, measuredHeight); + } + + protected int getMinHeight() { + if (mShowFramework) { + return mFrameworkHeight + mFrameworkPaddingVercital * 2; + } else { + return mPointerHeight + mFrameworkStrokeWidth * 2; + } + } + + protected int getMinWidth() { + return mPointerWidth + mFrameworkPaddingStart + mPointerLineInnerWidth + mTextPadding + mFrameworkStrokeWidth; + } + + protected int getFrameworkHeight() { + return mFrameworkHeight; + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + drawCurrentValue(canvas); + clipPointerArea(canvas); + if (mShowFramework) { + drawCalibration(canvas); + drawCalibrationFramework(canvas); + } + } + + protected float getCurrentValue() { + return mCurrentValue; + } + + protected boolean isShowFramework() { + return mShowFramework; + } + + /** + * 裁切中间文本部分,避免和刻度重合 + * + * @see #drawCurrentBackground(Canvas, int, int) + */ + private void clipPointerArea(Canvas canvas) { + int currentAreaOffsetX = mFrameworkPaddingStart + mPointerLineInnerWidth + mTextPadding; + boolean alginLeft = isAlginLeft(); + if (!alginLeft) { + currentAreaOffsetX = getWidth() - currentAreaOffsetX; + } + float currentAreaOffsetY = (getHeight() - mPointerHeight) / 2f; + PATH.reset(); + PATH.addRoundRect(0, 0, alginLeft ? mPointerWidth : -mPointerWidth, mPointerHeight, mBorderRadius, mBorderRadius, Path.Direction.CW); + PATH.offset(currentAreaOffsetX, currentAreaOffsetY); + canvas.clipPath(PATH, Region.Op.DIFFERENCE); + } + + + private Path tmpPath = new Path(); + + /** + * 绘制左边框架 + * + * @param canvas + */ + private void drawCalibrationFramework(Canvas canvas) { + RectF rect = new RectF(); + mPaint.setColor(mFrameworkPrimaryColor); + mPaint.setStrokeWidth(mFrameworkStrokeWidth); + mPaint.setStyle(Paint.Style.STROKE); + int width = getWidth(); + boolean alginLeft = isAlginLeft(); + tmpPath.reset(); + + float strokeWidth = mFrameworkStrokeWidth; + float halfStrokeWidth = mFrameworkStrokeWidth / 2f; + float shadowStrokeWidth = getShadowLineStrokeWidth(); + float halfShadowWidth = shadowStrokeWidth / 2; + + int offsetX = alginLeft ? mFrameworkPaddingStart : width - mFrameworkPaddingStart; + float fw = alginLeft ? mFrameworkWidth : -mFrameworkWidth; + // 设置坐标框架的四个点 + float top = (getHeight() - mFrameworkHeight) / 2f; + rect.set(offsetX, top, offsetX + fw, top + mFrameworkHeight); + // 获取框架的四个点坐标 + tmpPath.moveTo(rect.right, rect.top); + tmpPath.lineTo(rect.left, rect.top); + tmpPath.lineTo(rect.left, rect.bottom); + tmpPath.lineTo(rect.right, rect.bottom); + + // 绘制框架 + mPaint.setColor(mFrameworkPrimaryColor); + mPaint.setStrokeWidth(mFrameworkStrokeWidth); + canvas.drawPath(tmpPath, mPaint); + + // 获取描边外框四点坐标 + rect.inset(-halfShadowWidth - halfStrokeWidth, -halfShadowWidth - halfStrokeWidth); + tmpPath.reset(); + tmpPath.moveTo(rect.right, rect.top); + tmpPath.lineTo(rect.left, rect.top); + tmpPath.lineTo(rect.left, rect.bottom); + tmpPath.lineTo(rect.right, rect.bottom); + // 获取描边内框四个点坐标 + rect.inset(shadowStrokeWidth + strokeWidth, shadowStrokeWidth + strokeWidth); + tmpPath.lineTo(rect.right, rect.bottom); + tmpPath.lineTo(rect.left, rect.bottom); + tmpPath.lineTo(rect.left, rect.top); + tmpPath.lineTo(rect.right, rect.top); + tmpPath.close(); + + // 绘制框架描边 + mPaint.setStyle(Paint.Style.STROKE); + mPaint.setColor(mFrameworkStrokeColor); + mPaint.setStrokeWidth(getShadowLineStrokeWidth()); + canvas.drawPath(tmpPath, mPaint); + } + + /** + * @param canvas + */ + private void drawCalibration(Canvas canvas) { + int width = getWidth(); + int height = getHeight(); + float centerY = height / 2f; + float calibrationHorizontalMargin = (mPointerLineInnerWidth - mDegreeLineShortWidth) / 2f; + float offsetMargin = (float) mFrameworkHeight / mVisibleCalibrationUnitCount; + float currentPerUnitValue = mCurrentValue / mAttributeOffsetPerUnit; + int currentPerUnitCount = (int) currentPerUnitValue; + float currentValueOffset = (currentPerUnitValue - currentPerUnitCount) * offsetMargin; + + canvas.save(); + setCalibrationTypeface(); + + float offsetY = currentValueOffset + centerY; + mStrokePaint.setColor(mStrokeColor); + mStrokePaint.setStrokeWidth(getShadowLineStrokeWidth()); + mStrokePaint.setStyle(Paint.Style.STROKE); + boolean alignLeft = isAlginLeft(); + int offsetX = alignLeft ? mFrameworkPaddingStart : width - (mFrameworkPaddingStart); + canvas.translate(offsetX, 0); + for (int i = -mVisibleCalibrationUnitCount / 2; i <= mVisibleCalibrationUnitCount / 2; i++) { + int currentCalibrationUnit = currentPerUnitCount - i; + float y = i * offsetMargin; + float calibrationValue = currentCalibrationUnit * mAttributeOffsetPerUnit; + if (needDrawValue(calibrationValue)) { + continue; + } + mPaint.setColor(mFrameworkSecondaryColor); + mPaint.setStrokeWidth(mCalibrationLineStrokeWidth); + mPaint.setStyle(Paint.Style.FILL); + mStrokePaint.setColor(mStrokeColor); + mStrokePaint.setStrokeWidth(getShadowLineStrokeWidth()); + mStrokePaint.setStyle(Paint.Style.STROKE); + + // 如果是0,则画长的刻度线,以及标上刻度,否则只画小的刻度线 + int drawDirect = alignLeft ? 1 : -1; + float calibrationStartX = calibrationHorizontalMargin * drawDirect; + boolean drawText = currentCalibrationUnit % SMALL_CALIBRATION_UNIT_COUNT_BETWEEN_TWO_BIG_CALIBRATION_UNIT == 0; + int lineLength = drawDirect * (drawText ? mDegreeLineLongWidth : mDegreeLineShortWidth); + float lineOffsetY = y + offsetY; + if (lineInFramework(centerY, lineOffsetY)) { + // 绘制范围超出框架高度范围 + continue; + } + drawCalibrationHorizontal(canvas, calibrationStartX, lineOffsetY, lineLength, drawText); + if (drawText) { + // 主要刻度文字 + float textStartX = 2 * calibrationStartX + lineLength + (alignLeft ? mCalibrationTextPadding : -mCalibrationTextPadding); + drawCalibrationText(canvas, offsetMargin, lineOffsetY, calibrationValue, textStartX, alignLeft); + } + } + restoreTypeface(); + canvas.restore(); + } + + private boolean needDrawValue(float calibrationValue) { + return calibrationValue > mAttributeMaxValue || calibrationValue < mAttributeMinValue; + } + + private boolean lineInFramework(float centerY, float lineOffsetY) { + return lineOffsetY > centerY + mFrameworkHeight / 2f || lineOffsetY < centerY - mFrameworkHeight / 2f; + } + + /** + * 绘制刻度文字 + */ + private void drawCalibrationText(Canvas canvas, float offsetMargin, float y, float calibrationValue, float textStartX, boolean alignLeft) { + mPaint.setTextAlign(Paint.Align.LEFT); + mPaint.setTextSize(mAttributeCalibrationTextSize); + int value = Math.round(calibrationValue); + String currentValueString; + if (value < 0) { + currentValueString = value > -10 ? "-0" + value : "" + value; + } else { + currentValueString = value < 10 ? "0" + value : "" + value; + } + mPaint.getTextBounds(currentValueString, 0, currentValueString.length(), RECT); + Paint.FontMetricsInt fontMetrics = mPaint.getFontMetricsInt(); + float baseline = (offsetMargin - fontMetrics.bottom + fontMetrics.top) / 2 - fontMetrics.top; + drawTextWithStroke(canvas, currentValueString, alignLeft ? textStartX : textStartX - RECT.width(), baseline + y - offsetMargin / 2, + getShadowLineStrokeWidth(), mStrokeColor, mTextColor); + } + + /** + * 绘制小刻度线 + */ + private void drawCalibrationHorizontal(Canvas canvas, float x, float y, int length, boolean needText) { + float width = mPaint.getStrokeWidth(); + // 绘制区域,刻度线不与框架相交 + if (y - width / 2f < (getHeight() - mFrameworkHeight) / 2f - mFrameworkStrokeWidth / 2f || y + width / 2 > (getHeight() + mFrameworkHeight) / 2f - mFrameworkStrokeWidth / 2f) { + return; + } + mPaint.setColor(needText ? mFrameworkFrameValueColor : mFrameworkSecondaryColor); + canvas.drawLine(x, y, x + length, y, mPaint); + canvas.drawRect(x, y - width, x + length, y + width, mStrokePaint); + } + + protected int getIndicatorLineLength() { + return 0; + } + + /** + * 绘制当前值区域 + * + * @param canvas + */ + private void drawCurrentValue(Canvas canvas) { + int width = getWidth(); + int height = getHeight(); + DisplayValue displayValue; + synchronized (mDisplayValueLock) { + displayValue = mDisplayValue; + } + if (displayValue == null || displayValue.mDisplayValue == null || displayValue.mDisplayUnit == null) { + return; + } + String currentValueString = displayValue.mDisplayValue; + int canvasMark = canvas.save(); + + boolean alginLeft = isAlginLeft(); + int alginDirect = alginLeft ? 1 : -1; + + // 移动画布到当前值绘制区域,向左时为左上点,向右时为右上点 + int currentAreaOffsetX = mFrameworkPaddingStart + mPointerLineInnerWidth + mTextPadding; + if (!alginLeft) { + currentAreaOffsetX = width - currentAreaOffsetX; + } + float currentAreaOffsetY = (height - mPointerHeight) / 2f; + canvas.translate(currentAreaOffsetX, currentAreaOffsetY); + + int currentWidth = mPointerWidth * alginDirect; + if (mShowBorder) { + drawCurrentValueLine(canvas, mPointerHeight, alginLeft); + drawCurrentBackground(canvas, currentWidth, mPointerHeight); + } + drawCurrentText(canvas, currentValueString, alginLeft); + drawCurrentName(canvas, mAttributeName, alginLeft); + drawCurrentUnit(canvas, displayValue.mDisplayUnit, alginLeft); + + canvas.restoreToCount(canvasMark); + } + + private void drawCurrentValueLine(Canvas canvas, int pointerHeight, boolean alginLeft) { + int lineLength = mPointerLineInnerWidth + mTextPadding; + float left; + float top; + float right; + float bottom; + if (alginLeft) { + left = -lineLength; + right = 0; + } else { + left = 0; + right = lineLength; + } + Paint backgroundPaint = getBackgroundPaint(); + float lineWidth = backgroundPaint.getStrokeWidth(); + float centerY = pointerHeight / 2f; + top = centerY - lineWidth / 2; + bottom = centerY + lineWidth / 2; + float lineY = centerY; + canvas.drawLine(left, lineY, right, lineY, backgroundPaint); + float strokeWidth = getShadowLineStrokeWidth(); + mStrokePaint.setColor(getShadowLineStrokeColor()); + mStrokePaint.setStrokeWidth(strokeWidth); + mStrokePaint.setStyle(Paint.Style.STROKE); + lineY = top - strokeWidth / 2; + canvas.drawLine(left, lineY, right, lineY, backgroundPaint); + lineY = bottom + strokeWidth / 2; + canvas.drawLine(left, lineY, right, lineY, backgroundPaint); + } + + protected DisplayValue calcDisplayValue(float currentValue) { + float displayValue = getDisplayValue(currentValue); + // 数字比较添加 0.5 是为了避免出现 999.95 显示成 1000.0 + boolean shorthand = displayValue + 0.05f > 1000; + final String unit = getAttributeUnit(); + final String value = String.format(getCurrentValueDisplayFormat(shorthand), displayValue); + synchronized (mDisplayValueLock) { + if (mDisplayValue == null) { + mDisplayValue = new DisplayValue(); + } + mDisplayValue.set(value, unit); + } + return mDisplayValue; + } + + private boolean isAlginLeft() { + return mAttributeDashBoardAlign == DASH_BOARD_ALIGN_LEFT; + } + + /** + * 绘制当前值单位 + */ + private void drawCurrentUnit(Canvas canvas, String text, boolean alignLeft) { + Paint paint = getUnitPaint(); + float len = paint.measureText(text); + // 让属性单位紧贴顶部 + float unitTextOffset; + if (alignLeft) { + unitTextOffset = mPointerWidth - len - mAttributePadding; + } else { + unitTextOffset = -mPointerWidth + mAttributePadding; + } + float unitTextBaseline = FontUtils.getDigitalBaselineFromTop(paint, mPointerHeight / 2f) + 1; + drawTextWithStroke(canvas, text, unitTextOffset, unitTextBaseline, getShadowTextStrokeWidth(), getShadowTextStrokeColor(), + mAttributePropertyColor); + } + + private Paint getUnitPaint() { + // 画出属性单位 + mPaint.setTextSize(mAttributeUnitTextSize); + return mPaint; + } + + /** + * 绘制当前值名称 + */ + private void drawCurrentName(Canvas canvas, String text, boolean alginLeft) { + Paint paint = getCurrentNamePaint(); + float len = paint.measureText(text); + float attrTextOffset; + if (alginLeft) { + attrTextOffset = mPointerWidth - len - mAttributePadding; + } else { + attrTextOffset = -mPointerWidth + mAttributePadding; + } + float baseline = FontUtils.getDigitalBaselineFromBottom(mPaint, mPointerHeight / 2f) - 1; + drawTextWithStroke(canvas, text, attrTextOffset, baseline, getShadowTextStrokeWidth(), getShadowTextStrokeColor(), mAttributePropertyColor); + } + + private Paint getCurrentNamePaint() { + mPaint.setTextSize(mAttributeNameTextSize); + mPaint.setColor(Color.WHITE); + return mPaint; + } + + /** + * 绘制当前值文字 + * 当前文字为数字和小数点,行高通过 ascent 和 descent 计算,避免 top 和 bottom 过多留白导致的整体偏离过远 + */ + private void drawCurrentText(Canvas canvas, String text, boolean alginLeft) { + Paint paint = getCurrentPaint(); + float len = paint.measureText(text); + Paint.FontMetrics fontMetrics = paint.getFontMetrics(); + float top = fontMetrics.ascent; + float bottom = fontMetrics.descent; + + float baseline = ((float) mPointerHeight - bottom + top) / 2 - top; + float textStart = alginLeft ? mCurrentValuePadding : -mCurrentValuePadding - len; + drawTextWithStroke(canvas, text, textStart, baseline, mStrokeConfig.getStrokeBoldWidth(), getShadowTextStrokeColor(), mCurrentValueColor); + } + + private Paint getCurrentPaint() { + Paint paint = mPaint; + paint.setTextAlign(Paint.Align.LEFT); + paint.setTextSize(mAttributeCurrentCalibrationTextSize); + return paint; + } + + /** + * 绘制中间文字部分背景,后续会对这一部分区域进行裁切,避免覆盖/重叠 + * + * @see #clipPointerArea(Canvas) + */ + private void drawCurrentBackground(Canvas canvas, int width, int height) { + Paint backgroundPaint = getBackgroundPaint(); + canvas.drawRoundRect(0, 0, width, height, mBorderRadius, mBorderRadius, backgroundPaint); + } + + private Paint getBackgroundPaint() { + mPaint.setColor(mBorderColor); + mPaint.setStyle(Paint.Style.STROKE); + mPaint.setStrokeWidth(mBorderWidth); + return mPaint; + } + + protected void drawTextWithStroke(Canvas canvas, String currentValueString, float textOffset, float baseline, float strokeWidth, + int strokeColor, int textColor) { + mPaint.setStrokeWidth(strokeWidth); + mPaint.setColor(strokeColor); + mPaint.setStyle(Paint.Style.STROKE); + canvas.drawText(currentValueString, textOffset, baseline, mPaint); + mPaint.setColor(textColor); + mPaint.setStyle(Paint.Style.FILL); + canvas.drawText(currentValueString, textOffset, baseline, mPaint); + } + + protected abstract String getCurrentValueDisplayFormat(boolean shorthand); + + protected abstract String getAttributeUnit(); + + protected abstract float getDisplayValue(float value); + + protected static class DisplayValue { + String mDisplayValue; + String mDisplayUnit; + + public void set(String displayValue, String displayUnit) { + mDisplayValue = displayValue; + mDisplayUnit = displayUnit; + } + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/dashboard/SpeedDashBoard.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/dashboard/SpeedDashBoard.java new file mode 100644 index 00000000..a313aa20 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/dashboard/SpeedDashBoard.java @@ -0,0 +1,132 @@ +package dji.v5.ux.core.ui.hsi.dashboard; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; + +import androidx.annotation.Nullable; +import androidx.core.content.ContextCompat; + +import dji.v5.ux.R; +import dji.v5.ux.core.base.SchedulerProvider; +import dji.v5.common.utils.UnitUtils; +import dji.v5.ux.core.widget.hsi.SpeedDisplayModel; +import io.reactivex.rxjava3.disposables.CompositeDisposable; + +public class SpeedDashBoard extends ScrollableAttributeDashBoard { + + private float mSpeedX; + private float mSpeedY; + private float mSpeed; + private SpeedDisplayModel widgetModel; + + + private CompositeDisposable mCompositeDisposable = new CompositeDisposable(); + + public SpeedDashBoard(Context context) { + this(context, null); + } + + public SpeedDashBoard(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public SpeedDashBoard(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mWaypointIcon = ContextCompat.getDrawable(getContext(), R.drawable.uxsdk_fpv_pfd_waypoint_left); + } + public void setModel(SpeedDisplayModel model) { + widgetModel = model; + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (isInEditMode()) { + return; + } + + mCompositeDisposable.add(widgetModel.getVelocityProcessor().toFlowable().observeOn(SchedulerProvider.ui()) + .subscribe(speed -> { + mSpeedX = speed.getX().floatValue(); + mSpeedY = speed.getY().floatValue(); + mSpeed = updateSpeed(); + setCurrentValue(mSpeed); + + })); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + // 绘制航点速度 + drawSpeedIndicator(canvas); + } + + + /** + * 绘制速度标识和文字 + */ + private void drawSpeedIndicator(Canvas canvas) { +// MissionManagerDelegate instance = MissionManagerDelegate.INSTANCE; +// if (!instance.isRunningMission()) { +// return; +// } +// MissionExecutePointInfo pointInfo = MissionManagerDelegate.INSTANCE.getExecutePointInfo(); +// if (pointInfo == null) { +// return; +// } + Drawable icon = mWaypointIcon; + float speed = 23; + float current = getCurrentValue(); + float delta = speed - current; + int frameworkHeight = getFrameworkHeight(); + float ratio = (float) frameworkHeight / mVisibleCalibrationUnitCount / mAttributeOffsetPerUnit; + float y = delta * ratio; + if (Math.abs(y) >= getFrameworkHeight() / 2f) { + return; + } + canvas.save(); + + // 绘制 icon + int iconWidth = icon.getMinimumWidth(); + int iconHeight = icon.getMinimumHeight(); + int left = Math.round(getWidth() - mFrameworkPaddingStart + mWaypointIconPadding); + int top = Math.round(-y - icon.getMinimumHeight() / 2f + getHeight() / 2f); + int right = left + iconWidth; + int bottom = top + iconHeight; + icon.setBounds(left, top, right, bottom); + icon.draw(canvas); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + mCompositeDisposable.dispose(); + + } + + private float updateSpeed() { + double tmp = Math.pow(mSpeedX, 2) + Math.pow(mSpeedY, 2); + if (tmp < 0) { + tmp = 0; + } + return (float) Math.sqrt(tmp); + } + + @Override + protected String getCurrentValueDisplayFormat(boolean shorthand) { + return "%04.1f"; + } + + @Override + protected String getAttributeUnit() { + return UnitUtils.getSpeedUnit(); + } + + @Override + protected float getDisplayValue(float value) { + return UnitUtils.transFormSpeedIntoDifferentUnit(value); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/fpv/IFPVParams.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/fpv/IFPVParams.kt new file mode 100644 index 00000000..c3f2eebf --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/fpv/IFPVParams.kt @@ -0,0 +1,57 @@ +package dji.v5.ux.core.ui.hsi.fpv; + +import M300FpvParams +import M30FpvParams +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.key.ProductKey +import dji.sdk.keyvalue.value.product.ProductType +import dji.v5.manager.KeyManager +import dji.v5.utils.dpad.DpadProductManager + +/** + * FPV 能力参数 + */ +interface IFPVParams { + /** + * 镜头焦距,以像素为单位 + */ + fun getFocusX(): Float + + /** + * 镜头焦距,以像素为单位 + */ + fun getFocusY(): Float + + /** + * 视频原始宽度的1/2 + */ + fun getCenterX(): Float + + /** + * 视频原始高度的1/2 + */ + fun getCenterY(): Float + + + companion object { + /** + * 当前未考虑遥控器连接不同飞机,未观察连接飞机的变化,当出现遥控支持不同飞机时,需要观察飞机状态变化。 + */ + fun getCurrent(): IFPVParams { + val type = KeyManager.getInstance().getValue( + KeyTools.createKey( + ProductKey.KeyProductType), ProductType.UNKNOWN) + if (type == ProductType.M300_RTK || type == ProductType.M350_RTK || type == ProductType.DJI_MATRICE_400) { + return M300FpvParams + } else if (type == ProductType.M30_SERIES) { + return M30FpvParams + } + if (DpadProductManager.getInstance().isSmartController) { + return M300FpvParams + } else if (DpadProductManager.getInstance().isDjiRcPlus) { + return M30FpvParams + } + return M300FpvParams + } + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/fpv/M300FpvParams.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/fpv/M300FpvParams.kt new file mode 100644 index 00000000..5cb1ad43 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/fpv/M300FpvParams.kt @@ -0,0 +1,23 @@ + +import dji.v5.ux.core.ui.hsi.fpv.IFPVParams + +object M300FpvParams : IFPVParams { + private const val FPV_FOCUS = 1716.12f + private const val FPV_CENTER_X = 2028f + private const val FPV_CENTER_Y = 1520f + override fun getFocusX(): Float { + return FPV_FOCUS + } + + override fun getFocusY(): Float { + return FPV_FOCUS + } + + override fun getCenterX(): Float { + return FPV_CENTER_X + } + + override fun getCenterY(): Float { + return FPV_CENTER_Y + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/fpv/M30FpvParams.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/fpv/M30FpvParams.kt new file mode 100644 index 00000000..2ca3bc9f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/hsi/fpv/M30FpvParams.kt @@ -0,0 +1,23 @@ +import dji.v5.ux.core.ui.hsi.fpv.IFPVParams + +object M30FpvParams : IFPVParams { + private const val FPV_FOCUS_X = 915.221845859551f * 0.75f + private const val FPV_FOCUS_Y = 901.869063410212f * 0.75f + private const val FPV_CENTER_X = 2560f / 2 * 0.75f + private const val FPV_CENTER_Y = 1440f / 2 * 0.75f + override fun getFocusX(): Float { + return FPV_FOCUS_X + } + + override fun getFocusY(): Float { + return FPV_FOCUS_Y + } + + override fun getCenterX(): Float { + return FPV_CENTER_X + } + + override fun getCenterY(): Float { + return FPV_CENTER_Y + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/SettingFragmentPagerAdapter.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/SettingFragmentPagerAdapter.java new file mode 100644 index 00000000..ecc040d4 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/SettingFragmentPagerAdapter.java @@ -0,0 +1,197 @@ +package dji.v5.ux.core.ui.setting; + + +import android.text.TextUtils; +import android.view.Gravity; +import android.view.ViewGroup; + +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentPagerAdapter; + +import java.util.List; + +import dji.v5.utils.common.AndUtil; +import dji.v5.utils.common.ContextUtil; +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.ui.setting.data.MenuBean; +import dji.v5.ux.core.ui.setting.taplayout.QTabView; +import dji.v5.ux.core.ui.setting.taplayout.TabAdapter; +import dji.v5.ux.core.ui.setting.ui.MenuFragmentFactory; +import dji.v5.ux.core.ui.setting.ui.SettingMenuFragment; +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; + +/** + * Description : + * + * @author: Byte.Cai + * date : 2022/11/21 + *

+ * Copyright (c) 2022, DJI All Rights Reserved. + */ +public class SettingFragmentPagerAdapter extends FragmentPagerAdapter implements TabAdapter { + + private List mAdapterMenus; + private List mAdapterFragments; + private FragmentManager mCurrentFragmentManager; + + public SettingFragmentPagerAdapter(FragmentManager fm, List menus, List mFragments) { + super(fm); + this.mAdapterMenus = menus; + this.mAdapterFragments = mFragments; + this.mCurrentFragmentManager = fm; + } + + @Override + public Fragment getItem(int position) { + return mAdapterFragments.get(position); + } + + public int getSelectIndex(String str) { + if (mAdapterFragments != null && mAdapterFragments.size() > 0 && !TextUtils.isEmpty(str)) { + for (int i = 0; i < mAdapterFragments.size(); i++) { + if (mAdapterFragments.get(i) instanceof SettingMenuFragment) { + SettingMenuFragment fragment = (SettingMenuFragment) mAdapterFragments.get(i); + if (str.equals(fragment.getFragmentFlag())) { + return i; + } + } + } + } + return -1; + } + + public String getSelectFlag(int index) { + if (mAdapterFragments != null && index >= 0 && index < mAdapterFragments.size()) { + SettingMenuFragment fragment = (SettingMenuFragment) mAdapterFragments.get(index); + if (fragment != null) { + return fragment.getFragmentFlag(); + } + } + return ""; + } + + public void removePayloadPanel() { + removeMenuPanel(MenuFragmentFactory.FRAGMENT_TAG_PAYLOAD, R.drawable.uxsdk_ic_setting_psdk); + } + + public void addPayloadPanel() { + addMenuPanel(MenuFragmentFactory.FRAGMENT_TAG_GIMBAL, + MenuFragmentFactory.FRAGMENT_TAG_PAYLOAD, + R.drawable.uxsdk_ic_setting_psdk_active, + R.drawable.uxsdk_ic_setting_psdk); + } + + public void addSearchlightPayloadPanel() { + addMenuPanel(MenuFragmentFactory.FRAGMENT_TAG_GIMBAL, + MenuFragmentFactory.FRAGMENT_TAG_SEARCHLIGHT_ACCESSORY, + R.drawable.uxsdk_ic_setting_psdk_active, + R.drawable.uxsdk_ic_setting_psdk); + } + + public void removeSearchlightPayloadPanel() { + removeMenuPanel(MenuFragmentFactory.FRAGMENT_TAG_SEARCHLIGHT_ACCESSORY, R.drawable.uxsdk_ic_setting_psdk); + } + + public void removeRTKPanel() { + removeMenuPanel(MenuFragmentFactory.FRAGMENT_TAG_RTK, R.drawable.uxsdk_ic_setting_rtk); + } + + public void addRTKPanel() { + addMenuPanel(MenuFragmentFactory.FRAGMENT_TAG_GIMBAL, MenuFragmentFactory.FRAGMENT_TAG_RTK, R.drawable.uxsdk_ic_setting_rtk_active, + R.drawable.uxsdk_ic_setting_rtk); + } + + public void addMenuPanel(String prePage, String page, int selectedIcon, int normalIcon) { + + int payloadIndex = getSelectIndex(page); + if (payloadIndex >= 0) { + return; + } + int gimbalIndex = getSelectIndex(prePage); + if (gimbalIndex >= 0) { + payloadIndex = gimbalIndex + 1; + mAdapterMenus.add(payloadIndex, new MenuBean(selectedIcon, normalIcon)); + SettingMenuFragment fragment = SettingMenuFragment.newInstance(page); + mAdapterFragments.add(payloadIndex, fragment); + notifyDataSetChanged(); + } + } + + public void removeMenuPanel(String page, int normalIcon) { + int payloadIndex = getSelectIndex(page); + if (payloadIndex >= 0) { + MenuBean menu = mAdapterMenus.get(payloadIndex); + if (menu.getNormalIcon() == normalIcon) { + mAdapterMenus.remove(payloadIndex); + mAdapterFragments.remove(payloadIndex); + notifyDataSetChanged(); + } + } + } + + @Override + public int getItemPosition(Object object) { + // When call notifyDataSetChanged(), the view pager will remove all views and reload them all. As so the reload effect is obtained. + return POSITION_NONE; + } + + @Override + public int getCount() { + return mAdapterFragments.size(); + } + + @Override + public int getBadge(int position) { + return 0; + } + + @Override + public Object instantiateItem(ViewGroup container, int position) { + String name = ((SettingMenuFragment) getItem(position)).getFragmentFlag(); + Fragment fragment = mCurrentFragmentManager.findFragmentByTag(name); + if (fragment != null) { + mCurrentFragmentManager.beginTransaction().attach(fragment).commitNowAllowingStateLoss(); + } else { + fragment = getItem(position); + mCurrentFragmentManager.beginTransaction() + .add(container.getId(), fragment, name) + .commitNowAllowingStateLoss(); + } + mCurrentFragmentManager.executePendingTransactions(); + return fragment; + } + + @Override + public QTabView.TabIcon getIcon(int position) { + // 修复 position 和 mAdapterMenus 可能不一致的稳定性问题 + MenuBean menu = mAdapterMenus.get(position >= mAdapterMenus.size() ? mAdapterMenus.size() - 1 : position); + return new QTabView.TabIcon.Builder().setIcon(menu.getSelectIcon(), menu.getNormalIcon()) + .setIconGravity(Gravity.CENTER) + .setIconSize(AndUtil.dip2px(ContextUtil.getContext(), 50), + AndUtil.dip2px(ContextUtil.getContext(), 50)) + .setBackground(R.drawable.uxsdk_selector_blue_oval_mask) + .build(); + } + + @Override + public QTabView.TabTitle getTitle(int position) { + return null; + } + + @Override + public int getBackground(int position) { + return R.color.uxsdk_fpv_popover_content_background_color; + } + + public void destroy() { + mCurrentFragmentManager = null; + if (mAdapterFragments != null) { + mAdapterFragments.clear(); + } + if (mAdapterMenus != null) { + mAdapterMenus.clear(); + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/data/MenuBean.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/data/MenuBean.java new file mode 100644 index 00000000..f3708748 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/data/MenuBean.java @@ -0,0 +1,30 @@ +package dji.v5.ux.core.ui.setting.data; + +/** + * 设置页的图标类 + */ +public class MenuBean { + private int selectIcon; + private int normalIcon; + + public int getSelectIcon() { + return selectIcon; + } + + public void setSelectIcon(int selectIcon) { + this.selectIcon = selectIcon; + } + + public int getNormalIcon() { + return normalIcon; + } + + public void setNormalIcon(int normalIcon) { + this.normalIcon = normalIcon; + } + + public MenuBean(int selectIcon, int normalIcon) { + this.selectIcon = selectIcon; + this.normalIcon = normalIcon; + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/dialog/ActivityLifecycleCallbacksAdapter.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/dialog/ActivityLifecycleCallbacksAdapter.java new file mode 100644 index 00000000..fefc55b8 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/dialog/ActivityLifecycleCallbacksAdapter.java @@ -0,0 +1,54 @@ +package dji.v5.ux.core.ui.setting.dialog; + +import android.app.Activity; +import android.app.Application; +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +/** + * Description : + * + * @author: Byte.Cai + * date : 2022/12/16 + *

+ * Copyright (c) 2022, DJI All Rights Reserved. + */ +public class ActivityLifecycleCallbacksAdapter implements Application.ActivityLifecycleCallbacks { + @Override + public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) { + //do nothing + } + + @Override + public void onActivityStarted(@NonNull Activity activity) { + //do nothing + } + + @Override + public void onActivityResumed(@NonNull Activity activity) { + //do nothing + } + + @Override + public void onActivityPaused(@NonNull Activity activity) { + //do nothing + } + + @Override + public void onActivityStopped(@NonNull Activity activity) { + //do nothing + } + + @Override + public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) { + //do nothing + } + + @Override + public void onActivityDestroyed(@NonNull Activity activity) { + //do nothing + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/dialog/BaseDialog.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/dialog/BaseDialog.java new file mode 100644 index 00000000..995df13f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/dialog/BaseDialog.java @@ -0,0 +1,254 @@ +package dji.v5.ux.core.ui.setting.dialog; + +import android.app.Activity; +import android.app.Application; +import android.app.Dialog; +import android.content.Context; +import android.content.ContextWrapper; +import android.os.Looper; +import android.view.ContextThemeWrapper; +import android.view.Gravity; +import android.view.View; +import android.view.ViewGroup; +import android.view.Window; +import android.view.WindowManager; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.R; +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; + + +public class BaseDialog extends Dialog { + + private static boolean sCanShowDialog = true; + + @Nullable + private OnDismissListener mOnDismissListener; + + @Nullable + private OnShowListener mOnShowListener; + + public BaseDialog(Context context) { + super(context); + initListeners(); + } + + public BaseDialog(Context context, int themeResId) { + super(context, themeResId); + initListeners(); + } + + protected BaseDialog(Context context, boolean cancelable, OnCancelListener cancelListener) { + super(context, cancelable, cancelListener); + initListeners(); + } + + private void initListeners() { + super.setOnDismissListener(dialog -> { + unregisterActivityLifecycleCallbacks(getBaseContext()); + if (mOnDismissListener != null) { + mOnDismissListener.onDismiss(dialog); + } + }); + super.setOnShowListener(dialog -> { + registerActivityLifecycleCallbacks(getBaseContext()); + if (mOnShowListener != null) { + mOnShowListener.onShow(dialog); + } + }); + setOnKeyListener(new DispatchDialogKeyEventToActivityListener(getContext())); + } + + @Override + public void setOnDismissListener(@Nullable OnDismissListener listener) { + mOnDismissListener = listener; + } + + @Override + public void setOnShowListener(@Nullable OnShowListener listener) { + mOnShowListener = listener; + } + + @Override + protected void onStart() { + Window window = this.getWindow(); + if (window != null) { + window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN); + hideSystemUI(window); + } + super.onStart(); + } + + protected void hideSystemUI(Window window) { + if (window == null) { + return; + } + int uiOptions = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_LAYOUT_STABLE + | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + | View.SYSTEM_UI_FLAG_IMMERSIVE + | View.SYSTEM_UI_FLAG_FULLSCREEN; + window.getDecorView().setSystemUiVisibility(uiOptions); + } + + protected void resizeWindow() { + Window window = getWindow(); + if (window != null) { + WindowManager.LayoutParams params = window.getAttributes(); + params.width = getDialogWidth(); + params.height = getDialogHeight(); + params.gravity = Gravity.CENTER_VERTICAL; + window.setAttributes(params); + } + checkIsSuitableHeight(); + } + + protected void checkIsSuitableHeight() { + Window window = getWindow(); + if (window != null) { + View view = window.getDecorView(); + view.measure(WindowManager.LayoutParams.WRAP_CONTENT, WindowManager.LayoutParams.WRAP_CONTENT); + int dialogH = view.getMeasuredHeight(); + int dialogMaxH = getDialogMaxHeight(); + if (dialogH > dialogMaxH) { + WindowManager.LayoutParams params = window.getAttributes(); + params.height = ViewGroup.LayoutParams.WRAP_CONTENT; + params.gravity = Gravity.CENTER_VERTICAL; + window.setAttributes(params); + } + } + } + + public int getDialogWidth() { + return (int) getContext().getResources().getDimension(R.dimen.uxsdk_320_dp); + } + + public int getDialogHeight() { + return WindowManager.LayoutParams.WRAP_CONTENT; + } + + public int getDialogMaxHeight() { + return AndUtil.getLandScreenHeight(getContext()); + } + + @Override + public void setContentView(int layoutResID) { + super.setContentView(layoutResID); + resizeWindow(); + } + + @Override + public void setContentView(View view) { + super.setContentView(view); + resizeWindow(); + } + + @Override + public void setContentView(View view, ViewGroup.LayoutParams params) { + super.setContentView(view, params); + resizeWindow(); + } + + @Override + public void show() { + if (isCanShowDialog() && !isActivityFinish()) { + super.show(); + } + } + + @Override + public void dismiss() { + try { + if (Looper.getMainLooper() != Looper.myLooper()) { + AndroidSchedulers.mainThread().scheduleDirect(() -> dismiss()); + return; + } + super.dismiss(); + } catch (Exception ex) { +// ex.printStackTrace(); + } + } + + private boolean isActivityFinish() { + if (getContext() instanceof Activity) { + if (((Activity) getContext()).isFinishing()) { + return true; + } + } else if (getContext() instanceof ContextWrapper) { + Context context = ((ContextWrapper) getContext()).getBaseContext(); + if (context instanceof Activity && ((Activity) context).isFinishing()) { + return true; + } + } + return false; + } + + public static boolean isCanShowDialog() { + return sCanShowDialog; + } + + public static void setCanShowDialog(boolean sCanShowDialog) { + BaseDialog.sCanShowDialog = sCanShowDialog; + } + + private Context getBaseContext() { + Context context = getContext(); + if (context instanceof ContextThemeWrapper) { + context = ((ContextThemeWrapper) context).getBaseContext(); + } + return context; + } + + private Application getApplication(Context context) { + Application app = null; + if (context instanceof AppCompatActivity) { + app = ((AppCompatActivity) context).getApplication(); + } else if (context instanceof Activity) { + app = ((Activity) context).getApplication(); + } + return app; + } + + private void unregisterActivityLifecycleCallbacks(Context context) { + Application app = getApplication(context); + if (app == null) { + return; + } + if (mActivityLifecycleCallbacks != null) { + app.unregisterActivityLifecycleCallbacks(mActivityLifecycleCallbacks); + mActivityLifecycleCallbacks = null; + } + } + + // 之前直接在Constructor里面注册ActivityLifecycleCallbacks, + // 如果在View里面创建了一个dialog但是view被destroy了而activity还没有,就会导致内存泄漏 + private Application.ActivityLifecycleCallbacks mActivityLifecycleCallbacks; + + private void registerActivityLifecycleCallbacks(Context context) { + Application app = getApplication(context); + if (app == null) { + return; + } + + final Application finalApp = app; + unregisterActivityLifecycleCallbacks(context); + + mActivityLifecycleCallbacks=new ActivityLifecycleCallbacksAdapter(){ + @Override + public void onActivityDestroyed(@NonNull Activity activity) { + if (context == activity) { + if (isShowing()) { + dismiss(); + } + finalApp.unregisterActivityLifecycleCallbacks(this); + } + } + }; + + app.registerActivityLifecycleCallbacks(mActivityLifecycleCallbacks); + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/dialog/CommonLoadingDialog.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/dialog/CommonLoadingDialog.java new file mode 100644 index 00000000..baef78ae --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/dialog/CommonLoadingDialog.java @@ -0,0 +1,63 @@ +package dji.v5.ux.core.ui.setting.dialog; + + +import android.content.Context; +import android.os.Bundle; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.R; + + +/** + * 加载提醒对话框 + */ +public class CommonLoadingDialog extends BaseDialog { + + protected View rootView; + protected TextView mLoadText; + + public CommonLoadingDialog(Context context) { + this(context, R.style.SimpleProgressDialog); + } + + public CommonLoadingDialog(Context context, int theme) { + super(context, theme); + initialize(); + } + + protected void initialize() { + rootView = getLayoutInflater().inflate(R.layout.uxsdk_dialog_common_loading_layout, null); + mLoadText = rootView.findViewById(R.id.tv_load_dialog); + } + + @Override + public int getDialogWidth() { + return ViewGroup.LayoutParams.WRAP_CONTENT; + } + + @Override + public int getDialogHeight() { + return (int) AndUtil.getDimension(R.dimen.uxsdk_100_dp); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(rootView); + //设置不可取消,点击其他区域不能取消,实际中可以抽出去封装供外包设置 + setCancelable(false); + setCanceledOnTouchOutside(false); + } + + @Override + public void show() { + super.show(); + } + + public void setLoadingText(String text) { + mLoadText.setText(text); + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/dialog/DispatchDialogKeyEventToActivityListener.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/dialog/DispatchDialogKeyEventToActivityListener.kt new file mode 100644 index 00000000..190e6d7c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/dialog/DispatchDialogKeyEventToActivityListener.kt @@ -0,0 +1,60 @@ +package dji.v5.ux.core.ui.setting.dialog + +import android.app.Activity +import android.content.Context +import android.content.ContextWrapper +import android.content.DialogInterface +import android.view.KeyEvent + + +/** + * 把对话框的按钮事件传给Activity + */ +open class DispatchDialogKeyEventToActivityListener(val context: Context?) : DialogInterface.OnKeyListener { + private var needHandle = false + private var keyDown = false + override fun onKey(dialog: DialogInterface?, keyCode: Int, event: KeyEvent): Boolean { + // 返回键交给上面处理 + if (event.keyCode == KeyEvent.KEYCODE_BACK || dialog == null || context == null) { + return false + } else if (!keyDown && event.action == KeyEvent.ACTION_DOWN) { + // repeatCount == 0代表是第一次按下按键,这时开始处理按键事件 + keyDown = true + needHandle = event.repeatCount == 0 + } else if (event.action == KeyEvent.ACTION_UP) { + keyDown = false + } + + if (needHandle) { + dispatchKeyEvent(context, event) + } + + return false + + } + + private fun dispatchKeyEvent(context: Context?, keyEvent: KeyEvent?): Boolean { + val activity: Activity? = contextToActivity(context) + return if (activity != null) { + activity.dispatchKeyEvent(keyEvent) + true + } else { + false + } + } + + private fun contextToActivity(context: Context?): Activity? { + if (context == null) { + return null + } + if (context is Activity) { + return context + } else if (context is ContextWrapper) { + val context2 = context.baseContext + if (context2 is Activity) { + return context2 + } + } + return null + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/BatteryInfoDetailFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/BatteryInfoDetailFragment.java new file mode 100644 index 00000000..9c568d67 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/BatteryInfoDetailFragment.java @@ -0,0 +1,44 @@ +package dji.v5.ux.core.ui.setting.fragment; + +import android.os.Bundle; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.v5.utils.common.ContextUtil; +import dji.v5.utils.common.StringUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.ui.setting.ui.MenuFragment; +import dji.v5.ux.core.widget.battery.BatteryGroupInfoWidget; +import dji.v5.ux.core.widget.battery.BatteryGroupWidget; + +/** + * Description : + * + * @author: Byte.Cai + * date : 2023/9/21 + *

+ * Copyright (c) 2022, DJI All Rights Reserved. + */ +public class BatteryInfoDetailFragment extends MenuFragment { + @Override + protected int getLayoutId() { + return R.layout.uxsdk_fragment_battery_info_detail; + } + + @Override + protected String getPreferencesTitle() { + return StringUtils.getResStr(ContextUtil.getContext(), R.string.uxsdk_setting_menu_title_battery); + + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + BatteryGroupWidget batteryGroupWidget = (BatteryGroupWidget)view.findViewById(R.id.setting_menu_battery); + batteryGroupWidget.setEnableBatteryCells(true); + batteryGroupWidget.setEnableSerialNumber(true); + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/BatteryMenuFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/BatteryMenuFragment.java new file mode 100644 index 00000000..35d77695 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/BatteryMenuFragment.java @@ -0,0 +1,45 @@ +package dji.v5.ux.core.ui.setting.fragment; + +import android.os.Bundle; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.v5.utils.common.ContextUtil; +import dji.v5.utils.common.StringUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.ui.setting.ui.MenuFragment; +import dji.v5.ux.core.widget.battery.BatteryGroupInfoWidget; +import dji.v5.ux.core.widget.battery.BatterySettingWidget; + +/** + * Description : + * + * @author: Byte.Cai + * date : 2022/11/21 + *

+ * Copyright (c) 2022, DJI All Rights Reserved. + */ +public class BatteryMenuFragment extends MenuFragment { + + @Override + protected String getPreferencesTitle() { + return StringUtils.getResStr(ContextUtil.getContext(), R.string.uxsdk_setting_menu_title_battery); + } + + @Override + protected int getLayoutId() { + return R.layout.uxsdk_fragment_setting_menu_battery_layout; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + BatterySettingWidget batterySettingWidget = (BatterySettingWidget) view.findViewById(R.id.battery_setting_widget); + batterySettingWidget.getBatteryGroupInfoWidget().setOnDetailOnClickListener(v -> { + BatteryInfoDetailFragment fragment = new BatteryInfoDetailFragment(); + addFragment(getFragmentManager(), fragment, true); + }); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/ChannelSelectFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/ChannelSelectFragment.java new file mode 100644 index 00000000..9902f53f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/ChannelSelectFragment.java @@ -0,0 +1,37 @@ +package dji.v5.ux.core.ui.setting.fragment; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.R; +import dji.v5.ux.core.ui.setting.ui.MenuFragment; + + +public class ChannelSelectFragment extends MenuFragment { + + @Override + protected int getLayoutId() { + return R.layout.uxsdk_setting_menu_hd_channel_select; + } + + @Override + protected String getPreferencesTitle() { + return AndUtil.getResString(R.string.uxsdk_setting_ui_hd_sdr_channel_select); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + return mFragmentRoot; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + } + + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/CommonAboutFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/CommonAboutFragment.java new file mode 100644 index 00000000..dfb5bf43 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/CommonAboutFragment.java @@ -0,0 +1,41 @@ +package dji.v5.ux.core.ui.setting.fragment; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.R; +import dji.v5.ux.core.base.CompassStatusWidget; +import dji.v5.ux.core.base.ImuStatusWidget; +import dji.v5.ux.core.base.TabGroupWidget; +import dji.v5.ux.core.ui.setting.ui.MenuFragment; + + + + +public class CommonAboutFragment extends MenuFragment { + + @Override + protected int getLayoutId() { + return R.layout.uxsdk_setting_menu_common_about; + } + + @Override + protected String getPreferencesTitle() { + return AndUtil.getResString(R.string.uxsdk_setting_menu_title_about); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + return mFragmentRoot; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/CommonMenuFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/CommonMenuFragment.java new file mode 100644 index 00000000..1b7d2280 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/CommonMenuFragment.java @@ -0,0 +1,56 @@ +package dji.v5.ux.core.ui.setting.fragment; + +import android.os.Bundle; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.v5.utils.common.ContextUtil; +import dji.v5.utils.common.StringUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.base.TextCell; +import dji.v5.ux.core.ui.setting.ui.MenuFragment; + +/** + * Description : + * + * @author: Byte.Cai + * date : 2022/11/21 + *

+ * Copyright (c) 2022, DJI All Rights Reserved. + */ +public class CommonMenuFragment extends MenuFragment { + @Override + protected String getPreferencesTitle() { + return StringUtils.getResStr(ContextUtil.getContext(), R.string.uxsdk_setting_menu_title_common); + } + + @Override + protected int getLayoutId() { + return R.layout.uxsdk_setting_menu_common_layout; + } + + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + view.findViewById(R.id.setting_common_about).setOnClickListener(view1 -> { + CommonAboutFragment fragment = new CommonAboutFragment(); + addFragment(getFragmentManager(), fragment, true); + }); + + + view.findViewById(R.id.setting_device_name).setOnClickListener(view12 -> { + DeviceNameFragment fragment = new DeviceNameFragment(); + addFragment(getFragmentManager(), fragment, true); + }); + view.findViewById(R.id.setting_led).setOnClickListener(view13 -> { + LedMenuFragment fragment = new LedMenuFragment(); + addFragment(getFragmentManager(), fragment, true); + }); + + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/DeviceNameFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/DeviceNameFragment.java new file mode 100644 index 00000000..38f1427b --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/DeviceNameFragment.java @@ -0,0 +1,45 @@ +package dji.v5.ux.core.ui.setting.fragment; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.R; +import dji.v5.ux.core.base.CompassStatusWidget; +import dji.v5.ux.core.base.ImuStatusWidget; +import dji.v5.ux.core.base.TabGroupWidget; +import dji.v5.ux.core.ui.setting.ui.MenuFragment; + + +public class DeviceNameFragment extends MenuFragment { + + + @Override + protected int getLayoutId() { + return R.layout.uxsdk_setting_menu_common_devicename; + } + + @Override + protected String getPreferencesTitle() { + return AndUtil.getResString(R.string.uxsdk_setting_menu_title_device_name); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + + + + return mFragmentRoot; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + + super.onSaveInstanceState(outState); + } + + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/FlycMenuFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/FlycMenuFragment.java new file mode 100644 index 00000000..008d9c1b --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/FlycMenuFragment.java @@ -0,0 +1,44 @@ +package dji.v5.ux.core.ui.setting.fragment; + +import android.os.Bundle; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.v5.utils.common.ContextUtil; +import dji.v5.utils.common.StringUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.base.TextCell; +import dji.v5.ux.core.ui.setting.ui.MenuFragment; + +/** + * Description : + * + * @author: Byte.Cai + * date : 2022/11/21 + *

+ * Copyright (c) 2022, DJI All Rights Reserved. + */ +public class FlycMenuFragment extends MenuFragment { + @Override + protected String getPreferencesTitle() { + return StringUtils.getResStr(ContextUtil.getContext(), R.string.uxsdk_setting_menu_title_flyc); + } + + @Override + protected int getLayoutId() { + return R.layout.uxsdk_setting_menu_aircraft_layout; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + TextCell textCell = view.findViewById(R.id.setting_flyc_sensors_state); + textCell.setOnClickListener(view1 -> { + SensorsMenuFragment fragment = new SensorsMenuFragment(); + addFragment(getFragmentManager(), fragment, true); + }); + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/GimbalMenuFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/GimbalMenuFragment.java new file mode 100644 index 00000000..521500d5 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/GimbalMenuFragment.java @@ -0,0 +1,26 @@ +package dji.v5.ux.core.ui.setting.fragment; + +import dji.v5.utils.common.ContextUtil; +import dji.v5.utils.common.StringUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.ui.setting.ui.MenuFragment; + +/** + * Description : + * + * @author: Byte.Cai + * date : 2022/11/21 + *

+ * Copyright (c) 2022, DJI All Rights Reserved. + */ +public class GimbalMenuFragment extends MenuFragment { + @Override + protected String getPreferencesTitle() { + return StringUtils.getResStr(ContextUtil.getContext(), R.string.uxsdk_setting_menu_title_gimbal); + } + + @Override + protected int getLayoutId() { + return R.layout.uxsdk_setting_menu_gimbal_layout; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/HDMenuFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/HDMenuFragment.java new file mode 100644 index 00000000..a6d88895 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/HDMenuFragment.java @@ -0,0 +1,43 @@ +package dji.v5.ux.core.ui.setting.fragment; + +import android.os.Bundle; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.v5.utils.common.ContextUtil; +import dji.v5.utils.common.StringUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.ui.setting.ui.MenuFragment; + +/** + * Description : + * + * @author: Byte.Cai + * date : 2022/11/21 + *

+ * Copyright (c) 2022, DJI All Rights Reserved. + */ +public class HDMenuFragment extends MenuFragment { + + @Override + protected String getPreferencesTitle() { + return StringUtils.getResStr(ContextUtil.getContext(), R.string.uxsdk_setting_menu_title_hd); + } + + @Override + protected int getLayoutId() { + return R.layout.uxsdk_setting_menu_hd_layout; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + + view.findViewById(R.id.tc_setting_menu_sdr_info_text).setOnClickListener(view1 -> { + ChannelSelectFragment fragment = new ChannelSelectFragment(); + addFragment(getFragmentManager(), fragment, true); + }); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/LEDSettingFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/LEDSettingFragment.java new file mode 100644 index 00000000..f7463526 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/LEDSettingFragment.java @@ -0,0 +1,36 @@ +package dji.v5.ux.core.ui.setting.fragment; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.R; +import dji.v5.ux.core.ui.setting.ui.MenuFragment; + + +public class LEDSettingFragment extends MenuFragment { + + @Override + protected int getLayoutId() { + return R.layout.uxsdk_setting_menu_common_devicename; + } + + @Override + protected String getPreferencesTitle() { + return AndUtil.getResString(R.string.uxsdk_setting_menu_title_device_name); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + return mFragmentRoot; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/LedMenuFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/LedMenuFragment.java new file mode 100644 index 00000000..3e8780eb --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/LedMenuFragment.java @@ -0,0 +1,332 @@ +package dji.v5.ux.core.ui.setting.fragment; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + + +import dji.sdk.keyvalue.key.FlightAssistantKey; +import dji.sdk.keyvalue.key.FlightControllerKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.key.ProductKey; +import dji.sdk.keyvalue.value.flightassistant.AuxiliaryLightMode; +import dji.sdk.keyvalue.value.flightcontroller.LEDsSettings; +import dji.sdk.keyvalue.value.product.ProductType; +import dji.v5.common.callback.CommonCallbacks; +import dji.v5.common.error.IDJIError; +import dji.v5.manager.KeyManager; +import dji.v5.utils.common.LogUtils; +import dji.v5.utils.common.StringUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.base.SwitcherCell; +import dji.v5.ux.core.base.TabSelectCell; +import dji.v5.ux.core.ui.setting.ui.MenuFragment; +import dji.v5.ux.core.util.ViewUtil; + + + +/** + * Created by Lahm.Long on 2019/12/23 + * desc : + */ +public class LedMenuFragment extends MenuFragment + implements + SwitcherCell.OnCheckedChangedListener, + TabSelectCell.OnTabChangeListener { +// @Inject +// LedMenuContract.Presenter mPresenter; + + private SwitcherCell mLEDBeaconCell;//夜航灯 + private SwitcherCell mLEDArmCell;//机臂灯 + private SwitcherCell mLEDStatusCell;//状态灯 + private SwitcherCell m430LEDsHideModeCell;//隐藏模式 + private LinearLayout m430LedSettingLayout; + private SwitcherCell m430BeaconLedCell;//430夜航灯开关 + + private TabSelectCell m430TopAuxiliaryTabSelectCell;//430上补光灯 + private TabSelectCell m430BottomAuxiliaryTabSelectCell;//430下补光灯 + + private void initView(View view) { + mLEDBeaconCell = view.findViewById(R.id.setting_menu_common_led_beacon); + mLEDArmCell = view.findViewById(R.id.setting_menu_common_led_arm); + mLEDStatusCell = view.findViewById(R.id.setting_menu_common_led_status); + m430LEDsHideModeCell = view.findViewById(R.id.setting_menu_common_leds_hide_mode); + m430LedSettingLayout = view.findViewById(R.id.setting_menu_common_led); + m430BeaconLedCell = view.findViewById(R.id.setting_menu_common_beacon_led); + m430TopAuxiliaryTabSelectCell =view.findViewById(R.id.setting_menu_common_top_auxiliary_light); + m430BottomAuxiliaryTabSelectCell = view.findViewById(R.id.setting_menu_common_bottom_auxiliary_light); + } + + @Override + protected String getPreferencesTitle() { + return StringUtils.getResStr(R.string.uxsdk_setting_menu_title_led); + } + + @Override + protected int getLayoutId() { + return R.layout.uxsdk_setting_menu_led_layout; + } + + @Override + public void onCreate(Bundle savedInstanceState) { +// DaggerLedMenuComponent.builder() +// .appComponent(((AppActivity) getActivity()).getAppComponent()) +// .ledMenuModule(new LedMenuModule(this)) +// .build() +// .inject(this); + super.onCreate(savedInstanceState); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + + return mFragmentRoot; + } + + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + initView(view); + init430LEDsHideModeView(); + initKey(); + } + + private void initKey() { + KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyHasInternalBeaconLeds), new CommonCallbacks.CompletionCallbackWithParam() { + @Override + public void onSuccess(Boolean aBoolean) { + if (aBoolean) { + updateViewsByState(); + } + } + @Override + public void onFailure(@NonNull IDJIError error) { + //add log + } + }); + + KeyManager.getInstance().listen(KeyTools.createKey(FlightAssistantKey.KeyBottomAuxiliaryLightMode), this, (oldValue, mode) -> { + if (mode != null) { + setCellTab(m430BottomAuxiliaryTabSelectCell, mode.value()); + } + }); + + + KeyManager.getInstance().getValue(KeyTools.createKey(ProductKey.KeyProductType), new CommonCallbacks.CompletionCallbackWithParam() { + @Override + public void onSuccess(ProductType productType) { + + if (productType == ProductType.M30_SERIES || productType == ProductType.DJI_MAVIC_3_ENTERPRISE_SERIES) { + m430TopAuxiliaryTabSelectCell.setVisibility(View.GONE); + m430BeaconLedCell.setVisibility(View.VISIBLE); + }else{ + updateTopAuxiliaryTabSelectCell(); + + } + } + @Override + public void onFailure(@NonNull IDJIError error) { + //add log + } + }); + + + } + + private void updateTopAuxiliaryTabSelectCell() { + KeyManager.getInstance().listen(KeyTools.createKey(FlightAssistantKey.KeyTopAuxiliaryLightMode), this, (oldValue, mode) -> { + if(mode != null) { + setCellTab(m430TopAuxiliaryTabSelectCell, mode.value()); + } + }); + } + + private void updateViewsByState() { + KeyManager.getInstance().listen(KeyTools.createKey(FlightControllerKey.KeyLEDsSettings), this, (oldValue, leDsSettings) -> { + if (leDsSettings != null) { + setCellCheck(m430BeaconLedCell, leDsSettings.getNavigationLEDsOn()); + setCellCheck(mLEDStatusCell, leDsSettings.getStatusIndicatorLEDsOn()); + setCellCheck(mLEDArmCell, leDsSettings.getFrontLEDsOn()); + } + }); + + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + KeyManager.getInstance().cancelListen(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + } + + //可设置隐藏模式及夜航灯,上下补光灯 + private void init430LEDsHideModeView() { + mLEDBeaconCell.setVisibility(View.GONE); + mLEDArmCell.setVisibility(View.GONE); + mLEDStatusCell.setVisibility(View.GONE); + m430LEDsHideModeCell.setVisibility(View.GONE); + m430LEDsHideModeCell.setOnCheckedChangedListener(this); + m430BeaconLedCell.setOnCheckedChangedListener(this); + m430TopAuxiliaryTabSelectCell.setOnTabChangeListener(this); + m430BottomAuxiliaryTabSelectCell.setOnTabChangeListener(this); +// mCompositeDisposable.add(LEDDiscreetModeLiveData.getInstance().observable(getLifecycle()).subscribe(isHideMode -> { +// if (m430LEDsHideModeCell != null && m430LEDsHideModeCell.isChecked() != isHideMode) { +// setCellCheck(m430LEDsHideModeCell, isHideMode); +// } +// +// m430LedSettingLayout.setVisibility(isHideMode ? View.GONE : View.VISIBLE); +// })); + m430LedSettingLayout.setVisibility( View.VISIBLE); + } + + @Override + public void onCheckedChanged(SwitcherCell cell, boolean isChecked) { + int id = cell.getId();//夜航灯 + if (id == R.id.setting_menu_common_leds_hide_mode) {//隐藏模式按钮 + if (isChecked) { + openLEDsHide(true); + } else { + openLEDsHide(false); + } + } else if (id == R.id.setting_menu_common_beacon_led || id == R.id.setting_menu_common_led_beacon) {//非430夜航灯 + + LEDsSettings leDsSettings = createLedsBuilder(); + leDsSettings.setNavigationLEDsOn(isChecked); + KeyManager.getInstance().setValue(KeyTools.createKey(FlightControllerKey.KeyLEDsSettings), leDsSettings, new CommonCallbacks.CompletionCallback() { + @Override + public void onSuccess() { + //add tips + } + @Override + public void onFailure(@NonNull IDJIError error) { + //add log + } + }); + } else if (id == R.id.setting_menu_common_led_arm) {//机臂灯 + + LEDsSettings leDsSettings = createLedsBuilder(); + leDsSettings.setFrontLEDsOn(isChecked); + leDsSettings.setRearLEDsOn(isChecked); + leDsSettings.setStatusIndicatorLEDsOn(isChecked); + KeyManager.getInstance().setValue(KeyTools.createKey(FlightControllerKey.KeyLEDsSettings), leDsSettings, new CommonCallbacks.CompletionCallback() { + @Override + public void onSuccess() { + if (!isChecked) { + ViewUtil.showToast(getContext(), R.string.uxsdk_app_operator_fail, Toast.LENGTH_SHORT); + } + } + + @Override + public void onFailure(@NonNull IDJIError error) { + //add log + } + }); + } else if (id == R.id.setting_menu_common_led_status) {//状态灯 + LEDsSettings leDsSettings = createLedsBuilder(); + leDsSettings.setStatusIndicatorLEDsOn(isChecked); + KeyManager.getInstance().setValue(KeyTools.createKey(FlightControllerKey.KeyLEDsSettings), leDsSettings, new CommonCallbacks.CompletionCallback() { + @Override + public void onSuccess() { + if (!isChecked) { + ViewUtil.showToast(getContext(), R.string.uxsdk_app_operator_fail, Toast.LENGTH_SHORT); + } + } + + @Override + public void onFailure(@NonNull IDJIError error) { + //add log + } + }); + } + } + + private LEDsSettings createLedsBuilder() { + //先获取现阶段的值 + LEDsSettings defaultSettings = new LEDsSettings(); + LEDsSettings leDsSettings = KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyLEDsSettings) ,defaultSettings); + return new LEDsSettings(leDsSettings.getFrontLEDsOn(),leDsSettings.getStatusIndicatorLEDsOn(),leDsSettings.getRearLEDsOn(),leDsSettings.getNavigationLEDsOn()); + + } + + private void openLEDsHide(boolean isHide) { + LogUtils.i(TAG , "leds hide mode " + isHide); +// mCompositeDisposable.add(LEDDiscreetModeLiveData.getInstance().discreetMode(isHide) +// .subscribe(aBoolean -> { +// if (!aBoolean) { +// ViewUtil.showToast(getContext() ,(R.string.uxsdk_app_operator_fail,Toast.LENGTH_SHORT); +// } else { +// m430LedSettingLayout.setVisibility(isHide ? View.GONE : View.VISIBLE); +// m430BeaconLedCell.setChecked(false); +// } +// })); + + } + + + @Override + public void onTabChanged(TabSelectCell cell, int oldIndex, int newIndex) { + if (oldIndex == newIndex) { + return; + } + int id = cell.getId(); + if (id == R.id.setting_menu_common_top_auxiliary_light) { + + KeyManager.getInstance().setValue(KeyTools.createKey(FlightAssistantKey.KeyTopAuxiliaryLightMode), AuxiliaryLightMode.find(newIndex), new CommonCallbacks.CompletionCallback() { + @Override + public void onSuccess() { + //do nothing + } + + @Override + public void onFailure(@NonNull IDJIError error) { + ViewUtil.showToast(getContext(), R.string.uxsdk_app_operator_fail, Toast.LENGTH_SHORT); + } + }); + + } else if (id == R.id.setting_menu_common_bottom_auxiliary_light) { + AuxiliaryLightMode mode = AuxiliaryLightMode.find(newIndex); + if (mode == AuxiliaryLightMode.OFF) { + ViewUtil.showToast(getContext(),R.string.uxsdk_setting_menu_close_bottom_aux_tips , Toast.LENGTH_LONG); + } + KeyManager.getInstance().setValue(KeyTools.createKey(FlightAssistantKey.KeyBottomAuxiliaryLightMode), AuxiliaryLightMode.find(newIndex), new CommonCallbacks.CompletionCallback() { + @Override + public void onSuccess() { + //do nothing + } + @Override + public void onFailure(@NonNull IDJIError error) { + ViewUtil.showToast(getContext(), R.string.uxsdk_app_operator_fail, Toast.LENGTH_SHORT); + } + }); + + } + } + + private void setCellCheck(SwitcherCell cell, boolean isCheck) { + if (null != cell) { + cell.setOnCheckedChangedListener(null); + cell.setChecked(isCheck); + cell.setOnCheckedChangedListener(this); + } + } + + private void setCellTab(TabSelectCell cell, int tab) { + if (null != cell) { + cell.setOnTabChangeListener(null); + cell.setCurrentTab(tab); + cell.setOnTabChangeListener(this); + } + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/OmniPerceptionMenuFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/OmniPerceptionMenuFragment.java new file mode 100644 index 00000000..89544bac --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/OmniPerceptionMenuFragment.java @@ -0,0 +1,77 @@ +package dji.v5.ux.core.ui.setting.fragment; + +import android.os.Bundle; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import dji.sdk.keyvalue.key.FlightControllerKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.utils.ProductUtil; +import dji.v5.manager.KeyManager; +import dji.v5.utils.common.ContextUtil; +import dji.v5.utils.common.StringUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.ui.setting.ui.MenuFragment; +import dji.v5.ux.obstacle.PrecisionLandingWidget; +import dji.v5.ux.obstacle.VisionPositionWidget; + +/** + * Description : + * + * @author: Byte.Cai + * date : 2022/11/21 + *

+ * Copyright (c) 2022, DJI All Rights Reserved. + */ +public class OmniPerceptionMenuFragment extends MenuFragment { + private PrecisionLandingWidget precisionLandingWidget; + private boolean isDownwardVisionSystemOpen; + + @Override + protected String getPreferencesTitle() { + return StringUtils.getResStr(ContextUtil.getContext(), R.string.uxsdk_setting_menu_title_perception); + } + + @Override + protected int getLayoutId() { + return R.layout.uxsdk_fragemnt_setting_menu_omni_perception_layout; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + VisionPositionWidget visionPositionWidget = (VisionPositionWidget) view.findViewById(R.id.omni_vision_position_widget); + precisionLandingWidget = (PrecisionLandingWidget) view.findViewById(R.id.omni_vision_precision_landing_widget); + visionPositionWidget.setSwitchStateListener(check -> { + isDownwardVisionSystemOpen = check; + updatePrecisionWidgetVisible(); + }); + + KeyManager.getInstance().listen(KeyTools.createKey(FlightControllerKey.KeyConnection), this, (oldValue, newValue) -> updatePrecisionWidgetVisible()); + + + } + + @Override + public void onResume() { + super.onResume(); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + KeyManager.getInstance().cancelListen(this); + } + + private void updatePrecisionWidgetVisible() { + if (precisionLandingWidget == null) { + return; + } + if (isDownwardVisionSystemOpen && !ProductUtil.isM3EProduct() && !ProductUtil.isM4EProduct() && !ProductUtil.isM4DProduct()) { + precisionLandingWidget.setVisibility(View.VISIBLE); + } else { + precisionLandingWidget.setVisibility(View.GONE); + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/PayloadFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/PayloadFragment.java new file mode 100644 index 00000000..eeb269c1 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/PayloadFragment.java @@ -0,0 +1,26 @@ +package dji.v5.ux.core.ui.setting.fragment; + +import dji.v5.utils.common.ContextUtil; +import dji.v5.utils.common.StringUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.ui.setting.ui.MenuFragment; + +/** + * Description : + * + * @author: Byte.Cai + * date : 2022/11/21 + *

+ * Copyright (c) 2022, DJI All Rights Reserved. + */ +public class PayloadFragment extends MenuFragment { + @Override + protected String getPreferencesTitle() { + return StringUtils.getResStr(ContextUtil.getContext(), R.string.uxsdk_payload_setting_title); + } + + @Override + protected int getLayoutId() { + return R.layout.uxsdk_fragment_not_yet_implement; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/RCMenuFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/RCMenuFragment.java new file mode 100644 index 00000000..06ecfde8 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/RCMenuFragment.java @@ -0,0 +1,54 @@ +package dji.v5.ux.core.ui.setting.fragment; + +import android.os.Bundle; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.sdk.keyvalue.key.FlightControllerKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.v5.manager.KeyManager; +import dji.v5.utils.common.ContextUtil; +import dji.v5.utils.common.StringUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.ui.setting.ui.MenuFragment; +import dji.v5.ux.core.util.ViewUtil; + +/** + * Description : + * + * @author: Byte.Cai + * date : 2022/11/21 + *

+ * Copyright (c) 2022, DJI All Rights Reserved. + */ +public class RCMenuFragment extends MenuFragment { + @Override + protected String getPreferencesTitle() { + return StringUtils.getResStr(ContextUtil.getContext(), R.string.uxsdk_setting_menu_title_rc); + } + + @Override + protected int getLayoutId() { + return R.layout.uxsdk_fragment_setting_menu_remote_controller_layout; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + view.findViewById(R.id.setting_menu_rc_calibration).setOnClickListener(v -> { + if (isAircraftConnected()) { + String content = StringUtils.getResStr(R.string.uxsdk_setting_ui_rc_calibration_tip); + ViewUtil.showToast(getContext(), content); + }else { + RcCalibrationFragment fragment = new RcCalibrationFragment(); + addFragment(getFragmentManager(), fragment, true); + } + }); + } + + private boolean isAircraftConnected() { + return KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyConnection),false); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/RcCalibrationFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/RcCalibrationFragment.java new file mode 100644 index 00000000..75cfa290 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/RcCalibrationFragment.java @@ -0,0 +1,27 @@ +package dji.v5.ux.core.ui.setting.fragment; + +import dji.v5.utils.common.ContextUtil; +import dji.v5.utils.common.StringUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.ui.setting.ui.MenuFragment; + +/** + * Description : + * + * @author: Byte.Cai + * date : 2023/9/20 + *

+ * Copyright (c) 2022, DJI All Rights Reserved. + */ +public class RcCalibrationFragment extends MenuFragment { + @Override + protected int getLayoutId() { + return R.layout.uxsdk_fragment_rc_calibration; + } + + @Override + protected String getPreferencesTitle() { + return StringUtils.getResStr(ContextUtil.getContext(), R.string.uxsdk_setting_ui_rc_calibration); + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/RtkMenuFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/RtkMenuFragment.java new file mode 100644 index 00000000..d265e6bb --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/RtkMenuFragment.java @@ -0,0 +1,27 @@ +package dji.v5.ux.core.ui.setting.fragment; + +import dji.v5.utils.common.ContextUtil; +import dji.v5.utils.common.StringUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.ui.setting.ui.MenuFragment; + +/** + * Description : + * + * @author: Byte.Cai + * date : 2022/11/21 + *

+ * Copyright (c) 2022, DJI All Rights Reserved. + */ +public class RtkMenuFragment extends MenuFragment { + + @Override + protected String getPreferencesTitle() { + return StringUtils.getResStr(ContextUtil.getContext(), R.string.uxsdk_setting_menu_title_rtk); + } + + @Override + protected int getLayoutId() { + return R.layout.uxsdk_fragemnt_setting_ui_rtk_layout; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/SensorsMenuFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/SensorsMenuFragment.java new file mode 100644 index 00000000..e3950919 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/fragment/SensorsMenuFragment.java @@ -0,0 +1,86 @@ +package dji.v5.ux.core.ui.setting.fragment; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.R; +import dji.v5.ux.core.base.CompassStatusWidget; +import dji.v5.ux.core.base.ImuStatusWidget; +import dji.v5.ux.core.base.TabGroupWidget; +import dji.v5.ux.core.ui.setting.ui.MenuFragment; + + +/** + *

传感器状态页面

+ *

+ *

  • IMU状态
  • + *
  • Compass状态
  • + * + */ + +public class SensorsMenuFragment extends MenuFragment { + + private static final String CURRENT_INDEX = "current_sensor_index"; + private static final int INDEX_IMU = 0; + + TabGroupWidget mSettingMenuSensorsTab; + ImuStatusWidget mSettingMenuSensorsImu; + CompassStatusWidget mSettingMenuSensorsCompass; + + @Override + protected int getLayoutId() { + return R.layout.uxsdk_setting_menu_sensors_layout; + } + + @Override + protected String getPreferencesTitle() { + return AndUtil.getResString(R.string.uxsdk_setting_menu_title_sensors_state); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + super.onCreateView(inflater, container, savedInstanceState); + + mSettingMenuSensorsTab = mFragmentRoot.findViewById(R.id.setting_menu_sensors_tab); + mSettingMenuSensorsImu = mFragmentRoot.findViewById(R.id.setting_menu_sensors_imu); + mSettingMenuSensorsCompass = mFragmentRoot.findViewById(R.id.setting_menu_sensors_compass); + if (savedInstanceState != null) { + mSettingMenuSensorsTab.setCheckedIndex(savedInstanceState.getInt(CURRENT_INDEX, 0)); + } + initView(); + + mSettingMenuSensorsTab.setOnTabChangeListener((oldIndex, newIndex) -> { + if (newIndex == 0) { + mSettingMenuSensorsImu.setVisibility(View.VISIBLE); + mSettingMenuSensorsCompass.setVisibility(View.GONE); + } else { + mSettingMenuSensorsImu.setVisibility(View.GONE); + mSettingMenuSensorsCompass.setVisibility(View.VISIBLE); + } + }); + + return mFragmentRoot; + } + + @Override + public void onSaveInstanceState(Bundle outState) { + if (mSettingMenuSensorsTab != null) { + outState.putInt(CURRENT_INDEX, mSettingMenuSensorsTab.getCheckedIndex()); + } + super.onSaveInstanceState(outState); + } + + + + private void initView() { + final boolean visible = (View.VISIBLE == mSettingMenuSensorsTab.getVisibility()); + mSettingMenuSensorsTab.setVisibility(View.VISIBLE); + if (!visible) { + mSettingMenuSensorsImu.setVisibility(View.VISIBLE); + mSettingMenuSensorsTab.setCheckedIndex(INDEX_IMU); + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/taplayout/QTabView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/taplayout/QTabView.java new file mode 100644 index 00000000..de22792a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/taplayout/QTabView.java @@ -0,0 +1,380 @@ +package dji.v5.ux.core.ui.setting.taplayout; + +import android.content.Context; +import android.graphics.drawable.GradientDrawable; +import android.text.TextUtils; +import android.view.Gravity; +import android.view.View; +import android.widget.FrameLayout; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import dji.v5.utils.common.AndUtil; +import dji.v5.utils.common.ContextUtil; +import dji.v5.ux.R; + + +public class QTabView extends TabView { + private Context mContext; + private ImageView mIcon; + private TextView mTitle; + private TextView mBadge; + private int mMinHeight; + private TabIcon mTabIcon; + private TabTitle mTabTitle; + private boolean mChecked; + private LinearLayout mContainer; + private GradientDrawable gd; + + public QTabView(Context context) { + super(context); + mContext = context; + gd = new GradientDrawable(); + gd.setColor(0xFFE84E40); + mMinHeight = dp2px(30); + mTabIcon = new TabIcon.Builder().build(); + mTabTitle = new TabTitle.Builder(context).build(); + initView(); + } + + @Override + protected int[] onCreateDrawableState(int extraSpace) { + final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); + if (isChecked()) { + mergeDrawableStates(drawableState, new int[]{android.R.attr.state_checked}); + } + return drawableState; + } + + private void initView() { + initContainer(); + initIconView(); + initTitleView(); + initBadge(); + addView(mContainer); + addView(mBadge); + } + + private void initContainer() { + mContainer = new LinearLayout(mContext); + mContainer.setOrientation(LinearLayout.HORIZONTAL); + mContainer.setMinimumHeight(mMinHeight); + mContainer.setPadding(dp2px(5), dp2px(5), dp2px(5), dp2px(5)); + mContainer.setGravity(Gravity.CENTER); + } + + private void initBadge() { + mBadge = new TextView(mContext); + LayoutParams + params2 = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); + params2.gravity = Gravity.RIGHT | Gravity.TOP; + params2.setMargins(0, dp2px(5), dp2px(5), 0); + mBadge.setLayoutParams(params2); + mBadge.setGravity(Gravity.CENTER); + mBadge.setTextColor(0xFFFFFFFF); + mBadge.setTextSize(9); + setBadge(0); + } + + private void initTitleView() { + if (mTitle != null) { + mContainer.removeView(mTitle); + } + mTitle = new TextView(mContext); + LinearLayout.LayoutParams + params = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT); + params.weight = 1; + mTitle.setLayoutParams(params); + mTitle.setTextColor(mTabTitle.mColorNormal); + mTitle.setTextSize(mTabTitle.mTitleTextSize); + mTitle.setText(mTabTitle.mContent); + mTitle.setGravity(Gravity.LEFT); + mTitle.setSingleLine(); + mTitle.setEllipsize(TextUtils.TruncateAt.END); + mTitle.setPadding(dp2px(5), dp2px(5), dp2px(5), dp2px(5)); + requestContainerLayout(mTabIcon.mIconGravity); + } + + private void initIconView() { + if (mIcon != null) { + mContainer.removeView(mIcon); + } + mIcon = new ImageView(mContext); + int dp = AndUtil.isTabletDevice(ContextUtil.getContext()) ? 10 : 7; + mIcon.setPadding(dp2px(dp), dp2px(dp), dp2px(dp), dp2px(dp)); + mIcon.setScaleType(ImageView.ScaleType.FIT_CENTER); + LayoutParams params = new LayoutParams(getResources().getDimensionPixelSize(R.dimen.uxsdk_38_dp), + getResources().getDimensionPixelSize(R.dimen.uxsdk_38_dp)); + mIcon.setLayoutParams(params); + if (mTabIcon.mNormalIcon != 0) { + mIcon.setImageResource(mTabIcon.mNormalIcon); + } else { + mIcon.setVisibility(View.GONE); + } + if (mTabIcon.mBackground != 0) { + mIcon.setBackgroundResource(mTabIcon.mBackground); + } + requestContainerLayout(mTabIcon.mIconGravity); + } + + private void setBadgeImp(int num) { + LayoutParams lp = (LayoutParams) mBadge.getLayoutParams(); + if (num <= 9) { + lp.width = dp2px(12); + lp.height = dp2px(12); + gd.setShape(GradientDrawable.OVAL); + mBadge.setPadding(0, 0, 0, 0); + } else { + lp.width = LayoutParams.WRAP_CONTENT; + lp.height = LayoutParams.WRAP_CONTENT; + mBadge.setPadding(dp2px(3), 0, dp2px(3), 0); + gd.setShape(GradientDrawable.RECTANGLE); + gd.setCornerRadius(dp2px(6)); + } + mBadge.setLayoutParams(lp); + mBadge.setBackgroundDrawable(gd); + mBadge.setText(String.valueOf(num)); + mBadge.setVisibility(View.VISIBLE); + } + + @Override + public QTabView setBadge(int num) { + if (num > 0) { + setBadgeImp(num); + } else { + mBadge.setText(""); + mBadge.setVisibility(View.GONE); + } + return this; + } + + public QTabView setIcon(TabIcon icon) { + if (icon != null) { + mTabIcon = icon; + } + initIconView(); + setChecked(mChecked); + return this; + } + + public QTabView setTitle(TabTitle title) { + if (title != null) { + mTabTitle = title; + } + initTitleView(); + setChecked(mChecked); + return this; + } + + public QTabView setBackground(int resId) { + super.setBackgroundResource(resId); + return this; + } + + private void requestContainerLayout(int gravity) { + mContainer.removeAllViews(); + switch (gravity) { + case Gravity.LEFT: + mContainer.setOrientation(LinearLayout.HORIZONTAL); + setIconAndTitle(); + break; + case Gravity.TOP: + mContainer.setOrientation(LinearLayout.VERTICAL); + setIconAndTitle(); + + break; + case Gravity.RIGHT: + mContainer.setOrientation(LinearLayout.HORIZONTAL); + setTitleAndICon(); + break; + case Gravity.BOTTOM: + mContainer.setOrientation(LinearLayout.VERTICAL); + setTitleAndICon(); + break; + case Gravity.CENTER: + mContainer.setOrientation(LinearLayout.VERTICAL); + if (mIcon != null) { + mContainer.addView(mIcon); + } + if (mTitle != null && !TextUtils.isEmpty(mTitle.getText().toString())) { + mContainer.addView(mTitle); + } + break; + default: + break; + } + } + + private void setIconAndTitle() { + if (mIcon != null) { + mContainer.addView(mIcon); + } + if (mTitle != null && !TextUtils.isEmpty(mTitle.getText().toString())) { + mContainer.addView(mTitle); + } + } + + private void setTitleAndICon() { + if (mTitle != null) { + mContainer.addView(mTitle); + } + if (mIcon != null) { + mContainer.addView(mIcon); + } + } + + protected int dp2px(float dp) { + final float scale = mContext.getResources().getDisplayMetrics().density; + return (int) (dp * scale + 0.5f); + } + + @Override + public void setChecked(boolean checked) { + mChecked = checked; + refreshDrawableState(); + setSelected(mChecked); + if (mChecked) { + mTitle.setTextColor(mTabTitle.mColorSelected); + if (mTabIcon.mSelectedIcon != 0) { + mIcon.setVisibility(View.VISIBLE); + mIcon.setImageResource(mTabIcon.mSelectedIcon); + } else { + mIcon.setVisibility(View.GONE); + } + } else { + mTitle.setTextColor(mTabTitle.mColorNormal); + if (mTabIcon.mNormalIcon != 0) { + mIcon.setVisibility(View.VISIBLE); + mIcon.setImageResource(mTabIcon.mNormalIcon); + } else { + mIcon.setVisibility(View.GONE); + } + } + } + + @Override + public boolean isChecked() { + return mChecked; + } + + @Override + public void toggle() { + setChecked(!mChecked); + } + + public static class TabIcon { + public int mSelectedIcon; + public int mNormalIcon; + public int mIconGravity; + public int mIconWidth; + public int mIconHeight; + public int mBackground; + + private TabIcon(int mSelectedIcon, int mNormalIcon, int mIconGravity, int mIconWidth, int mIconHeight, int mBackground) { + this.mSelectedIcon = mSelectedIcon; + this.mNormalIcon = mNormalIcon; + this.mIconGravity = mIconGravity; + this.mIconWidth = mIconWidth; + this.mIconHeight = mIconHeight; + this.mBackground = mBackground; + } + + public static class Builder { + private int mSelectedIcon; + private int mNormalIcon; + private int mIconGravity; + private int mIconWidth; + private int mIconHeight; + private int mBackground; + + public Builder() { + mSelectedIcon = 0; + mNormalIcon = 0; + mIconWidth = LayoutParams.WRAP_CONTENT; + mIconHeight = LayoutParams.WRAP_CONTENT; + mIconGravity = Gravity.LEFT; + mBackground = 0; + } + + public Builder setIcon(int selectIconResId, int normalIconResId) { + mSelectedIcon = selectIconResId; + mNormalIcon = normalIconResId; + return this; + } + + public Builder setBackground(int background) { + mBackground = background; + return this; + } + + public Builder setIconSize(int width, int height) { + mIconWidth = width; + mIconHeight = height; + return this; + } + + public Builder setIconGravity(int gravity) { + if (gravity != Gravity.LEFT && gravity != Gravity.RIGHT + && gravity != Gravity.TOP && gravity != Gravity.BOTTOM && gravity != Gravity.CENTER) { + throw new IllegalStateException("iconGravity only support Gravity.LEFT " + + "or Gravity.RIGHT or Gravity.TOP or Gravity.BOTTOM"); + } + mIconGravity = gravity; + return this; + } + + public TabIcon build() { + return new TabIcon(mSelectedIcon, mNormalIcon, mIconGravity, mIconWidth, mIconHeight, mBackground); + } + } + } + + public static class TabTitle { + public int mColorSelected; + public int mColorNormal; + public int mTitleTextSize; + public String mContent; + + private TabTitle(int mColorSelected, int mColorNormal, int mTitleTextSize, String mContent) { + this.mColorSelected = mColorSelected; + this.mColorNormal = mColorNormal; + this.mTitleTextSize = mTitleTextSize; + this.mContent = mContent; + } + + public static class Builder { + private int mColorSelected; + private int mColorNormal; + private int mTitleTextSize; + private String mContent; + + public Builder(Context context) { + this.mColorSelected = context.getResources().getColor(R.color.uxsdk_blue_highlight); + this.mColorNormal = 0xFF757575; + this.mTitleTextSize = 16; + this.mContent = null; + } + + public Builder setTextColor(int colorSelected, int colorNormal) { + mColorSelected = colorSelected; + mColorNormal = colorNormal; + return this; + } + + public Builder setTextSize(int sizeSp) { + mTitleTextSize = sizeSp; + return this; + } + + public Builder setContent(String content) { + mContent = content; + return this; + } + + public TabTitle build() { + return new TabTitle(mColorSelected, mColorNormal, mTitleTextSize, mContent); + } + } + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/taplayout/TabAdapter.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/taplayout/TabAdapter.java new file mode 100644 index 00000000..21bc16bd --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/taplayout/TabAdapter.java @@ -0,0 +1,13 @@ +package dji.v5.ux.core.ui.setting.taplayout; + +public interface TabAdapter { + int getCount(); + + int getBadge(int position); + + QTabView.TabIcon getIcon(int position); + + QTabView.TabTitle getTitle(int position); + + int getBackground(int position); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/taplayout/TabView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/taplayout/TabView.java new file mode 100644 index 00000000..b399cd97 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/taplayout/TabView.java @@ -0,0 +1,15 @@ +package dji.v5.ux.core.ui.setting.taplayout; + +import android.content.Context; +import android.widget.Checkable; +import android.widget.FrameLayout; + + +public abstract class TabView extends FrameLayout implements Checkable{ + + protected TabView(Context context) { + super(context); + } + + public abstract TabView setBadge(int num); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/taplayout/TabViewPager.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/taplayout/TabViewPager.java new file mode 100644 index 00000000..c5e953e8 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/taplayout/TabViewPager.java @@ -0,0 +1,43 @@ +package dji.v5.ux.core.ui.setting.taplayout; +/* + * Copyright (c) 2014, DJI All Rights Reserved. + */ + +import android.content.Context; +import android.util.AttributeSet; +import android.view.MotionEvent; + +import androidx.viewpager.widget.ViewPager; + + +public class TabViewPager extends ViewPager { + + private boolean isPagingEnabled = true; + + public TabViewPager(Context context) { + super(context); + } + + public TabViewPager(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + public boolean onTouchEvent(MotionEvent event) { + return this.isPagingEnabled && super.onTouchEvent(event); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent event) { + return this.isPagingEnabled && super.onInterceptTouchEvent(event); + } + + public void setPagingEnabled(boolean b) { + this.isPagingEnabled = b; + } + + @Override + public void setCurrentItem(int item, boolean smoothScroll) { + super.setCurrentItem(item, false); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/taplayout/VerticalTabLayout.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/taplayout/VerticalTabLayout.java new file mode 100644 index 00000000..e1353776 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/taplayout/VerticalTabLayout.java @@ -0,0 +1,518 @@ +package dji.v5.ux.core.ui.setting.taplayout; + +import android.animation.ValueAnimator; +import android.content.Context; +import android.content.res.TypedArray; +import android.database.DataSetObserver; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.graphics.RectF; +import android.util.AttributeSet; +import android.view.Gravity; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.ScrollView; + +import androidx.annotation.Nullable; +import androidx.viewpager.widget.PagerAdapter; +import androidx.viewpager.widget.ViewPager; + +import dji.v5.ux.R; + + +public class VerticalTabLayout extends ScrollView { + private Context mContext; + private TabStrip mTabStrip; + private int mColorIndicator; + private TabView mSelectedTab; + private int mTabMargin; + private int mIndicatorWidth; + private int mIndicatorGravity; + private float mIndicatorCorners; + private int mTabMode; + private int mTabHeight; + + public static int TAB_MODE_FIXED = 10; + public static int TAB_MODE_SCROLLABLE = 11; + + private ViewPager mViewPager; + private PagerAdapter mPagerAdapter; + protected TabAdapter mTabAdapter; + + private OnTabSelectedListener mTabSelectedListener; + private OnTabPageChangeListener mTabPageChangeListener; + private DataSetObserver mPagerAdapterObserver; + + public VerticalTabLayout(Context context) { + this(context, null); + } + + public VerticalTabLayout(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public VerticalTabLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + mContext = context; + setFillViewport(true); + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.VerticalTabLayout); + mColorIndicator = typedArray.getColor(R.styleable.VerticalTabLayout_uxsdk_indicator_color, + context.getResources().getColor(R.color.uxsdk_blue_highlight)); + mIndicatorWidth = (int) typedArray.getDimension(R.styleable.VerticalTabLayout_uxsdk_indicator_width, dp2px(3)); + mIndicatorCorners = typedArray.getDimension(R.styleable.VerticalTabLayout_uxsdk_indicator_corners, 0); + mIndicatorGravity = typedArray.getInteger(R.styleable.VerticalTabLayout_uxsdk_indicator_gravity, Gravity.LEFT); + mTabMargin = (int) typedArray.getDimension(R.styleable.VerticalTabLayout_uxsdk_tab_margin, 0); + mTabMode = typedArray.getInteger(R.styleable.VerticalTabLayout_uxsdk_tab_mode, TAB_MODE_FIXED); + mTabHeight = (int) typedArray.getDimension(R.styleable.VerticalTabLayout_uxsdk_tab_height, LayoutParams.WRAP_CONTENT); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + if (getChildCount() > 0) { + removeAllViews(); + } + initTabStrip(); + } + + private void initTabStrip() { + mTabStrip = new TabStrip(mContext); + addView(mTabStrip, new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); + } + + public void removeAllTabs() { + // fix Attempt to invoke virtual method 'void android.view.View.unFocus(android.view.View)' on a null object reference + mTabStrip.removeAllViews(); + mSelectedTab = null; + } + + public TabView getTabAt(int position) { + return (TabView) mTabStrip.getChildAt(position); + } + + private void addTabWithMode(TabView tabView) { + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT); + initTabWithMode(params); + mTabStrip.addView(tabView, params); + if (mTabStrip.indexOfChild(tabView) == 0) { + tabView.setChecked(true); + params = (LinearLayout.LayoutParams) tabView.getLayoutParams(); + if (mTabMode == TAB_MODE_SCROLLABLE) { + params.height = mTabHeight; + } + params.setMargins(0, 0, 0, 0); + tabView.setLayoutParams(params); + mSelectedTab = tabView; + } + } + + private void initTabWithMode(LinearLayout.LayoutParams params) { + if (mTabMode == TAB_MODE_FIXED) { + params.height = 0; + params.weight = 1.0f; + params.setMargins(0, 0, 0, 0); + } else if (mTabMode == TAB_MODE_SCROLLABLE) { + params.height = mTabHeight; + params.weight = 0f; + params.setMargins(0, mTabMargin, 0, 0); + } + } + + private void scrollTab(final TabView tabView) { + tabView.post(() -> { + int y = getScrollY(); + int tabTop = tabView.getTop() + tabView.getHeight() / 2 - y; + int target = getHeight() / 2; + smoothScrollBy(0, tabTop - target); + }); + } + + public void addTab(TabView tabView) { + if (tabView != null) { + addTabWithMode(tabView); + tabView.setOnClickListener(view -> { + int position = mTabStrip.indexOfChild(view); + if (position >= 0 && position < mTabStrip.getChildCount()) { + setTabSelected(position); + } + }); + } else { + throw new IllegalStateException("tabview can't be null"); + } + } + + public void setTabSelected(int position) { + TabView view = getTabAt(position); + if (view != mSelectedTab) { + mSelectedTab.setChecked(false); + view.setChecked(true); + if (mViewPager == null) { + mTabStrip.moveIndicator(position); + } + mSelectedTab = view; + notifyTabSelected(view, position); + scrollTab(mSelectedTab); + } + } + + private void notifyTabSelected(TabView view, int position) { + if (mTabSelectedListener != null) { + mTabSelectedListener.onTabSelected(view, position); + } + } + + public void setTabBadge(int position, int num) { + getTabAt(position).setBadge(num); + } + + public void setTabMode(int mode) { + if (mode != TAB_MODE_FIXED && mode != TAB_MODE_SCROLLABLE) { + throw new IllegalStateException("only support TAB_MODE_FIXED or TAB_MODE_SCROLLABLE"); + } + if (mode == mTabMode) { + return; + } + mTabMode = mode; + for (int i = 0; i < mTabStrip.getChildCount(); i++) { + View view = mTabStrip.getChildAt(i); + LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams(); + initTabWithMode(params); + if (i == 0) { + params.setMargins(0, 0, 0, 0); + } + view.setLayoutParams(params); + } + mTabStrip.invalidate(); + mTabStrip.post(() -> mTabStrip.updataIndicatorMargin()); + } + + /** + * only in TAB_MODE_SCROLLABLE mode will be supported + * + * @param margin margin + */ + public void setTabMargin(int margin) { + if (margin == mTabMargin) { + return; + } + mTabMargin = margin; + if (mTabMode == TAB_MODE_FIXED) { + return; + } + for (int i = 0; i < mTabStrip.getChildCount(); i++) { + View view = mTabStrip.getChildAt(i); + LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams(); + params.setMargins(0, i == 0 ? 0 : mTabMargin, 0, 0); + view.setLayoutParams(params); + } + mTabStrip.invalidate(); + mTabStrip.post(() -> mTabStrip.updataIndicatorMargin()); + } + + /** + * only in TAB_MODE_SCROLLABLE mode will be supported + * + * @param height height + */ + public void setTabHeight(int height) { + if (height == mTabHeight) { + return; + } + mTabHeight = height; + if (mTabMode == TAB_MODE_FIXED) { + return; + } + for (int i = 0; i < mTabStrip.getChildCount(); i++) { + View view = mTabStrip.getChildAt(i); + LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams(); + params.height = mTabHeight; + view.setLayoutParams(params); + } + mTabStrip.invalidate(); + mTabStrip.post(() -> mTabStrip.updataIndicatorMargin()); + } + + public void setIndicatorColor(int color) { + mColorIndicator = color; + mTabStrip.invalidate(); + } + + public void setIndicatorWidth(int width) { + mIndicatorWidth = width; + mTabStrip.setIndicatorGravity(); + } + + public void setIndicatorCorners(int corners) { + mIndicatorCorners = corners; + mTabStrip.invalidate(); + } + + /** + * @param gravity only support Gravity.LEFT,Gravity.RIGHT,Gravity.FILL + */ + public void setIndicatorGravity(int gravity) { + if (gravity == Gravity.LEFT || gravity == Gravity.RIGHT || Gravity.FILL == gravity) { + mIndicatorGravity = gravity; + mTabStrip.setIndicatorGravity(); + } else { + throw new IllegalStateException("only support Gravity.LEFT,Gravity.RIGHT,Gravity.FILL"); + } + } + + public void setOnTabSelectedListener(OnTabSelectedListener listener) { + mTabSelectedListener = listener; + } + + public void setTabAdapter(TabAdapter adapter) { + removeAllTabs(); + if (adapter != null) { + mTabAdapter = adapter; + for (int i = 0; i < adapter.getCount(); i++) { + addTab(new QTabView(mContext).setIcon(adapter.getIcon(i)) + .setTitle(adapter.getTitle(i)).setBadge(adapter.getBadge(i)) + .setBackground(adapter.getBackground(i))); + } + } else { + removeAllTabs(); + } + } + + public void setupWithViewPager(@Nullable final ViewPager viewPager) { + if (mViewPager != null && mTabPageChangeListener != null) { + mViewPager.removeOnPageChangeListener(mTabPageChangeListener); + } + + if (viewPager != null) { + final PagerAdapter adapter = viewPager.getAdapter(); + if (adapter == null) { + throw new IllegalArgumentException("ViewPager does not have a PagerAdapter set"); + } + + mViewPager = viewPager; + + if (mTabPageChangeListener == null) { + mTabPageChangeListener = new OnTabPageChangeListener(); + } + viewPager.addOnPageChangeListener(mTabPageChangeListener); + + setOnTabSelectedListener((tab, position) -> viewPager.setCurrentItem(position, false)); + + setPagerAdapter(adapter, true); + } else { + mViewPager = null; + setOnTabSelectedListener(null); + setPagerAdapter(null, true); + } + } + + private void setPagerAdapter(@Nullable final PagerAdapter adapter, final boolean addObserver) { + if (mPagerAdapter != null && mPagerAdapterObserver != null) { + mPagerAdapter.unregisterDataSetObserver(mPagerAdapterObserver); + } + + mPagerAdapter = adapter; + + if (addObserver && adapter != null) { + if (mPagerAdapterObserver == null) { + mPagerAdapterObserver = new PagerAdapterObserver(); + } + adapter.registerDataSetObserver(mPagerAdapterObserver); + } + + populateFromPagerAdapter(); + } + + private void populateFromPagerAdapter() { + removeAllTabs(); + if (mPagerAdapter != null) { + final int adapterCount = mPagerAdapter.getCount(); + for (int i = 0; i < adapterCount; i++) { + addTab(i); + } + // Make sure we reflect the currently set ViewPager item + if (mViewPager != null && adapterCount > 0) { + final int curItem = mViewPager.getCurrentItem(); + if (curItem != getSelectedTabPosition() && curItem < getTabCount()) { + setTabSelected(curItem); + } + } + return; + } + removeAllTabs(); + + } + + private void addTab(int i) { + if (mPagerAdapter instanceof TabAdapter) { + mTabAdapter = (TabAdapter) mPagerAdapter; + addTab(new QTabView(mContext).setIcon(mTabAdapter.getIcon(i)) + .setTitle(mTabAdapter.getTitle(i)).setBadge(mTabAdapter.getBadge(i)) + .setBackground(mTabAdapter.getBackground(i))); + } else { + String title = mPagerAdapter.getPageTitle(i) == null ? "tab" + i : mPagerAdapter.getPageTitle(i).toString(); + addTab(new QTabView(mContext).setTitle( + new QTabView.TabTitle.Builder(mContext).setContent(title).build())); + } + } + + private int getTabCount() { + return mTabStrip.getChildCount(); + } + + private int getSelectedTabPosition() { + // if (mViewPager != null) return mViewPager.getCurrentItem(); + int index = mTabStrip.indexOfChild(mSelectedTab); + return index == -1 ? 0 : index; + } + + + private class TabStrip extends LinearLayout { + private float mIndicatorY; + private int mIndicatorX; + private int mLastWidth; + private int mIndicatorHeight; + private Paint mIndicatorPaint; + + public TabStrip(Context context) { + super(context); + setWillNotDraw(false); + setOrientation(LinearLayout.VERTICAL); + mIndicatorPaint = new Paint(); + mIndicatorGravity = mIndicatorGravity == 0 ? Gravity.LEFT : mIndicatorGravity; + setIndicatorGravity(); + } + + @Override + protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { + super.onMeasure(widthMeasureSpec, heightMeasureSpec); + if (getChildCount() > 0) { + View childView = getChildAt(0); + mIndicatorHeight = childView.getMeasuredHeight(); + } + } + + public void updataIndicatorMargin() { + int index = getSelectedTabPosition(); + mIndicatorY = calcIndicatorY(index); + invalidate(); + } + + + public void setIndicatorGravity() { + if (mIndicatorGravity == Gravity.LEFT) { + mIndicatorX = 0; + if (mLastWidth != 0) { + mIndicatorWidth = mLastWidth; + } + setPadding(mIndicatorWidth, 0, 0, 0); + } else if (mIndicatorGravity == Gravity.RIGHT) { + if (mLastWidth != 0) { + mIndicatorWidth = mLastWidth; + } + setPadding(0, 0, mIndicatorWidth, 0); + } else if (mIndicatorGravity == Gravity.FILL) { + mIndicatorX = 0; + setPadding(0, 0, 0, 0); + } + post(() -> { + if (mIndicatorGravity == Gravity.RIGHT) { + mIndicatorX = getWidth() - mIndicatorWidth; + } else if (mIndicatorGravity == Gravity.FILL) { + mLastWidth = mIndicatorWidth; + mIndicatorWidth = getWidth(); + } + invalidate(); + }); + } + + private float calcIndicatorY(float offset) { + if (mTabMode == TAB_MODE_FIXED) { + return offset * mIndicatorHeight; + } + return offset * (mIndicatorHeight + mTabMargin); + } + + public void moveIndicator(float offset) { + mIndicatorY = calcIndicatorY(offset); + invalidate(); + } + + public void moveIndicator(final int index) { + final float target = calcIndicatorY(index); + if (mIndicatorY == target) { + return; + } + post(() -> { + ValueAnimator anime = ValueAnimator.ofFloat(mIndicatorY, target); + anime.addUpdateListener(animation -> { + float value = Float.parseFloat(animation.getAnimatedValue().toString()); + mIndicatorY = value; + invalidate(); + }); + anime.setDuration(200).start(); + }); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + mIndicatorPaint.setColor(mColorIndicator); + RectF r = new RectF(mIndicatorX * 1f, mIndicatorY * 1f, + mIndicatorX + mIndicatorWidth * 1f, mIndicatorY + mIndicatorHeight * 1f); + if (mIndicatorCorners != 0) { + canvas.drawRoundRect(r, mIndicatorCorners, mIndicatorCorners, mIndicatorPaint); + } else { + canvas.drawRect(r, mIndicatorPaint); + } + } + + } + + protected int dp2px(float dp) { + final float scale = mContext.getResources().getDisplayMetrics().density; + return (int) (dp * scale + 0.5f); + } + + private class OnTabPageChangeListener implements ViewPager.OnPageChangeListener { + + public OnTabPageChangeListener() { + //do nothing + } + + @Override + public void onPageScrollStateChanged(int state) { + //do nothing + } + + @Override + public void onPageScrolled(int position, float positionOffset, + int positionOffsetPixels) { + mTabStrip.moveIndicator(positionOffset + position); + } + + @Override + public void onPageSelected(int position) { + if (position != getSelectedTabPosition()) { + setTabSelected(position); + } + } + } + + private class PagerAdapterObserver extends DataSetObserver { + @Override + public void onChanged() { + populateFromPagerAdapter(); + } + + @Override + public void onInvalidated() { + populateFromPagerAdapter(); + } + } + + public interface OnTabSelectedListener { + + void onTabSelected(TabView tab, int position); + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/AppFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/AppFragment.java new file mode 100644 index 00000000..c3d490af --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/AppFragment.java @@ -0,0 +1,176 @@ +package dji.v5.ux.core.ui.setting.ui; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.Nullable; +import androidx.fragment.app.FragmentActivity; + + +import io.reactivex.rxjava3.disposables.CompositeDisposable; + +/* + * Copyright (c) 2014, DJI All Rights Reserved. + */ + +/** + * + * @author luca + * @date 2016/12/13 + */ + +public abstract class AppFragment extends BaseFragment { + + protected CompositeDisposable mCompositeDisposable = new CompositeDisposable(); + protected OnBackPressedHandler mOnBackPressedHandler; + protected CommonLoadingDialog mLoadingDialog; + + protected Object mBusListener; + protected boolean isRcConnected = false; + protected boolean isDeviceConnected = false; + + //region Fragment Lifecycle + @Override + public void onCreate(@Nullable Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + if((getActivity() instanceof OnBackPressedHandler)){ + this.mOnBackPressedHandler = (OnBackPressedHandler) getActivity(); + } + } + + @Override + public void onStart() { + super.onStart(); + if (mOnBackPressedHandler != null) { + //告诉FragmentActivity,当前Fragment在栈顶 + mOnBackPressedHandler.setSelectedFragment(this); + } + } + + /** + * FragmentActivity捕捉到物理返回键点击事件后会首先询问Fragment是否消费该事件 + * @return 如果没有Fragment消息时FragmentActivity自己才会消费该事件 + */ + protected boolean onBackPressed() { + return false; + } + //endregion + + //region Loading Dialog + /** + * 进度对话框是否正在显示 + * @return true 正在显示 + */ + public boolean isShowLoadingDialog() { + return mLoadingDialog != null && mLoadingDialog.isShowing(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + initData(); + return super.onCreateView(inflater, container, savedInstanceState); + } + + private void initData() { +// mBusListener = new Object(){ +// @Subscribe(thread = EventThread.MAIN_THREAD, tags = {@Tag(BusAction.TAG_RESTART_MANUAL_FLIGHT)}) +// @SuppressWarnings("unused") +// public void onEventRestartFlight(Boolean restart) { +// if (restart) { +// onRestartFlight(); +// } +// } +// +// @Subscribe(thread = EventThread.MAIN_THREAD, tags = { @Tag(DroneEvent.TAG)}) +// @SuppressWarnings("unused") +// public void onEventDeviceDisconnected(DroneEvent event) { +// if (event.getType() == DroneEvent.COMPONENT_CONNECTED && event.getComponentKey() == DroneEvent.ComponentKey.FlightController) { +// if (!event.isConnected()) { +// onDeviceDisconnected(); +// } else { +// onDeviceConnected(); +// } +// isDeviceConnected = event.isConnected(); +// } +// +// if (!isRcConnected && Pilot2Repo.RemoteController().Connection().getValue(false)) { +// isRcConnected = true; +// onRcConnected(); +// } else if (isRcConnected && !Pilot2Repo.RemoteController().Connection().getValue(false)) { +// isRcConnected = false; +// onRcDisconnected(); +// } +// } +// }; +// RxBus.get().register(mBusListener); + } + + @Nullable + protected FragmentActivity getAppActivity() { + return getActivity(); + } + @Override + public void onDestroyView() { + //调用clear可以保证disposed未false,使得Fragment恢复时能够再次调用add + if (mCompositeDisposable != null) { + mCompositeDisposable.clear(); + } + super.onDestroyView(); + } + + protected boolean isFinishing() { + return getActivity() == null || getActivity().isFinishing(); + } + + protected void showLoadingDialog() { + if (mLoadingDialog == null) { + mLoadingDialog = new CommonLoadingDialog(getAppActivity()); + mLoadingDialog.setCancelable(true); + mLoadingDialog.setCanceledOnTouchOutside(true); + } + if (!mLoadingDialog.isShowing()) { + mLoadingDialog.show(); + } + } + + protected void hideLoadingDialog() { + if (mLoadingDialog != null && mLoadingDialog.isShowing()) { + mLoadingDialog.dismiss(); + } + } + //endregion + + /** + * 重启飞控界面 + */ + protected void onRestartFlight() { + + } + + /** + * 设备断开连接 + */ + protected void onDeviceDisconnected() { + + } + + protected void onDeviceConnected() { + + } + + /** + * APP与遥控器建立连接 + */ + protected void onRcConnected() { + + } + + /** + * APP与遥控器断开连接 + */ + protected void onRcDisconnected() { + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/BaseFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/BaseFragment.java new file mode 100644 index 00000000..9f45bb2c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/BaseFragment.java @@ -0,0 +1,85 @@ +package dji.v5.ux.core.ui.setting.ui; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; + + + +/** + * A simple {@link Fragment} subclass. + */ +public abstract class BaseFragment extends Fragment { + + protected final String TAG = getClass().getSimpleName(); + + protected View mFragmentRoot; + + protected abstract int getLayoutId(); + + protected BaseFragment() { + // Required empty public constructor + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + mFragmentRoot = inflater.inflate(getLayoutId(), container, false); + return mFragmentRoot; + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + mFragmentRoot = null; + } + + //添加fragment + protected void addChildFragment(int containerViewId, BaseFragment fragment) { + if (null != fragment) { + FragmentTransaction transaction = getChildFragmentManager().beginTransaction(); + transaction.replace(containerViewId, fragment, fragment.getClass().getSimpleName()); + transaction.addToBackStack(fragment.getClass().getSimpleName()); + transaction.commitAllowingStateLoss(); + } + } + + //移除fragment + protected void removeChildFragment() { + if (getChildFragmentManager().getBackStackEntryCount() > 1) { + getChildFragmentManager().popBackStack(); + } + } + + protected static void addFragment(FragmentManager fm, int containerViewId, BaseFragment fragment) { + if (fm == null || fragment == null) { + return; + } + FragmentTransaction transaction = fm.beginTransaction(); + // TODO Animation + transaction.replace(containerViewId, fragment); + transaction.addToBackStack(fragment.getClass().getSimpleName()); + transaction.commitAllowingStateLoss(); + } + + protected static void replaceFragment(FragmentManager fm, int containerViewId, BaseFragment fragment) { + if (fm == null || fragment == null) { + return; + } + FragmentTransaction transaction = fm.beginTransaction(); + // TODO Animation + transaction.replace(containerViewId, fragment); + transaction.commitAllowingStateLoss(); + } + + protected static void clearBackStack(FragmentManager fragmentManager) { + if (fragmentManager.getBackStackEntryCount() > 0) { + FragmentManager.BackStackEntry entry = fragmentManager.getBackStackEntryAt(0); + fragmentManager.popBackStack(entry.getId(), FragmentManager.POP_BACK_STACK_INCLUSIVE); + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/CommonLoadingDialog.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/CommonLoadingDialog.java new file mode 100644 index 00000000..f425dcca --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/CommonLoadingDialog.java @@ -0,0 +1,67 @@ +package dji.v5.ux.core.ui.setting.ui; + +/** + * Created by Luca.Wu on 2017/4/5. + */ + +import android.content.Context; +import android.os.Bundle; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + + +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.R; +import dji.v5.ux.core.ui.setting.dialog.BaseDialog; + +/** + * 加载提醒对话框 + */ +public class CommonLoadingDialog extends BaseDialog { + + protected View rootView; + protected TextView mLoadText; + + public CommonLoadingDialog(Context context) { + this(context, R.style.SimpleProgressDialog); + } + + public CommonLoadingDialog(Context context, int theme) { + super(context, theme); + initialize(); + } + + protected void initialize() { + rootView = getLayoutInflater().inflate(R.layout.uxsdk_dialog_common_loading_layout, null); + mLoadText = (TextView) rootView.findViewById(R.id.tv_load_dialog); + } + + @Override + public int getDialogWidth() { + return ViewGroup.LayoutParams.WRAP_CONTENT; + } + + @Override + public int getDialogHeight() { + return (int) AndUtil.getDimension(R.dimen.uxsdk_100_dp); + } + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(rootView); + //设置不可取消,点击其他区域不能取消,实际中可以抽出去封装供外包设置 + setCancelable(false); + setCanceledOnTouchOutside(false); + } + + @Override + public void show() { + super.show(); + } + + public void setLoadingText(String text) { + mLoadText.setText(text); + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/Loader.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/Loader.java new file mode 100644 index 00000000..c4e79208 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/Loader.java @@ -0,0 +1,107 @@ +package dji.v5.ux.core.ui.setting.ui; + +import android.annotation.SuppressLint; +import android.app.Activity; + +import androidx.annotation.UiThread; +import androidx.annotation.WorkerThread; +import androidx.fragment.app.Fragment; + +import dji.v5.utils.common.LogUtils; +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.schedulers.Schedulers; + + +/** + * 初始化加载,将页面初始化抽象为data和view + * view初始化在ui线程 onCreateView(),data初始化在work线程 onCreateData() 中执行 + * ui和work线程是并发执行,当ui与work线程都准备好之后,最后刷新view onRefreshView() + * + * @author young.huang + */ +public class Loader { + + private static final String TAG = Loader.class.getSimpleName(); + + private LoaderListener listener; + + private boolean isStopLoad = false; + + private Loader() { + + } + + public static Loader createLoader() { + return new Loader(); + } + + public Loader setListener(LoaderListener listener) { + this.listener = listener; + return this; + } + + @SuppressLint("CheckResult") + public void start() { + if (listener == null) { + LogUtils.e(TAG, "loader listener is not set!!!"); + return; + } + Flowable uiTask = Flowable.fromCallable(() -> { + if (hostIsDead()) { + cancel(); + return 0; + } + listener.onCreateView(); + return 1; + }).subscribeOn(AndroidSchedulers.mainThread()); + + Flowable dataTask = Flowable.fromCallable(() -> { + if (hostIsDead()) { + cancel(); + return 0; + } + listener.onCreateData(); + return 1; + }).subscribeOn(Schedulers.io()); + + Flowable.zip(uiTask, dataTask, (o1, o2) -> o1 + o2).observeOn(AndroidSchedulers.mainThread()).subscribe(o -> { + if (hostIsDead()) { + cancel(); + return; + } + listener.onRefreshView(); + cancel(); + }); + return; + } + + private boolean hostIsDead() { + if (listener == null) { + return true; + } + LoaderListener l = listener; + if (l instanceof Fragment) { + return ((Fragment) l).isDetached(); + } + if (l instanceof Activity) { + return ((Activity) l).isFinishing() || ((Activity) l).isDestroyed(); + } + + return isStopLoad; + } + + public void cancel() { + listener = null; + isStopLoad = true; + } + + public interface LoaderListener { + @UiThread + void onCreateView(); + @WorkerThread + void onCreateData(); + @UiThread + void onRefreshView(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/MenuFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/MenuFragment.java new file mode 100644 index 00000000..aaf72108 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/MenuFragment.java @@ -0,0 +1,141 @@ +package dji.v5.ux.core.ui.setting.ui; + +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import androidx.annotation.UiThread; +import androidx.annotation.WorkerThread; +import androidx.fragment.app.FragmentManager; +import androidx.fragment.app.FragmentTransaction; + + +import dji.v5.ux.R; + + +/* + * Copyright (c) 2014, DJI All Rights Reserved. + */ + +/** + *

    Created by luca on 2017/1/15.

    + */ + +public abstract class MenuFragment extends AppFragment { + + private Loader initLoader; + protected abstract String getPreferencesTitle(); + + protected static void addFragment(FragmentManager fm, MenuFragment menuFragment) { + addFragment(fm, menuFragment, false); + } + + protected static void addFragment(FragmentManager fm, MenuFragment menuFragment, boolean isAnimated) { + if (fm == null || menuFragment == null) { + return; + } + FragmentTransaction transaction = fm.beginTransaction(); + if (isAnimated) { + transaction.setCustomAnimations(R.anim.uxsdk_push_right_in, R.anim.uxsdk_fade_out, R.anim.uxsdk_fade_in, R.anim.uxsdk_push_right_out); + } + // TODO + // transaction.setCustomAnimations(R.animator.fragment_slide_right_enter, R.animator.fragment_slide_right_exit); + transaction.replace(R.id.fragment_content, menuFragment); + transaction.addToBackStack(menuFragment.getPreferencesTitle()); + transaction.commitAllowingStateLoss(); + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = super.onCreateView(inflater, container, savedInstanceState); + initLoader = Loader.createLoader(); + initLoader.setListener(new Loader.LoaderListener() { + @Override + public void onCreateView() { + onPrepareView(); + } + @Override + public void onCreateData() { + onPrepareDataInBackground(); + } + @Override + public void onRefreshView() { + onRefreshDataOnView(); + } + }).start(); + return view; + } + /** + * UI 控件初始化 + */ + @UiThread + protected void onPrepareView() { + + } + /** + * 在工作线程中准备初始化页面时需要的数据,不包含UI控件 + */ + @WorkerThread + protected void onPrepareDataInBackground() { + + } + + /** + * UI 与 数据准备好之后,这里刷新一下页面 + */ + @UiThread + protected void onRefreshDataOnView() { + + } + + protected static void popBackFragmentStack(FragmentManager fm) { + if (fm.getBackStackEntryCount() > 1) { + fm.popBackStackImmediate(); + } + } + +// protected void handleCheckChanged(final String tag, final boolean checked) { +// Single.create(new SingleOnSubscribe() { +// @Override +// public void subscribe(SingleEmitter e) throws Exception { +// PreferencesUtil.putBoolean(tag, checked); +// new SimpleEvent(tag, checked).send(); +// } +// }).subscribeOn(Schedulers.io()).subscribe(); +// } +// +// protected void handleItemSelected(final String tag, final int position) { +// Single.create(new SingleOnSubscribe() { +// @Override +// public void subscribe(SingleEmitter e) throws Exception { +// PreferencesUtil.putInt(tag, position); +// new SimpleEvent(tag, position).send(); +// } +// }).subscribeOn(Schedulers.io()).subscribe(); +// } +// +// protected void handleValueChanged(final String tag, final int value) { +// Single.create(new SingleOnSubscribe() { +// @Override +// public void subscribe(SingleEmitter e) throws Exception { +// PreferencesUtil.putInt(tag, value); +// new SimpleEvent(tag, value).send(); +// } +// }).subscribeOn(Schedulers.io()).subscribe(); +// } + + @Override + public void onDestroyView() { + super.onDestroyView(); + if (initLoader != null) { + initLoader.cancel(); + initLoader = null; + } + } + + @Override + public boolean onBackPressed() { + return false; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/MenuFragmentFactory.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/MenuFragmentFactory.java new file mode 100644 index 00000000..8ffba154 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/MenuFragmentFactory.java @@ -0,0 +1,62 @@ +package dji.v5.ux.core.ui.setting.ui; + + +import dji.v5.ux.core.ui.setting.fragment.BatteryMenuFragment; +import dji.v5.ux.core.ui.setting.fragment.CommonMenuFragment; +import dji.v5.ux.core.ui.setting.fragment.FlycMenuFragment; +import dji.v5.ux.core.ui.setting.fragment.GimbalMenuFragment; +import dji.v5.ux.core.ui.setting.fragment.HDMenuFragment; +import dji.v5.ux.core.ui.setting.fragment.OmniPerceptionMenuFragment; +import dji.v5.ux.core.ui.setting.fragment.PayloadFragment; +import dji.v5.ux.core.ui.setting.fragment.RCMenuFragment; +import dji.v5.ux.core.ui.setting.fragment.RtkMenuFragment; + +/** + * Description : 生成不同设置Fragment的工厂 + * + * @author: Byte.Cai + * date : 2022/11/17 + *

    + * Copyright (c) 2022, DJI All Rights Reserved. + */ +public class MenuFragmentFactory { + + public static final String FRAGMENT_TAG_AIRCRAFT = "FlycMenuFragment"; + public static final String FRAGMENT_TAG_GIMBAL = "GimbalMenuFragment"; + public static final String FRAGMENT_TAG_RC = "RCMenuFragment"; + public static final String FRAGMENT_TAG_PERCEPTION = "PerceptionMenuFragment"; + public static final String FRAGMENT_TAG_HD = "HDMenuFragment"; + public static final String FRAGMENT_TAG_BATTERY = "BatteryMenuFragment"; + public static final String FRAGMENT_TAG_COMMON = "CommonMenuFragment"; + public static final String FRAGMENT_TAG_PAYLOAD = "PayloadFragment"; + public static final String FRAGMENT_TAG_SEARCHLIGHT_ACCESSORY = "SearchlightSettingFragment"; + public static final String FRAGMENT_TAG_RTK = "RtkMenuFragment"; + + public static MenuFragment getMenuFragment(String tag) { + if (FRAGMENT_TAG_AIRCRAFT.equals(tag)) { + return new FlycMenuFragment(); + } else if (FRAGMENT_TAG_GIMBAL.equals(tag)) { + return new GimbalMenuFragment(); + } else if (FRAGMENT_TAG_RC.equals(tag)) { + return new RCMenuFragment(); + } else if (FRAGMENT_TAG_PERCEPTION.equals(tag)) { + return new OmniPerceptionMenuFragment(); + } else if (FRAGMENT_TAG_HD.equals(tag)) { + return new HDMenuFragment(); + } else if (FRAGMENT_TAG_BATTERY.equals(tag)) { + return new BatteryMenuFragment(); + } else if (FRAGMENT_TAG_COMMON.equals(tag)) { + return new CommonMenuFragment(); + } else if (FRAGMENT_TAG_PAYLOAD.equals(tag)) { + return new PayloadFragment(); + } else if (FRAGMENT_TAG_RTK.equals(tag)) { + return new RtkMenuFragment(); + } else { + throw new IllegalArgumentException(tag + " Not support now."); + } + } + + private MenuFragmentFactory() { + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/OnBackPressedHandler.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/OnBackPressedHandler.java new file mode 100644 index 00000000..072436e5 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/OnBackPressedHandler.java @@ -0,0 +1,26 @@ +package dji.v5.ux.core.ui.setting.ui; +/* + * WWWWWW||WWWWWW + * W W W||W W W + * || + * ( OO )__________ + * / | \ + * /o o| DJI \ + * \___/||_||__||_|| ** + * || || || || + * _||_|| _||_|| + * (__|__|(__|__| + * + * Copyright (c) 2017, DJI All Rights Reserved. + */ + +/** + *

    Description:

    + * + * @author create at 2018/5/18 22:14 by luca for DJIPilot + * @version v1.0 + */ + +public interface OnBackPressedHandler { + void setSelectedFragment(AppFragment selectedFragment); +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/OnBackPressedListener.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/OnBackPressedListener.kt new file mode 100644 index 00000000..98e7d117 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/OnBackPressedListener.kt @@ -0,0 +1,5 @@ +package com.dji.industry.pilot.common + +interface OnBackPressedListener { + fun onBackPressed(): Boolean = false +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/SettingMenuFragment.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/SettingMenuFragment.java new file mode 100644 index 00000000..11ca6d97 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/ui/setting/ui/SettingMenuFragment.java @@ -0,0 +1,193 @@ +package dji.v5.ux.core.ui.setting.ui; + +import android.os.Bundle; +import android.text.TextUtils; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentManager; + +import dji.v5.ux.R; + +/** + * Description : 所有设置界面创建的入口 + * + * @author: Byte.Cai + * date : 2022/11/18 + *

    + * Copyright (c) 2022, DJI All Rights Reserved. + */ +public class SettingMenuFragment extends Fragment implements FragmentManager.OnBackStackChangedListener { + public static final String ARG_PARAM = "fragment_tag"; + private static final String NEED_LAZY_INFLATE = "need_lazy_inflate"; + + private TextView mTitleView; + private ImageView mBackBtn; + private ImageView mProgressBar; + + private String mFragmentTag; + private String mFragmentFlag; + private View mFragmentRoot; + private FragmentManager fragmentManager; + private Runnable mLazyInflateTask; + + private SettingMenuFragment() { + // Required empty private constructor + } + + public static SettingMenuFragment newInstance(String tag) { + return newInstance(tag, true); + } + + public static SettingMenuFragment newInstance(String tag, boolean needLazyInitView) { + SettingMenuFragment fragment = new SettingMenuFragment(); + Bundle args = fragment.getArguments(); + if (args == null) { + args = new Bundle(); + } + args.putString(ARG_PARAM, tag); + args.putBoolean(NEED_LAZY_INFLATE, needLazyInitView); + fragment.setArguments(args); + fragment.setFragmentFlag(tag); + return fragment; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + fragmentManager = getChildFragmentManager(); + fragmentManager.addOnBackStackChangedListener(this); + mFragmentTag = getArguments().getString(ARG_PARAM, ""); + + mLazyInflateTask = this::inflateFunctionFragment; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + mFragmentRoot = inflater.inflate(R.layout.uxsdk_setting_menu_fragment_layout, null); + return mFragmentRoot; + } + + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + mTitleView = view.findViewById(R.id.setting_menu_header_title); + mBackBtn = view.findViewById(R.id.setting_menu_header_back); + mProgressBar = view.findViewById(R.id.setting_menu_progress_bar); + + if (!TextUtils.isEmpty(mFragmentTag)) { + if (getArguments() == null) { + return; + } + mProgressBar.setVisibility(View.VISIBLE); + boolean needLazyInflate = getArguments().getBoolean(NEED_LAZY_INFLATE, true); + if (needLazyInflate) { + mFragmentRoot.post(mLazyInflateTask); + } else { + inflateFunctionFragment(); + } + } else { + updateTitle(); + } + + mBackBtn.setOnClickListener(v -> { + if (fragmentManager.getBackStackEntryCount() > 1) { + MenuFragment menuFragment = getLastMenuFragment(); + if (menuFragment != null && !menuFragment.onBackPressed()) { + popBackFragmentStack(); + } + } else { + popBackFragmentStack(); + } + }); + } + + private void inflateFunctionFragment() { + if (TextUtils.isEmpty(mFragmentTag) || mProgressBar == null) { + return; + } + MenuFragment menuFragment = MenuFragmentFactory.getMenuFragment(mFragmentTag); + MenuFragment.addFragment(fragmentManager, menuFragment); + mProgressBar.setVisibility(View.GONE); + mFragmentTag = null; + } + + private void popBackFragmentStack() { + if (fragmentManager.getBackStackEntryCount() > 1) { + fragmentManager.popBackStackImmediate(); + } + } + + @Override + public void onBackStackChanged() { + updateTitle(); + } + + private void updateTitle() { + int entryCount = fragmentManager.getBackStackEntryCount(); + + if (mBackBtn != null) { + mBackBtn.setVisibility(entryCount > 1 ? View.VISIBLE : View.INVISIBLE); + } + if (entryCount > 0) { + FragmentManager.BackStackEntry entry = fragmentManager.getBackStackEntryAt(entryCount - 1); + if (mTitleView != null) { + mTitleView.setText(entry.getName()); + } + } + } + + + private MenuFragment getLastMenuFragment() { + if (fragmentManager.getFragments().size() > 0) { + Fragment fragment = fragmentManager.getFragments().get(fragmentManager.getFragments().size() - 1); + if (fragment instanceof MenuFragment) { + return (MenuFragment) fragment; + } else { + return null; + } + } else { + return null; + } + } + + + @Override + public void onDestroyView() { + mProgressBar.setVisibility(View.GONE); + mProgressBar = null; + mBackBtn = null; + mTitleView = null; + if (mLazyInflateTask != null && mFragmentRoot != null) { + mFragmentRoot.removeCallbacks(mLazyInflateTask); + } + mFragmentRoot = null; + super.onDestroyView(); + } + + @Override + public void onDestroy() { + mLazyInflateTask = null; + + super.onDestroy(); + } + + @Override + public void onDetach() { + super.onDetach(); + } + + public String getFragmentFlag() { + return mFragmentFlag; + } + + public void setFragmentFlag(String mFragmentFlag) { + this.mFragmentFlag = mFragmentFlag; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/AudioUtil.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/AudioUtil.java new file mode 100644 index 00000000..6e8b562c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/AudioUtil.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.util; + +import android.content.Context; +import android.media.AudioManager; +import android.media.MediaPlayer; + +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.core.base.SchedulerProvider; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.disposables.Disposable; + +/** + * Utility class for playing sounds. + */ +public final class AudioUtil { + + private static final float MIN_RATIO = 0.3f; + private static MediaPlayer player; + + private AudioUtil() { + // Util class + } + + /** + * Plays a sound. + * + * @param context A context object. + * @param resID The resource ID of the sound to play. + */ + public static void playSound(Context context, int resID) { + playSound(context, resID, false); + } + + /** + * Plays a sound. + * + * @param context A context object. + * @param resID The resource ID of the sound to play. + * @param ignoreWhenBusy If set to true, will do nothing if a sound is already being played. + */ + public synchronized static void playSound(Context context, int resID, boolean ignoreWhenBusy) { + try { + if (player != null) { + if (player.isPlaying()) { + if (ignoreWhenBusy) { + return; + } + player.stop(); + } + player.release(); + player = null; + } + + player = MediaPlayer.create(context, resID); + player.setOnCompletionListener(mp -> { + if (player != null) { + player.release(); + player = null; + } + }); + AudioManager am = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); + final float audioMaxVolume = am.getStreamMaxVolume(AudioManager.STREAM_MUSIC); + final float audioCurrentVolume = am.getStreamVolume(AudioManager.STREAM_MUSIC); + float volumeRatio = audioCurrentVolume / audioMaxVolume; + if (volumeRatio < MIN_RATIO) { + volumeRatio = MIN_RATIO; + } + player.setVolume(volumeRatio, volumeRatio); + player.start(); + } catch (Exception e) { + LogUtils.d("PlaySound", e.getMessage()); + } + } + + /** + * Plays a sound in the background. + * + * @param context A context object. + * @param resID The resource ID of the sound to play. + */ + public static Disposable playSoundInBackground(final Context context, final int resID) { + return Observable.just(true) + .subscribeOn(SchedulerProvider.computation()) + .subscribe(aBoolean -> playSound(context, resID), + e -> LogUtils.d("PlaySound", e.getMessage())); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/CameraUtil.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/CameraUtil.java new file mode 100644 index 00000000..ea52f1cc --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/CameraUtil.java @@ -0,0 +1,411 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.util; + +import android.content.res.Resources; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import androidx.annotation.NonNull; +import dji.sdk.keyvalue.value.camera.CameraAperture; +import dji.sdk.keyvalue.value.camera.CameraExposureCompensation; +import dji.sdk.keyvalue.value.camera.CameraFlatMode; +import dji.sdk.keyvalue.value.camera.CameraISO; +import dji.sdk.keyvalue.value.camera.CameraShutterSpeed; +import dji.sdk.keyvalue.value.camera.CameraType; +import dji.sdk.keyvalue.value.camera.CameraVideoStreamSourceType; +import dji.sdk.keyvalue.value.camera.PhotoFileFormat; +import dji.sdk.keyvalue.value.camera.VideoFrameRate; +import dji.sdk.keyvalue.value.camera.VideoResolution; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.sdk.keyvalue.value.payload.PayloadCameraType; +import dji.v5.ux.R; + +/** + * Utility class for displaying camera information. + */ +public final class CameraUtil { + + private static final String SHUTTER_SUBSTITUENT1 = "SHUTTER_SPEED1_"; + private static final String SHUTTER_SUPPLANTER1 = ""; + + private static final String SHUTTER_WIFI_REGEX_2 = "(\\d+)_DOT_(\\d+)"; + private static final String SHUTTER_WIFI_REPLACE_2 = "$1.$2"; + + private static final String SHUTTER_SUBSTITUENT3 = "SHUTTER_SPEED_([0-9.]+)"; + private static final String SHUTTER_SUPPLANTER3 = "$1\""; + + private static final String SHUTTER_SUBSTITUENT4 = "DOT_(\\d+)"; + private static final String SHUTTER_SUPPLANTER4 = "1.$1\""; + + // Convert the N_5_0 to -5.0, N_0_0 to 0, P_1_0 to +1.0 + private static final String EV_SUBSTITUENT1 = "EV"; + private static final String EV_SUPPLANTER1 = ""; + + private static final String EV_SUBSTITUENT2 = "NEG_"; + private static final String EV_SUPPLANTER2 = "-"; + + private static final String EV_SUBSTITUENT3 = "POS_"; + private static final String EV_SUPPLANTER3 = "+"; + + private static final String EV_SUBSTITUENT4 = "P"; + private static final String EV_SUPPLANTER4 = "."; + + private static final String DEFAULT_PAYLOAD_NAME = "Payload Camera"; + + private final static Map CAMERA_TYPE_STRING_MAP = new HashMap(); + + static { + CAMERA_TYPE_STRING_MAP.put(CameraType.ZENMUSE_XT, "XT"); + CAMERA_TYPE_STRING_MAP.put(CameraType.ZENMUSE_X30, "X30"); + CAMERA_TYPE_STRING_MAP.put(CameraType.ZENMUSE_XT2, "XT2"); + CAMERA_TYPE_STRING_MAP.put(CameraType.PAYLOAD, DEFAULT_PAYLOAD_NAME); + CAMERA_TYPE_STRING_MAP.put(CameraType.ZENMUSE_XTS, "XT S"); + CAMERA_TYPE_STRING_MAP.put(CameraType.ZENMUSE_H20, "H20"); + CAMERA_TYPE_STRING_MAP.put(CameraType.ZENMUSE_H20T, "H20T"); + CAMERA_TYPE_STRING_MAP.put(CameraType.ZENMUSE_H20N, "H20N"); + CAMERA_TYPE_STRING_MAP.put(CameraType.M200_V2_CAMERA, "FPV"); + CAMERA_TYPE_STRING_MAP.put(CameraType.M30, "M30"); + CAMERA_TYPE_STRING_MAP.put(CameraType.M30T, "M30T"); + CAMERA_TYPE_STRING_MAP.put(CameraType.M3E, "M3E"); + CAMERA_TYPE_STRING_MAP.put(CameraType.M3T, "M3T"); + CAMERA_TYPE_STRING_MAP.put(CameraType.M3M, "M3M"); + CAMERA_TYPE_STRING_MAP.put(CameraType.ZENMUSE_L1, "L1"); + CAMERA_TYPE_STRING_MAP.put(CameraType.ZENMUSE_P1, "P1"); + } + + private CameraUtil() { + // prevent instantiation of util class + } + + @NonNull + public static String resolutionShortDisplayName(@NonNull VideoResolution resolution) { + + String shortName; + + switch (resolution) { + case RESOLUTION_336x256: + shortName = "256P"; + break; + case RESOLUTION_640x480: + shortName = "480P"; + break; + case RESOLUTION_640x512: + shortName = "512P"; + break; + case RESOLUTION_1280x720: + shortName = "720P"; + break; + case RESOLUTION_1920x1080: + shortName = "1080P"; + break; + case RESOLUTION_2048x1080: + shortName = "2K"; + break; + case RESOLUTION_2688x1512: + case RESOLUTION_2704x1520: + case RESOLUTION_2720x1530: + shortName = "2.7K"; + break; + case RESOLUTION_3840x1572: + case RESOLUTION_3840x2160: + case RESOLUTION_4096x2160: + shortName = "4K"; + break; + case RESOLUTION_4608x2160: + case RESOLUTION_4608x2592: + shortName = "4.5K"; + break; + case RESOLUTION_5280x2160: + case RESOLUTION_5280x2972: + shortName = "5K"; + break; + case RESOLUTION_5760x3240: + case RESOLUTION_6016x3200: + shortName = "6K"; + break; + default: + shortName = "Unknown"; + } + + return shortName; + } + + @NonNull + public static String frameRateDisplayName(@NonNull VideoFrameRate frameRate) { + final String originalFrameRateString = frameRate.toString(); + String processedFrameRateString; + Matcher matcher = Pattern.compile("RATE_(\\d{2,3})DOT_.*").matcher(originalFrameRateString); + if (matcher.find()) { + String tempRate = matcher.group(1); + processedFrameRateString = Integer.toString(Integer.parseInt(tempRate) + 1); + } else { + matcher = Pattern.compile("RATE_(\\d{2,3})FPS").matcher(originalFrameRateString); + if (matcher.find()) { + processedFrameRateString = matcher.group(1); + } else { + processedFrameRateString = "Null"; + } + } + + return processedFrameRateString; + } + + @NonNull + public static String convertPhotoFileFormatToString(@NonNull Resources resources, @NonNull PhotoFileFormat photoFileFormat) { + String formatString; + if (photoFileFormat.value() == PhotoFileFormat.RAW.value()) { + formatString = resources.getString(R.string.uxsdk_camera_picture_format_raw); + } else if (photoFileFormat.value() == PhotoFileFormat.JPEG.value()) { + formatString = resources.getString(R.string.uxsdk_camera_picture_format_jpeg); + } else if (photoFileFormat.value() == PhotoFileFormat.RAW_JPEG.value()) { + formatString = resources.getString(R.string.uxsdk_camera_picture_format_jpegraw); + } else if (photoFileFormat.value() == PhotoFileFormat.TIFF_14_BIT.value()) { + formatString = resources.getString(R.string.uxsdk_camera_picture_format_tiff); + } else if (photoFileFormat.value() == PhotoFileFormat.RADIOMETRIC_JPEG.value()) { + formatString = resources.getString(R.string.uxsdk_camera_picture_format_radiometic_jpeg); + } else if (photoFileFormat.value() == PhotoFileFormat.TIFF_14_BIT_LINEAR_LOW_TEMP_RESOLUTION.value()) { + formatString = resources.getString(R.string.uxsdk_camera_picture_format_low_tiff); + } else if (photoFileFormat.value() == PhotoFileFormat.TIFF_14_BIT_LINEAR_HIGH_TEMP_RESOLUTION.value()) { + formatString = resources.getString(R.string.uxsdk_camera_picture_format_high_tiff); + } else { + formatString = photoFileFormat.toString(); + } + + return formatString; + } + + @NonNull + public static String formatVideoTime(@NonNull Resources resources, int flyTime) { + String result; + final int[] time = UnitConversionUtil.formatSecondToHour(flyTime); + if (time[2] > 0) { + result = resources.getString(R.string.uxsdk_video_time_hours, time[2], time[1], time[0]); + } else { + result = resources.getString(R.string.uxsdk_video_time, time[1], time[0]); + } + return result; + + } + + + /** + * Convert the Aperture enum name to the string to show on the UI. + * + * @param resources A resources object. + * @param aperture The aperture value to convert. + * @return A String to display. + */ + public static String apertureDisplayName(@NonNull Resources resources, @NonNull CameraAperture aperture) { + String displayName; + if (aperture == CameraAperture.UNKNOWN) { + displayName = resources.getString(R.string.uxsdk_string_default_value); + } else { + // Convert the F_1p7 to 1.7, F_4p0 to 4, F_4p5 to 4.5 + int apertureValue = aperture.value(); + int apertureInteger = apertureValue / 100; + // Just keep one decimal number, so divide by 10. + int apertureDecimal = apertureValue % 100 / 10; + if (apertureDecimal == 0) { + displayName = String.format(Locale.US, "%d", apertureInteger); + } else { + displayName = String.format(Locale.US, "%d.%d", apertureInteger, apertureDecimal); + } + } + + return displayName; + } + + /** + * Convert the Shutter Speed enum name to the string to show on the UI. + * + * @param shutterSpeed The shutter speed value to convert. + * @return A String to display. + */ + @NonNull + public static String shutterSpeedDisplayName(@NonNull CameraShutterSpeed shutterSpeed) { + + String shutterName = shutterSpeed.name(); + shutterName = shutterName.replace(SHUTTER_SUBSTITUENT1, SHUTTER_SUPPLANTER1). + replace(SHUTTER_WIFI_REGEX_2, SHUTTER_WIFI_REPLACE_2). + replace(SHUTTER_SUBSTITUENT3, SHUTTER_SUPPLANTER3). + replace(SHUTTER_SUBSTITUENT4, SHUTTER_SUPPLANTER4); + + return shutterName; + } + + /** + * Convert the Exposure Compensation enum name to the string to show on the UI. + * + * @param ev The exposure compensation value to convert. + * @return A String to display. + */ + @NonNull + public static String exposureValueDisplayName(@NonNull CameraExposureCompensation ev) { + if (ev == CameraExposureCompensation.NEG_0EV) { + return "0"; + } + String enumName = ev.name(); + return enumName.replace(EV_SUBSTITUENT1, EV_SUPPLANTER1). + replace(EV_SUBSTITUENT2, EV_SUPPLANTER2). + replace(EV_SUBSTITUENT3, EV_SUPPLANTER3). + replace(EV_SUBSTITUENT4, EV_SUPPLANTER4); + } + + public static int convertISOToInt(CameraISO iso) { + if (iso == CameraISO.ISO_AUTO || iso == CameraISO.UNKNOWN) { + return 0; + } + + String name = iso.toString(); + String[] isoValue = name.split("_"); + return Integer.parseInt(isoValue[1]); + } + + @NonNull + public static CameraISO convertIntToISO(int isoValue) { + if (isoValue > 0 && isoValue < 200) { + return CameraISO.ISO_100; + } else if (isoValue >= 200 && isoValue < 400) { + return CameraISO.ISO_200; + } else if (isoValue >= 400 && isoValue < 800) { + return CameraISO.ISO_400; + } else if (isoValue >= 800 && isoValue < 1600) { + return CameraISO.ISO_800; + } else { + return convertInt2ISO(isoValue); + } + } + + private static CameraISO convertInt2ISO(int isoValue) { + if (isoValue >= 1600 && isoValue < 3200) { + return CameraISO.ISO_1600; + } else if (isoValue >= 3200 && isoValue < 6400) { + return CameraISO.ISO_3200; + } else if (isoValue >= 6400 && isoValue < 12800) { + return CameraISO.ISO_6400; + } else if (isoValue >= 12800 && isoValue < 25600) { + return CameraISO.ISO_12800; + } else if (isoValue >= 25600) { + return CameraISO.ISO_25600; + } else { + return CameraISO.UNKNOWN; + } + } + + /** + * Get the lens index based on the given stream source and camera name. + * + * @param streamSource The streamSource + * @return The lens index + */ + public static CameraLensType getLensIndex(CameraVideoStreamSourceType streamSource) { + if (streamSource == CameraVideoStreamSourceType.WIDE_CAMERA) { + return CameraLensType.CAMERA_LENS_WIDE; + } else if (streamSource == CameraVideoStreamSourceType.INFRARED_CAMERA) { + return CameraLensType.CAMERA_LENS_THERMAL; + } else { + return CameraLensType.CAMERA_LENS_ZOOM; + } + } + + public static boolean isPictureMode(CameraFlatMode flatCameraMode) { + return flatCameraMode == CameraFlatMode.VIDEO_TIMELAPSE + || flatCameraMode == CameraFlatMode.PHOTO_AEB + || flatCameraMode == CameraFlatMode.PHOTO_NORMAL + || flatCameraMode == CameraFlatMode.PHOTO_BURST + || flatCameraMode == CameraFlatMode.PHOTO_HDR + || flatCameraMode == CameraFlatMode.PHOTO_INTERVAL + || flatCameraMode == CameraFlatMode.PHOTO_HYPERLIGHT + || flatCameraMode == CameraFlatMode.PHOTO_PANO + || flatCameraMode == CameraFlatMode.PHOTO_EHDR; + } + + public static boolean isAutoISOSupportedByProduct() { + return true; +// return (!ProductUtil.isMavicAir()) && (!ProductUtil.isMavicPro() && (!ProductUtil.isMavicMini())); + } + + public static boolean isSupportForNDVI(CameraLensType lensType) { + return lensType == CameraLensType.CAMERA_LENS_MS_G || + lensType == CameraLensType.CAMERA_LENS_MS_R || + lensType == CameraLensType.CAMERA_LENS_MS_RE || + lensType == CameraLensType.CAMERA_LENS_MS_NIR || + lensType == CameraLensType.CAMERA_LENS_MS_NDVI; + } + + public static boolean isFPVTypeView(ComponentIndexType devicePosition) { + return devicePosition == ComponentIndexType.FPV || devicePosition == ComponentIndexType.VISION_ASSIST; + } + + public static String getCameraDisplayName(CameraType cameraType) { + String name = CAMERA_TYPE_STRING_MAP.get(cameraType); + if (name == null) { + name = ""; + } + return name; + } + + public static String getPayloadCameraName(PayloadCameraType payloadCameraType) { + String name = "UNKNOWN"; + switch (payloadCameraType) { + case EP600: + name = "P1"; + break; + case EP800: + name = "L1"; + break; + default: + break; + } + + return name; + } + + public static List getConnectionCameraList( + boolean cameraConnection1, + boolean cameraConnection2, + boolean cameraConnection3 + ) { + List list = new ArrayList<>(); + if (cameraConnection1) { + list.add(ComponentIndexType.LEFT_OR_MAIN); + } + if (cameraConnection2) { + list.add(ComponentIndexType.RIGHT); + } + if (cameraConnection3) { + list.add(ComponentIndexType.UP); + } + return list; + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/CommonUtils.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/CommonUtils.java new file mode 100644 index 00000000..146a6fb5 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/CommonUtils.java @@ -0,0 +1,48 @@ +//package dji.v5.ux.core.util; +// +//import java.util.ArrayList; +//import java.util.List; +// +//import dji.sdk.keyvalue.value.common.ComponentIndexType; +// +///** +// * Class Description +// * +// * @author Hoker +// * @date 2021/11/23 +// *

    +// * Copyright (c) 2021, DJI All Rights Reserved. +// */ +//public class CommonUtils { +// +// public static List toList(int [] ints){ +// List list = new ArrayList<>(); +// if (ints == null){ +// return list; +// } +// for (int i : ints){ +// list.add(i); +// } +// return list; +// } +// +// public static SettingDefinitions.GimbalIndex getGimbalIndex(ComponentIndexType devicePosition) { +// if (devicePosition == null){ +// return SettingDefinitions.GimbalIndex.UNKONWN; +// } +// switch (devicePosition) { +// case LEFT_OR_MAIN: +// return SettingDefinitions.GimbalIndex.PORT; +// case RIGHT: +// return SettingDefinitions.GimbalIndex.STARBOARD; +// case UP: +// return SettingDefinitions.GimbalIndex.TOP; +// default: +// return SettingDefinitions.GimbalIndex.UNKONWN; +// } +// } +// +// private CommonUtils() { +// +// } +//} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/DJIDeviceUtil.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/DJIDeviceUtil.kt new file mode 100644 index 00000000..9465f377 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/DJIDeviceUtil.kt @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.util + +import android.os.Build + +/** + * Contains util methods for android devices made by DJI + */ +object DJIDeviceUtil { + + /** + * Whether the current device is made by DJI + */ + @JvmStatic + fun isDJIDevice(): Boolean { + return getDJIDeviceType() == DJIDeviceType.NONE + } + + /** + * Whether the current device is a smart controller + */ + @JvmStatic + fun isSmartController(): Boolean { + val deviceType = getDJIDeviceType() + return deviceType == DJIDeviceType.SMART_CONTROLLER || + deviceType == DJIDeviceType.MATRICE_300_RTK + } + + /** + * Get the current device type + */ + @JvmStatic + fun getDJIDeviceType(): DJIDeviceType { + return DJIDeviceType.find(Build.PRODUCT) + } +} + +/** + * Type of android device made by DJI + */ +enum class DJIDeviceType(val modelName: String) { + /** + * Not a known DJI device + */ + NONE("UNKNOWN"), + + /** + * Smart Controller Built-in Display Device + */ + SMART_CONTROLLER("SMART_CONTROLLER"), + + /** + * Matrice 300 RTK Smart Controller Built-in Display Device + */ + MATRICE_300_RTK("MATRICE_300_RTK"); + + companion object { + @JvmStatic + val values = values() + + @JvmStatic + fun find(modelName: String?): DJIDeviceType { + if (modelName != null && modelName.trim { it <= ' ' }.isNotEmpty()) { + return values.find { it.modelName == modelName } ?: NONE + } + + return NONE + } + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/DataProcessor.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/DataProcessor.java new file mode 100644 index 00000000..94a4e5cc --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/DataProcessor.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.util; + +import androidx.annotation.NonNull; + +import dji.v5.ux.core.base.SchedulerProvider; +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.processors.BehaviorProcessor; + +/** + * Processor that emits the most recent item it has observed and all subsequent observed items + * + * @param the type of item expected to be observed and emitted by the Processor + */ +public final class DataProcessor { + + private final BehaviorProcessor processor; + + private final T defaultValue; + + /** + * Creates a DataProcessor with the given default value + * + * @param defaultValue The first item that will be emitted + * @param The type of item the processor will emit + * @return The constructed DataProcessor + */ + @NonNull + public static DataProcessor create(@NonNull T defaultValue) { + return new DataProcessor<>(defaultValue); + } + + private DataProcessor(@NonNull T defaultValue) { + processor = BehaviorProcessor.createDefault(defaultValue); + this.defaultValue = defaultValue; + } + + /** + * Emit a new item + * + * @param data item to be emitted + */ + public void onNext(@NonNull T data) { + processor.onNext(data); + } + + /** + * Emit completion event + */ + public void onComplete() { + processor.onComplete(); + } + + /** + * Emit an error event + * + * @param error The error to emit + */ + public void onError(@NonNull Throwable error) { + processor.onError(error); + } + + /** + * Get the latest value of the processor + * + * @return The latest value of the processor + */ + @NonNull + public T getValue() { + T t = processor.getValue(); + if (t == null) { + t = defaultValue; + } + return t; + } + + /** + * Get the stream of data from the processor + * + * @return A Flowable representing the stream of data + */ + @NonNull + public Flowable toFlowable() { + return processor.observeOn(SchedulerProvider.computation()).onBackpressureLatest(); + } + + @NonNull + public Flowable toFlowableOnUI() { + return processor.observeOn(SchedulerProvider.ui()).onBackpressureLatest(); + } + + public Observable toObservableOnUI() { + return toFlowableOnUI().toObservable(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/DrawUtils.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/DrawUtils.java new file mode 100644 index 00000000..7e56c9a5 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/DrawUtils.java @@ -0,0 +1,85 @@ +package dji.v5.ux.core.util; + +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.PixelFormat; +import android.graphics.drawable.BitmapDrawable; +import android.graphics.drawable.Drawable; +import android.graphics.drawable.VectorDrawable; +import android.util.LruCache; + +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; + +import dji.v5.utils.common.ContextUtil; + + +public class DrawUtils { + + /** + * VectorDrawable比较特殊, VMRuntime.RegisterNativeAllocation, 会触发FinalizerReference.awaitFinialization, 需要尽量避免VectorDrawable的频繁创建 + * VerctorDrawale大小不好计算,就缓存30个左右 + */ + private static final LruCache vectorDrawableLruCache = new LruCache<>(30); + private static final LruCache bitmapLruCache = new BitmapLruCache(1024 * 1024); + + private DrawUtils() { + } + + public static synchronized Bitmap drawableRes2Bitmap(@DrawableRes int resId) { + Bitmap bitmap = bitmapLruCache.get(resId); + if (bitmap == null || bitmap.isRecycled()) { + bitmap = drawable2Bitmap(getDrawable(resId)); + bitmapLruCache.put(resId, bitmap); + } + return bitmap; + } + + public static synchronized Drawable getDrawable(int resId) { + Drawable drawable = vectorDrawableLruCache.get(resId); + if (null == drawable) { + drawable = ContextUtil.getContext().getResources().getDrawable(resId); + if (drawable instanceof VectorDrawable) { + vectorDrawableLruCache.put(resId, (VectorDrawable) drawable); + } + } + return drawable; + } + + public static synchronized Bitmap drawable2Bitmap(@NonNull Drawable drawable) { + if (drawable instanceof BitmapDrawable) { + return ((BitmapDrawable) drawable).getBitmap(); + } + int width = drawable.getMinimumWidth(); + int height = drawable.getMinimumHeight(); + // 取 drawable 的颜色格式 + Bitmap.Config config = + drawable.getOpacity() != PixelFormat.OPAQUE ? Bitmap.Config.ARGB_8888 : Bitmap.Config.RGB_565; + // 建立对应 bitmap + Bitmap bitmap = Bitmap.createBitmap(width, height, config); + // 建立对应 bitmap 的画布 + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, width, height); + // 把 drawable 内容画到画布中 + drawable.draw(canvas); + return bitmap; + } + + + private static class BitmapLruCache extends LruCache { + + /** + * @param maxSize for caches that do not override {@link #sizeOf}, this is + * the maximum number of entries in the cache. For all other caches, + * this is the maximum sum of the sizes of the entries in this cache. + */ + public BitmapLruCache(int maxSize) { + super(maxSize); + } + + @Override + protected int sizeOf(Integer key, Bitmap value) { + return value.getByteCount(); + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/EditTextNumberInputFilter.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/EditTextNumberInputFilter.java new file mode 100644 index 00000000..aca38d9f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/EditTextNumberInputFilter.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.util; + +import android.text.InputFilter; +import android.text.Spanned; + +public class EditTextNumberInputFilter implements InputFilter{ + private int min, max; + + public EditTextNumberInputFilter(int min, int max) { + this.min = min; + this.max = max; + } + + public EditTextNumberInputFilter(String min, String max) { + this.min = Integer.parseInt(min); + this.max = Integer.parseInt(max); + } + + @Override + public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) { + try { + String stringInput = dest.toString() + source.toString(); + double value; + if (stringInput.length() == 1 && stringInput.charAt(0) == '-') { + value = -1; + } else { + value = Double.parseDouble(dest.toString() + source.toString()); + } + if (isInRange(min, max, value)) { + return null; + } + } catch (NumberFormatException nfe) { + //Do nothing as the number is not valid + } + return ""; + } + + private boolean isInRange(int a, int b, double c) { + return b > a ? c >= a && c <= b : c >= b && c <= a; + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/FontUtils.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/FontUtils.kt new file mode 100644 index 00000000..560765d5 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/FontUtils.kt @@ -0,0 +1,59 @@ +package dji.v5.ux.core.util + +import android.graphics.Paint +import android.graphics.Rect + +/** + * 在 FPV 页面绘制过程中,使用的字体计算问题高度时部分场景异常,相关计算由此类完成 + */ +class FontUtils { + companion object { + var calcCache: ThreadLocal = ThreadLocal() + private const val DIGITAL_TEXT = "1.234567890" + + /** + * 获取文字绘制高度 + * 使用的字体在上下分别有 FontMetrics.bottom 高的空白 + */ + @JvmStatic + @JvmOverloads + fun getDigitalTextDrawHeight(paint: Paint, text: String = DIGITAL_TEXT): Float { + val rect = getCachedRect() + paint.getTextBounds(text, 0, text.length, rect) + return rect.height().toFloat() + } + + @JvmStatic + @JvmOverloads + fun getDigitalBaselineFromTop(paint: Paint, top: Float, text: String = DIGITAL_TEXT): Float { + val rect = getCachedRect() + paint.getTextBounds(text, 0, text.length, rect) + return top - rect.top + } + + @JvmStatic + @JvmOverloads + fun getDigitalBaselineFromCenter(paint: Paint, center: Float, text: String = DIGITAL_TEXT): Float { + val rect = getCachedRect() + paint.getTextBounds(text, 0, text.length, rect) + return center + rect.height() / 2f - rect.bottom + } + + @JvmStatic + @JvmOverloads + fun getDigitalBaselineFromBottom(paint: Paint, bottom: Float, text: String = DIGITAL_TEXT): Float { + val rect = getCachedRect() + paint.getTextBounds(text, 0, text.length, rect) + return bottom - rect.bottom + } + + private fun getCachedRect(): Rect { + var cache = calcCache.get() + if (cache == null) { + cache = Rect() + calcCache.set(cache) + } + return cache + } + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/MathUtil.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/MathUtil.java new file mode 100644 index 00000000..4fbf9772 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/MathUtil.java @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.util; + +public final class MathUtil { + + private static final int ROTATION_VECTOR_LENGTH_MAX = 4; + private static final int ROTATION_MATRIX_SMALL = 9; + private static final int ROTATION_MATRIX_BIG = 16; + + private MathUtil() { + //Util class + } + + /** + * Customized helper function to convert a rotation vector to a rotation matrix. + * Given a rotation vector (presumably from a ROTATION_VECTOR sensor), this function returns a + * 9 or 16 element rotation matrix in the array rotationMatrix. The rotationMatrix array must have + * a length of 9 or 16. If rotationMatrix.length == 9, the following matrix is returned: + * / R[ 0] R[ 1] R[ 2] \ + * | R[ 3] R[ 4] R[ 5] | + * \ R[ 6] R[ 7] R[ 8] / + *

    + * If rotationMatrix.length == 16, the following matrix is returned: + * / R[ 0] R[ 1] R[ 2] 0 \ + * | R[ 4] R[ 5] R[ 6] 0 | + * | R[ 8] R[ 9] R[10] 0 | + * \ 0 0 0 1 / + */ + public static void getRotationMatrixFromVector(float[] rotationMatrix, float[] rotationVector) { + + float q0; + float q1 = rotationVector[0]; + float q2 = rotationVector[1]; + float q3 = rotationVector[2]; + + if (rotationVector.length == ROTATION_VECTOR_LENGTH_MAX) { + q0 = rotationVector[3]; + } else { + q0 = 1 - q1 * q1 - q2 * q2 - q3 * q3; + q0 = (q0 > 0) ? (float) Math.sqrt(q0) : 0; + } + + float sqQ1 = 2 * q1 * q1; + float sqQ2 = 2 * q2 * q2; + float sqQ3 = 2 * q3 * q3; + float q1Q2 = 2 * q1 * q2; + float q3Q0 = 2 * q3 * q0; + float q1Q3 = 2 * q1 * q3; + float q2Q0 = 2 * q2 * q0; + float q2Q3 = 2 * q2 * q3; + float q1Q0 = 2 * q1 * q0; + + if (rotationMatrix.length == ROTATION_MATRIX_SMALL) { + rotationMatrix[0] = 1 - sqQ2 - sqQ3; + rotationMatrix[1] = q1Q2 - q3Q0; + rotationMatrix[2] = q1Q3 + q2Q0; + + rotationMatrix[3] = q1Q2 + q3Q0; + rotationMatrix[4] = 1 - sqQ1 - sqQ3; + rotationMatrix[5] = q2Q3 - q1Q0; + + rotationMatrix[6] = q1Q3 - q2Q0; + rotationMatrix[7] = q2Q3 + q1Q0; + rotationMatrix[8] = 1 - sqQ1 - sqQ2; + } else if (rotationMatrix.length == ROTATION_MATRIX_BIG) { + rotationMatrix[0] = 1 - sqQ2 - sqQ3; + rotationMatrix[1] = q1Q2 - q3Q0; + rotationMatrix[2] = q1Q3 + q2Q0; + rotationMatrix[3] = 0.0f; + + rotationMatrix[4] = q1Q2 + q3Q0; + rotationMatrix[5] = 1 - sqQ1 - sqQ3; + rotationMatrix[6] = q2Q3 - q1Q0; + rotationMatrix[7] = 0.0f; + + rotationMatrix[8] = q1Q3 - q2Q0; + rotationMatrix[9] = q2Q3 + q1Q0; + rotationMatrix[10] = 1 - sqQ1 - sqQ2; + rotationMatrix[11] = 0.0f; + + rotationMatrix[12] = rotationMatrix[13] = rotationMatrix[14] = 0.0f; + rotationMatrix[15] = 1.0f; + } + } + + /** + * Normalize the given value with the given current range to a value in the new + * range. + * + * @param oldValue Given value in current range + * @param oldMin Current range minimum value + * @param oldMax Current range maximum value + * @param newMin New range minimum value + * @param newMax New range maximum value + * @return Converted integer value of oldValue in the new range + */ + public static int normalize(int oldValue, int oldMin, int oldMax, int newMin, int newMax) { + int oldRange = (oldMax - oldMin); + int newRange = (newMax - newMin); + if (oldRange == 0) oldRange = 1; + return (((oldValue - oldMin) * newRange) / oldRange) + newMin; + } + + /** + * Check if the string is valid integer + * + * @param number String representing the number + * @return boolean true - string is number + */ + public static boolean isInteger(String number) { + try { + Integer.parseInt(number); + return true; + + } catch (NumberFormatException ex) { + return false; + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/MatrixUtils.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/MatrixUtils.java new file mode 100644 index 00000000..c0760609 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/MatrixUtils.java @@ -0,0 +1,100 @@ +package dji.v5.ux.core.util; + + +/** + *

    Description:

    + * + * @author create at 2019/7/29 9:05 PM by ron.liu for dji-pilot + * @version v1.0 + */ +public class MatrixUtils { + + public static float[] createRotationMatrix(float yaw, float pitch, float roll) { + float[] result = new float[9]; + float radianYaw = (float) Math.toRadians(yaw); + float radianPitch = (float) Math.toRadians(pitch); + float radianRoll = (float) Math.toRadians(roll); + float cy = (float) Math.cos(radianYaw); + float sy = (float) Math.sin(radianYaw); + + float cp = (float) Math.cos(radianPitch); + float sp = (float) Math.sin(radianPitch); + + float cr = (float) Math.cos(radianRoll); + float sr = (float) Math.sin(radianRoll); + + result[0] = cy * cp; + result[1] = -sy * cr + cy * sp * sr; + result[2] = sy * sr + cy * sp * cr; + result[3] = sy * cp; + result[4] = cy * cr +sy * sp *sr; + result[5] = -cy * sr + sy * sp * cr; + result[6] = -sp; + result[7] = cp * sr; + result[8] = cp * cr; + return result; + } + + public static float[] createIntrinsicMatrix(float fx, float fy, float u, float v) { + float[] result = new float[9]; + result[0] = fx; + result[1] = 0.0f; + result[2] = u; + result[3] = 0.0f; + result[4] = fy; + result[5] = v; + result[6] = 0.0f; + result[7] = 0.0f; + result[8] = 1.0f; + return result; + } + + public static float[] transposeMatrix(float[] matrix) { + float[] result = new float[9]; + + result[0] = matrix[0]; + result[1] = matrix[3]; + result[2] = matrix[6]; + result[3] = matrix[1]; + result[4] = matrix[4]; + result[5] = matrix[7]; + result[6] = matrix[2]; + result[7] = matrix[5]; + result[8] = matrix[8]; + return result; + } + + public static float[] productMatrix(float[] matrix1, float[] matrix2) { + float[] result = new float[9]; + result[0] = matrix1[0] * matrix2[0] + matrix1[1] * matrix2[3] + matrix1[2] * matrix2[6]; + result[1] = matrix1[0] * matrix2[1] + matrix1[1] * matrix2[4] + matrix1[2] * matrix2[7]; + result[2] = matrix1[0] * matrix2[2] + matrix1[1] * matrix2[5] + matrix1[2] * matrix2[8]; + result[3] = matrix1[3] * matrix2[0] + matrix1[4] * matrix2[3] + matrix1[5] * matrix2[6]; + result[4] = matrix1[3] * matrix2[1] + matrix1[4] * matrix2[4] + matrix1[5] * matrix2[7]; + result[5] = matrix1[3] * matrix2[2] + matrix1[4] * matrix2[5] + matrix1[5] * matrix2[8]; + result[6] = matrix1[6] * matrix2[0] + matrix1[7] * matrix2[3] + matrix1[8] * matrix2[6]; + result[7] = matrix1[6] * matrix2[1] + matrix1[7] * matrix2[4] + matrix1[8] * matrix2[7]; + result[8] = matrix1[6] * matrix2[2] + matrix1[7] * matrix2[5] + matrix1[8] * matrix2[8]; + + return result; + } + + public static float[] rotateVector(float[] vector, float[] matrix) { + float[] result = new float[3]; + result[0] = matrix[0] * vector[0] + matrix[1] * vector[1] + matrix[2] * vector[2]; + result[1] = matrix[3] * vector[0] + matrix[4] * vector[1] + matrix[5] * vector[2]; + result[2] = matrix[6] * vector[0] + matrix[7] * vector[1] + matrix[8] * vector[2]; + return result; + } + + public static float[] multiple(float[] matrix, float vector) { + for (int i = 0; i < matrix.length; i ++) { + matrix[i] = matrix[i] * vector; + } + return matrix; + } + + private MatrixUtils() { + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/MobileGPSLocationUtil.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/MobileGPSLocationUtil.java new file mode 100644 index 00000000..957aa49e --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/MobileGPSLocationUtil.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.util; + +import android.content.Context; +import android.location.Location; +import android.location.LocationListener; +import android.location.LocationManager; +import android.os.Bundle; + +import java.util.ArrayList; +import java.util.List; + +import dji.v5.utils.common.ContextUtil; +import dji.v5.utils.common.LogUtils; + +import static android.content.Context.LOCATION_SERVICE; + +/** + * Util class to use location manager to get the mobile device's GPS location. + */ +public class MobileGPSLocationUtil { + //region properties + + // The minimum distance to change updates in meters + private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 1; + // The minimum time between updates in milliseconds + private static final long MIN_TIME_BW_UPDATES = 1000; + + private static final String TAG = "MobileGPSLocationUtil"; + private final List locationListeners = new ArrayList<>(); + + private final LocationListener locationManagerListener = new LocationListener() { + @Override + public void onLocationChanged(Location location) { + for (LocationListener listener : locationListeners) { + listener.onLocationChanged(location); + } + } + + @Override + public void onStatusChanged(String provider, int status, Bundle extras) { + for (LocationListener listener : locationListeners) { + listener.onStatusChanged(provider, status, extras); + } + } + + @Override + public void onProviderEnabled(String provider) { + for (LocationListener listener : locationListeners) { + listener.onProviderEnabled(provider); + } + } + + @Override + public void onProviderDisabled(String provider) { + for (LocationListener listener : locationListeners) { + listener.onProviderDisabled(provider); + } + } + }; + + private static class LazyHolder { + private static final MobileGPSLocationUtil INSTANCE = new MobileGPSLocationUtil(); + } + + public static MobileGPSLocationUtil getInstance() { + return LazyHolder.INSTANCE; + } + + private MobileGPSLocationUtil() { + } + + public void addLocationListener(LocationListener listener) { + if (listener != null) { + locationListeners.add(listener); + } + } + + public void removeLocationListener(LocationListener listener) { + locationListeners.remove(listener); + } + + public void clearAllLocationListener() { + locationListeners.clear(); + } + + /** + * Start receiving updates from the location manager + */ + @SuppressWarnings("MissingPermission") + public void startUpdateLocation() { + Context context = ContextUtil.getContext(); + if (context == null) { + return; + } + try { + LocationManager locationManager = (LocationManager) context.getSystemService(LOCATION_SERVICE); + if (locationManager == null){ + return; + } + + // getting GPS status + boolean isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER); + // if GPS Enabled get lat/long using GPS Services + if (isGPSEnabled) { + locationManager.removeUpdates(locationManagerListener); + locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, + MIN_TIME_BW_UPDATES, + MIN_DISTANCE_CHANGE_FOR_UPDATES, + locationManagerListener); + } + } catch (SecurityException e) { + LogUtils.e(TAG, e.getMessage()); + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/SettingDefinitions.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/SettingDefinitions.java new file mode 100644 index 00000000..e931b615 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/SettingDefinitions.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.util; + +import androidx.annotation.IntRange; +import androidx.annotation.NonNull; + +/** + * This class contains enums for UX SDK settings. + */ +public final class SettingDefinitions { + + private SettingDefinitions() { + //Empty Constructor + } + + /** + * The mode which will be controlled by tapping the + * FPVInteractionWidget. + */ + public enum ControlMode { + /** + * The camera will perform spot metering when the + * FPVInteractionWidget is tapped. + */ + SPOT_METER(0), + /** + * The camera will perform center metering. + */ + CENTER_METER(1), + /** + * The camera will set an auto focus target + * FPVInteractionWidget is tapped. + */ + AUTO_FOCUS(2), + /** + * The camera will set a manual focus target when the + * FPVInteractionWidget is tapped. + */ + MANUAL_FOCUS(3), + /** + * The camera will set an auto focus continuous target when the + * FPVInteractionWidget is tapped. + */ + AUTO_FOCUS_CONTINUE(4); + + private int value; + + ControlMode(int value) { + this.value = value; + } + + public int value() { + return this.value; + } + + private boolean _equals(int b) { + return value == b; + } + + private static ControlMode[] values; + + public static ControlMode[] getValues() { + if (values == null) { + values = values(); + } + return values; + } + + public static ControlMode find(int value) { + ControlMode result = SPOT_METER; + for (int i = 0; i < getValues().length; i++) { + if (getValues()[i]._equals(value)) { + result = getValues()[i]; + break; + } + } + return result; + } + + } + + /** + * The enum defines the various Map Providers + * to be used with the MapWidget + */ + public enum MapProvider { + /** + * Unknown Provider + */ + UNKNOWN(-1), + /** + * Google Maps Provider + */ + GOOGLE(0), + /** + * Here Maps Provider + */ + HERE(1), + /** + * AMap Provider + */ + AMAP(2), + /** + * MapLibre Provider + */ + MAPLIBRE(3); + + private int index; + + MapProvider(int index) { + this.index = index; + } + + private static MapProvider[] values; + + public static MapProvider[] getValues() { + if (values == null) { + values = values(); + } + return values; + } + + @NonNull + public static MapProvider find(@IntRange(from = -1, to = 3) int index) { + for (MapProvider mapProvider : MapProvider.getValues()) { + if (mapProvider.getIndex() == index) { + return mapProvider; + } + } + return UNKNOWN; + } + + public int getIndex() { + return index; + } + } + + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/UnitConversionUtil.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/UnitConversionUtil.java new file mode 100644 index 00000000..242b0049 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/UnitConversionUtil.java @@ -0,0 +1,370 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.util; + +import android.content.Context; + +import androidx.annotation.NonNull; +import dji.v5.ux.R; + +/** + * Utility class for unit conversions + */ +public final class UnitConversionUtil { + public static final float TEMPERATURE_K2C = 273.15f; + //region Constants + private static final float METER_TO_FOOT = 3.2808f; + private static final float METER_PER_SEC_TO_MILE_PER_HR = 2.2369f; + private static final float METER_PER_SEC_TO_KM_PER_HR = 3.6f; + private static final int SEC_TO_MIN = 60; + private static final int MIN_TO_HOUR = 60; + private static final int SEC_TO_HOUR = 3600; + //endregion + + //region Constructor + private UnitConversionUtil() { + //Empty + } + //endregion + + //region Length or Distance Conversion Functions + + + /** + * Utility function to convert meters to feet + * + * @param value in meters + * @return float value of the input meter value converted to feet + */ + public static float convertMetersToFeet(float value) { + return (value * METER_TO_FOOT); + } + + /** + * Utility function to convert meters to feet + * + * @param value in meters + * @return double value of the input meter value converted to feet + */ + public static double convertMetersToFeet(double value) { + return (value * METER_TO_FOOT); + } + + /** + * Utility function to convert feet to meters + * + * @param value in feet + * @return float value of the input feet value converted to meters + */ + public static float convertFeetToMeters(float value) { + return (value / METER_TO_FOOT); + } + //endregion + + //region Speed Conversion Functions + + /** + * Utility function to convert meters per second to miles per hour + * + * @param value in meter per second + * @return float value of the input m/s converted to mph + */ + public static float convertMetersPerSecToMilesPerHr(float value) { + return (value * METER_PER_SEC_TO_MILE_PER_HR); + } + + public static double convertMetersPerSecToMilesPerHr(double value) { + return (value * METER_PER_SEC_TO_MILE_PER_HR); + } + + /** + * Utility function to convert miles per hour to meters per second + * + * @param value in miles per hour + * @return float value of the input mph converted to m/s + */ + public static float convertMilesPerHrToMetersPerSec(float value) { + return (value / METER_PER_SEC_TO_MILE_PER_HR); + } + + /** + * Utility function to convert meters per second to kilometers per hour + * + * @param value in meters per second + * @return float value of the input m/s converted to km/hr + */ + public static float convertMetersPerSecToKmPerHr(float value) { + return (value * METER_PER_SEC_TO_KM_PER_HR); + } + + /** + * Utility function to convert kilometers per hour to meters per second + * + * @param value in kilometers per hour + * @return float value of the input km/hr converted to m/s + */ + public static float convertKmPerHrToMetersPerSec(float value) { + return (value / METER_PER_SEC_TO_KM_PER_HR); + } + //endregion + + //region Time Conversion Functions + + /** + * Convert the total value of seconds into an array with seconds, minutes, hours. + * + * @param second value in seconds + * @return Array with equivalent value formatted as seconds, minutes, hours + */ + public static int[] formatSecondToHour(int second) { + final int[] time = new int[3]; + time[0] = second % SEC_TO_MIN; + time[1] = (second / SEC_TO_MIN) % MIN_TO_HOUR; + time[2] = second / (SEC_TO_HOUR); + return time; + } + + /** + * Convert temperature value from kelvin to Celsius + * + * @param value temperature in kelvin + * @return float temperature in Celsius + */ + public static float kelvinToCelsius(final float value) { + return (value - TEMPERATURE_K2C); + } + + /** + * Convert temperature value from Celsius to kelvin + * + * @param value temperature in Celsius + * @return float temperature in kelvin + */ + public static float celsiusToKelvin(final float value) { + return (value + TEMPERATURE_K2C); + } + + public static double celsiusToKelvin(final double value) { + return (value + TEMPERATURE_K2C); + } + + /** + * Convert temperature value from Celsius to fahrenheit + * + * @param value temperature in Celsius + * @return float temperature in Fahrenheit + */ + public static float celsiusToFahrenheit(final float value) { + return (value * 1.8f + 32); + } + + public static double celsiusToFahrenheit(final double value) { + return (value * 1.8f + 32); + } + + /** + * Convert temperature value from Fahrenheit to Celsius + * + * @param value temperature in Fahrenheit + * @return float temperature in Celsius + */ + public static float fahrenheitToCelsius(final float value) { + return (value - 32) / 1.8f; + } + + public static String getSpaceWithUnit(@NonNull Context context, int space) { + String result = context.getString(R.string.uxsdk_storage_status_remaining_space_mb, space); + if (space > 1024) { + result = context.getString(R.string.uxsdk_storage_status_remaining_space_gb, space / 1024f); + } + return result; + } + //endregion + + //region Enums + + /** + * Specify the unit type of a given value + */ + public enum UnitType { + /** + * The unit type is metric + */ + METRIC("Metric", 0), + + /** + * The unit type is imperial + */ + IMPERIAL("Imperial", 1); + + private String stringValue; + private int intValue; + + UnitType(String toString, int value) { + stringValue = toString; + intValue = value; + } + + private static UnitType[] values; + + public static UnitType[] getValues() { + if (values == null) { + values = values(); + } + return values; + } + + public static UnitType find(int value) { + UnitType result = METRIC; + for (int i = 0; i < getValues().length; i++) { + if (getValues()[i].intValue == value) { + result = getValues()[i]; + break; + } + } + return result; + } + + @Override + @NonNull + public String toString() { + return stringValue; + } + + public int value() { + return this.intValue; + } + } + + /** + * Specify the metric unit type of a given speed value + */ + public enum SpeedMetricUnitType { + /** + * The unit type is meters per second + */ + METERS_PER_SECOND("MeterPerSec", 0), + + /** + * The unit type is kilometers per hour + */ + KM_PER_HOUR("KmPerHour", 1); + private String stringValue; + private int intValue; + + SpeedMetricUnitType(String toString, int value) { + stringValue = toString; + intValue = value; + } + + private static SpeedMetricUnitType[] values; + + public static SpeedMetricUnitType[] getValues() { + if (values == null) { + values = values(); + } + return values; + } + + public static SpeedMetricUnitType find(int value) { + SpeedMetricUnitType result = METERS_PER_SECOND; + for (int i = 0; i < getValues().length; i++) { + if (getValues()[i].intValue == value) { + result = getValues()[i]; + break; + } + } + return result; + } + + @Override + @NonNull + public String toString() { + return stringValue; + } + + public int value() { + return this.intValue; + } + } + + + /** + * Specify the temperature unit + */ + public enum TemperatureUnitType { + /** + * The unit type degrees CELSIUS + */ + CELSIUS("CELSIUS", 0), + /** + * The unit type degrees FAHRENHEIT + */ + FAHRENHEIT("FAHRENHEIT", 1), + /** + * The unit type KELVIN + */ + KELVIN("KELVIN", 2); + + private String stringValue; + private int intValue; + + TemperatureUnitType(String toString, int value) { + stringValue = toString; + intValue = value; + } + + private static TemperatureUnitType[] values; + + public static TemperatureUnitType[] getValues() { + if (values == null) { + values = values(); + } + return values; + } + + public static TemperatureUnitType find(int value) { + TemperatureUnitType result = CELSIUS; + for (int i = 0; i < getValues().length; i++) { + if (getValues()[i].intValue == value) { + result = getValues()[i]; + break; + } + } + return result; + } + + @Override + @NonNull + public String toString() { + return stringValue; + } + + public int value() { + return this.intValue; + } + + } + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/UxErrorHandle.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/UxErrorHandle.java new file mode 100644 index 00000000..4e70f604 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/UxErrorHandle.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.util; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import dji.v5.utils.common.LogUtils; +import io.reactivex.rxjava3.functions.Consumer; + +/** + * Util class to help with reactive functions + */ +public final class UxErrorHandle { + + private UxErrorHandle() { + // Util class + } + + /** + * Get a throwable error consumer for the given error. + * + * @param tag Tag for the log + * @param message Message to be logged + * @return Throwable consumer + */ + public static Consumer logErrorConsumer(@NonNull String tag, @NonNull String message) { + return errorConsumer(null, tag, message); + } + + public static Consumer errorConsumer(@Nullable errorHandler handler, @NonNull String tag, @NonNull String message) { + return throwable -> { + if (handler != null) { + handler.onErrorHandler(); + } + LogUtils.e(tag, message + throwable.getLocalizedMessage()); + }; + } + + public interface errorHandler { + void onErrorHandler(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/UxSharedPreferencesUtil.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/UxSharedPreferencesUtil.java new file mode 100644 index 00000000..c98dc153 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/UxSharedPreferencesUtil.java @@ -0,0 +1,244 @@ +package dji.v5.ux.core.util; + +import android.annotation.SuppressLint; +import android.content.Context; +import android.content.SharedPreferences; +import android.preference.PreferenceManager; + +import java.util.Set; + +/** + * @author dnld + * @date 31/07/16 + */ + +public class UxSharedPreferencesUtil { + + public static final String PREF_KEY_UNIT = "pref_key_unit"; + + private static volatile boolean INITIALIZED = false; + private static String sUserId; + private static SharedPreferences SP; + + private UxSharedPreferencesUtil() { + } + + /** + * 不能放在Application中初始化 + */ + public static synchronized void initialize(Context context) { + if (context == null || INITIALIZED) { + return; + } + sUserId = "ux_" + context.getPackageName(); + SP = PreferenceManager.getDefaultSharedPreferences(context); + INITIALIZED = true; + } + + /** + * 未登录状态下设置一个默认的UserId,即空字符串 + */ + public static void setEmptyUserId() { + setUserId(""); + } + + /** + * 设置关联的UserID. + * + * @param userId 用户唯一ID + */ + public static void setUserId(String userId) { + sUserId = userId; + } + + public static SharedPreferences.Editor getEditor() { + return SP.edit(); + } + + /** + * @param key + * @return Returns if that key exists + */ + public static boolean contains(final String key) { + return SP.contains(key); + } + + //region String + + /** + * 获取String类型 + * + * @param key key + * @param defValue 默认值 + * @param user true和用户ID关联,false则和用户无关 + * @return + */ + public static String getString(String key, String defValue, boolean user) { + return SP.getString(user ? key + sUserId : key, defValue); + } + + /** + * 存储String类型 + * + * @param key 键 + * @param value 值 + * @param user true和用户ID关联,false则和用户无关 + * @return + */ + public static void putString(String key, String value, boolean user) { + getEditor().putString(user ? key + sUserId : key, value).apply(); + } + + /** + * {@link #putString(String, String, boolean)} 是现将数据存储到内存中然后异步更新到磁盘, + * 因此可以在主线程调用,但是缺点是如果调用的时候突然crash导致APP退出的话有可能没有 + * 将数据持久化到磁盘,而 {@link #commitString(String, String, boolean)} 则是同步的方法 + * 直接将数据存储到磁盘,但是不应该在主线程调用。 + * + * @param key + * @param value + */ + @SuppressLint("ApplySharedPref") + public static void commitString(String key, String value, boolean user) { + getEditor().putString(user ? key + sUserId : key, value).commit(); + } + //endregion + + //region Boolean + + public static boolean getBoolean(String key, boolean defValue, boolean user) { + return SP.getBoolean(user ? key + sUserId : key, defValue); + } + + public static void putBoolean(String key, boolean value, boolean user) { + getEditor().putBoolean(user ? key + sUserId : key, value).apply(); + } + + @SuppressLint("ApplySharedPref") + public static void commitBoolean(String key, boolean value, boolean user) { + getEditor().putBoolean(user ? key + sUserId : key, value).commit(); + } + //endregion + + //region Integer + + public static int getInt(String key, int defValue, boolean user) { + return SP.getInt(user ? key + sUserId : key, defValue); + } + + public static void putInt(String key, int value, boolean user) { + getEditor().putInt(user ? key + sUserId : key, value).apply(); + } + + @SuppressLint("ApplySharedPref") + public static void commitInteger(String key, int value, boolean user) { + getEditor().putInt(user ? key + sUserId : key, value).commit(); + } + //endregion + + //region Long + + public static long getLong(String key, long defValue, boolean user) { + return SP.getLong(user ? key + sUserId : key, defValue); + } + + public static void putLong(String key, long value, boolean user) { + getEditor().putLong(user ? key + sUserId : key, value).apply(); + } + + @SuppressLint("ApplySharedPref") + public static void commitLong(String key, long value, boolean user) { + getEditor().putLong(user ? key + sUserId : key, value).commit(); + } + //endregion + + + //region Float + + public static float getFloat(String key, float defValue, boolean user) { + return SP.getFloat(user ? key + sUserId : key, defValue); + } + + public static void putFloat(String key, float value, boolean user) { + getEditor().putFloat(user ? key + sUserId : key, value).apply(); + } + + @SuppressLint("ApplySharedPref") + public static void commitFloat(String key, float value, boolean user) { + getEditor().putFloat(user ? key + sUserId : key, value).commit(); + } + //endregion + + //region Double + + /** + * @param key + * @return Returns the stored value of 'what' + */ + public static double getDouble(String key, double defValue, boolean user) { + if (!contains(key)) { + return defValue; + } + return Double.longBitsToDouble(getLong(key, 0, user)); + } + + public static void putDouble(String key, double value, boolean user) { + putLong(key, Double.doubleToLongBits(value), user); + } + + @SuppressLint("ApplySharedPref") + public static void commitDouble(String key, double value, boolean user) { + commitLong(key, Double.doubleToLongBits(value), user); + } + //endregion + + //region StringSet + + public static Set getStringSet(String key, Set defValue, boolean user) { + return SP.getStringSet(user ? key + sUserId : key, defValue); + } + + public static void putStringSet(String key, Set value, boolean user) { + getEditor().putStringSet(user ? key + sUserId : key, value).apply(); + } + + @SuppressLint("ApplySharedPref") + public static void commitStringSet(String key, Set value, boolean user) { + getEditor().putStringSet(user ? key + sUserId : key, value).commit(); + } + //endregion + + + //region Remove + + public static void remove(String key, boolean user) { + getEditor().remove(user ? key + sUserId : key).apply(); + } + + public static void commitRemove(String key, boolean user) { + getEditor().remove(user ? key + sUserId : key).commit(); + } + + public static void remove(boolean user, String... keys) { + if (keys != null && keys.length > 0) { + for (String key : keys) { + remove(key, user); + } + } + } + + /** + * 会清楚所有数据,谨慎操作 + */ + public static void clear() { + getEditor().clear().apply(); + } + + /** + * 会清楚所有数据,谨慎操作 + */ + public static void commitClear() { + getEditor().clear().commit(); + } + //endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/ViewIDGenerator.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/ViewIDGenerator.kt new file mode 100644 index 00000000..d874799c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/ViewIDGenerator.kt @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.util + +import android.view.View + +import java.util.concurrent.atomic.AtomicInteger + +object ViewIDGenerator { + private val nextGeneratedID = AtomicInteger(1) + + /** + * Generates a unique ID that can be assigned to a @see[View]. + * Backwards compatible to any Android version. + */ + fun generateViewId(): Int { + while (true) { + val result = nextGeneratedID.get() + var newValue = result + 1 + if (newValue > 0x00FFFFFF) + newValue = 1 // Roll over to 1, not 0. + if (nextGeneratedID.compareAndSet(result, newValue)) { + return result + } + } + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/ViewUtil.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/ViewUtil.java new file mode 100644 index 00000000..45d3e797 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/util/ViewUtil.java @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.util; + +import android.app.Activity; +import android.content.Context; +import android.content.ContextWrapper; +import android.content.res.ColorStateList; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.os.Handler; +import android.os.Looper; +import android.view.KeyEvent; +import android.view.Window; +import android.view.WindowManager; +import android.widget.ImageView; +import android.widget.Toast; + +import androidx.annotation.ColorInt; +import androidx.annotation.NonNull; +import androidx.core.graphics.drawable.DrawableCompat; +import androidx.core.widget.ImageViewCompat; + +/** + * Utility class for converting and applying changes to Views. + */ +public final class ViewUtil { + + private static final Handler UI_Handler = new Handler(Looper.getMainLooper()); + + private ViewUtil() { + // Util class + } + + /** + * Applies a tint to the ImageView. + * + * @param imageView The ImageView to apply the tint to. + * @param color The tinting color. + */ + public static void tintImage(@NonNull ImageView imageView, @ColorInt int color) { + if (imageView.getDrawable() == null) { + return; + } + Drawable wrapDrawable = DrawableCompat.wrap(imageView.getDrawable().mutate()); + DrawableCompat.setTint(wrapDrawable, color); + if (Build.VERSION.SDK_INT == Build.VERSION_CODES.LOLLIPOP) { + imageView.invalidate(); //Fixes invalidation bug on lollipop devices + } + } + + /** + * Applies tint to ImageView + * + * @param imageView The ImageView to apply tint to + * @param colorStateList The ColorStateList representing the tint + */ + public static void tintImage(@NonNull ImageView imageView, @NonNull ColorStateList colorStateList) { + ImageViewCompat.setImageTintList(imageView, colorStateList); + } + + /** + * Converts a VectorDrawable to a Bitmap. + * + * @param drawable The VectorDrawable to convert. + * @return A {@link Bitmap} object. + */ + @NonNull + public static Bitmap getBitmapFromVectorDrawable(@NonNull Drawable drawable) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + drawable = (DrawableCompat.wrap(drawable)).mutate(); + } + + Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(), + drawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888); + Canvas canvas = new Canvas(bitmap); + drawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight()); + drawable.draw(canvas); + + return bitmap; + } + + /** + * Shows a toast, or logs an error if a BadTokenException is thrown. + * + * @param context An android context object + * @param resId The resource ID of the string to display + * @param duration How long to display the toast. + */ + public static void showToast(Context context, int resId, int duration) { + showToast(context, context.getString(resId), duration); + } + + /** + * Shows a toast, or logs an error if a BadTokenException is thrown. + * + * @param context An android context object + * @param message The string to display + * @param duration How long to display the toast. + */ + public static void showToast(Context context, String message, int duration) { + if (context == null) { + return; + } + Runnable runnable = () -> Toast.makeText(context, message, duration).show(); + if (UI_Handler.getLooper().isCurrentThread()) { + runnable.run(); + } else { + UI_Handler.post(runnable); + } + } + + public static void showToast(Context context, String message) { + showToast(context, message, Toast.LENGTH_SHORT); + } + + public static boolean dispatchKeyEvent(Context context, KeyEvent keyEvent) { + Activity activity = contextToActivity(context); + if (activity != null) { + activity.dispatchKeyEvent(keyEvent); + return true; + } else { + return false; + } + } + + public static Activity contextToActivity(Context context) { + if (context == null) { + return null; + } + if (context instanceof Activity) { + return (Activity) context; + } else if (context instanceof ContextWrapper) { + Context context2 = ((ContextWrapper) context).getBaseContext(); + if (context2 instanceof Activity) { + return (Activity) context2; + } + } + return null; + } + + public static void setKeepScreen(Activity activity, boolean isKeep) { + Window window = activity.getWindow(); + if (window == null) { + return; + } + if (isKeep) { + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } else { + window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); + } + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/airsense/AirSenseWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/airsense/AirSenseWidget.kt new file mode 100644 index 00000000..5390c2ce --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/airsense/AirSenseWidget.kt @@ -0,0 +1,612 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.airsense + +import android.annotation.SuppressLint +import android.content.Context +import android.content.Context.LAYOUT_INFLATER_SERVICE +import android.content.DialogInterface +import android.content.res.ColorStateList +import android.graphics.drawable.Drawable +import android.text.SpannableString +import android.text.Spanned +import android.text.TextPaint +import android.text.method.LinkMovementMethod +import android.text.style.ClickableSpan +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import android.view.animation.Animation +import android.view.animation.AnimationUtils +import android.webkit.WebView +import android.widget.CheckBox +import android.widget.CompoundButton +import android.widget.ImageView +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.annotation.Dimension +import androidx.annotation.DrawableRes +import androidx.annotation.StyleRes +import androidx.appcompat.app.AlertDialog +import androidx.appcompat.view.ContextThemeWrapper +import androidx.core.content.res.use +import dji.sdk.keyvalue.value.flightcontroller.AirSenseWarningLevel +import dji.v5.utils.common.DisplayUtil +import dji.v5.ux.R +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.SchedulerProvider +import io.reactivex.rxjava3.functions.Consumer +import io.reactivex.rxjava3.processors.PublishProcessor +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.GlobalPreferencesManager +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.util.ViewUtil +import dji.v5.ux.core.widget.airsense.AirSenseWidget.ModelState +import dji.v5.ux.core.widget.airsense.AirSenseWidget.ModelState.* +import dji.v5.ux.core.widget.airsense.AirSenseWidget.UIState.* +import dji.v5.ux.core.widget.airsense.AirSenseWidgetModel.AirSenseState +import dji.v5.ux.core.util.UxErrorHandle + +/** + * Widget that displays an icon representing whether there are any aircraft nearby and how likely + * a collision is. The icon is shown in different colors representing the current + * [AirSenseWarningLevel]. The widget will be hidden on devices that do not have DJI AirSense + * installed. + * + * When the warning level is at [AirSenseWarningLevel.LEVEL_0] or above, a warning dialog will + * appear. This warning dialog contains a warning message, an option to never show the dialog + * again, and a link to an additional dialog with AirSense Terms and Conditions for the user to + * agree to. + * + * When the warning level is at [AirSenseWarningLevel.LEVEL_2] or above, a WarningMessage is sent + * to suggest that the user should descend immediately. To react to all WarningMessages sent by all + * widgets including the AirSenseWidget, listen to MessagingKeys.SEND_WARNING_MESSAGE. + * + * The icon is gray when no airplanes are nearby, and adds the text "N/A" when no product is + * connected. + */ +open class AirSenseWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ConstraintLayoutWidget(context, attrs, defStyleAttr) { + + //region Fields + private val airSenseImageView: ImageView = findViewById(R.id.imageview_air_sense) + private val colorMap: MutableMap = + mutableMapOf( + AirSenseState.DISCONNECTED to getColor(R.color.uxsdk_gray_58), + AirSenseState.NO_AIR_SENSE_CONNECTED to getColor(R.color.uxsdk_gray_58), + AirSenseState.NO_AIRPLANES_NEARBY to getColor(R.color.uxsdk_gray_58), + AirSenseState.WARNING_LEVEL_0 to getColor(R.color.uxsdk_white), + AirSenseState.WARNING_LEVEL_1 to getColor(R.color.uxsdk_blue_highlight), + AirSenseState.WARNING_LEVEL_2 to getColor(R.color.uxsdk_yellow_500), + AirSenseState.WARNING_LEVEL_3 to getColor(R.color.uxsdk_red_500), + AirSenseState.WARNING_LEVEL_4 to getColor(R.color.uxsdk_red_500)) + private val blinkAnimation: Animation = AnimationUtils.loadAnimation(context, R.anim.uxsdk_anim_blink) + private var warningDialogDisplayed: Boolean = false + private val uiUpdateStateProcessor: PublishProcessor = PublishProcessor.create() + private val widgetModel by lazy { + AirSenseWidgetModel(DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()) + } + + var airSenseDisconnectedStateIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_topbar_adsb_disconnected) + set(value) { + field = value + checkAndUpdateIcon() + } + var airSenseConnectedStateIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_topbar_adsb_normal) + set(value) { + field = value + checkAndUpdateIcon() + } + + /** + * The drawable resource for the AirSense icon's background + */ + var airSenseIconBackground: Drawable? + get() = airSenseImageView.background + set(value) { + airSenseImageView.background = value + } + + /** + * The theme of the warning dialog + */ + @get:StyleRes + @setparam:StyleRes + var warningDialogTheme = R.style.UXSDKAirSenseWarningDialogTheme + + /** + * The theme of the terms dialog + */ + @get:StyleRes + @setparam:StyleRes + var termsDialogTheme = 0 + + /** + * The text appearance of the terms link text view + */ + @get:StyleRes + @setparam:StyleRes + var termsLinkTextAppearance = 0 + + /** + * The text color for the terms link text view + */ + @get:ColorInt + @setparam:ColorInt + var termsLinkTextColor = getColor(R.color.uxsdk_blue) + + /** + * The background of the terms link text view + */ + var termsLinkTextBackground: Drawable? = null + + /** + * The text size of the terms link text view + */ + @get:Dimension + @setparam:Dimension + var termsLinkTextSize: Float = 0f + + /** + * The text appearance of the check box label + */ + @get:StyleRes + @setparam:StyleRes + var checkBoxTextAppearance = 0 + + /** + * The text color state list of the check box label + */ + var checkBoxTextColor: ColorStateList? = null + + /** + * The background of the check box + */ + var checkBoxTextBackground: Drawable? = null + + /** + * The text size of the check box label + */ + @get:Dimension + @setparam:Dimension + var checkBoxTextSize: Float = 0f + //endregion + + //region Constructor + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + View.inflate(context, R.layout.uxsdk_widget_air_sense, this) + } + + init { + attrs?.let { initAttributes(context, it) } + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.airSenseWarningLevel + .observeOn(SchedulerProvider.ui()) + .subscribe { updateAirSenseWarningLevel(it) }) + addReaction(widgetModel.airSenseState + .observeOn(SchedulerProvider.ui()) + .subscribe { updateIcon(it) }) + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + } + + //endregion + + //region Reactions + + private fun updateAirSenseWarningLevel(warningLevel: AirSenseWarningLevel) { + updateWarningMessages(warningLevel) + if (warningLevel != AirSenseWarningLevel.LEVEL_0 + && warningLevel != AirSenseWarningLevel.UNKNOWN) { + showWarningDialog() + } + widgetStateDataProcessor.onNext(AirSenseWarningLevelUpdated(warningLevel)) + } + + private fun updateIcon(state: AirSenseState) { + visibility = if (state == AirSenseState.NO_AIR_SENSE_CONNECTED) GONE else VISIBLE + airSenseImageView.imageDrawable = + if (state == AirSenseState.DISCONNECTED) { + airSenseDisconnectedStateIcon + } else { + airSenseConnectedStateIcon + } + + if (colorMap.containsKey(state)) { + ViewUtil.tintImage(airSenseImageView, getAirSenseIconTintColor(state)) + } + if (state == AirSenseState.WARNING_LEVEL_4) { + airSenseImageView.startAnimation(blinkAnimation) + } else { + airSenseImageView.clearAnimation() + } + widgetStateDataProcessor.onNext(AirSenseStateUpdated(state)) + } + + private fun updateWarningMessages(warningLevel: AirSenseWarningLevel) { + addDisposable(widgetModel.sendWarningMessages(getString(R.string.uxsdk_message_air_sense_warning_title), + getString(R.string.uxsdk_message_air_sense_dangerous_content), + getString(R.string.uxsdk_message_air_sense_warning_content), + warningLevel) + .subscribe()) + } + + private fun showWarningDialog() { + val checked = GlobalPreferencesManager.getInstance().isAirSenseTermsNeverShown + if (!checked && !warningDialogDisplayed) { + val builder: AlertDialog.Builder = if (warningDialogTheme != 0) { + AlertDialog.Builder(context, warningDialogTheme) + } else { + AlertDialog.Builder(context) + } + builder.setCancelable(true) + builder.setOnCancelListener { onWarningDialogClosed() } + builder.setTitle(getString(R.string.uxsdk_message_air_sense_warning_title)) + builder.setPositiveButton(R.string.uxsdk_app_ok) { dialogInterface: DialogInterface, _: Int -> + dialogInterface.dismiss() + onWarningDialogClosed() + } + builder.setView(createTermsView()) + builder.create().show() + warningDialogDisplayed = true + } + } + + private fun onWarningDialogClosed() { + warningDialogDisplayed = false + uiUpdateStateProcessor.onNext(WarningDialogDismissed) + } + + @SuppressLint("InflateParams") + private fun createTermsView(): View { + val termsView = if (warningDialogTheme != 0) { + val ctw = ContextThemeWrapper(context, warningDialogTheme) + val inflater: LayoutInflater = ctw.getSystemService(LAYOUT_INFLATER_SERVICE) as LayoutInflater + inflater.inflate(R.layout.uxsdk_layout_dialog_checkbox, null) + } else { + View.inflate(context, R.layout.uxsdk_layout_dialog_checkbox, null) + } + val dontShowAgainCheckBox = termsView.findViewById(R.id.checkbox_dont_show_again) + dontShowAgainCheckBox.setOnCheckedChangeListener { _: CompoundButton?, checked: Boolean -> + GlobalPreferencesManager.getInstance().isAirSenseTermsNeverShown = checked + uiUpdateStateProcessor.onNext(NeverShowAgainCheckChanged(checked)) + } + if (checkBoxTextAppearance != INVALID_RESOURCE) { + dontShowAgainCheckBox.setTextAppearance(context, checkBoxTextAppearance) + } + if (checkBoxTextColor != null) { + dontShowAgainCheckBox.setTextColor(checkBoxTextColor) + } + if (checkBoxTextBackground != null) { + dontShowAgainCheckBox.background = checkBoxTextBackground + } + if (checkBoxTextSize != INVALID_DIMENSION) { + dontShowAgainCheckBox.textSize = checkBoxTextSize + } + val termsLinkTextView = termsView.findViewById(R.id.textview_dialog_content) + val termsLink = SpannableString(getString(R.string.uxsdk_air_sense_terms_content)) + val clickableSpan: ClickableSpan = object : ClickableSpan() { + override fun onClick(view: View) { + showTermsDialog() + uiUpdateStateProcessor.onNext(TermsLinkClicked) + } + + override fun updateDrawState(ds: TextPaint) { + super.updateDrawState(ds) + if (termsLinkTextColor != 0) { + ds.color = termsLinkTextColor + } + } + } + termsLink.setSpan(clickableSpan, 0, termsLink.length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE) + termsLinkTextView.linksClickable = true + termsLinkTextView.movementMethod = LinkMovementMethod.getInstance() + termsLinkTextView.text = termsLink + if (termsLinkTextAppearance != INVALID_RESOURCE) { + termsLinkTextView.setTextAppearance(context, termsLinkTextAppearance) + } + if (termsLinkTextBackground != null) { + termsLinkTextView.background = termsLinkTextBackground + } + if (termsLinkTextSize != INVALID_DIMENSION) { + termsLinkTextView.textSize = termsLinkTextSize + } + return termsView + } + + private fun showTermsDialog() { + val builder: AlertDialog.Builder = if (termsDialogTheme != 0) { + AlertDialog.Builder(context, termsDialogTheme) + } else { + AlertDialog.Builder(context) + } + builder.setCancelable(true) + builder.setOnCancelListener { onTermsDialogClosed() } + builder.setPositiveButton(R.string.uxsdk_app_ok) { dialogInterface: DialogInterface, _: Int -> + dialogInterface.dismiss() + onTermsDialogClosed() + } + val myWebView = WebView(context) + myWebView.loadUrl(AIR_SENSE_TERMS_URL) + builder.setView(myWebView) + builder.create().show() + } + + private fun onTermsDialogClosed() { + uiUpdateStateProcessor.onNext(TermsDialogDismissed) + } + + private fun checkAndUpdateIcon() { + if (!isInEditMode) { + addDisposable(widgetModel.airSenseState.firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(Consumer { this.updateIcon(it) }, UxErrorHandle.logErrorConsumer(TAG, "Update Icon "))) + } + } + //endregion + + //region Customization + override fun getIdealDimensionRatioString() = null + + /** + * Tints the AirSense icon to the given color when the AirSense state is the given value. + * + * @param state The state for which to tint the AirSense icon. + * @param color The color to tint the AirSense icon. + */ + fun setAirSenseIconTintColor(state: AirSenseState, @ColorInt color: Int) { + colorMap[state] = color + checkAndUpdateIcon() + } + + /** + * Returns the color that the AirSense icon will be tinted when the AirSense state is + * the given value. + * + * @param state The state for which the AirSense icon will be tinted the returned + * color. + * @return The color the AirSense icon will be tinted. + */ + @ColorInt + fun getAirSenseIconTintColor(state: AirSenseState): Int { + return (colorMap[state]?.let { it } ?: getColor(R.color.uxsdk_white)) + } + + /** + * Set the resource ID for the AirSense icon when there is no product connected + * + * @param resourceId Integer ID of the drawable resource + */ + fun setAirSenseDisconnectedStateIcon(@DrawableRes resourceId: Int) { + airSenseDisconnectedStateIcon = getDrawable(resourceId) + } + + /** + * Set the resource ID for the AirSense icon when a product is connected + * + * @param resourceId Integer ID of the drawable resource + */ + fun setAirSenseConnectedStateIcon(@DrawableRes resourceId: Int) { + airSenseConnectedStateIcon = getDrawable(resourceId) + } + + /** + * Set the resource ID for the AirSense icon's background + * + * @param resourceId Integer ID of the icon's background resource + */ + fun setAirSenseIconBackground(@DrawableRes resourceId: Int) { + airSenseIconBackground = getDrawable(resourceId) + } + + /** + * Set the resource ID for the background of the terms link text view + * + * @param resourceId Integer ID of the text view's background resource + */ + fun setTermsLinkTextBackground(@DrawableRes resourceId: Int) { + termsLinkTextBackground = getDrawable(resourceId) + } + + /** + * Set the text color for the check box label + * + * @param color color integer resource + */ + fun setCheckBoxTextColor(@ColorInt color: Int) { + if (color != INVALID_COLOR) { + checkBoxTextColor = ColorStateList.valueOf(color) + } + } + + /** + * Set the resource ID for the background of the check box + * + * @param resourceId Integer ID of the text view's background resource + */ + fun setCheckBoxBackground(@DrawableRes resourceId: Int) { + checkBoxTextBackground = getDrawable(resourceId) + } + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.AirSenseWidget).use { typedArray -> + typedArray.getDrawableAndUse(R.styleable.AirSenseWidget_uxsdk_airSenseConnectedStateIcon) { + this.airSenseConnectedStateIcon = it + } + typedArray.getDrawableAndUse(R.styleable.AirSenseWidget_uxsdk_airSenseDisconnectedStateIcon) { + this.airSenseDisconnectedStateIcon = it + } + typedArray.getDrawableAndUse(R.styleable.AirSenseWidget_uxsdk_airSenseIconBackground) { + airSenseIconBackground = it + } + typedArray.getColorAndUse(R.styleable.AirSenseWidget_uxsdk_airSenseIconDisconnectedTint) { + setAirSenseIconTintColor(AirSenseState.DISCONNECTED, it) + } + typedArray.getColorAndUse(R.styleable.AirSenseWidget_uxsdk_airSenseIconNoAirplanesNearbyTint) { + setAirSenseIconTintColor(AirSenseState.NO_AIRPLANES_NEARBY, it) + } + typedArray.getColorAndUse(R.styleable.AirSenseWidget_uxsdk_airSenseIconWarningLevel0Tint) { + setAirSenseIconTintColor(AirSenseState.WARNING_LEVEL_0, it) + } + typedArray.getColorAndUse(R.styleable.AirSenseWidget_uxsdk_airSenseIconWarningLevel1Tint) { + setAirSenseIconTintColor(AirSenseState.WARNING_LEVEL_1, it) + } + typedArray.getColorAndUse(R.styleable.AirSenseWidget_uxsdk_airSenseIconWarningLevel2Tint) { + setAirSenseIconTintColor(AirSenseState.WARNING_LEVEL_2, it) + } + typedArray.getColorAndUse(R.styleable.AirSenseWidget_uxsdk_airSenseIconWarningLevel3Tint) { + setAirSenseIconTintColor(AirSenseState.WARNING_LEVEL_3, it) + } + typedArray.getColorAndUse(R.styleable.AirSenseWidget_uxsdk_airSenseIconWarningLevel4Tint) { + setAirSenseIconTintColor(AirSenseState.WARNING_LEVEL_4, it) + } + typedArray.getResourceIdAndUse(R.styleable.AirSenseWidget_uxsdk_linkTextAppearance) { + termsLinkTextAppearance = it + } + typedArray.getColorAndUse(R.styleable.AirSenseWidget_uxsdk_linkTextColor) { + termsLinkTextColor = it + } + typedArray.getDrawableAndUse(R.styleable.AirSenseWidget_uxsdk_linkTextBackground) { + termsLinkTextBackground = it + } + typedArray.getDimensionAndUse(R.styleable.AirSenseWidget_uxsdk_linkTextSize) { + termsLinkTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getResourceIdAndUse(R.styleable.AirSenseWidget_uxsdk_checkBoxTextAppearance) { + checkBoxTextAppearance = it + } + typedArray.getColorStateListAndUse(R.styleable.AirSenseWidget_uxsdk_checkBoxTextColor) { + checkBoxTextColor = it + } + typedArray.getDrawableAndUse(R.styleable.AirSenseWidget_uxsdk_checkBoxTextBackground) { + checkBoxTextBackground = it + } + typedArray.getDimensionAndUse(R.styleable.AirSenseWidget_uxsdk_checkBoxTextSize) { + checkBoxTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getResourceIdAndUse(R.styleable.AirSenseWidget_uxsdk_warningDialogTheme) { + warningDialogTheme = it + } + typedArray.getResourceIdAndUse(R.styleable.AirSenseWidget_uxsdk_termsDialogTheme) { + termsDialogTheme = it + } + } + } + //endregion + + //region Hooks + /** + * Get the [UIState] updates + */ + fun getUIStateUpdates(): Flowable { + return uiUpdateStateProcessor.onBackpressureBuffer() + } + + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Widget UI update State + */ + sealed class UIState { + + /** + * Update when warning dialog is dismissed + */ + object WarningDialogDismissed : UIState() + + /** + * Update when terms link is tapped + */ + object TermsLinkClicked : UIState() + + /** + * Update when terms dialog is dismissed + */ + object TermsDialogDismissed : UIState() + + /** + * Update when "Don't show again" checkbox is tapped + */ + data class NeverShowAgainCheckChanged(val isChecked: Boolean) : UIState() + } + + /** + * Class defines the widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * AirSense warning level update + */ + data class AirSenseWarningLevelUpdated(val airSenseWarningLevel: AirSenseWarningLevel) : ModelState() + + /** + * AirSense status update + */ + data class AirSenseStateUpdated(val airSenseState: AirSenseState) : ModelState() + + } + //endregion + + companion object { + private const val AIR_SENSE_TERMS_URL = "file:///android_asset/htmls/air_sense_terms_of_use.html" + private const val TAG = "AirSenseWidget" + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/airsense/AirSenseWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/airsense/AirSenseWidgetModel.kt new file mode 100644 index 00000000..aa0778da --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/airsense/AirSenseWidgetModel.kt @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.airsense + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.value.flightcontroller.AirSenseSystemInformation +import dji.sdk.keyvalue.value.flightcontroller.AirSenseWarningLevel +import dji.sdk.keyvalue.key.KeyTools +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.MessagingKeys +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.communication.UXKey +import dji.v5.ux.core.communication.UXKeys +import dji.v5.ux.core.model.WarningMessage +import dji.v5.ux.core.model.WarningMessageError +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Completable + +/** + * Widget Model for the [AirSenseWidget] used to define + * the underlying logic and communication + */ +class AirSenseWidgetModel @JvmOverloads constructor( + djiSdkModel: DJISDKModel, + private val keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + + private val airSenseConnectedProcessor: DataProcessor = DataProcessor.create(false) + private val airSenseSystemInformationProcessor : DataProcessor = DataProcessor.create(AirSenseSystemInformation()) + private val airSenseWarningLevelProcessor: DataProcessor = DataProcessor.create(AirSenseWarningLevel.UNKNOWN) + private val sendWarningMessageKey: UXKey = UXKeys.create(MessagingKeys.SEND_WARNING_MESSAGE) + private val airSenseStateProcessor: DataProcessor = DataProcessor.create(AirSenseState.DISCONNECTED) + + //region Data + /** + * Get the AirSense warning level. + */ + val airSenseWarningLevel: Flowable + get() = airSenseWarningLevelProcessor.toFlowable().distinctUntilChanged() + + /** + * Get the number of airplanes detected by AirSense + */ + val airSenseState: Flowable + get() = airSenseStateProcessor.toFlowable() + //endregion + + //region Actions + /** + * Send two warning messages with the given solutions for warning and dangerous levels. Based + * on the warning level, only one message at a time will be displayed, and the other will be + * removed. + * + * @param reason The reason to display on the warning message. + * @param warningSolution The solution to display if the level is [WarningMessage.Level.WARNING] + * @param dangerousSolution The solution to display if the level is [WarningMessage.Level.DANGEROUS] + * @param warningLevel The current AirSense warning level. + * @return Completable representing the success/failure of the set action. + */ + fun sendWarningMessages(reason: String?, warningSolution: String?, dangerousSolution: String?, warningLevel: AirSenseWarningLevel): Completable { + return when (warningLevel) { + AirSenseWarningLevel.LEVEL_2 -> sendWarningMessage(reason, warningSolution, WarningMessage.Level.WARNING, WarningMessage.Action.INSERT) + .andThen(sendWarningMessage(reason, dangerousSolution, WarningMessage.Level.DANGEROUS, WarningMessage.Action.REMOVE)) + AirSenseWarningLevel.LEVEL_3, AirSenseWarningLevel.LEVEL_4 -> sendWarningMessage(reason, warningSolution, WarningMessage.Level.WARNING, WarningMessage.Action.REMOVE) + .andThen(sendWarningMessage(reason, dangerousSolution, WarningMessage.Level.DANGEROUS, WarningMessage.Action.INSERT)) + else -> sendWarningMessage(reason, warningSolution, WarningMessage.Level.WARNING, WarningMessage.Action.REMOVE) + .andThen(sendWarningMessage(reason, dangerousSolution, WarningMessage.Level.DANGEROUS, WarningMessage.Action.REMOVE)) + } + } + + private fun sendWarningMessage(reason: String?, solution: String?, level: WarningMessage.Level?, action: WarningMessage.Action?): Completable { + val builder = WarningMessage.Builder(WarningMessage.WarningType.FLY_SAFE) + .code(-1) + .subCode(WarningMessageError.OTHER_AIRCRAFT_NEARBY.value()) + .reason(reason) + .solution(solution) + .level(level) + .type(WarningMessage.Type.PINNED) + .action(action) + val warningMessage = builder.build() + return keyedStore.setValue(sendWarningMessageKey, warningMessage) + } + + //endregion + + //region Lifecycle + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAirSenseSystemConnected), airSenseConnectedProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAirSenseSystemInformation), airSenseSystemInformationProcessor){ + airSenseWarningLevelProcessor.onNext(it.warningLevel) + } + } + + override fun inCleanup() { + // do nothing + } + + override fun updateStates() { + airSenseStateProcessor.onNext( + if (!productConnectionProcessor.value) { + AirSenseState.DISCONNECTED + } else if (!airSenseConnectedProcessor.value) { + AirSenseState.NO_AIR_SENSE_CONNECTED + } else if (airSenseSystemInformationProcessor.value.airplaneStates.isEmpty()) { + AirSenseState.NO_AIRPLANES_NEARBY + } else { + when (airSenseSystemInformationProcessor.value.warningLevel) { + AirSenseWarningLevel.LEVEL_0 -> AirSenseState.WARNING_LEVEL_0 + AirSenseWarningLevel.LEVEL_1 -> AirSenseState.WARNING_LEVEL_1 + AirSenseWarningLevel.LEVEL_2 -> AirSenseState.WARNING_LEVEL_2 + AirSenseWarningLevel.LEVEL_3 -> AirSenseState.WARNING_LEVEL_3 + AirSenseWarningLevel.LEVEL_4 -> AirSenseState.WARNING_LEVEL_4 + else -> AirSenseState.UNKNOWN + } + } + ) + } + //endregion + + //region States + /** + * The status of the AirSense system. + */ + enum class AirSenseState { + /** + * There is no product connected. + */ + DISCONNECTED, + + /** + * The connected product does not have DJI AirSense. + */ + NO_AIR_SENSE_CONNECTED, + + /** + * A product that has DJI AirSense is connected and no airplanes are nearby. + */ + NO_AIRPLANES_NEARBY, + + /** + * A product that has DJI AirSense is connected and the system detects an airplane but the + * DJI aircraft is either far away from the airplane or is in the opposite direction of the + * airplane's heading. + */ + WARNING_LEVEL_0, + + /** + * A product that has DJI AirSense is connected and the system detects an airplane. The + * probability that it will pass through the location of the DJI aircraft is considered + * low. + */ + WARNING_LEVEL_1, + + /** + * A product that has DJI AirSense is connected and the system detects an airplane. The + * probability that it will pass through the location of the DJI aircraft is considered + * medium. + */ + WARNING_LEVEL_2, + + /** + * A product that has DJI AirSense is connected and the system detects an airplane. The + * probability that it will pass through the location of the DJI aircraft is considered + * high. + */ + WARNING_LEVEL_3, + + /** + * A product that has DJI AirSense is connected and the system detects an airplane. The + * probability that it will pass through the location of the DJI aircraft is very high. + */ + WARNING_LEVEL_4, + + /** + * Unknown. + */ + UNKNOWN + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/altitude/AGLAltitudeWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/altitude/AGLAltitudeWidget.kt new file mode 100644 index 00000000..e4a042d1 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/altitude/AGLAltitudeWidget.kt @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.altitude + +import android.content.Context +import android.util.AttributeSet +import dji.v5.ux.R +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.widget.BaseTelemetryWidget +import dji.v5.ux.core.communication.GlobalPreferencesManager +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getDistanceString +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.util.UnitConversionUtil +import dji.v5.ux.core.widget.altitude.AGLAltitudeWidget.ModelState +import dji.v5.ux.core.widget.altitude.AltitudeWidgetModel.AltitudeState +import java.text.DecimalFormat + +/** + * Widget displays the above ground level altitude + */ +open class AGLAltitudeWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + widgetTheme: Int = 0 +) : BaseTelemetryWidget( + context, + attrs, + defStyleAttr, + WidgetType.TEXT, + widgetTheme, + R.style.UXSDKAGLAltitudeWidget +) { + + //region Fields + override val metricDecimalFormat: DecimalFormat = DecimalFormat("###0.0") + + override val imperialDecimalFormat: DecimalFormat = DecimalFormat("###0") + + private val widgetModel: AltitudeWidgetModel by lazy { + AltitudeWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + GlobalPreferencesManager.getInstance()) + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ModelState.ProductConnected(it)) }) + addReaction(widgetModel.altitudeState + .observeOn(SchedulerProvider.ui()) + .subscribe { updateUI(it) }) + } + //endregion + + //region Reactions to model + private fun updateUI(altitudeState: AltitudeState) { + widgetStateDataProcessor.onNext(ModelState.AltitudeStateUpdated(altitudeState)) + if (altitudeState is AltitudeState.CurrentAltitude) { + if(altitudeState.unitType == UnitConversionUtil.UnitType.IMPERIAL) { + setValueTextViewMinWidthByText("8888") + } else { + setValueTextViewMinWidthByText("888.8") + } + unitString = getDistanceString(altitudeState.unitType) + valueString = getDecimalFormat(altitudeState.unitType) + .format(altitudeState.altitudeAGL).toString() + } else { + unitString = null + valueString = getString(R.string.uxsdk_string_default_value) + } + } + //endregion + + //region customizations + override fun getIdealDimensionRatioString(): String? = null + + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP) + + //endregion + + //region Hooks + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val boolean: Boolean) : ModelState() + + /** + * Altitude widget state updated + */ + data class AltitudeStateUpdated(val altitudeState: AltitudeState) : ModelState() + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/altitude/AMSLAltitudeWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/altitude/AMSLAltitudeWidget.kt new file mode 100644 index 00000000..3ef7b106 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/altitude/AMSLAltitudeWidget.kt @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.altitude + +import android.content.Context +import android.util.AttributeSet +import dji.v5.ux.R +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.widget.BaseTelemetryWidget +import dji.v5.ux.core.communication.GlobalPreferencesManager +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getDistanceString +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.util.UnitConversionUtil +import dji.v5.ux.core.widget.altitude.AMSLAltitudeWidget.ModelState +import java.text.DecimalFormat + +/** + * Widget displays the above mean sea level altitude + */ +open class AMSLAltitudeWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + widgetTheme: Int = 0 +) : BaseTelemetryWidget( + context, + attrs, + defStyleAttr, + WidgetType.TEXT, + widgetTheme, + R.style.UXSDKAMSLAltitudeWidget +) { + + //region Fields + override val metricDecimalFormat: DecimalFormat = DecimalFormat("###0.0") + + override val imperialDecimalFormat: DecimalFormat = DecimalFormat("###0") + + private val widgetModel: AltitudeWidgetModel by lazy { + AltitudeWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + GlobalPreferencesManager.getInstance()) + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ModelState.ProductConnected(it)) }) + addReaction(widgetModel.altitudeState + .observeOn(SchedulerProvider.ui()) + .subscribe { updateUI(it) }) + } + //endregion + + //region Reactions to model + private fun updateUI(altitudeState: AltitudeWidgetModel.AltitudeState) { + widgetStateDataProcessor.onNext(ModelState.AltitudeStateUpdated(altitudeState)) + if (altitudeState is AltitudeWidgetModel.AltitudeState.CurrentAltitude) { + if(altitudeState.unitType == UnitConversionUtil.UnitType.IMPERIAL) { + setValueTextViewMinWidthByText("8888") + } else { + setValueTextViewMinWidthByText("888.8") + } + unitString = getDistanceString(altitudeState.unitType) + valueString = getDecimalFormat(altitudeState.unitType) + .format(altitudeState.altitudeAMSL).toString() + } else { + unitString = null + valueString = getString(R.string.uxsdk_string_default_value) + } + } + //endregion + + //region customizations + override fun getIdealDimensionRatioString(): String? = null + + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP) + + //endregion + + //region Hooks + + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val boolean: Boolean) : ModelState() + + /** + * Altitude widget state updated + */ + data class AltitudeStateUpdated(val altitudeState: AltitudeWidgetModel.AltitudeState) : ModelState() + } + + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/altitude/AltitudeWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/altitude/AltitudeWidgetModel.kt new file mode 100644 index 00000000..2be8081b --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/altitude/AltitudeWidgetModel.kt @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.altitude + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.key.KeyTools +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.GlobalPreferenceKeys +import dji.v5.ux.core.communication.GlobalPreferencesInterface +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.toDistance +import dji.v5.ux.core.util.DataProcessor +import dji.v5.ux.core.util.UnitConversionUtil.UnitType + +/** + * Widget Model for the [AMSLAltitudeWidget] and [AGLAltitudeWidget] used to define + * the underlying logic and communication. + */ +class AltitudeWidgetModel @JvmOverloads constructor( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, + private val preferencesManager: GlobalPreferencesInterface? +) : WidgetModel(djiSdkModel, keyedStore) { + + private val altitudeProcessor: DataProcessor = DataProcessor.create(0.0) + private val takeOffLocationAltitudeProcessor: DataProcessor = DataProcessor.create(0.0) + private val unitTypeDataProcessor: DataProcessor = DataProcessor.create(UnitType.METRIC) + private val altitudeStateProcessor: DataProcessor = DataProcessor.create(AltitudeState.ProductDisconnected) + + /** + * Value of the altitude state of the aircraft + */ + val altitudeState: Flowable + get() = altitudeStateProcessor.toFlowable() + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAltitude), altitudeProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyTakeoffLocationAltitude), takeOffLocationAltitudeProcessor) + bindDataProcessor(GlobalPreferenceKeys.create(GlobalPreferenceKeys.UNIT_TYPE), unitTypeDataProcessor) + preferencesManager?.setUpListener() + preferencesManager?.let { unitTypeDataProcessor.onNext(it.unitType) } + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + altitudeStateProcessor.onNext( + AltitudeState.CurrentAltitude( + altitudeAGL = altitudeProcessor.value.toDistance(unitTypeDataProcessor.value), + altitudeAMSL = (altitudeProcessor.value + takeOffLocationAltitudeProcessor.value) + .toDistance(unitTypeDataProcessor.value), + unitType = unitTypeDataProcessor.value)) + } else { + altitudeStateProcessor.onNext(AltitudeState.ProductDisconnected) + } + } + + override fun inCleanup() { + preferencesManager?.cleanup() + } + + /** + * Class to represent states of Altitude + */ + sealed class AltitudeState { + + /** + * When product is disconnected + */ + object ProductDisconnected : AltitudeState() + + /** + * When product is connected and altitude level is available + * + * @property altitudeAGL - Above Ground Level Altitude + * @property altitudeAMSL - Above Mean Sea Level Altitude + * @property unitType - Unit of altitude + */ + data class CurrentAltitude(val altitudeAGL: Double, + val altitudeAMSL: Double, + val unitType: UnitType) : AltitudeState() + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryAlertWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryAlertWidget.java new file mode 100644 index 00000000..547bb01c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryAlertWidget.java @@ -0,0 +1,159 @@ +package dji.v5.ux.core.widget.battery; + +import android.content.Context; +import android.text.SpannableStringBuilder; +import android.text.Spanned; +import android.text.style.ForegroundColorSpan; +import android.util.AttributeSet; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.Locale; + +import dji.v5.utils.common.AndUtil; +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.widget.BasicRangeSeekBar; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; + +public class BatteryAlertWidget extends ConstraintLayoutWidget implements BasicRangeSeekBar.OnRangeSeekBarListener { + + private static final String TAG = "BatteryAlertWidget"; + + private static final int GO_HOME_MAX = 50; + private static final int LANDING_MIN = 10; + private static final int LANDING_GAP = 5; + + protected BatteryAlertWidgetModel widgetModel = new BatteryAlertWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()); + protected TextView mTvSeriousLowBattery; + protected TextView mTvLowBattery; + protected BasicRangeSeekBar mBasicRangeSeekBar; + + protected int lowBatteryValue = -1; + protected int seriousLowBatteryValue = -1; + + public BatteryAlertWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public BatteryAlertWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public BatteryAlertWidget(@NonNull Context context) { + super(context); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_setting_menu_battery_controller_layout, this); + mTvSeriousLowBattery = findViewById(R.id.tv_serious_low_battery_title); + mTvLowBattery = findViewById(R.id.tv_low_battery_title); + mBasicRangeSeekBar = findViewById(R.id.checklist_item_range_seek_bar); + + mBasicRangeSeekBar.setRange(LANDING_MIN, GO_HOME_MAX, 1, LANDING_GAP); + mBasicRangeSeekBar.setListener(this); + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.getLowBatteryWarning().subscribe(value -> { + lowBatteryValue = value; + updateProgress(); + })); + + addReaction(widgetModel.getSeriousLowBatteryWarning().subscribe(integer -> { + seriousLowBatteryValue = integer; + updateProgress(); + })); + + addReaction(widgetModel.getConnection().subscribe(isConnected -> { + mBasicRangeSeekBar.setEnabled(isConnected); + if (Boolean.TRUE.equals(isConnected)) { + mTvLowBattery.setVisibility(View.VISIBLE); + mTvSeriousLowBattery.setVisibility(View.VISIBLE); + return; + } + mTvLowBattery.setVisibility(View.GONE); + mTvSeriousLowBattery.setVisibility(View.GONE); + lowBatteryValue = -1; + seriousLowBatteryValue = -1; + onValuesChanging(0.0f, 0.0f); + mBasicRangeSeekBar.setCurrentValues(LANDING_MIN, GO_HOME_MAX); + })); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + } + + @Override + public void onValuesChanging(float newSeriousLow, float newLow) { + String newSeriousLowText = String.format(Locale.getDefault(), "%02d%%", (int) newSeriousLow); + String newLowText = String.format(Locale.getDefault(), "%02d%%", (int) newLow); + + updateText(mTvSeriousLowBattery, R.string.uxsdk_checklist_manual_serious_low_battery_percent, newSeriousLowText, AndUtil.getResColor(R.color.uxsdk_red_in_dark)); + updateText(mTvLowBattery, R.string.uxsdk_checklist_manual_low_battery_percent, newLowText, AndUtil.getResColor(R.color.uxsdk_orange_in_dark)); + } + + @Override + public void onValuesChanged(float newSeriousLow, float newLow) { + if (lowBatteryValue != (int) newLow) { + addDisposable(widgetModel.changeLowBatteryWarning((int) newLow).subscribe(() -> { + + }, throwable -> { + LogUtils.e(TAG, "changeLowBatteryWarning fail: " + throwable); + updateProgress(); + })); + } + + if (seriousLowBatteryValue != (int) newSeriousLow) { + addDisposable(widgetModel.changeSeriousLowBatteryWarning((int) newSeriousLow).subscribe(() -> { + + }, throwable -> { + LogUtils.e(TAG, "changeSeriousLowBatteryWarning fail: " + throwable); + updateProgress(); + })); + } + } + + private void updateProgress() { + if (seriousLowBatteryValue <= 0 || lowBatteryValue <= 0 || !mBasicRangeSeekBar.isEnabled()) { + return; + } + + mBasicRangeSeekBar.setCurrentValues(seriousLowBatteryValue, lowBatteryValue); + onValuesChanging(seriousLowBatteryValue, lowBatteryValue); + + } + + private void updateText(TextView textView, int res, String value, int valueColor) { + String rawText = AndUtil.getResString(res, value); + + SpannableStringBuilder spannableString = new SpannableStringBuilder(rawText); + ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(valueColor); + int start = rawText.indexOf(value); + int end = start + value.length(); + spannableString.setSpan(foregroundColorSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); + textView.setText(spannableString); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryAlertWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryAlertWidgetModel.java new file mode 100644 index 00000000..f1b1244b --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryAlertWidgetModel.java @@ -0,0 +1,58 @@ +package dji.v5.ux.core.widget.battery; + +import androidx.annotation.NonNull; + +import dji.sdk.keyvalue.key.FlightControllerKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; + +public class BatteryAlertWidgetModel extends WidgetModel { + + private final DataProcessor lowBatteryWarningProcessor = DataProcessor.create(0); + private final DataProcessor seriousLowBatteryWarningProcessor = DataProcessor.create(0); + private final DataProcessor connectionProcessor = DataProcessor.create(false); + + protected BatteryAlertWidgetModel( + @NonNull DJISDKModel djiSdkModel, + @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + } + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyLowBatteryWarningThreshold), lowBatteryWarningProcessor); + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeySeriousLowBatteryWarningThreshold), seriousLowBatteryWarningProcessor); + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyConnection), connectionProcessor); + + } + + @Override + protected void inCleanup() { + // do noting + } + + public Completable changeLowBatteryWarning(int value) { + return djiSdkModel.setValue(KeyTools.createKey(FlightControllerKey.KeyLowBatteryWarningThreshold), value); + } + + public Completable changeSeriousLowBatteryWarning(int value) { + return djiSdkModel.setValue(KeyTools.createKey(FlightControllerKey.KeySeriousLowBatteryWarningThreshold), value); + } + + public Flowable getLowBatteryWarning() { + return lowBatteryWarningProcessor.toFlowableOnUI(); + } + + public Flowable getSeriousLowBatteryWarning() { + return seriousLowBatteryWarningProcessor.toFlowableOnUI(); + } + + public Flowable getConnection() { + return connectionProcessor.toFlowableOnUI(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryCellView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryCellView.java new file mode 100644 index 00000000..2d3cc7b0 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryCellView.java @@ -0,0 +1,65 @@ +package dji.v5.ux.core.widget.battery; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.ProgressBar; +import android.widget.RelativeLayout; +import android.widget.TextView; + + +import java.util.Locale; + +import dji.v5.ux.R; + + +public class BatteryCellView extends RelativeLayout { + + private static final float[] SECTION_PART_VOLTAGE = new float[]{ + 3.0f, 4.35f + }; + + ProgressBar batteryPartPgb; + TextView batteryVoltageTv; + + private float mCurrentVoltage; + + public BatteryCellView(Context context) { + this(context, null); + } + + public BatteryCellView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public BatteryCellView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + inflate(context, R.layout.uxsdk_view_battery_detail_cell, this); + batteryPartPgb = findViewById(R.id.battery_part_pgb); + batteryVoltageTv = findViewById(R.id.battery_part_tv); + } + + public void setVoltage(float voltage) { + if (mCurrentVoltage == voltage) { + return; + } + int progress = calculatePartVoltageProgress(voltage); + if (batteryPartPgb.getProgress() != progress) { + batteryPartPgb.setProgress(progress); + } + batteryVoltageTv.setText(String.format(Locale.getDefault(), "%.2fV", voltage)); + mCurrentVoltage = voltage; + } + + private int calculatePartVoltageProgress(final float voltage) { + int progress; + if (voltage >= SECTION_PART_VOLTAGE[1]) { + progress = 100; + } else if (voltage <= SECTION_PART_VOLTAGE[0]) { + progress = 0; + } else { + progress = (int) (((voltage - SECTION_PART_VOLTAGE[0]) * 100) / (SECTION_PART_VOLTAGE[1] - SECTION_PART_VOLTAGE[0])); + } + return progress; + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryConfig.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryConfig.kt new file mode 100644 index 00000000..0e4033fa --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryConfig.kt @@ -0,0 +1,21 @@ +package dji.v5.ux.core.widget.battery + +/** + * 电池配置 + */ +object BatteryConfig { + /** + * 高电位存储红色显示 + */ + const val HIGH_VOLTAGE_SAVE_DAYS_DANGER = 120 + + /** + * 高电位存储黄色显示 + */ + const val HIGH_VOLTAGE_SAVE_DAYS_WARN = 60 + + /** + * 高电位存储接口: 秒->天 + */ + const val SECONDS_IN_DAY = 24 * 60 * 60 +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryGroupInfoWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryGroupInfoWidget.java new file mode 100644 index 00000000..8f5f3f70 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryGroupInfoWidget.java @@ -0,0 +1,114 @@ +package dji.v5.ux.core.widget.battery; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import dji.sdk.keyvalue.value.battery.BatteryOverviewValue; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; + +public class BatteryGroupInfoWidget extends ConstraintLayoutWidget { + + + protected BatteryGroupInfoWidgetModel widgetModel = new BatteryGroupInfoWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + + protected BatteryGroupWidget batteryGroupWidget; + protected TextView batteryChargeRemaining; + protected TextView flightTime; + protected Button batteryDetail; + + protected boolean isConnected; + + + public BatteryGroupInfoWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public BatteryGroupInfoWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public BatteryGroupInfoWidget(@NonNull Context context) { + super(context); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_view_group_battery_info, this); + + batteryChargeRemaining = findViewById(R.id.setting_menu_battery_charge_remain); + flightTime = findViewById(R.id.setting_menu_battery_fly_time); + batteryDetail = findViewById(R.id.setting_menu_battery_info_detail_view); + batteryGroupWidget = findViewById(R.id.setting_menu_battery_group_view); + + setBackgroundResource(R.drawable.uxsdk_background_fpv_setting_battery_group); + + batteryGroupWidget.setEnableBatteryCells(false); + batteryGroupWidget.setEnableSerialNumber(false); + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.getBatteryChargeRemaining().subscribe(this::updateBatteryChargeRemaining)); + + addReaction(widgetModel.getFlightTimeInSeconds().subscribe(this::updateFlightTime)); + + addReaction(widgetModel.getConnection().subscribe(connection -> { + if (Boolean.compare(isConnected, connection) == 0) { + return; + } + isConnected = connection; + if (!isConnected) { + widgetModel.reset(); + } + })); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + } + + private void updateFlightTime(int time) { + // 除以10才是正确的值 + time /= 10; + int seconds = time % 60; + int minute = time / 60; + String data = String.format(Locale.getDefault(), "%1$02d:%2$02d", minute, seconds); + flightTime.setText(data); + } + + private void updateBatteryChargeRemaining(int percent) { + batteryChargeRemaining.setText(getResources().getString(R.string.uxsdk_battery_percent, percent)); + } + + public void setOnDetailOnClickListener(@Nullable OnClickListener listener) { + batteryDetail.setVisibility(listener == null ? GONE : VISIBLE); + batteryDetail.setOnClickListener(listener); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryGroupInfoWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryGroupInfoWidgetModel.java new file mode 100644 index 00000000..b9d8b3f1 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryGroupInfoWidgetModel.java @@ -0,0 +1,89 @@ +package dji.v5.ux.core.widget.battery; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import androidx.annotation.NonNull; +import dji.sdk.keyvalue.key.BatteryKey; +import dji.sdk.keyvalue.key.FlightControllerKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.key.ProductKey; +import dji.sdk.keyvalue.utils.ProductUtil; +import dji.sdk.keyvalue.value.battery.BatteryOverviewValue; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.sdk.keyvalue.value.product.ProductType; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Flowable; + +public class BatteryGroupInfoWidgetModel extends WidgetModel { + + private final DataProcessor batteryChargeRemainingProcessorForConsume = DataProcessor.create(0); + private final DataProcessor batteryChargeRemainingProcessor = DataProcessor.create(0); + private final DataProcessor> batteryOverviewProcessor = DataProcessor.create(new ArrayList<>()); + private final DataProcessor flightTimeInSecondsProcessor = DataProcessor.create(0); + private final DataProcessor connectionProcessor = DataProcessor.create(false); + private final DataProcessor productTypeProcessor = DataProcessor.create(ProductType.UNKNOWN); + + public BatteryGroupInfoWidgetModel( + @NonNull DJISDKModel djiSdkModel, + @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + } + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createKey(BatteryKey.KeyChargeRemainingInPercent, ComponentIndexType.AGGREGATION), batteryChargeRemainingProcessor); + bindDataProcessor(KeyTools.createKey(BatteryKey.KeyBatteryOverviews, ComponentIndexType.AGGREGATION), batteryOverviewProcessor); + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyFlightTimeInSeconds), flightTimeInSecondsProcessor); + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyConnection), connectionProcessor); + + bindDataProcessor(KeyTools.createKey(ProductKey.KeyProductType), productTypeProcessor, productType -> { + if (ProductUtil.isConsumeMachine()){ + batteryOverviewProcessor.onNext(Collections.singletonList(new BatteryOverviewValue( + ComponentIndexType.LEFT_OR_MAIN.value(), + true, + 0, + 0, + 0 + ))); + } + }); + bindDataProcessor(KeyTools.createKey(BatteryKey.KeyChargeRemainingInPercent, ComponentIndexType.LEFT_OR_MAIN), batteryChargeRemainingProcessorForConsume, integer -> { + if (ProductUtil.isConsumeMachine()){ + batteryChargeRemainingProcessor.onNext(integer); + } + }); + } + + @Override + protected void inCleanup() { + //do noting + } + + public void reset() { + batteryChargeRemainingProcessor.onNext(0); + batteryOverviewProcessor.onNext(new ArrayList<>()); + flightTimeInSecondsProcessor.onNext(0); + connectionProcessor.onNext(false); + } + + public Flowable getBatteryChargeRemaining() { + return batteryChargeRemainingProcessor.toFlowableOnUI(); + } + + public Flowable> getBatteryOverview() { + return batteryOverviewProcessor.toFlowableOnUI(); + } + + public Flowable getFlightTimeInSeconds() { + return flightTimeInSecondsProcessor.toFlowableOnUI(); + } + + public Flowable getConnection() { + return connectionProcessor.toFlowableOnUI(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryGroupWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryGroupWidget.java new file mode 100644 index 00000000..8351b80d --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryGroupWidget.java @@ -0,0 +1,138 @@ +package dji.v5.ux.core.widget.battery; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; + +import dji.sdk.keyvalue.value.battery.BatteryOverviewValue; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.base.widget.FrameLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; + +public class BatteryGroupWidget extends FrameLayoutWidget { + + protected BatteryGroupInfoWidgetModel widgetModel = new BatteryGroupInfoWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + + protected ViewGroup container; + + protected boolean isConnected = false; + protected boolean isEnableBatteryCells = true; + protected boolean isEnableSerialNumber = true; + + + public BatteryGroupWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public BatteryGroupWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public BatteryGroupWidget(@NonNull Context context) { + super(context); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_view_group_battery, this); + + container = findViewById(R.id.setting_menu_battery_info_view_layout); + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.getBatteryOverview().subscribe(this::updateBatteryWidget)); + + addReaction(widgetModel.getConnection().subscribe(connection -> { + if (Boolean.compare(isConnected, connection) == 0) { + return; + } + isConnected = connection; + if (!isConnected) { + widgetModel.reset(); + } + })); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + } + + private void updateBatteryWidget(List batteryOverviewList) { + List availableList = new ArrayList<>(); + for (BatteryOverviewValue value : batteryOverviewList) { + if (value.getIsConnected().equals(true)) { + availableList.add(value); + } + } + int childCount = container.getChildCount(); + int newCount = availableList.size(); + if (childCount < newCount) { + for (int i = childCount; i < newCount; i++) { + BatteryInfoWidget view = new BatteryInfoWidget(getContext()); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT); + params.topMargin = getResources().getDimensionPixelSize(R.dimen.uxsdk_15_dp); + container.addView(view, params); + view.setEnableSerialNumber(isEnableSerialNumber); + view.setEnableBatteryCells(isEnableBatteryCells); + } + } else if (childCount > newCount) { + for (int i = childCount - 1; i >= newCount; i--) { + container.removeViewAt(i); + } + } + + for (int i = 0; i < container.getChildCount(); i++) { + BatteryInfoWidget view = (BatteryInfoWidget) container.getChildAt(i); + view.setBatteryIndex(availableList.get(i).getIndex()); + } + + } + + public void setEnableBatteryCells(boolean isEnable) { + this.isEnableBatteryCells = isEnable; + updateBatteryInfoWidget(); + } + + public void setEnableSerialNumber(boolean isEnable) { + this.isEnableSerialNumber = isEnable; + updateBatteryInfoWidget(); + } + + private void updateBatteryInfoWidget() { + for (int i = 0; i < container.getChildCount(); i++) { + View childView = container.getChildAt(i); + if (childView instanceof BatteryInfoWidget) { + BatteryInfoWidget widget = (BatteryInfoWidget) childView; + widget.setEnableBatteryCells(isEnableBatteryCells); + widget.setEnableSerialNumber(isEnableSerialNumber); + } + } + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryInfoWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryInfoWidget.java new file mode 100644 index 00000000..0669faf1 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryInfoWidget.java @@ -0,0 +1,434 @@ +package dji.v5.ux.core.widget.battery; + + +import android.content.Context; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.LinearLayout; +import android.widget.TextView; + +import androidx.annotation.IntDef; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.constraintlayout.widget.Group; +import androidx.core.content.ContextCompat; + + +import java.util.List; +import java.util.Locale; + +import dji.sdk.keyvalue.utils.ProductUtil; +import dji.sdk.keyvalue.value.battery.BatteryConnectionState; +import dji.sdk.keyvalue.value.battery.BatteryException; +import dji.sdk.keyvalue.value.battery.BatteryOverviewValue; +import dji.sdk.keyvalue.value.battery.BatterySelfCheckState; +import dji.sdk.keyvalue.value.battery.IndustryBatteryType; +import dji.v5.common.utils.UnitUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.popover.Popover; + +public class BatteryInfoWidget extends ConstraintLayoutWidget { + + private static final String SEPARATOR = ","; + + @IntDef + public @interface Temperature { + int TEMPERATURE_FAHRENHEIT = 0; // 华氏度 + int TEMPERATURE_CELSIUS = 1; // 摄氏度 + int TEMPERATURE_KELVIN = 2; // 开氏度 + } + + protected BatteryInfoWidgetModel widgetModel = new BatteryInfoWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + + protected TextView batteryHighVoltageSave; + protected ImageView batteryHighVoltageHint; + protected TextView batteryCycleTime; + protected TextView batteryVoltage; + protected TextView batteryTemperature; + protected TextView batteryChargeRemaining; + protected TextView batteryStatus; + protected TextView battery; + protected TextView serialNumber; + protected TextView productionDate; + protected ViewGroup cellsLayout; + protected ViewGroup batteryBottomLayout; + protected Group highVoltage; + + protected int temperatureType = Temperature.TEMPERATURE_CELSIUS; + protected float temperatureValue = 0.0f; + protected boolean supportHighVoltageHint = false; + protected boolean isConnected; + + protected int batteryCount; + protected IndustryBatteryType batteryType; + protected BatteryConnectionState batteryConnectionState; + protected BatteryException warningRecord; + + public BatteryInfoWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public BatteryInfoWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public BatteryInfoWidget(@NonNull Context context) { + super(context); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_view_battery_info, this); + + batteryHighVoltageSave = findViewById(R.id.setting_menu_battery_high_voltage_save_value_tv); + batteryHighVoltageHint = findViewById(R.id.icon_high_voltage); + batteryCycleTime = findViewById(R.id.setting_menu_battery_cycle_time_value_tv); + batteryVoltage = findViewById(R.id.setting_menu_battery_voltage_value_tv); + batteryTemperature = findViewById(R.id.setting_menu_battery_temperature_value_tv); + batteryChargeRemaining = findViewById(R.id.setting_menu_battery_charge_remain_value_tv); + batteryStatus = findViewById(R.id.setting_menu_battery_status); + battery = findViewById(R.id.setting_menu_battery_tv); + serialNumber = findViewById(R.id.setting_menu_battery_sn); + productionDate = findViewById(R.id.setting_menu_battery_production_date); + highVoltage = findViewById(R.id.group_high_voltage); + cellsLayout = findViewById(R.id.setting_menu_battery_cells_view_stub); + batteryBottomLayout = findViewById(R.id.setting_menu_battery_bottom_view); + + setBackgroundResource(R.drawable.uxsdk_background_fpv_setting); + showHighVoltage(supportHighVoltage()); + batteryHighVoltageHint.setOnClickListener(v -> { + int[] outLocation = new int[2]; + batteryHighVoltageHint.getLocationOnScreen(outLocation); + int heightPixels = getResources().getDisplayMetrics().heightPixels; + Popover.Position pos = outLocation[1] > heightPixels / 2 ? Popover.Position.TOP : Popover.Position.BOTTOM; + int color = ContextCompat.getColor(getContext(), R.color.uxsdk_fpv_popover_content_background_color); + new Popover.Builder(batteryHighVoltageHint) + .content(supportHighVoltageHint ? R.string.uxsdk_hms_carepage_maintenance_highvoltage_info : R.string.uxsdk_hms_carepage_maintenance_highvoltage_need_upgrade_info) + .textColor(R.color.uxsdk_white) + .showArrow(true) + .arrowColor(color) + .size(getResources().getDimensionPixelSize(R.dimen.uxsdk_240_dp), ViewGroup.LayoutParams.WRAP_CONTENT) + .allScreenMargin(getResources().getDimensionPixelSize(R.dimen.uxsdk_8_dp)) + .backgroundColor(color) + .position(pos) + .focusable(false) + .align(Popover.Align.CENTER) + .build() + .show(); + }); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel + .getBatteryException() + .subscribe(e -> { + warningRecord = e; + updateStatus(); + })); + + addReaction(widgetModel + .getBatteryTemperature() + .subscribe(temperature -> { + temperatureValue = temperature.floatValue(); + updateTemperature(); + })); + + addReaction(widgetModel + .getBatteryConnection() + .subscribe(this::updateConnectionState)); + + addReaction(widgetModel + .getBatteryIsCommunicationException() + .subscribe(batteryConnectionStateMsg -> { + batteryConnectionState = batteryConnectionStateMsg.getState(); + updateStatus(); + })); + + addReaction(widgetModel + .getBatteryBatteryHighVoltageStorageSec() + .subscribe(this::updateBatteryBatteryHighVoltageStorage)); + + addReaction(widgetModel + .getBatterySerialNumber() + .subscribe(this::updateSerialNumber)); + + addReaction(widgetModel + .getBatteryManufacturedDate() + .subscribe(date -> { + String text = getContext().getString(R.string.uxsdk_setting_ui_battery_product_date) + date.getYear() + "-" + (date.getMonth()); + productionDate.setText(text); + })); + + addReaction(widgetModel + .getBatteryCellVoltages() + .subscribe(this::updateBatteryCells)); + + addReaction(widgetModel + .getBatteryVoltage() + .subscribe(voltage -> batteryVoltage.setText(String.format(Locale.getDefault(), "%.2fV", voltage / 1000.0f)))); + + addReaction(widgetModel + .getBatteryChargeRemaining() + .subscribe(percent -> batteryChargeRemaining.setText(getContext().getString(R.string.uxsdk_battery_percent, percent)))); + + addReaction(widgetModel + .getProductType() + .subscribe(product -> showHighVoltage(supportHighVoltage()))); + + addReaction(widgetModel + .getBatteryNumberOfDischarges() + .subscribe(number -> batteryCycleTime.setText(String.valueOf(number)))); + + addReaction(widgetModel + .getBatteryIndustryBatteryType() + .subscribe(type -> { + batteryType = type; + showHighVoltage(supportHighVoltage()); + updateBatteryTitle(); + })); + + addReaction(widgetModel + .getBatteryOverview() + .subscribe(this::updateBatteryOverview)); + } + + private void showHighVoltage(boolean show) { + int v = show ? VISIBLE : GONE; + highVoltage.setVisibility(v); + } + + private void updateBatteryOverview(List overviewValueList) { + batteryCount = overviewValueList.size(); + updateBatteryTitle(); + } + + private void updateConnectionState(boolean connection) { + if (isConnected == connection) { + return; + } + isConnected = connection; + if (!connection) { + widgetModel.reset(); + supportHighVoltageHint = false; + batteryHighVoltageSave.setText(R.string.uxsdk_not_a_num); + batteryHighVoltageSave.setTextColor(ContextCompat.getColor(getContext(), R.color.uxsdk_white)); + } + + } + + private void updateSerialNumber(String serial) { + String text = getContext().getString(R.string.uxsdk_setting_ui_battery_serial_number); + if (serial != null) { + text += serial; + } + serialNumber.setText(text); + } + + + private void updateBatteryBatteryHighVoltageStorage(long result) { + if (result > 0) { + long sec = result; + long days = (sec + BatteryConfig.SECONDS_IN_DAY / 2) / BatteryConfig.SECONDS_IN_DAY; + int colorRes; + if (days >= BatteryConfig.HIGH_VOLTAGE_SAVE_DAYS_DANGER) { + colorRes = R.color.uxsdk_tips_danger_in_dark; + } else if (days >= BatteryConfig.HIGH_VOLTAGE_SAVE_DAYS_WARN) { + colorRes = R.color.uxsdk_warning_state_color; + } else { + colorRes = R.color.uxsdk_white; + } + supportHighVoltageHint = true; + batteryHighVoltageSave.setTextColor(ContextCompat.getColor(getContext(), colorRes)); + batteryHighVoltageSave.setText(String.format(getResources().getString(R.string.uxsdk_setting_ui_battery_discharge_day), days)); + } else { + supportHighVoltageHint = false; + batteryHighVoltageSave.setText(R.string.uxsdk_not_a_num); + batteryHighVoltageSave.setTextColor(ContextCompat.getColor(getContext(), R.color.uxsdk_white)); + } + } + + private void updateStatus() { + String text = getContext().getString(R.string.uxsdk_setting_ui_battery_history_normal_status); + int textColor = ContextCompat.getColor(getContext(), R.color.uxsdk_setting_ui_battery_green); + + if (batteryConnectionState != null && batteryConnectionState != BatteryConnectionState.NORMAL) { + if (batteryConnectionState == BatteryConnectionState.INVALID) { + text = getContext().getString(R.string.uxsdk_setting_ui_battery_history_invalid_status); + } else { + text = getContext().getString(R.string.uxsdk_setting_ui_battery_history_exception_status); + } + textColor = ContextCompat.getColor(getContext(), R.color.uxsdk_setting_ui_battery_red); + } else { + String warning = getWarning(); + if (!TextUtils.isEmpty(warning)) { + text = warning; + textColor = ContextCompat.getColor(getContext(), R.color.uxsdk_setting_ui_battery_red); + } + } + + batteryStatus.setText(text); + batteryStatus.setTextColor(textColor); + } + + private String getWarning() { + if (warningRecord == null) { + return ""; + } + final StringBuilder sb = new StringBuilder(); + if (warningRecord.getFirstLevelOverCurrent() || warningRecord.getSecondLevelOverCurrent()) { + appendWarningContent(sb, getContext().getString(R.string.uxsdk_setting_ui_battery_history_firstlevel_current)); + } + if (warningRecord.getFirstLevelOverHeating() || warningRecord.getSecondLevelOverHeating()) { + appendWarningContent(sb, getContext().getString(R.string.uxsdk_setting_ui_battery_history_firstlevel_over_temperature)); + } + if (warningRecord.getFirstLevelLowTemperature() || warningRecord.getSecondLevelLowTemperature()) { + sb.append(getContext().getString(R.string.uxsdk_setting_ui_battery_history_firstlevel_low_temperature)); + } + if (Boolean.TRUE.equals(warningRecord.getShortCircuited())) { + appendWarningContent(sb, getContext().getString(R.string.uxsdk_setting_ui_battery_history_short_circuit)); + } + if (warningRecord.getLowVoltageCellIndex() > 0) { + appendWarningContent(sb, getContext().getString(R.string.uxsdk_setting_ui_battery_history_under_voltage)); + } + if (warningRecord.getBrokenCellIndex() > 0) { + appendWarningContent(sb, getContext().getString(R.string.uxsdk_setting_ui_battery_history_invalid)); + } + if (warningRecord.getSelfCheckState() != BatterySelfCheckState.NORMAL && warningRecord.getSelfCheckState() != BatterySelfCheckState.UNKNOWN) { + appendWarningContent(sb, getContext().getString(R.string.uxsdk_setting_ui_battery_history_discharge)); + } + return sb.toString(); + } + + private void appendWarningContent(StringBuilder builder, String content) { + if (builder.length() > 0) { + builder.append(SEPARATOR); + } + builder.append(content); + } + + private void updateBatteryTitle() { + if (batteryType == null || batteryCount <= 0) { + return; + } + + String title; + int batteryIndex = widgetModel.getBatteryIndex(); + switch (batteryCount) { + case 1: + title = getResources().getString(R.string.uxsdk_setting_ui_general_battery); + break; + case 2: + if (batteryIndex == 0) { + title = getResources().getString(R.string.uxsdk_fpv_top_bar_battery_left_battery); + } else { + title = getResources().getString(R.string.uxsdk_fpv_top_bar_battery_right_battery); + } + break; + default: + title = getResources().getString(R.string.uxsdk_setting_ui_general_battery) + " " + (batteryIndex + 1); + } + String typeName; + switch (batteryType) { + case TB60: + typeName = "(TB60)"; + break; + case TB65: + typeName = "(TB65)"; + break; + default: + typeName = ""; + break; + } + battery.setText(String.format(Locale.getDefault(), "%s%s", title, typeName)); + } + + private void updateTemperature() { + String unit; + float value; + if (Temperature.TEMPERATURE_FAHRENHEIT == temperatureType) { + unit = getResources().getString(R.string.uxsdk_fahrenheit); + value = UnitUtils.celsiusToFahrenheit(temperatureValue); + } else if (Temperature.TEMPERATURE_KELVIN == temperatureType) { + unit = getResources().getString(R.string.uxsdk_kelvins); + value = UnitUtils.celsiusToKelvin(temperatureValue); + } else { + value = temperatureValue; + unit = getResources().getString(R.string.uxsdk_celsius); + } + batteryTemperature.setText(String.format(Locale.getDefault(), "%.1f%s", value, unit)); + } + + private void updateBatteryCells(List cellVoltages) { + if (cellVoltages == null || cellVoltages.isEmpty()) { + cellsLayout.removeAllViews(); + return; + } + int cellNumber = cellVoltages.size(); + int childCount = cellsLayout.getChildCount(); + if (childCount < cellNumber) { + for (int i = childCount; i <= cellNumber; i++) { + BatteryCellView cellView = new BatteryCellView(getContext()); + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); + params.weight = 1; + cellsLayout.addView(cellView, params); + } + } + for (int i = 0; i < cellsLayout.getChildCount(); i++) { + BatteryCellView cellView = (BatteryCellView) cellsLayout.getChildAt(i); + if (i < cellNumber) { + cellView.setVisibility(VISIBLE); + } else { + cellView.setVisibility(GONE); + continue; + } + cellView.setVoltage(1f * cellVoltages.get(i) / 1000); + } + } + + public void setEnableBatteryCells(boolean isEnable) { + cellsLayout.setVisibility(isEnable ? VISIBLE : GONE); + } + + public void setEnableSerialNumber(boolean isEnable) { + batteryBottomLayout.setVisibility(isEnable ? VISIBLE : GONE); + } + + /** + * 是否支持高压存储,M350新电池、M30新版本电池 + */ + private boolean supportHighVoltage() { + return ProductUtil.isM30Product() || batteryType == IndustryBatteryType.TB65; + } + + + public void setBatteryIndex(int index) { + widgetModel.setBatteryIndex(index); + } + + public void setTemperatureType(@Temperature int temperatureType) { + this.temperatureType = temperatureType; + updateTemperature(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryInfoWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryInfoWidgetModel.kt new file mode 100644 index 00000000..359128d1 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryInfoWidgetModel.kt @@ -0,0 +1,148 @@ +package dji.v5.ux.core.widget.battery + +import dji.sdk.keyvalue.key.BatteryKey +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.key.ProductKey +import dji.sdk.keyvalue.value.battery.BatteryConnectionStateMsg +import dji.sdk.keyvalue.value.battery.BatteryException +import dji.sdk.keyvalue.value.battery.BatteryOverviewValue +import dji.sdk.keyvalue.value.battery.IndustryBatteryType +import dji.sdk.keyvalue.value.common.ComponentIndexType +import dji.sdk.keyvalue.value.common.Date +import dji.sdk.keyvalue.value.product.ProductType +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Flowable + +class BatteryInfoWidgetModel( + djiSdkModel: DJISDKModel, uxKeyManager: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, uxKeyManager) { + + private var batteryIndex = 0 + private val batteryExceptionProcessor = DataProcessor.create(BatteryException()) + private val batteryTemperatureProcessor = DataProcessor.create(0.0) + private val batteryVoltageProcessor = DataProcessor.create(0) + private val batteryChargeRemainingProcessor = DataProcessor.create(0) + private val batteryConnectionProcessor = DataProcessor.create(false) + private val batteryIsCommunicationExceptionProcessor = DataProcessor.create(BatteryConnectionStateMsg()) + private val batteryNumberOfDischargesProcessor = DataProcessor.create(0) + private val batteryIndustryBatteryTypeProcessor = DataProcessor.create(IndustryBatteryType.UNKNOWN) + private val batteryBatteryHighVoltageStorageSecProcessor = DataProcessor.create(0L) + private val batterySerialNumberProcessor = DataProcessor.create("") + private val batteryManufacturedDateProcessor = DataProcessor.create(Date()) + private val batteryCellVoltagesProcessor = DataProcessor.create>(ArrayList()) + private val batteryOverviewProcessor = DataProcessor.create>(ArrayList()) + private val productTypeProcessor = DataProcessor.create(ProductType.UNKNOWN) + + val batteryException: Flowable + get() = batteryExceptionProcessor.toFlowableOnUI() + val batteryTemperature: Flowable + get() = batteryTemperatureProcessor.toFlowableOnUI() + val batteryVoltage: Flowable + get() = batteryVoltageProcessor.toFlowableOnUI() + val batteryChargeRemaining: Flowable + get() = batteryChargeRemainingProcessor.toFlowableOnUI() + val batteryConnection: Flowable + get() = batteryConnectionProcessor.toFlowableOnUI() + val batteryIsCommunicationException: Flowable + get() = batteryIsCommunicationExceptionProcessor.toFlowableOnUI() + val batteryNumberOfDischarges: Flowable + get() = batteryNumberOfDischargesProcessor.toFlowableOnUI() + val batteryIndustryBatteryType: Flowable + get() = batteryIndustryBatteryTypeProcessor.toFlowableOnUI() + val batteryBatteryHighVoltageStorageSec: Flowable + get() = batteryBatteryHighVoltageStorageSecProcessor.toFlowableOnUI() + val batterySerialNumber: Flowable + get() = batterySerialNumberProcessor.toFlowableOnUI() + val batteryManufacturedDate: Flowable + get() = batteryManufacturedDateProcessor.toFlowableOnUI() + val batteryCellVoltages: Flowable> + get() = batteryCellVoltagesProcessor.toFlowableOnUI() + val batteryOverview: Flowable> + get() = batteryOverviewProcessor.toFlowableOnUI() + val productType: Flowable + get() = productTypeProcessor.toFlowableOnUI() + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyBatteryException, batteryIndex), batteryExceptionProcessor) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyBatteryTemperature, batteryIndex), batteryTemperatureProcessor) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyVoltage, batteryIndex), batteryVoltageProcessor) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyChargeRemainingInPercent, batteryIndex), batteryChargeRemainingProcessor) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyConnection, batteryIndex), batteryConnectionProcessor) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyIsCommunicationException, batteryIndex), batteryIsCommunicationExceptionProcessor) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyNumberOfDischarges, batteryIndex), batteryNumberOfDischargesProcessor) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyIndustryBatteryType, batteryIndex), batteryIndustryBatteryTypeProcessor) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyBatteryHighVoltageStorageTime, batteryIndex), batteryBatteryHighVoltageStorageSecProcessor) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeySerialNumber, batteryIndex), batterySerialNumberProcessor) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyBatteryManufacturedDate, batteryIndex), batteryManufacturedDateProcessor) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyCellVoltages, batteryIndex), batteryCellVoltagesProcessor) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyBatteryOverviews, ComponentIndexType.AGGREGATION), batteryOverviewProcessor) + bindDataProcessor( + KeyTools.createKey( + ProductKey.KeyProductType), productTypeProcessor) + } + + override fun inCleanup() { + // do noting + } + fun setBatteryIndex(batteryIndex: Int) { + if (this.batteryIndex != batteryIndex) { + this.batteryIndex = batteryIndex + reset() + restart() + } + } + + fun reset() { + batteryExceptionProcessor.onNext(BatteryException()) + batteryTemperatureProcessor.onNext(0.0) + batteryVoltageProcessor.onNext(0) + batteryChargeRemainingProcessor.onNext(0) + batteryConnectionProcessor.onNext(false) + batteryIsCommunicationExceptionProcessor.onNext(BatteryConnectionStateMsg()) + batteryNumberOfDischargesProcessor.onNext(0) + batteryIndustryBatteryTypeProcessor.onNext(IndustryBatteryType.UNKNOWN) + batteryBatteryHighVoltageStorageSecProcessor.onNext(0L) + batterySerialNumberProcessor.onNext("") + batteryManufacturedDateProcessor.onNext(Date()) + batteryCellVoltagesProcessor.onNext(ArrayList()) + batteryOverviewProcessor.onNext(ArrayList()) + restart() + } + + public override fun restart() { + super.restart() + } + + fun getBatteryIndex(): Int { + return batteryIndex + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryResourceUtil.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryResourceUtil.kt new file mode 100644 index 00000000..0d2fa44e --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryResourceUtil.kt @@ -0,0 +1,45 @@ +package dji.v5.ux.core.widget.battery + +import dji.sdk.keyvalue.key.BatteryKey +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.value.battery.IndustryBatteryType +import dji.sdk.keyvalue.value.common.ComponentIndexType +import dji.v5.manager.KeyManager +import dji.v5.utils.common.AndUtil +import dji.v5.ux.R + +object BatteryResourceUtil { + + + /** + * 获取电池的标题 + * 如果是一个电池的飞机,返回`电池` + * 如果是两个电池的飞机,返回的是`左电池`或者`右电池` + * 否则返回电池1、电池2、电池3 + */ + fun getBatteryTitle(index: Int): String { + val batteryOverview = KeyManager.getInstance().getValue( + KeyTools.createKey(BatteryKey.KeyBatteryOverviews, ComponentIndexType.AGGREGATION)) + return when (batteryOverview?.size) { + 1 -> AndUtil.getResString(R.string.uxsdk_setting_ui_general_battery) + 2 -> if (index == 0) { + AndUtil.getResString(R.string.uxsdk_fpv_top_bar_battery_left_battery) + } else { + AndUtil.getResString(R.string.uxsdk_fpv_top_bar_battery_right_battery) + } + + else -> AndUtil.getResString(R.string.uxsdk_setting_ui_general_battery) + .toString() + " " + (index + 1) + + } + } + + + fun IndustryBatteryType.productName(): String { + return when (this) { + IndustryBatteryType.TB60 -> "TB60" + IndustryBatteryType.TB65 -> "TB65" + else -> "" + } + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatterySettingWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatterySettingWidget.java new file mode 100644 index 00000000..39ec90ae --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatterySettingWidget.java @@ -0,0 +1,43 @@ +package dji.v5.ux.core.widget.battery; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.v5.ux.R; +import dji.v5.ux.core.base.widget.FrameLayoutWidget; + +public class BatterySettingWidget extends FrameLayoutWidget { + private BatteryGroupInfoWidget batteryGroupInfoWidget; + + public BatterySettingWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public BatterySettingWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public BatterySettingWidget(@NonNull Context context) { + super(context); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + View view = inflate(context, R.layout.uxsdk_setting_battery_widget, this); + batteryGroupInfoWidget = view.findViewById(R.id.setting_menu_battery_group); + } + + @Override + protected void reactToModelChanges() { + //Do NothingBasicRangeSeekBarWidget + } + + public BatteryGroupInfoWidget getBatteryGroupInfoWidget() { + return batteryGroupInfoWidget; + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryVerticalProgressBar.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryVerticalProgressBar.java new file mode 100644 index 00000000..61c67f2d --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryVerticalProgressBar.java @@ -0,0 +1,59 @@ +/** + * @filename : DJIVerticalProgressBar.java + * @package : dji.pilot.publics.widget + * @date : 2014年8月11日 上午11:47:16 + * @author : gashion.fang + * @description : + * + * Copyright (c) 2014, DJI All Rights Reserved. + * + */ + +package dji.v5.ux.core.widget.battery; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.widget.ProgressBar; + +public class BatteryVerticalProgressBar extends ProgressBar{ + + private int mH = 0; + private int mW = 0; + private int mOldH = 0; + private int mOldW = 0; + + public BatteryVerticalProgressBar(Context context, AttributeSet attrs) { + super(context, attrs); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(h, w, oldh, oldw); + mH = h; + mW = w; + mOldH = oldh; + mOldW = oldw; + } + + @Override + public void setProgressDrawable(Drawable d) { + super.setProgressDrawable(d); + onSizeChanged(mW, mH, mOldW, mOldH); + } + + @Override + public synchronized void setProgress(int progress) { + super.setProgress(progress); + onSizeChanged(mW, mH, mOldW, mOldH); + } + + @Override + protected synchronized void onDraw(Canvas c) { + c.rotate(-90); + c.translate(-getHeight(), 0); + super.onDraw(c); + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryWidget.kt new file mode 100644 index 00000000..353ced82 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryWidget.kt @@ -0,0 +1,729 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.battery + +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.PorterDuff +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.View +import android.widget.ImageView +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.annotation.Dimension +import androidx.annotation.DrawableRes +import androidx.annotation.StyleRes +import androidx.constraintlayout.widget.ConstraintSet +import androidx.core.content.res.use +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.SchedulerProvider +import io.reactivex.rxjava3.functions.Consumer +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.util.UxErrorHandle +import dji.v5.ux.core.widget.battery.BatteryWidget.ModelState +import dji.v5.ux.core.widget.battery.BatteryWidget.ModelState.BatteryStateUpdated +import dji.v5.ux.core.widget.battery.BatteryWidget.ModelState.ProductConnected +import dji.v5.ux.core.widget.battery.BatteryWidgetModel.BatteryState +import dji.v5.ux.core.widget.battery.BatteryWidgetModel.BatteryStatus + +/** + * Battery Widget + * Widget represents the current state of the aircraft battery. + * Defaults to showing the aggregate battery percentage for the aircraft unless a dual battery + * is detected or the user overrides this configuration. + */ +open class BatteryWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ConstraintLayoutWidget(context, attrs, defStyleAttr) { + + //region Fields + private val widgetModel by lazy { + BatteryWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()) + } + + private var singleIconDimensionRatio = getString(R.string.uxsdk_icon_single_battery_ratio) + private var dualIconDimensionRatio = getString(R.string.uxsdk_icon_dual_battery_ratio) + + + private val batteryIconImageView: ImageView = findViewById(R.id.imageview_battery_icon) + private val singleBatteryValueTextView: TextView = findViewById(R.id.textview_battery_value) + private val dualBattery1ValueTextView: TextView = findViewById(R.id.textview_battery1_value) + private val dualBattery2ValueTextView: TextView = findViewById(R.id.textview_battery2_value) + private val dualBattery1VoltageTextView: TextView = findViewById(R.id.textview_battery1_voltage) + private val dualBattery2VoltageTextView: TextView = findViewById(R.id.textview_battery2_voltage) + private var percentColorStates: MutableMap = mutableMapOf( + BatteryStatus.NORMAL to ColorStateList.valueOf(getColor(R.color.uxsdk_battery_healthy)), + BatteryStatus.UNKNOWN to ColorStateList.valueOf(getColor(R.color.uxsdk_battery_healthy)), + BatteryStatus.OVERHEATING to ColorStateList.valueOf(getColor(R.color.uxsdk_battery_overheating)), + BatteryStatus.WARNING_LEVEL_1 to ColorStateList.valueOf(getColor(R.color.uxsdk_battery_danger)), + BatteryStatus.WARNING_LEVEL_2 to ColorStateList.valueOf(getColor(R.color.uxsdk_battery_danger)), + BatteryStatus.ERROR to ColorStateList.valueOf(getColor(R.color.uxsdk_battery_danger)) + ) + private var voltageColorStates: MutableMap = mutableMapOf( + BatteryStatus.NORMAL to ColorStateList.valueOf(getColor(R.color.uxsdk_battery_healthy)), + BatteryStatus.UNKNOWN to ColorStateList.valueOf(getColor(R.color.uxsdk_battery_healthy)), + BatteryStatus.OVERHEATING to ColorStateList.valueOf(getColor(R.color.uxsdk_battery_overheating)), + BatteryStatus.WARNING_LEVEL_1 to ColorStateList.valueOf(getColor(R.color.uxsdk_battery_danger)), + BatteryStatus.WARNING_LEVEL_2 to ColorStateList.valueOf(getColor(R.color.uxsdk_battery_danger)), + BatteryStatus.ERROR to ColorStateList.valueOf(getColor(R.color.uxsdk_battery_danger)) + ) + + private var voltageBackgroundStates: MutableMap = mutableMapOf( + BatteryStatus.NORMAL to getDrawable(R.drawable.uxsdk_background_battery_voltage_bg_normal), + BatteryStatus.UNKNOWN to getDrawable(R.drawable.uxsdk_background_battery_voltage_bg_normal), + BatteryStatus.OVERHEATING to getDrawable(R.drawable.uxsdk_background_battery_voltage_bg_overheating), + BatteryStatus.WARNING_LEVEL_1 to getDrawable(R.drawable.uxsdk_background_battery_voltage_bg_danger), + BatteryStatus.WARNING_LEVEL_2 to getDrawable(R.drawable.uxsdk_background_battery_voltage_bg_danger), + BatteryStatus.ERROR to getDrawable(R.drawable.uxsdk_background_battery_voltage_bg_danger) + ) + private var singleIconStates: MutableMap = mutableMapOf( + BatteryStatus.NORMAL to getDrawable(R.drawable.uxsdk_ic_topbar_battery_single_nor), + BatteryStatus.UNKNOWN to getDrawable(R.drawable.uxsdk_ic_topbar_battery_single_nor), + BatteryStatus.OVERHEATING to getDrawable(R.drawable.uxsdk_ic_topbar_battery_single_overheating), + BatteryStatus.WARNING_LEVEL_1 to getDrawable(R.drawable.uxsdk_ic_topbar_battery_single_warning), + BatteryStatus.WARNING_LEVEL_2 to getDrawable(R.drawable.uxsdk_ic_topbar_battery_single_land_immediately), + BatteryStatus.ERROR to getDrawable(R.drawable.uxsdk_ic_topbar_battery_single_error) + ) + + private var dualIconStates: MutableMap = mutableMapOf( + BatteryStatus.NORMAL to getDrawable(R.drawable.uxsdk_ic_topbar_battery_double_nor), + BatteryStatus.UNKNOWN to getDrawable(R.drawable.uxsdk_ic_topbar_battery_double_nor), + BatteryStatus.OVERHEATING to getDrawable(R.drawable.uxsdk_ic_topbar_battery_double_overheating), + BatteryStatus.WARNING_LEVEL_1 to getDrawable(R.drawable.uxsdk_ic_topbar_battery_double_warning), + BatteryStatus.WARNING_LEVEL_2 to getDrawable(R.drawable.uxsdk_ic_topbar_battery_double_land_immediately), + BatteryStatus.ERROR to getDrawable(R.drawable.uxsdk_ic_topbar_battery_double_warning) + ) + + /** + * Represents visibility of voltage text for dual battery + */ + var voltageVisibility: Boolean = true + set(value) { + field = value + checkAndUpdateUI() + } + + /** + * Represents text size of single battery percentage + */ + var singleBatteryPercentageTextSize: Float + get() = singleBatteryValueTextView.textSize + set(@Dimension value) { + singleBatteryValueTextView.textSize = value + } + + /** + * Represents background of single battery percentage + */ + var singleBatteryPercentageBackground: Drawable? + get() = singleBatteryValueTextView.background + set(value) { + singleBatteryValueTextView.background = value + } + + /** + * Represents text size of dual battery percentage + */ + var dualBatteryPercentageTextSize: Float + get() = dualBattery1ValueTextView.textSize + set(@Dimension value) { + dualBattery1ValueTextView.textSize = value + dualBattery2ValueTextView.textSize = value + } + + /** + * Represents text size of dual battery voltage + */ + var dualBatteryVoltageTextSize: Float + get() = dualBattery1VoltageTextView.textSize + set(@Dimension value) { + dualBattery1VoltageTextView.textSize = value + dualBattery2VoltageTextView.textSize = value + } + + + /** + * Represents background of dual battery percentage + */ + var dualBatteryPercentageBackground: Drawable? + get() = dualBattery1ValueTextView.background + set(value) { + dualBattery1ValueTextView.background = value + dualBattery2ValueTextView.background = value + } + + //endregion + + //region Constructors + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + View.inflate(context, R.layout.uxsdk_widget_battery, this) + } + + init { + attrs?.let { initAttributes(context, it) } + } + //endregion + + //region Lifecycle + override fun reactToModelChanges() { + addReaction(widgetModel.batteryState + .observeOn(SchedulerProvider.ui()) + .subscribe { updateUI(it) }) + + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + //endregion + + //region Reactions to model + private fun updateUI(batteryState: BatteryState) { + widgetStateDataProcessor.onNext(BatteryStateUpdated(batteryState)) + when (batteryState) { + is BatteryState.DualBatteryState -> { + setDualBatteryUI() + updateDualBatteryValues(batteryState) + } + is BatteryState.SingleBatteryState -> { + setSingleBatteryUI() + updateSingleBatteryValues(batteryState) + } + is BatteryState.AggregateBatteryState -> { + setSingleBatteryUI() + updateAggregateState(batteryState) + } + is BatteryState.DisconnectedState -> { + setSingleBatteryUI() + updateDisconnectedUI() + } + } + } + + private fun updateDisconnectedUI() { + setSingleBatteryUI() + singleBatteryValueTextView.text = getString(R.string.uxsdk_string_default_value) + singleBatteryValueTextView.textColor = getColor(R.color.uxsdk_white_60_percent) + batteryIconImageView.imageDrawable = singleIconStates[BatteryStatus.NORMAL] + batteryIconImageView.setColorFilter(getColor(R.color.uxsdk_white_60_percent), PorterDuff.Mode.SRC_IN) + + + } + + private fun updateAggregateState(batteryState: BatteryState.AggregateBatteryState) { + singleBatteryValueTextView.text = resources.getString(R.string.uxsdk_battery_percent, batteryState.aggregatePercentage) + setPercentageTextColorByState(singleBatteryValueTextView, batteryState.aggregateBatteryStatus) + singleIconStates[batteryState.aggregateBatteryStatus]?.let { + batteryIconImageView.imageDrawable = it + } + } + + private fun updateSingleBatteryValues(batteryState: BatteryState.SingleBatteryState) { + singleBatteryValueTextView.text = resources.getString(R.string.uxsdk_battery_percent, batteryState.percentageRemaining) + setPercentageTextColorByState(singleBatteryValueTextView, batteryState.batteryStatus) + singleIconStates[batteryState.batteryStatus]?.let { + batteryIconImageView.imageDrawable = it + } + } + + private fun updateDualBatteryValues(batteryState: BatteryState.DualBatteryState) { + dualBattery1ValueTextView.text = resources.getString(R.string.uxsdk_battery_percent, batteryState.percentageRemaining1) + dualBattery2ValueTextView.text = resources.getString(R.string.uxsdk_battery_percent, batteryState.percentageRemaining2) + dualBattery1VoltageTextView.text = resources.getString(R.string.uxsdk_battery_voltage_unit, batteryState.voltageLevel1) + dualBattery2VoltageTextView.text = resources.getString(R.string.uxsdk_battery_voltage_unit, batteryState.voltageLevel2) + setPercentageTextColorByState(dualBattery1ValueTextView, batteryState.batteryStatus1) + setPercentageTextColorByState(dualBattery2ValueTextView, batteryState.batteryStatus2) + setVoltageTextColorByState(dualBattery1VoltageTextView, batteryState.batteryStatus1) + setVoltageTextColorByState(dualBattery2VoltageTextView, batteryState.batteryStatus2) + dualBattery1VoltageTextView.background = voltageBackgroundStates[batteryState.batteryStatus1] + dualBattery2VoltageTextView.background = voltageBackgroundStates[batteryState.batteryStatus2] + val priorityStatus: BatteryStatus = + if (batteryState.batteryStatus1.index > batteryState.batteryStatus2.index) + batteryState.batteryStatus1 + else + batteryState.batteryStatus2 + dualIconStates[priorityStatus]?.let { + batteryIconImageView.imageDrawable = it + } + + + } + //endregion + + //region private helpers + private fun setPercentageTextColorByState(textView: TextView, batteryStatus: BatteryStatus) { + percentColorStates[batteryStatus]?.let { + textView.textColorStateList = it + } + } + + private fun setVoltageTextColorByState(textView: TextView, batteryStatus: BatteryStatus) { + voltageColorStates[batteryStatus]?.let { + textView.textColorStateList = it + } + } + + + private fun setSingleBatteryUI() { + batteryIconImageView.clearColorFilter() + singleBatteryValueTextView.visibility = View.VISIBLE + dualBattery1ValueTextView.visibility = View.GONE + dualBattery2ValueTextView.visibility = View.GONE + dualBattery1VoltageTextView.visibility = View.GONE + dualBattery2VoltageTextView.visibility = View.GONE + } + + private fun setDualBatteryUI() { + batteryIconImageView.clearColorFilter() + singleBatteryValueTextView.visibility = View.GONE + dualBattery1ValueTextView.visibility = View.VISIBLE + dualBattery2ValueTextView.visibility = View.VISIBLE + dualBattery1VoltageTextView.visibility = if (voltageVisibility) View.VISIBLE else View.GONE + dualBattery2VoltageTextView.visibility = if (voltageVisibility) View.VISIBLE else View.GONE + } + + private fun checkAndUpdateUI() { + if (!isInEditMode) { + addDisposable(widgetModel.batteryState.firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(Consumer { this.updateUI(it) }, UxErrorHandle.logErrorConsumer(TAG, "Update UI "))) + } + } + + private fun checkAndUpdateIconDimensionRatio() { + if (!isInEditMode) { + addDisposable(widgetModel.batteryState.firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(Consumer { this.updateIconRatio(it) }, UxErrorHandle.logErrorConsumer(TAG, "Update icon dimension ratio "))) + } + } + + + private fun updateIconRatio(batteryState: BatteryState) { + val set = ConstraintSet() + set.clone(this) + set.setDimensionRatio(batteryIconImageView.id, + if (batteryState is BatteryState.DualBatteryState) dualIconDimensionRatio else singleIconDimensionRatio) + set.applyTo(this) + } + //endregion + + //region customizations + override fun getIdealDimensionRatioString(): String? { + return null + } + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.WRAP, + heightDimension = WidgetSizeDescription.Dimension.EXPAND) + + /** + * Set the single battery icon drawable for the given batteryStatus + * + * @param batteryStatus batteryStatus to apply the change to + * @param resource drawable resource for the icon + */ + fun setSingleIcon(batteryStatus: BatteryStatus, @DrawableRes resource: Int) { + setSingleIcon(batteryStatus, getDrawable(resource)) + } + + /** + * Set the single battery icon drawable for the given batteryStatus with the given dimension ratio + * + * @param batteryStatus batteryStatus to apply the change to + * @param resource drawable resource for the icon + * @param ratio A String containing the dimension ratio of the single battery icon. + */ + fun setSingleIcon(batteryStatus: BatteryStatus, @DrawableRes resource: Int, ratio: String) { + setSingleIcon(batteryStatus, getDrawable(resource), ratio) + } + + /** + * Set the single battery icon drawable for the given batteryStatus + * + * @param batteryStatus batteryStatus to apply the change to + * @param drawable drawable for the icon + */ + fun setSingleIcon(batteryStatus: BatteryStatus, drawable: Drawable) { + singleIconStates[batteryStatus] = drawable + checkAndUpdateUI() + } + + /** + * Set the single battery icon drawable for the given batteryStatus with the given dimension ratio + * + * @param batteryStatus batteryStatus to apply the change to + * @param drawable drawable for the icon + * @param ratio A String containing the dimension ratio of the single battery icon. + */ + fun setSingleIcon(batteryStatus: BatteryStatus, drawable: Drawable, ratio: String) { + setSingleIcon(batteryStatus, drawable) + singleIconDimensionRatio = ratio + checkAndUpdateIconDimensionRatio() + } + + /** + * Set the dual battery icon drawable for the given batteryStatus + * + * @param batteryStatus batteryStatus to apply the change to + * @param resource drawable resource for the icon + */ + fun setDualIcon(batteryStatus: BatteryStatus, @DrawableRes resource: Int) { + setDualIcon(batteryStatus, getDrawable(resource)) + } + + /** + * Set the dual battery icon drawable for the given batteryStatus with the given dimension ratio + * + * @param batteryStatus batteryStatus to apply the change to + * @param resource drawable resource for the icon + * @param ratio A String containing the dimension ratio of the dual battery icon. + */ + fun setDualIcon(batteryStatus: BatteryStatus, @DrawableRes resource: Int, ratio: String) { + setDualIcon(batteryStatus, getDrawable(resource), ratio) + } + + /** + * Set the dual battery icon drawable for the given batteryStatus + * + * @param batteryStatus batteryStatus to apply the change to + * @param drawable drawable for the icon + */ + fun setDualIcon(batteryStatus: BatteryStatus, drawable: Drawable) { + dualIconStates[batteryStatus] = drawable + checkAndUpdateUI() + } + + /** + * Set the dual battery icon drawable for the given batteryStatus with the given dimension ratio + * + * @param batteryStatus batteryStatus to apply the change to + * @param drawable drawable for the icon + * @param ratio A String containing the dimension ratio of the dual battery icon. + */ + fun setDualIcon(batteryStatus: BatteryStatus, drawable: Drawable, ratio: String) { + setDualIcon(batteryStatus, drawable) + dualIconDimensionRatio = ratio + checkAndUpdateIconDimensionRatio() + } + + /** + * Set appearance of the percent text in single battery mode + * + * @param textAppearance appearance to apply + */ + fun setSinglePercentTextAppearance(@StyleRes textAppearance: Int) { + singleBatteryValueTextView.setTextAppearance(context, textAppearance) + } + + /** + * Set appearance of the percent text in dual battery mode + * + * @param textAppearance appearance to apply + */ + fun setDualPercentTextAppearance(@StyleRes textAppearance: Int) { + dualBattery1ValueTextView.setTextAppearance(context, textAppearance) + dualBattery2ValueTextView.setTextAppearance(context, textAppearance) + } + + /** + * Set appearance of the voltage text in dual battery mode + * + * @param textAppearance appearance to apply + */ + fun setDualVoltageTextAppearance(@StyleRes textAppearance: Int) { + dualBattery1VoltageTextView.setTextAppearance(context, textAppearance) + dualBattery2VoltageTextView.setTextAppearance(context, textAppearance) + } + + /** + * Set the current color of the percent text view for the given state + * + * @param batteryStatus to apply the color to + * @param color color integer resource to apply + */ + fun setPercentTextColor(batteryStatus: BatteryStatus, @ColorInt color: Int) { + setPercentTextColor(batteryStatus, ColorStateList.valueOf(color)) + } + + /** + * Set current color state list of the percent text view for the given state + * + * @param batteryStatus state to apply the color to + * @param colorStateList ColorStateList to apply + */ + fun setPercentTextColor(batteryStatus: BatteryStatus, colorStateList: ColorStateList) { + percentColorStates[batteryStatus] = colorStateList + checkAndUpdateUI() + } + + /** + * Set current color of the voltage text view for the given state + * + * @param batteryStatus to apply the color to + * @param color color integer resource to apply + */ + fun setVoltageTextColor(batteryStatus: BatteryStatus, @ColorInt color: Int) { + setVoltageTextColor(batteryStatus, ColorStateList.valueOf(color)) + } + + /** + * Set current color state list of the voltage text view for the given state + * + * @param batteryStatus state to apply the color to + * @param colorStateList ColorStateList to apply + */ + fun setVoltageTextColor(batteryStatus: BatteryStatus, colorStateList: ColorStateList) { + voltageColorStates[batteryStatus] = colorStateList + checkAndUpdateUI() + } + + /** + * Set the background of the dual battery percentage text + * + * @param resourceId integer id of the resource + */ + fun setDualBatteryPercentageBackground(@DrawableRes resourceId: Int) { + dualBatteryPercentageBackground = getDrawable(resourceId) + } + + /** + * Set the background of the dual battery voltage text + * + * @param resourceId integer id of the resource + */ + fun setDualBatteryVoltageBackground(batteryStatus: BatteryStatus, @DrawableRes resourceId: Int) { + setDualBatteryVoltageBackground(batteryStatus, getDrawable(resourceId)) + } + + fun setDualBatteryVoltageBackground(batteryStatus: BatteryStatus, drawable: Drawable?) { + voltageBackgroundStates[batteryStatus] = drawable + checkAndUpdateUI() + } + + fun getDualBatteryVoltageBackground(batteryStatus: BatteryStatus): Drawable? { + return voltageBackgroundStates[batteryStatus] + } + + /** + * Set the background of the single battery percentage text + * + * @param resourceId integer id of the resource + */ + fun setSingleBatteryPercentageBackground(@DrawableRes resourceId: Int) { + singleBatteryPercentageBackground = getDrawable(resourceId) + } + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.BatteryWidget).use { typedArray -> + + voltageVisibility = typedArray.getBoolean(R.styleable.BatteryWidget_uxsdk_voltageVisibility, true) + + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_singlePercentAppearance) { + setSinglePercentTextAppearance(it) + } + + typedArray.getDimensionAndUse(R.styleable.BatteryWidget_uxsdk_singlePercentTextSize) { + singleBatteryPercentageTextSize = it + } + + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_singleIconUnknown) { + setSingleIcon(BatteryStatus.UNKNOWN, it) + } + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_singleIconNormal) { + setSingleIcon(BatteryStatus.NORMAL, it) + } + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_singleIconOverheating) { + setSingleIcon(BatteryStatus.OVERHEATING, it) + } + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_singleIconWarningLevel1) { + setSingleIcon(BatteryStatus.WARNING_LEVEL_1, it) + } + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_singleIconWarningLevel2) { + setSingleIcon(BatteryStatus.WARNING_LEVEL_2, it) + } + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_singleIconError) { + setSingleIcon(BatteryStatus.ERROR, it) + } + + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_dualPercentAppearance) { + setDualPercentTextAppearance(it) + } + + typedArray.getDimensionAndUse(R.styleable.BatteryWidget_uxsdk_dualPercentTextSize) { + dualBatteryPercentageTextSize = it + } + + typedArray.getColorAndUse(R.styleable.BatteryWidget_uxsdk_percentTextColorUnknown) { + setPercentTextColor(BatteryStatus.UNKNOWN, it) + } + typedArray.getColorAndUse(R.styleable.BatteryWidget_uxsdk_percentTextColorNormal) { + setPercentTextColor(BatteryStatus.NORMAL, it) + } + typedArray.getColorAndUse(R.styleable.BatteryWidget_uxsdk_percentTextColorOverheating) { + setPercentTextColor(BatteryStatus.OVERHEATING, it) + } + typedArray.getColorAndUse(R.styleable.BatteryWidget_uxsdk_percentTextColorWarningLevel1) { + setPercentTextColor(BatteryStatus.WARNING_LEVEL_1, it) + } + typedArray.getColorAndUse(R.styleable.BatteryWidget_uxsdk_percentTextColorWarningLevel2) { + setPercentTextColor(BatteryStatus.WARNING_LEVEL_2, it) + } + typedArray.getColorAndUse(R.styleable.BatteryWidget_uxsdk_percentTextColorError) { + setPercentTextColor(BatteryStatus.ERROR, it) + } + + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_dualVoltageAppearance) { + setDualVoltageTextAppearance(it) + } + + typedArray.getDimensionAndUse(R.styleable.BatteryWidget_uxsdk_dualPercentTextSize) { + dualBatteryVoltageTextSize = it + } + + typedArray.getColorAndUse(R.styleable.BatteryWidget_uxsdk_voltageTextColorUnknown) { + setVoltageTextColor(BatteryStatus.UNKNOWN, it) + } + typedArray.getColorAndUse(R.styleable.BatteryWidget_uxsdk_voltageTextColorNormal) { + setVoltageTextColor(BatteryStatus.NORMAL, it) + } + typedArray.getColorAndUse(R.styleable.BatteryWidget_uxsdk_voltageTextColorOverheating) { + setVoltageTextColor(BatteryStatus.OVERHEATING, it) + } + typedArray.getColorAndUse(R.styleable.BatteryWidget_uxsdk_voltageTextColorWarningLevel1) { + setVoltageTextColor(BatteryStatus.WARNING_LEVEL_1, it) + } + typedArray.getColorAndUse(R.styleable.BatteryWidget_uxsdk_voltageTextColorWarningLevel2) { + setVoltageTextColor(BatteryStatus.WARNING_LEVEL_2, it) + } + typedArray.getColorAndUse(R.styleable.BatteryWidget_uxsdk_voltageTextColorError) { + setVoltageTextColor(BatteryStatus.ERROR, it) + } + + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_voltageBackgroundUnknown) { + setDualBatteryVoltageBackground(BatteryStatus.UNKNOWN, it) + } + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_voltageBackgroundNormal) { + setDualBatteryVoltageBackground(BatteryStatus.NORMAL, it) + } + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_voltageBackgroundOverheating) { + setDualBatteryVoltageBackground(BatteryStatus.OVERHEATING, it) + } + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_voltageBackgroundWarningLevel1) { + setDualBatteryVoltageBackground(BatteryStatus.WARNING_LEVEL_1, it) + } + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_voltageBackgroundWarningLevel2) { + setDualBatteryVoltageBackground(BatteryStatus.WARNING_LEVEL_2, it) + } + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_voltageBackgroundError) { + setDualBatteryVoltageBackground(BatteryStatus.ERROR, it) + } + + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_dualIconUnknown) { + setDualIcon(BatteryStatus.UNKNOWN, it) + } + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_dualIconNormal) { + setDualIcon(BatteryStatus.NORMAL, it) + } + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_dualIconOverheating) { + setDualIcon(BatteryStatus.OVERHEATING, it) + } + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_dualIconWarningLevel1) { + setDualIcon(BatteryStatus.WARNING_LEVEL_1, it) + } + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_dualIconWarningLevel2) { + setDualIcon(BatteryStatus.WARNING_LEVEL_2, it) + } + typedArray.getResourceIdAndUse(R.styleable.BatteryWidget_uxsdk_dualIconError) { + setDualIcon(BatteryStatus.ERROR, it) + } + + singleIconDimensionRatio = + typedArray.getString(R.styleable.BatteryWidget_uxsdk_singleIconDimensionRatio, singleIconDimensionRatio) + dualIconDimensionRatio = + typedArray.getString(R.styleable.BatteryWidget_uxsdk_dualIconDimensionRatio, dualIconDimensionRatio) + } + } + + //endregion + + //region Hooks + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * + * Class defines widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Battery state update + */ + data class BatteryStateUpdated(val batteryState: BatteryState) : ModelState() + } + //endregion + + companion object { + private const val TAG = "BatteryWidget" + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryWidgetModel.kt new file mode 100644 index 00000000..aa72b097 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/battery/BatteryWidgetModel.kt @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.battery + +import androidx.annotation.IntRange +import dji.sdk.keyvalue.key.BatteryKey +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.value.battery.BatteryException +import dji.sdk.keyvalue.value.battery.BatteryOverviewValue +import dji.sdk.keyvalue.value.common.ComponentIndexType +import dji.sdk.keyvalue.value.flightcontroller.FCBatteryThresholdBehavior +import dji.sdk.keyvalue.key.KeyTools +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.milliVoltsToVolts +import dji.v5.ux.core.util.DataProcessor +import java.util.ArrayList + +private const val DUAL_BATTERY = 2 +private val DEFAULT_ARRAY = arrayOf(0) +private const val DEFAULT_PERCENTAGE = 0 + +/** + * Widget Model for [BatteryWidget] used to define the + * underlying logic and communication + */ +class BatteryWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + + + private val batteryPercentageProcessor1 = DataProcessor.create(DEFAULT_PERCENTAGE) + private val batteryPercentageProcessor2 = DataProcessor.create(DEFAULT_PERCENTAGE) + private val batteryVoltageProcessor1: DataProcessor> = DataProcessor.create(ArrayList()) + private val batteryVoltageProcessor2: DataProcessor> = DataProcessor.create(ArrayList()) + private val batteryWarningRecordProcessor1 = DataProcessor.create(BatteryException()) + private val batteryWarningRecordProcessor2 = DataProcessor.create(BatteryException()) + + private val batteryOverviewsProcessor: DataProcessor> = DataProcessor.create(ArrayList()) + private val batteryConnectedProcessor = DataProcessor.create(0) + private val isAnyBatteryDisconnectedProcessor = DataProcessor.create(false) + private val isCellDamagedDisconnectedProcessor = DataProcessor.create(false) + private val isFirmwareDifferenceDetectedProcessor = DataProcessor.create(false) + private val isVoltageDifferenceDetectedProcessor = DataProcessor.create(false) + private val isLowCellVoltageDetectedProcessor = DataProcessor.create(false) + + private val batteryStateProcessor: DataProcessor = DataProcessor.create(BatteryState.DisconnectedState) + private val batteryThresholdBehaviorProcessor = DataProcessor.create(FCBatteryThresholdBehavior.UNKNOWN) + private val batteryNeededToGoHomeProcessor: DataProcessor = DataProcessor.create(0) + private val isAircraftFlyingDataProcessor: DataProcessor = DataProcessor.create(false) + + /** + * Get the current state of the battery of the connected product + */ + val batteryState: Flowable + get() = batteryStateProcessor.toFlowable() + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyChargeRemainingInPercent, ComponentIndexType.LEFT_OR_MAIN + ), batteryPercentageProcessor1 + ) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyCellVoltages, ComponentIndexType.LEFT_OR_MAIN + ), batteryVoltageProcessor1 + ) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyBatteryException, ComponentIndexType.LEFT_OR_MAIN + ), batteryWarningRecordProcessor1 + ) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyChargeRemainingInPercent, ComponentIndexType.RIGHT + ), batteryPercentageProcessor2 + ) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyCellVoltages, ComponentIndexType.RIGHT + ), batteryVoltageProcessor2 + ) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyBatteryException, ComponentIndexType.RIGHT + ), batteryWarningRecordProcessor2 + ) + + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyNumberOfConnectedBatteries, ComponentIndexType.AGGREGATION + ), batteryConnectedProcessor + ) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyIsAnyBatteryDisconnected, ComponentIndexType.AGGREGATION + ), isAnyBatteryDisconnectedProcessor + ) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyIsCellDamaged, ComponentIndexType.AGGREGATION + ), isCellDamagedDisconnectedProcessor + ) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyIsFirmwareDifferenceDetected, ComponentIndexType.AGGREGATION + ), isFirmwareDifferenceDetectedProcessor + ) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyIsVoltageDifferenceDetected, ComponentIndexType.AGGREGATION + ), isVoltageDifferenceDetectedProcessor + ) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyIsLowCellVoltageDetected, ComponentIndexType.AGGREGATION + ), isLowCellVoltageDetectedProcessor + ) + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyBatteryOverviews, ComponentIndexType.AGGREGATION + ), batteryOverviewsProcessor + ) + + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyBatteryThresholdBehavior + ), batteryThresholdBehaviorProcessor + ) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyBatteryPercentNeededToGoHome + ), batteryNeededToGoHomeProcessor + ) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyIsFlying + ), isAircraftFlyingDataProcessor + ) + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + when (batteryConnectedProcessor.value) { + DUAL_BATTERY -> { + val battery1Voltage = calculateAverageVoltage(batteryVoltageProcessor1.value) + val battery2Voltage = calculateAverageVoltage(batteryVoltageProcessor2.value) + batteryStateProcessor.onNext( + BatteryState.DualBatteryState( + batteryPercentageProcessor1.value, + battery1Voltage, + calculateBatteryStatus( + batteryWarningRecordProcessor1.value, + batteryThresholdBehaviorProcessor.value, + batteryPercentageProcessor1.value, + batteryNeededToGoHomeProcessor.value, + isAircraftFlyingDataProcessor.value, + battery1Voltage + ), + batteryPercentageProcessor2.value, + battery2Voltage, + calculateBatteryStatus( + batteryWarningRecordProcessor2.value, + batteryThresholdBehaviorProcessor.value, + batteryPercentageProcessor2.value, + batteryNeededToGoHomeProcessor.value, + isAircraftFlyingDataProcessor.value, + battery2Voltage + ) + ) + ) + } + + else -> { + when (findConnectedBattery()) { + ComponentIndexType.LEFT_OR_MAIN -> { + val voltage = calculateAverageVoltage(batteryVoltageProcessor1.value) + batteryStateProcessor.onNext( + BatteryState.SingleBatteryState( + batteryPercentageProcessor1.value, + voltage, + calculateBatteryStatus( + batteryWarningRecordProcessor1.value, + batteryThresholdBehaviorProcessor.value, + batteryPercentageProcessor1.value, + batteryNeededToGoHomeProcessor.value, + isAircraftFlyingDataProcessor.value, + voltage + ) + ) + ) + } + + ComponentIndexType.RIGHT -> { + val voltage = calculateAverageVoltage(batteryVoltageProcessor2.value) + batteryStateProcessor.onNext( + BatteryState.SingleBatteryState( + batteryPercentageProcessor2.value, + voltage, + calculateBatteryStatus( + batteryWarningRecordProcessor2.value, + batteryThresholdBehaviorProcessor.value, + batteryPercentageProcessor2.value, + batteryNeededToGoHomeProcessor.value, + isAircraftFlyingDataProcessor.value, + voltage + ) + ) + ) + } + + else -> { + // nothing + } + } + } + } + } else { + batteryStateProcessor.onNext(BatteryState.DisconnectedState) + } + } + + override fun inCleanup() { + // No Code + } + + private fun findConnectedBattery(): ComponentIndexType { + val batteryIndex = batteryOverviewsProcessor.value.filter { + it.isConnected + }.getOrNull(0)?.index ?: 0 + return ComponentIndexType.find(batteryIndex) + } + + private fun calculateAverageVoltage(cellVoltages: List?): Float { + return if (cellVoltages != null && cellVoltages.isNotEmpty()) { + cellVoltages.average().toFloat().milliVoltsToVolts() + } else 0f + } + + private fun calculateBatteryStatus( + batteryException: BatteryException, + batteryThresholdBehavior: FCBatteryThresholdBehavior, + percentage: Int, + goHomeBattery: Int, + isFlying: Boolean, + voltage: Float + ): BatteryStatus { + if (percentage < 0 || voltage < 0f) { + return BatteryStatus.UNKNOWN + } else if (batteryException.firstLevelOverHeating || batteryException.secondLevelOverHeating) { + return BatteryStatus.OVERHEATING + } else if (batteryException.isError()) { + return BatteryStatus.ERROR + } else if (FCBatteryThresholdBehavior.LAND_IMMEDIATELY == batteryThresholdBehavior) { + return BatteryStatus.WARNING_LEVEL_2 + } else if (FCBatteryThresholdBehavior.GO_HOME == batteryThresholdBehavior + || (percentage <= goHomeBattery && isFlying)) { + return BatteryStatus.WARNING_LEVEL_1 + } + return BatteryStatus.NORMAL + } + + private fun BatteryException.isError(): Boolean { + return this.firstLevelOverHeating || this.secondLevelOverHeating || this.communicationException + || this.hasBrokenCell || this.hasLowVoltageCell || this.shortCircuited + || this.firstLevelLowTemperature || this.secondLevelLowTemperature + } + + /** + * Class representing the current state of the battery + * based on information received from the product + */ + sealed class BatteryState { + /** + * Product is currently disconnected + */ + object DisconnectedState : BatteryState() + + /** + * Product with single battery is connected. The status includes + * + * @property percentageRemaining - battery remaining in percentage + * @property voltageLevel - voltage level of the battery + * @property batteryStatus - [BatteryStatus] instance representing the battery + */ + data class SingleBatteryState( + val percentageRemaining: Int, + val voltageLevel: Float, + val batteryStatus: BatteryStatus + ) : BatteryState() + + /** + * Product with dual battery is connected. The status includes + * + * @property percentageRemaining1 - battery remaining in percentage of battery 1 + * @property voltageLevel1 - voltage level of the battery 1 + * @property batteryStatus1 - [BatteryStatus] instance representing the battery 1 + * @property percentageRemaining2 - battery remaining in percentage of battery 2 + * @property voltageLevel2 - voltage level of the battery 2 + * @property batteryStatus2 - [BatteryStatus] instance representing the battery 2 + */ + data class DualBatteryState( + val percentageRemaining1: Int, + val voltageLevel1: Float, + val batteryStatus1: BatteryStatus, + val percentageRemaining2: Int, + val voltageLevel2: Float, + val batteryStatus2: BatteryStatus + ) : BatteryState() + + /** + * Product with more than 2 batteries is connected. The status includes + * + * @property aggregatePercentage - aggregate percentage remaining from all batteries + * @property aggregateVoltage - aggregate voltage level of all batteries + * @property aggregateBatteryStatus - [BatteryStatus] instance representing the aggregate status + */ + data class AggregateBatteryState( + val aggregatePercentage: Int, + val aggregateVoltage: Float, + val aggregateBatteryStatus: BatteryStatus + ) : BatteryState() + } + + //endregion + + + /** + * Enum representing the state of each battery in the battery bank + */ + enum class BatteryStatus constructor(val index: Int) { + /** + * Battery is operating without issue + */ + NORMAL(0), + + /** + * Battery charge is starting to get low, to the point that the aircraft should return home + */ + WARNING_LEVEL_1(1), + + /** + * Battery charge is starting to get very low, to the point that the aircraft should + * land immediately. + */ + WARNING_LEVEL_2(2), + + /** + * Battery has an error that is preventing a proper reading + */ + ERROR(3), + + /** + * Battery temperature is too high + */ + OVERHEATING(4), + + /** + * The state of the battery is unknown or the system is initializing + */ + UNKNOWN(5); + + companion object { + @JvmStatic + val values = values() + + @JvmStatic + fun find(@IntRange(from = 0, to = 5) index: Int): BatteryStatus { + return values.find { it.index == index } ?: UNKNOWN + } + } + } + + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/common/CommonAboutWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/common/CommonAboutWidget.java new file mode 100644 index 00000000..4e64b39b --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/common/CommonAboutWidget.java @@ -0,0 +1,385 @@ +package dji.v5.ux.core.widget.common; + +import android.content.Context; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.View; +import android.view.ViewGroup; +import android.widget.LinearLayout; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import dji.sdk.keyvalue.utils.ProductUtil; +import dji.sdk.keyvalue.value.camera.CameraType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.v5.utils.common.BytesUtil; +import dji.v5.utils.common.LogPath; +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.TextCell; +import dji.v5.ux.core.base.widget.FrameLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.CameraUtil; +import dji.v5.ux.core.widget.battery.BatteryResourceUtil; +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.core.ObservableSource; +import io.reactivex.rxjava3.core.Single; +import io.reactivex.rxjava3.core.SingleSource; +import io.reactivex.rxjava3.disposables.CompositeDisposable; +import io.reactivex.rxjava3.functions.Function; + +public class CommonAboutWidget extends FrameLayoutWidget { + + public static final String NO_VALUE = "N/A"; + + protected CommonAboutWidgetModel widgetModel = + new CommonAboutWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()); + + protected TextCell fcVerCell; + protected TextCell rcVerCell; + protected LinearLayout gimbalVersionLy; + protected LinearLayout cameraVersionLy; + protected TextCell camera1SnCell; + protected TextCell camera2SnCell; + protected TextCell camera3SnCell; + protected TextCell flycSerialCell; + protected TextCell rcSerialCell; + protected TextCell rtkSerialCell; + protected LinearLayout batterVersionLayout; + + protected int textCellHeight; + private int batteryNumber; + + protected final Map cameraTypeMap = new HashMap<>(); + + protected final HashMap cameraViews = new HashMap<>(); + + protected CompositeDisposable batteryDisposable; + + public CommonAboutWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public CommonAboutWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public CommonAboutWidget(@NonNull Context context) { + super(context); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_setting_menu_about, this); + + fcVerCell = findViewById(R.id.common_menu_fc_version); + rcVerCell = findViewById(R.id.common_menu_rc_version); + gimbalVersionLy = findViewById(R.id.common_menu_gimbal_version_ly); + cameraVersionLy = findViewById(R.id.common_menu_camera_version_ly); + camera1SnCell = findViewById(R.id.common_menu_camera1_sn); + camera2SnCell = findViewById(R.id.common_menu_camera2_sn); + camera3SnCell = findViewById(R.id.common_menu_camera3_sn); + flycSerialCell = findViewById(R.id.common_menu_flyc_serial); + rcSerialCell = findViewById(R.id.common_menu_rc_serial); + rtkSerialCell = findViewById(R.id.common_menu_rtk_serial); + batterVersionLayout = findViewById(R.id.common_menu_battery_version_layout); + + textCellHeight = getResources().getDimensionPixelSize(R.dimen.uxsdk_58_dp); + + // setBackgroundResource(R.drawable.uxsdk_background_black_rectangle); + } + + @Override + protected void reactToModelChanges() { + addDisposable(widgetModel.rcConnectionProcessor.toFlowableOnUI().subscribe(value -> updateRCVersion())); + + addDisposable(Observable.combineLatest( + widgetModel.gimbal1ConnectionProcessor.toObservableOnUI(), + widgetModel.gimbal2ConnectionProcessor.toObservableOnUI(), + widgetModel.gimbal3ConnectionProcessor.toObservableOnUI(), + CameraUtil::getConnectionCameraList + ).subscribe(this::updateGimbalVersion)); + + addDisposable(Observable.combineLatest( + widgetModel.camera1ConnectionProcessor.toObservableOnUI(), + widgetModel.camera2ConnectionProcessor.toObservableOnUI(), + widgetModel.camera3ConnectionProcessor.toObservableOnUI(), + CameraUtil::getConnectionCameraList + ).subscribe(this::updateCameraView)); + + addDisposable(widgetModel.fcConnectionProcessor.toFlowableOnUI().subscribe(value -> { + if (Boolean.TRUE.equals(value)) { + addDisposable(widgetModel.getFCSerialNumber().subscribe(this::updateFlycSerialNumber, throwable -> LogUtils.e(LogPath.COMMON, throwable.getMessage()))); + addDisposable(widgetModel.getProductVersion().subscribe(this::updateProductVersion, throwable -> LogUtils.e(LogPath.COMMON, throwable.getMessage()))); + } else { + updateFlycSerialNumber(NO_VALUE); + updateProductVersion(NO_VALUE); + } + })); + + addDisposable(widgetModel.rcSerialNumberProcessor.toFlowableOnUI().subscribe(this::updateRcSerialNumber)); + + addDisposable(widgetModel.rtkConnectionProcessor.toFlowableOnUI().subscribe(value -> { + if (Boolean.TRUE.equals(value)) { + addDisposable(widgetModel.getRTKSerialNumber().subscribe(this::updateRTKSerialNumber)); + } else { + updateRTKSerialNumber(""); + } + })); + + addDisposable(widgetModel.batteryOverviewProcessor.toFlowableOnUI().subscribe(overviewValues -> { + if (batteryNumber != overviewValues.size() + || batterVersionLayout.getChildCount() == 0) { + batteryNumber = overviewValues.size(); + updateBatteryView(); + } + })); + + if (ProductUtil.isM350Product() || ProductUtil.isM400Product() || ProductUtil.isM300Product()) { + addDisposable(Observable.combineLatest( + widgetModel.camera1SerialNumberProcessor.toObservableOnUI(), + widgetModel.camera2SerialNumberProcessor.toObservableOnUI(), + widgetModel.camera3SerialNumberProcessor.toObservableOnUI(), + (camera1, camera2, camera3) -> { + updateCameraSerialNumber(camera1SnCell, camera1, ComponentIndexType.LEFT_OR_MAIN); + updateCameraSerialNumber(camera2SnCell, camera2, ComponentIndexType.RIGHT); + updateCameraSerialNumber(camera3SnCell, camera3, ComponentIndexType.UP); + return new Object(); + } + ).subscribe()); + } + } + + private void updateRCVersion() { + addDisposable(widgetModel.doForceUpdateCache().andThen(widgetModel.getRCVersion()).subscribe( + (version, throwable) -> { + if (throwable == null) { + rcVerCell.setContent(version); + } else { + rcVerCell.setContent(NO_VALUE); + } + })); + } + + private void updateGimbalVersion(Collection cameraIndexList) { + gimbalVersionLy.removeAllViews(); + for (ComponentIndexType cameraIndex : cameraIndexList) { + addDisposable(widgetModel.getGimbalVersion(cameraIndex) + .delay(cameraIndex.value() * 100L, TimeUnit.MILLISECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe((version, throwable) -> { + for (int i = 0; i < gimbalVersionLy.getChildCount(); i++) { + View v = gimbalVersionLy.getChildAt(i); + if (v.getTag() == cameraIndex) { + gimbalVersionLy.removeViewAt(i); + } + } + TextCell gimbalTc = new TextCell(getContext()); + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, textCellHeight); + gimbalTc.setTag(cameraIndex); + gimbalVersionLy.addView(gimbalTc, layoutParams); + gimbalTc.setContent(version); + if (cameraIndexList.size() > 1) { + gimbalTc.setTitle(getResources().getString(R.string.uxsdk_setting_menu_common_gimbal_version, String.valueOf(cameraIndex.value() + 1))); + } else { + gimbalTc.setTitle(getResources().getString(R.string.uxsdk_setting_menu_common_gimbal_version, "")); + } + })); + } + } + + private void updateCameraView(Collection cameraIndexList) { + cameraVersionLy.removeAllViews(); + for (ComponentIndexType cameraIndex : cameraIndexList) { + addDisposable(widgetModel.getCameraType(cameraIndex) + .delay(cameraIndex.value() * 100L, TimeUnit.MILLISECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .doOnSuccess(cameraType -> cameraTypeMap.put(cameraIndex, cameraType)) + .flatMap((Function>) cameraType -> { + cameraTypeMap.put(cameraIndex, cameraType); + if (cameraType == CameraType.PAYLOAD) { + return Single.zip(widgetModel.getPayloadCameraVersion(cameraIndex), widgetModel.getPayloadCameraName(cameraIndex), + (version, cameraName) -> { + updateCameraVersion(cameraIndex, version, cameraName); + return version; + }); + } else { + return Single.zip(widgetModel.getCameraVersion(cameraIndex), Single.just(CameraUtil.getCameraDisplayName(cameraType)), + (version, cameraName) -> { + updateCameraVersion(cameraIndex, version, cameraName); + return version; + }); + } + }) + .subscribe()); + } + } + + private void updateCameraVersion(ComponentIndexType cameraIndex, String version, String cameraName) { + TextCell[] textCells; + //XT2 需要显示两个相机的版本号 + LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, textCellHeight); + if (CameraType.ZENMUSE_XT2 == cameraTypeMap.get(cameraIndex)) { + if (cameraViews.get(cameraIndex.value()) != null && cameraViews.get(cameraIndex.value() + 1) != null) { + //倒着清除 + cameraVersionLy.removeView(cameraViews.get(cameraIndex.value() + 1)); + cameraVersionLy.removeView(cameraViews.get(cameraIndex.value())); + } + textCells = new TextCell[]{new TextCell(getContext()), new TextCell(getContext())}; + cameraViews.put(cameraIndex.value(), textCells[0]); + cameraViews.put(cameraIndex.value() + 1, textCells[1]); + cameraVersionLy.addView(textCells[0], layoutParams); + cameraVersionLy.addView(textCells[1], layoutParams); + } else { + if (cameraViews.get(cameraIndex.value()) != null) { + cameraVersionLy.removeView(cameraViews.get(cameraIndex.value())); + } + textCells = new TextCell[]{new TextCell(getContext())}; + cameraViews.put(cameraIndex.value(), textCells[0]); + cameraVersionLy.addView(textCells[0], layoutParams); + } + if (textCells.length == 1) { + textCells[0].setContent(version); + textCells[0].setTitle(getResources().getString(R.string.uxsdk_setting_menu_common_camera_version, cameraName)); + } else { + //XT2 通过相机1、相机2区分不同相机的版本号 + textCells[0].setContent(version); + textCells[0].setTitle(getResources().getString(R.string.uxsdk_setting_menu_common_camera_version, cameraName) + "1"); + textCells[1].setContent(getXT2Version(version)); + textCells[1].setTitle(getResources().getString(R.string.uxsdk_setting_menu_common_camera_version, cameraName) + "2"); + } + } + + /** + * 获取XT2另一个相机的版本号 + * + * @param origin 相机版本号 + */ + private String getXT2Version(String origin) { + int dotIndex = origin.lastIndexOf('.'); + String forthNum = origin.substring(dotIndex + 1); + String remain = origin.substring(0, dotIndex); + dotIndex = remain.lastIndexOf('.'); + String thirdNum = remain.substring(dotIndex + 1); + remain = remain.substring(0, dotIndex); + int realValue = Integer.parseInt(forthNum) + 100 * Integer.parseInt(thirdNum); + byte[] bytes = BytesUtil.getBytes(realValue & 0xFFFF); + return remain + "." + (BytesUtil.getInt(bytes[1]) >= 10 ? "" : "0") + BytesUtil.getInt(bytes[1]) + + "." + (BytesUtil.getInt(bytes[0]) > 10 ? "" : "0") + BytesUtil.getInt(bytes[0]); + } + + private void updateCameraSerialNumber(TextCell cell, String sn, ComponentIndexType cameraIndex) { + if (TextUtils.isEmpty(sn)) { + cell.setVisibility(View.GONE); + return; + } + addDisposable(widgetModel.getCameraName(cameraIndex) + .subscribe(name -> { + cell.setVisibility(View.VISIBLE); + cell.setTitle(getResources().getString(R.string.uxsdk_setting_menu_common_camera_version, name) + + getResources().getString(R.string.uxsdk_setting_menu_common_serial)); + cell.setContent(sn); + })); + } + + public void updateProductVersion(String version) { + fcVerCell.setContent(version); + } + + public void updateFlycSerialNumber(String serialNum) { + flycSerialCell.setContent(serialNum); + } + + public void updateRcSerialNumber(String serialNum) { + rcSerialCell.setContent(serialNum); + } + + private void updateRTKSerialNumber(String sn) { + if (!TextUtils.isEmpty(sn) && (ProductUtil.isM3EProduct() || ProductUtil.isM4EProduct() || ProductUtil.isM4DProduct())) { + rtkSerialCell.setContent(sn); + rtkSerialCell.setVisibility(View.VISIBLE); + } else { + rtkSerialCell.setVisibility(View.GONE); + } + } + + private void updateBatteryView() { + batterVersionLayout.removeAllViews(); + if (batteryDisposable != null && !batteryDisposable.isDisposed()) { + batteryDisposable.dispose(); + } + batteryDisposable = new CompositeDisposable(); + for (int i = 0; i < batteryNumber; i++) { + TextCell textCell = new TextCell(getContext()); + batterVersionLayout.addView(textCell); + onBatteryVersionGet(i, null); + int finalI = i; + batteryDisposable.add(widgetModel.getBatteryConnection(i, batteryDisposable).toObservable() + .flatMap((Function>) value -> { + if (Boolean.TRUE.equals(value)) { + return widgetModel.getBatteryVersion(finalI).toObservable(); + } else { + return Observable.just(""); + } + }) + .subscribe(version -> { + if (!TextUtils.isEmpty(version)) { + onBatteryVersionGet(finalI, version); + } else { + onBatteryVersionGet(finalI, null); + } + }) + ); + } + } + + private void onBatteryVersionGet(int index, String versionStr) { + TextCell textCell = (TextCell) batterVersionLayout.getChildAt(index); + if (textCell != null) { + if (!TextUtils.isEmpty(versionStr)) { + textCell.setContent(versionStr); + textCell.setVisibility(VISIBLE); + } else { + textCell.setVisibility(GONE); + } + final String batteryTitle = BatteryResourceUtil.INSTANCE.getBatteryTitle(index); + textCell.setTitle(batteryTitle); + if (ProductUtil.isM350Product() || ProductUtil.isM400Product() || ProductUtil.isM300Product()) { + batteryDisposable.add(widgetModel.getIndustryBatteryType(index).subscribe(type -> { + if (type != null) { + textCell.setTitle(batteryTitle + " (" + BatteryResourceUtil.INSTANCE.productName(type) + ")"); + } + })); + } + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + if (batteryDisposable != null) { + batteryDisposable.dispose(); + batteryDisposable = null; + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/common/CommonAboutWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/common/CommonAboutWidgetModel.java new file mode 100644 index 00000000..6a4ba086 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/common/CommonAboutWidgetModel.java @@ -0,0 +1,160 @@ +package dji.v5.ux.core.widget.common; + +import androidx.annotation.NonNull; + +import java.util.ArrayList; +import java.util.List; + +import dji.sdk.keyvalue.key.BatteryKey; +import dji.sdk.keyvalue.key.CameraKey; +import dji.sdk.keyvalue.key.FlightControllerKey; +import dji.sdk.keyvalue.key.GimbalKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.key.PayloadKey; +import dji.sdk.keyvalue.key.ProductKey; +import dji.sdk.keyvalue.key.RemoteControllerKey; +import dji.sdk.keyvalue.key.RtkMobileStationKey; +import dji.sdk.keyvalue.value.battery.BatteryOverviewValue; +import dji.sdk.keyvalue.value.battery.IndustryBatteryType; +import dji.sdk.keyvalue.value.camera.CameraType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.sdk.keyvalue.value.payload.PayloadCameraType; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.CameraUtil; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; +import io.reactivex.rxjava3.core.Single; + +public class CommonAboutWidgetModel extends WidgetModel { + + public final DataProcessor rcSerialNumberProcessor = DataProcessor.create(""); + public final DataProcessor rtkConnectionProcessor = DataProcessor.create(false); + public final DataProcessor> batteryOverviewProcessor = DataProcessor.create(new ArrayList<>()); + public final DataProcessor rcConnectionProcessor = DataProcessor.create(false); + public final DataProcessor fcConnectionProcessor = DataProcessor.create(false); + public final DataProcessor gimbal1ConnectionProcessor = DataProcessor.create(false); + public final DataProcessor gimbal2ConnectionProcessor = DataProcessor.create(false); + public final DataProcessor gimbal3ConnectionProcessor = DataProcessor.create(false); + public final DataProcessor camera1ConnectionProcessor = DataProcessor.create(false); + public final DataProcessor camera2ConnectionProcessor = DataProcessor.create(false); + public final DataProcessor camera3ConnectionProcessor = DataProcessor.create(false); + public final DataProcessor camera1SerialNumberProcessor = DataProcessor.create(""); + public final DataProcessor camera2SerialNumberProcessor = DataProcessor.create(""); + public final DataProcessor camera3SerialNumberProcessor = DataProcessor.create(""); + + protected CommonAboutWidgetModel( + @NonNull DJISDKModel djiSdkModel, + @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + } + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createKey(RemoteControllerKey.KeyRcRK3399SirialNumber), rcSerialNumberProcessor); + bindDataProcessor(KeyTools.createKey(RemoteControllerKey.KeyConnection), rcConnectionProcessor); + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyConnection), fcConnectionProcessor); + bindDataProcessor(KeyTools.createKey(RtkMobileStationKey.KeyIsRTKDongleConnect), rtkConnectionProcessor); + bindDataProcessor(KeyTools.createKey(BatteryKey.KeyBatteryOverviews, ComponentIndexType.AGGREGATION), batteryOverviewProcessor); + bindDataProcessor(KeyTools.createKey(GimbalKey.KeyConnection, ComponentIndexType.LEFT_OR_MAIN), gimbal1ConnectionProcessor); + bindDataProcessor(KeyTools.createKey(GimbalKey.KeyConnection, ComponentIndexType.RIGHT), gimbal2ConnectionProcessor); + bindDataProcessor(KeyTools.createKey(GimbalKey.KeyConnection, ComponentIndexType.UP), gimbal3ConnectionProcessor); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyConnection, ComponentIndexType.LEFT_OR_MAIN), camera1ConnectionProcessor); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyConnection, ComponentIndexType.RIGHT), camera2ConnectionProcessor); + bindDataProcessor(KeyTools.createKey(CameraKey.KeyConnection, ComponentIndexType.UP), camera3ConnectionProcessor); + bindDataProcessor(KeyTools.createKey(CameraKey.KeySerialNumber, ComponentIndexType.LEFT_OR_MAIN), camera1SerialNumberProcessor); + bindDataProcessor(KeyTools.createKey(CameraKey.KeySerialNumber, ComponentIndexType.RIGHT), camera2SerialNumberProcessor); + bindDataProcessor(KeyTools.createKey(CameraKey.KeySerialNumber, ComponentIndexType.UP), camera3SerialNumberProcessor); + } + + @Override + protected void inCleanup() { + // do noting + } + + public Single getRCVersion() { + return djiSdkModel.getValue(KeyTools.createKey(RemoteControllerKey.KeyFirmwareVersion)) + .observeOn(AndroidSchedulers.mainThread()); + } + + public Completable doForceUpdateCache() { + return djiSdkModel.performActionWithOutResult(KeyTools.createKey(RemoteControllerKey.KeyForceUpdateCacheValue), "FirmwareVersion") + .observeOn(AndroidSchedulers.mainThread()); + } + + public Single getGimbalVersion(ComponentIndexType cameraIndex) { + return djiSdkModel.getValue(KeyTools.createKey(GimbalKey.KeyFirmwareVersion, cameraIndex)) + .observeOn(AndroidSchedulers.mainThread()); + } + + public Single getCameraVersion(ComponentIndexType cameraIndex) { + return djiSdkModel.getValue(KeyTools.createKey(CameraKey.KeyFirmwareVersion, cameraIndex)) + .observeOn(AndroidSchedulers.mainThread()); + } + + + public Single getCameraType(ComponentIndexType cameraIndex) { + return djiSdkModel.getValue(KeyTools.createKey(CameraKey.KeyCameraType, cameraIndex)) + .observeOn(AndroidSchedulers.mainThread()); + } + + public Single getPayloadCameraVersion(ComponentIndexType cameraIndex) { + return djiSdkModel.getValue(KeyTools.createKey(PayloadKey.KeyFirmwareVersion, cameraIndex)) + .observeOn(AndroidSchedulers.mainThread()); + } + + public Single getPayloadCameraName(ComponentIndexType cameraIndex) { + return djiSdkModel.getValue(KeyTools.createKey(PayloadKey.KeyPayloadCameraType, cameraIndex)) + .flatMap(type -> { + if (type != PayloadCameraType.UNKNOWN) { + return Single.just(CameraUtil.getPayloadCameraName(type)); + } + return djiSdkModel.getValue(KeyTools.createKey(PayloadKey.KeyPayloadProductName, cameraIndex)); + }) + .observeOn(AndroidSchedulers.mainThread()); + } + + public Single getCameraName(ComponentIndexType cameraIndex) { + return getCameraType(cameraIndex).flatMap(cameraType -> { + if (cameraType != CameraType.PAYLOAD) { + return Single.just(CameraUtil.getCameraDisplayName(cameraType)) + .observeOn(AndroidSchedulers.mainThread()); + } else { + return getPayloadCameraName(cameraIndex); + } + }); + } + + public Single getFCSerialNumber() { + return djiSdkModel.getValue(KeyTools.createKey(FlightControllerKey.KeySerialNumber)) + .observeOn(AndroidSchedulers.mainThread()); + } + + public Single getRTKSerialNumber() { + return djiSdkModel.getValue(KeyTools.createKey(RtkMobileStationKey.KeyRTKDongleSN)) + .observeOn(AndroidSchedulers.mainThread()); + } + + public Flowable getBatteryConnection(int index, Object listenerHolder) { + return djiSdkModel.addListener(KeyTools.createKey(BatteryKey.KeyConnection, index), listenerHolder) + .observeOn(AndroidSchedulers.mainThread()); + } + + public Single getBatteryVersion(int index) { + return djiSdkModel.getValue(KeyTools.createKey(BatteryKey.KeyFirmwareVersion, index)) + .observeOn(AndroidSchedulers.mainThread()); + } + + public Single getIndustryBatteryType(int index) { + return djiSdkModel.getValue(KeyTools.createKey(BatteryKey.KeyIndustryBatteryType, index)) + .observeOn(AndroidSchedulers.mainThread()); + } + + public Single getProductVersion() { + return djiSdkModel.getValue(KeyTools.createKey(ProductKey.KeyFirmwareVersion)) + .observeOn(AndroidSchedulers.mainThread()); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/common/CommonDeviceNameWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/common/CommonDeviceNameWidget.java new file mode 100644 index 00000000..cf20867a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/common/CommonDeviceNameWidget.java @@ -0,0 +1,95 @@ +package dji.v5.ux.core.widget.common; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.EditText; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + + +import dji.v5.utils.common.LogUtils; +import dji.v5.utils.common.StringUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.widget.FrameLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.ViewUtil; + +public class CommonDeviceNameWidget extends FrameLayoutWidget { + + private static final String TAG = "DeviceRenameWidget"; + + protected CommonDeviceNameWidgetModel widgetModel = + new CommonDeviceNameWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()); + + + protected TextView saveTv; + protected EditText renameCell; + + public CommonDeviceNameWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public CommonDeviceNameWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public CommonDeviceNameWidget(@NonNull Context context) { + super(context); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_setting_menu_common_device_rename, this); + + saveTv = findViewById(R.id.setting_menu_common_save_tv); + renameCell = findViewById(R.id.setting_menu_common_rename_cell); + + saveTv.setOnClickListener(v -> handleSaveAction()); + + // setBackgroundResource(R.drawable.uxsdk_background_black_rectangle); + } + + @Override + protected void reactToModelChanges() { + addDisposable(widgetModel.getAircraftName().subscribe(name -> renameCell.setText(name))); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + } + + private void handleSaveAction() { + String deviceName = renameCell.getText().toString(); + if (deviceName.length() == 0) { + ViewUtil.showToast(getContext(), R.string.uxsdk_setting_common_device_name_input_tip, Toast.LENGTH_SHORT); + return; + } + if (StringUtils.containsEmoji(deviceName)) { + ViewUtil.showToast(getContext(), R.string.uxsdk_setting_common_device_name_illegal, Toast.LENGTH_SHORT); + return; + } + + addDisposable(widgetModel.setAircraftName(deviceName).subscribe(() -> ViewUtil.showToast(getContext(), R.string.uxsdk_setting_common_device_name_save_success, Toast.LENGTH_SHORT), throwable -> { + LogUtils.e(TAG, "handleSaveAction fail: " + throwable); + ViewUtil.showToast(getContext(), R.string.uxsdk_setting_common_device_name_save_fail, Toast.LENGTH_SHORT); + })); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/common/CommonDeviceNameWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/common/CommonDeviceNameWidgetModel.java new file mode 100644 index 00000000..1152d6f9 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/common/CommonDeviceNameWidgetModel.java @@ -0,0 +1,41 @@ +package dji.v5.ux.core.widget.common; + +import androidx.annotation.NonNull; + +import dji.sdk.keyvalue.key.FlightControllerKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Single; + +public class CommonDeviceNameWidgetModel extends WidgetModel { + + protected CommonDeviceNameWidgetModel( + @NonNull DJISDKModel djiSdkModel, + @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + } + + @Override + protected void inSetup() { + // do noting + } + + @Override + protected void inCleanup() { + // do noting + } + + public Single getAircraftName() { + return djiSdkModel.getValue(KeyTools.createKey(FlightControllerKey.KeyAircraftName)) + .observeOn(AndroidSchedulers.mainThread()); + } + + public Completable setAircraftName(String name) { + return djiSdkModel.setValue(KeyTools.createKey(FlightControllerKey.KeyAircraftName), name) + .observeOn(AndroidSchedulers.mainThread()); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/compass/CompassWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/compass/CompassWidget.kt new file mode 100644 index 00000000..ad7c173c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/compass/CompassWidget.kt @@ -0,0 +1,815 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +package dji.v5.ux.core.widget.compass + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.drawable.Drawable +import android.hardware.SensorManager +import android.util.AttributeSet +import android.view.View +import android.view.WindowManager +import android.widget.ImageView +import android.widget.ProgressBar +import androidx.annotation.ColorInt +import androidx.annotation.DrawableRes +import androidx.annotation.FloatRange +import androidx.annotation.IntRange +import androidx.core.content.res.use +import dji.sdk.keyvalue.value.common.Attitude +import dji.sdk.keyvalue.value.common.ComponentIndexType +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.widget.compass.CompassWidget.ModelState +import dji.v5.ux.core.widget.compass.CompassWidget.ModelState.CompassStateUpdated +import dji.v5.ux.core.widget.compass.CompassWidget.ModelState.ProductConnected +import dji.v5.ux.core.widget.compass.CompassWidgetModel.* +import io.reactivex.rxjava3.core.Flowable +import kotlin.math.cos +import kotlin.math.sin + +private const val TAG = "CompassWidget" +private const val MAX_DISTANCE = 400 +private const val MAX_SCALE_DISTANCE = 2000 +private const val MIN_SCALE = 0.6f +private const val MAX_PROGRESS = 100 +private const val MIN_PROGRESS = 0 +private const val FULL_TURN = 360 +private const val HALF_TURN = 180 +private const val QUARTER_TURN = 90 + +/** + * This widget aggregates the attitude and location data of the aircraft + * into one widget. This includes - + * - Position of the aircraft relative to the pilot + * - Distance of the aircraft from the pilot + * - Heading of the aircraft relative to the pilot + * - True north relative to the pilot and the aircraft + * - The aircraft's last recorded home location + * - Attitude of the aircraft + * - Yaw of the gimbal + */ +open class CompassWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ConstraintLayoutWidget(context, attrs, defStyleAttr) { + + //region Fields + private var halfNorthIconWidth = 0f + private var halfAttitudeBallWidth = 0f + private var paddingWidth = 0f + private var paddingHeight = 0f + + private val homeImageView: ImageView = findViewById(R.id.imageview_compass_home) + private val rcImageView: ImageView = findViewById(R.id.imageview_compass_rc) + private val aircraftImageView: ImageView = findViewById(R.id.imageview_compass_aircraft) + private val gimbalYawImageView: ImageView = findViewById(R.id.imageview_gimbal_heading) + private val innerCirclesImageView: ImageView = findViewById(R.id.imageview_inner_circles) + private val northImageView: ImageView = findViewById(R.id.imageview_north) + private val compassBackgroundImageView: ImageView = findViewById(R.id.imageview_compass_background) + private val aircraftAttitudeProgressBar: ProgressBar = findViewById(R.id.progressbar_compass_attitude) + private val visualCompassView: VisualCompassView = findViewById(R.id.visual_compass_view) + private val gimbalYawView: GimbalYawView = findViewById(R.id.gimbal_yaw_view) + + private val widgetModel: CompassWidgetModel by lazy { + CompassWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + context.getSystemService(Context.SENSOR_SERVICE) as SensorManager, + context.getSystemService(Context.WINDOW_SERVICE) as WindowManager + ) + } + + /** + * The drawable resource for the home icon + */ + var homeIcon: Drawable + get() = homeImageView.drawable + set(icon) { + homeImageView.setImageDrawable(icon) + } + + /** + * The drawable resource for the home icon's background + */ + var homeIconBackground: Drawable + get() = homeImageView.background + set(background) { + homeImageView.background = background + } + + /** + * The drawable resource for the RC location icon + */ + var rcLocationIcon: Drawable + @JvmName("getRCLocationIcon") + get() = rcImageView.drawable + @JvmName("setRCLocationIcon") + set(icon) { + rcImageView.setImageDrawable(icon) + } + + /** + * The drawable resource for the RC location icon's background + */ + var rcLocationIconBackground: Drawable + @JvmName("getRCLocationIconBackground") + get() = rcImageView.background + @JvmName("setRCLocationIconBackground") + set(background) { + rcImageView.background = background + } + + /** + * The drawable resource for the aircraft icon + */ + var aircraftIcon: Drawable + get() = aircraftImageView.drawable + set(icon) { + aircraftImageView.setImageDrawable(icon) + } + + /** + * The drawable resource for the aircraft icon's background + */ + var aircraftIconBackground: Drawable + get() = aircraftImageView.background + set(background) { + aircraftImageView.background = background + } + + /** + * The drawable resource for the gimbal yaw icon + */ + var gimbalYawIcon: Drawable + get() = gimbalYawImageView.drawable + set(icon) { + gimbalYawImageView.setImageDrawable(icon) + } + + /** + * The drawable resource for the gimbal yaw icon's background + */ + var gimbalYawIconBackground: Drawable + get() = gimbalYawImageView.background + set(background) { + gimbalYawImageView.background = background + } + + /** + * The drawable resource for the north icon + */ + var northIcon: Drawable + get() = northImageView.drawable + set(icon) { + northImageView.setImageDrawable(icon) + } + + /** + * The drawable resource for the north icon's background + */ + var northIconBackground: Drawable + get() = northImageView.background + set(background) { + northImageView.background = background + } + + /** + * The drawable resource for the inner circles icon + */ + var innerCirclesIcon: Drawable + get() = innerCirclesImageView.drawable + set(icon) { + innerCirclesImageView.setImageDrawable(icon) + } + + /** + * The drawable resource for the inner circles icon's background + */ + var innerCirclesIconBackground: Drawable + get() = innerCirclesImageView.background + set(background) { + innerCirclesImageView.background = background + } + + /** + * The drawable resource for the compass background icon + */ + var compassBackgroundIcon: Drawable + get() = compassBackgroundImageView.drawable + set(icon) { + compassBackgroundImageView.setImageDrawable(icon) + } + + /** + * The drawable resource for the compass background icon's background + */ + var compassBackgroundIconBackground: Drawable + get() = compassBackgroundImageView.background + set(background) { + compassBackgroundImageView.background = background + } + + /** + * The drawable resource for the aircraft attitude icon + */ + var aircraftAttitudeIcon: Drawable? + get() = aircraftAttitudeProgressBar.progressDrawable + set(icon) { + aircraftAttitudeProgressBar.progressDrawable = icon + } + + /** + * The drawable resource for the aircraft attitude icon's background + */ + var aircraftAttitudeIconBackground: Drawable + get() = aircraftAttitudeProgressBar.background + set(background) { + aircraftAttitudeProgressBar.background = background + } + + /** + * The stroke width in px for the lines in the visual compass view + */ + var visualCompassViewStrokeWidth: Float + @FloatRange(from = 1.0, to = VisualCompassView.MAX_LINE_WIDTH.toDouble()) + get() = visualCompassView.strokeWidth + set(@FloatRange(from = 1.0, to = VisualCompassView.MAX_LINE_WIDTH.toDouble()) strokeWidth) { + visualCompassView.strokeWidth = strokeWidth + } + + /** + * The color for the lines in the visual compass view + */ + var visualCompassViewLineColor: Int + @ColorInt + get() = visualCompassView.lineColor + set(@ColorInt color) { + visualCompassView.lineColor = color + } + + /** + * The interval between the lines in the visual compass view + */ + var visualCompassViewLineInterval: Int + get() = visualCompassView.lineInterval + set(@IntRange(from = 1) interval) { + visualCompassView.lineInterval = interval + } + + /** + * The number of lines to be drawn in the visual compass view + */ + var visualCompassViewNumberOfLines: Int + get() = visualCompassView.numberOfLines + set(@IntRange(from = 3) numberOfLines) { + visualCompassView.numberOfLines = numberOfLines + } + + /** + * The stroke width in px for the lines in the gimbal yaw view + */ + var gimbalYawViewStrokeWidth: Float + get() = gimbalYawView.strokeWidth + set(@FloatRange(from = 1.0, to = GimbalYawView.MAX_LINE_WIDTH.toDouble()) strokeWidth) { + gimbalYawView.strokeWidth = strokeWidth + } + + /** + * The yaw color in the gimbal yaw view + */ + var gimbalYawViewYawColor: Int + @ColorInt + get() = gimbalYawView.yawColor + set(@ColorInt color) { + gimbalYawView.yawColor = color + } + + /** + * The invalid color in the gimbal yaw view + */ + var gimbalYawViewInvalidColor: Int + @ColorInt + get() = gimbalYawView.invalidColor + set(@ColorInt color) { + gimbalYawView.invalidColor = color + } + + /** + * Set the blink color in the gimbal yaw view + */ + var gimbalYawViewBlinkColor: Int + @ColorInt + get() = gimbalYawView.blinkColor + set(@ColorInt color) { + gimbalYawView.blinkColor = color + } + + //endregion + + //region Constructor + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + View.inflate(context, R.layout.uxsdk_widget_compass, this) + } + + init { + attrs?.let { initAttributes(context, it) } + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { + super.onLayout(changed, left, top, right, bottom) + if (!isInEditMode) { + synchronized(this) { + gimbalYawImageView.pivotX = gimbalYawImageView.measuredWidth / 2f + gimbalYawImageView.pivotY = gimbalYawImageView.measuredHeight.toFloat() + } + halfNorthIconWidth = northImageView.width.toFloat() / 2 + halfAttitudeBallWidth = compassBackgroundImageView.width.toFloat() / 2 + paddingWidth = width.toFloat() - compassBackgroundImageView.width + paddingHeight = height.toFloat() - compassBackgroundImageView.height + } + } + + override fun reactToModelChanges() { + addReaction(widgetModel.compassWidgetState + .observeOn(SchedulerProvider.ui()) + .subscribe { compassWidgetState -> onCompassStateUpdated(compassWidgetState) }) + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + } + //endregion + + //region Reaction Helpers + private fun onCompassStateUpdated(compassWidgetState: CompassWidgetState) { + widgetStateDataProcessor.onNext(CompassStateUpdated(compassWidgetState)) + updateAircraftAttitudeUI(compassWidgetState.aircraftAttitude) + updateNorthHeadingUI(compassWidgetState.phoneAzimuth) + updateAircraftHeadingUI(compassWidgetState.phoneAzimuth, compassWidgetState.aircraftAttitude) + + val viewCoordinates = getAircraftLocationCoordinates(compassWidgetState.phoneAzimuth, compassWidgetState.aircraftState, compassWidgetState.currentLocationState) + updateAircraftLocationUI( + getMaxDistance(compassWidgetState.aircraftState, compassWidgetState.currentLocationState), + calculateScale(compassWidgetState.aircraftState.distance), + viewCoordinates + ) + + updateGimbalHeadingUI(compassWidgetState.gimbalHeading, compassWidgetState.aircraftAttitude.yaw.toFloat() - compassWidgetState.phoneAzimuth) + + val secondViewCoordinates = getSecondGPSLocationCoordinates(compassWidgetState.phoneAzimuth, compassWidgetState.currentLocationState, compassWidgetState.aircraftState) + updateSecondGPSLocationUI(compassWidgetState.centerType, secondViewCoordinates) + } + //endregion + + //region Calculations + private fun getSecondGPSLocationCoordinates( + phoneAzimuth: Float, + state: CurrentLocationState, + aircraftState: AircraftState + ): ViewCoordinates { + val radians = Math.toRadians(state.angle + phoneAzimuth.toDouble()) + val maxDistance = getMaxDistance(aircraftState, state) + val rcHomeDistance = state.distance + val x: Float + val y: Float + if (rcHomeDistance == maxDistance) { + x = cos(radians).toFloat() + y = sin(radians).toFloat() + } else { + x = (rcHomeDistance * cos(radians) / maxDistance).toFloat() + y = (rcHomeDistance * sin(radians) / maxDistance).toFloat() + } + return ViewCoordinates(x, y) + } + + private fun getMaxDistance( + aircraftState: AircraftState, + state: CurrentLocationState + ): Float { + var maxDistance = aircraftState.distance + if (maxDistance < state.distance) { + maxDistance = state.distance + } + if (maxDistance < MAX_DISTANCE) { + maxDistance = MAX_DISTANCE.toFloat() + } + return maxDistance + } + + private fun getAircraftLocationCoordinates( + phoneAzimuth: Float, + aircraftState: AircraftState, + state: CurrentLocationState + ): ViewCoordinates { + val maxDistance = getMaxDistance(aircraftState, state) + val radians = Math.toRadians(aircraftState.angle + phoneAzimuth.toDouble()) + val aircraftDistance = aircraftState.distance + val x: Float + val y: Float + if (aircraftDistance >= maxDistance) { + x = cos(radians).toFloat() + y = sin(radians).toFloat() + } else { + x = (aircraftDistance * cos(radians) / maxDistance).toFloat() + y = (aircraftDistance * sin(radians) / maxDistance).toFloat() + } + return ViewCoordinates(x, y) + } + + private fun calculateScale(distance: Float): Float { + var scale = 1.0f + if (distance >= MAX_SCALE_DISTANCE) { + scale = MIN_SCALE + } else if (distance > MAX_DISTANCE) { + scale = 1 - MIN_SCALE + (MAX_SCALE_DISTANCE - distance) / (MAX_SCALE_DISTANCE - MAX_DISTANCE) * MIN_SCALE + } + return scale + } + + //endregion + //region update UI + private fun updateNorthHeadingUI(phoneAzimuth: Float) { + // update north image + val northRadian = Math.toRadians((FULL_TURN - phoneAzimuth) % FULL_TURN.toDouble()) + val moveX = (halfAttitudeBallWidth + paddingWidth / 2 + halfAttitudeBallWidth * sin(northRadian)).toFloat() + val moveY = (halfAttitudeBallWidth + paddingHeight / 2 - halfAttitudeBallWidth * cos(northRadian)).toFloat() + northImageView.x = moveX - halfNorthIconWidth + northImageView.y = moveY - halfNorthIconWidth + } + + private fun updateAircraftAttitudeUI(aircraftAttitude: Attitude) { + //Update aircraft roll + aircraftAttitudeProgressBar.rotation = aircraftAttitude.roll.toFloat() + + //Update aircraft pitch + val tempPitch = (-aircraftAttitude.pitch).toFloat() + QUARTER_TURN + var progress = (tempPitch * 100 / HALF_TURN).toInt() + if (progress < MIN_PROGRESS) { + progress = MIN_PROGRESS + } else if (progress > MAX_PROGRESS) { + progress = MAX_PROGRESS + } + if (aircraftAttitudeProgressBar.progress != progress) { + aircraftAttitudeProgressBar.progress = progress + } + } + + private fun updateAircraftHeadingUI(phoneAzimuth: Float, aircraftAttitude: Attitude) { + aircraftImageView.rotation = aircraftAttitude.yaw.toFloat() - phoneAzimuth + } + + private fun updateAircraftLocationUI(maxDistance: Float, scale: Float, viewCoordinates: ViewCoordinates) { + val wRadius = (measuredWidth - paddingWidth - aircraftImageView.width) / 2.0f + val hRadius = (measuredHeight - paddingHeight - aircraftImageView.height) / 2.0f + + //update the size and heading of the aircraft + aircraftImageView.x = paddingWidth / 2.0f + wRadius + viewCoordinates.x * wRadius + aircraftImageView.y = paddingHeight / 2.0f + hRadius - viewCoordinates.y * hRadius + aircraftImageView.scaleX = scale + aircraftImageView.scaleY = scale + + // Update the size and heading of the gimbal + gimbalYawImageView.x = (aircraftImageView.x + aircraftImageView.width / 2f + - gimbalYawImageView.width / 2f) + gimbalYawImageView.y = (aircraftImageView.y + aircraftImageView.height / 2f + - gimbalYawImageView.height) + gimbalYawImageView.scaleX = scale + gimbalYawImageView.scaleY = scale + + //update the compass view + visualCompassView.visibility = View.VISIBLE + innerCirclesImageView.visibility = View.GONE + visualCompassView.setDistance(maxDistance) + } + + private fun updateGimbalHeadingUI(gimbalHeading: Float, rotationOffset: Float) { + gimbalYawView.setYaw(gimbalHeading) + gimbalYawImageView.rotation = gimbalHeading + rotationOffset + } + + private fun updateSecondGPSLocationUI( + type: CenterType, + viewCoordinates: ViewCoordinates + ) { + // Calculate the second GPS image's parameters using the center point's parameters + val centerGPSImage: ImageView? + val secondGPSImage: ImageView? + if (type == CenterType.HOME_GPS) { + centerGPSImage = homeImageView + secondGPSImage = rcImageView + } else { + centerGPSImage = rcImageView + secondGPSImage = homeImageView + } + centerGPSImage.visibility = View.VISIBLE + val centerParam = centerGPSImage.layoutParams as LayoutParams + centerParam.leftMargin = 0 + centerParam.topMargin = 0 + centerGPSImage.layoutParams = centerParam + + //Updating second GPS location and show the second GPS image if both exist + if (type != CenterType.HOME_GPS) { + secondGPSImage.visibility = View.VISIBLE + val wRadius = (measuredWidth - paddingWidth - secondGPSImage.width) / 2.0f + val hRadius = (measuredHeight - paddingHeight - secondGPSImage.height) / 2.0f + secondGPSImage.x = paddingWidth / 2.0f + wRadius + viewCoordinates.x * wRadius + secondGPSImage.y = paddingHeight / 2.0f + hRadius - viewCoordinates.y * hRadius + } else { + secondGPSImage.visibility = View.GONE + } + } + //endregion + + //region Customization + override fun getIdealDimensionRatioString(): String { + return getString(R.string.uxsdk_widget_compass_ratio) + } + + /** + * Get the index of the gimbal to which the widget is reacting + * + * @return [GimbalIndex] + */ + fun getGimbalIndex(): ComponentIndexType { + return widgetModel.getGimbalIndex() + } + + /** + * Set the index of gimbal to which the widget should react + * + * @param gimbalIndex index of the gimbal. + */ + fun setGimbalIndex(gimbalIndex: ComponentIndexType?) { + if (!isInEditMode) { + widgetModel.setGimbalIndex(gimbalIndex) + } + } + + /** + * Set the resource ID for the home icon + * + * @param resourceId Integer ID of the drawable resource + */ + fun setHomeIcon(@DrawableRes resourceId: Int) { + homeImageView.setImageResource(resourceId) + } + + /** + * Set the resource ID for the home icon's background + * + * @param resourceId Integer ID of the icon's background resource + */ + fun setHomeIconBackground(@DrawableRes resourceId: Int) { + homeImageView.setBackgroundResource(resourceId) + } + + /** + * Set the resource ID for the RC location icon + * + * @param resourceId Integer ID of the drawable resource + */ + fun setRCLocationIcon(@DrawableRes resourceId: Int) { + rcImageView.setImageResource(resourceId) + } + + /** + * Set the resource ID for the RC location icon's background + * + * @param resourceId Integer ID of the icon's background resource + */ + fun setRCLocationIconBackground(@DrawableRes resourceId: Int) { + rcImageView.setBackgroundResource(resourceId) + } + + /** + * Set the resource ID for the aircraft icon + * + * @param resourceId Integer ID of the drawable resource + */ + fun setAircraftIcon(@DrawableRes resourceId: Int) { + aircraftImageView.setImageResource(resourceId) + } + + /** + * Set the resource ID for the aircraft icon's background + * + * @param resourceId Integer ID of the icon's background resource + */ + fun setAircraftIconBackground(@DrawableRes resourceId: Int) { + aircraftImageView.setBackgroundResource(resourceId) + } + + /** + * Set the resource ID for the gimbal yaw icon + * + * @param resourceId Integer ID of the drawable resource + */ + fun setGimbalYawIcon(@DrawableRes resourceId: Int) { + gimbalYawImageView.setImageResource(resourceId) + } + + /** + * Set the resource ID for the gimbal yaw icon's background + * + * @param resourceId Integer ID of the icon's background resource + */ + fun setGimbalYawIconBackground(@DrawableRes resourceId: Int) { + gimbalYawImageView.setBackgroundResource(resourceId) + } + + /** + * Set the resource ID for the north icon + * + * @param resourceId Integer ID of the drawable resource + */ + fun setNorthIcon(@DrawableRes resourceId: Int) { + northImageView.setImageResource(resourceId) + } + + /** + * Set the resource ID for the north icon's background + * + * @param resourceId Integer ID of the icon's background resource + */ + fun setNorthIconBackground(@DrawableRes resourceId: Int) { + northImageView.setBackgroundResource(resourceId) + } + + /** + * Set the resource ID for the inner circles icon + * + * @param resourceId Integer ID of the drawable resource + */ + fun setInnerCirclesIcon(@DrawableRes resourceId: Int) { + innerCirclesImageView.setImageResource(resourceId) + } + + /** + * Set the resource ID for the inner circles icon's background + * + * @param resourceId Integer ID of the icon's background resource + */ + fun setInnerCirclesIconBackground(@DrawableRes resourceId: Int) { + innerCirclesImageView.setBackgroundResource(resourceId) + } + + /** + * Set the resource ID for the compass background icon + * + * @param resourceId Integer ID of the drawable resource + */ + fun setCompassBackgroundIcon(@DrawableRes resourceId: Int) { + compassBackgroundImageView.setImageResource(resourceId) + } + + /** + * Set the resource ID for the compass background icon's background + * + * @param resourceId Integer ID of the icon's background resource + */ + fun setCompassBackgroundIconBackground(@DrawableRes resourceId: Int) { + compassBackgroundImageView.setBackgroundResource(resourceId) + } + + /** + * Set the resource ID for the aircraft attitude icon's background + * + * @param resourceId Integer ID of the icon's background resource + */ + fun setAircraftAttitudeIconBackground(@DrawableRes resourceId: Int) { + aircraftAttitudeProgressBar.setBackgroundResource(resourceId) + } + //endregion + + //region Customization Helpers + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.CompassWidget).use { typedArray -> + typedArray.getIntAndUse(R.styleable.CompassWidget_uxsdk_cameraIndex) { + setGimbalIndex(ComponentIndexType.find(it)) + } + typedArray.getDrawableAndUse(R.styleable.CompassWidget_uxsdk_homeIcon) { + homeIcon = it + } + typedArray.getDrawableAndUse(R.styleable.CompassWidget_uxsdk_rcLocationIcon) { + rcLocationIcon = it + } + typedArray.getDrawableAndUse(R.styleable.CompassWidget_uxsdk_aircraftIcon) { + aircraftIcon = it + } + typedArray.getDrawableAndUse(R.styleable.CompassWidget_uxsdk_gimbalYawIcon) { + gimbalYawIcon = it + } + typedArray.getDrawableAndUse(R.styleable.CompassWidget_uxsdk_northIcon) { + northIcon = it + } + typedArray.getDrawableAndUse(R.styleable.CompassWidget_uxsdk_innerCirclesIcon) { + innerCirclesIcon = it + } + typedArray.getDrawableAndUse(R.styleable.CompassWidget_uxsdk_compassBackgroundIcon) { + compassBackgroundIcon = it + } + typedArray.getDrawableAndUse(R.styleable.CompassWidget_uxsdk_aircraftAttitudeIcon) { + aircraftAttitudeIcon = it + } + typedArray.getDimensionAndUse(R.styleable.CompassWidget_uxsdk_visualCompassViewStrokeWidth) { + visualCompassViewStrokeWidth = it + } + typedArray.getColorAndUse(R.styleable.CompassWidget_uxsdk_visualCompassViewLineColor) { + visualCompassViewLineColor = it + } + typedArray.getIntegerAndUse(R.styleable.CompassWidget_uxsdk_visualCompassViewLineInterval) { + visualCompassViewLineInterval = it + } + typedArray.getIntegerAndUse(R.styleable.CompassWidget_uxsdk_visualCompassViewNumberOfLines) { + visualCompassViewNumberOfLines = it + } + typedArray.getDimensionAndUse(R.styleable.CompassWidget_uxsdk_gimbalYawViewStrokeWidth) { + gimbalYawViewStrokeWidth = it + } + typedArray.getColorAndUse(R.styleable.CompassWidget_uxsdk_gimbalYawViewYawColor) { + gimbalYawViewYawColor = it + } + typedArray.getColorAndUse(R.styleable.CompassWidget_uxsdk_gimbalYawViewInvalidColor) { + gimbalYawViewInvalidColor = it + } + typedArray.getColorAndUse(R.styleable.CompassWidget_uxsdk_gimbalYawViewBlinkColor) { + gimbalYawViewBlinkColor = it + } + } + } + //endregion + + //region Classes + /** + * Wrapper that holds the x and y values of the view coordinates + */ + private inner class ViewCoordinates internal constructor(val x: Float, val y: Float) + //endregion + + //region Hooks + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines the widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Compass state update + */ + data class CompassStateUpdated(val compassWidgetState: CompassWidgetState) : ModelState() + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/compass/CompassWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/compass/CompassWidgetModel.kt new file mode 100644 index 00000000..75858c6f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/compass/CompassWidgetModel.kt @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +package dji.v5.ux.core.widget.compass + +import android.hardware.Sensor +import android.hardware.SensorEvent +import android.hardware.SensorEventListener +import android.hardware.SensorManager +import android.location.Location +import android.location.LocationListener +import android.os.Bundle +import android.view.Surface +import android.view.WindowManager +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.key.GimbalKey +import dji.sdk.keyvalue.key.RemoteControllerKey +import dji.sdk.keyvalue.value.common.Attitude +import dji.sdk.keyvalue.value.common.LocationCoordinate2D +import dji.sdk.keyvalue.value.remotecontroller.RcGPSInfo +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.value.common.ComponentIndexType +import dji.v5.utils.common.LocationUtil +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.* +import kotlin.math.abs + +private const val SENSOR_SENSITIVE_PARAM = 2 +private const val HALF_TURN = 180 +private const val QUARTER_TURN = 90 + +/** + * Widget Model for the [CompassWidget] used to define + * the underlying logic and communication + */ +class CompassWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, + private val sensorManager: SensorManager?, + private val windowManager: WindowManager?, +) : WidgetModel(djiSdkModel, keyedStore), SensorEventListener, LocationListener { + + private val homeLocationProcessor = DataProcessor.create(LocationCoordinate2D(Double.NaN, Double.NaN)) + private val aircraftLocationProcessor = DataProcessor.create(LocationCoordinate2D(Double.NaN, Double.NaN)) + private val rcGPSDataProcessor: DataProcessor = DataProcessor.create(RcGPSInfo()) + private val gimbalYawProcessor: DataProcessor = DataProcessor.create(0.0) + private val centerTypeProcessor: DataProcessor = DataProcessor.create(CenterType.HOME_GPS) + private val mobileDeviceAzimuthProcessor: DataProcessor = DataProcessor.create(0f) + private val aircraftAttitudeProcessor: DataProcessor = DataProcessor.create(Attitude()) + private val aircraftStateProcessor: DataProcessor = DataProcessor.create(AircraftState(0f, 0f)) + private val currentLocationStateProcessor: DataProcessor = DataProcessor.create(CurrentLocationState(0f, 0f)) + + private val compassWidgetStateProcessor: DataProcessor = DataProcessor.create( + CompassWidgetState( + 0f, + Attitude(0.0, 0.0, 0.0), + AircraftState(0f, 0f), + CurrentLocationState(0f, 0f), + 0f, + CenterType.HOME_GPS + ) + ) + + private var rotationVector: Sensor? = null + private var rcOrMobileLatitude = 0.0 + private var rcOrMobileLongitude = 0.0 + private var latestSensorValue = 0f + private var gimbalIndex = ComponentIndexType.LEFT_OR_MAIN + + /** + * values[0]: azimuth, rotation around the Z axis. + * values[1]: pitch, rotation around the X axis. + * values[2]: roll, rotation around the Y axis. + */ + private val values = FloatArray(3) + private val rotations = FloatArray(9) + + /** + * The state of the compass widget + */ + val compassWidgetState: Flowable + get() = compassWidgetStateProcessor.toFlowable() + + //endregion + + //region Lifecycle + override fun inSetup() { + + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAircraftAttitude), aircraftAttitudeProcessor) + + // Set the home location when changed and update the various calculations + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyHomeLocation), homeLocationProcessor) { + updateCalculations() + } + + // Update the aircraft's location + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAircraftLocation), aircraftLocationProcessor) { + calculateAircraftAngleAndDistanceFromCenterLocation() + } + + // Update the RC's location + bindDataProcessor( + KeyTools.createKey( + RemoteControllerKey.KeyRcGPSInfo), rcGPSDataProcessor) { + updateGPSData(it) + } + + // Update the gimbal heading + bindDataProcessor( + KeyTools.createKey( + GimbalKey.KeyYawRelativeToAircraftHeading, gimbalIndex), gimbalYawProcessor) + registerMobileDeviceSensorListener() + + // Start mobile device's location updates if available + MobileGPSLocationUtil.getInstance().addLocationListener(this) + MobileGPSLocationUtil.getInstance().startUpdateLocation() + } + + override fun inCleanup() { + unregisterMobileDeviceSensorListener() + + // Stop mobile device's location updates if available + MobileGPSLocationUtil.getInstance()?.removeLocationListener(this) + } + //endregion + + //region Updates + override fun updateStates() { + compassWidgetStateProcessor.onNext( + CompassWidgetState( + mobileDeviceAzimuthProcessor.value, + aircraftAttitudeProcessor.value, + aircraftStateProcessor.value, + currentLocationStateProcessor.value, + gimbalYawProcessor.value.toFloat(), + centerTypeProcessor.value + ) + ) + } + //endregion + + //region Mobile Device Sensor listener + private fun registerMobileDeviceSensorListener() { + if (sensorManager != null) { + // Register the mobile device's rotation sensor to start listening for updates + // DJI devices cannot get rotation from TYPE_ROTATION_VECTOR, so use TYPE_ORIENTATION + rotationVector = if (DJIDeviceUtil.isDJIDevice()) { + sensorManager.getDefaultSensor(Sensor.TYPE_ORIENTATION) + } else { + sensorManager.getDefaultSensor(Sensor.TYPE_ROTATION_VECTOR) + } + if (rotationVector != null) { + sensorManager.registerListener(this, rotationVector, SensorManager.SENSOR_DELAY_UI) + } + } + } + + private fun unregisterMobileDeviceSensorListener() { + sensorManager?.unregisterListener(this, rotationVector) + } + + override fun onSensorChanged(event: SensorEvent) { + // Update the mobile device azimuth when updated by the sensor + var sensorValue = latestSensorValue + if (event.sensor.type == Sensor.TYPE_ORIENTATION) { + sensorValue = event.values[0] + } else if (event.sensor.type == Sensor.TYPE_ROTATION_VECTOR) { + MathUtil.getRotationMatrixFromVector(rotations, event.values) + SensorManager.getOrientation(rotations, values) + sensorValue = Math.toDegrees(values[0].toDouble()).toFloat() + } + if (abs(sensorValue - latestSensorValue) > SENSOR_SENSITIVE_PARAM) { + latestSensorValue = sensorValue + val rotation: Int = getDisplayRotation() + if (rotation == Surface.ROTATION_270) { + sensorValue += HALF_TURN.toFloat() + } + if (DJIDeviceUtil.isSmartController()) { + sensorValue += QUARTER_TURN.toFloat() + } + val mobileDeviceAzimuth = sensorValue + QUARTER_TURN + mobileDeviceAzimuthProcessor.onNext(mobileDeviceAzimuth) + } + updateStates() + } + + override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) { + // Do nothing + } + + override fun onLocationChanged(location: Location) { + // Update the center type to be the RC/Mobile device type + centerTypeProcessor.onNext(CenterType.RC_MOBILE_GPS) + // Update location using received location of the mobile device + rcOrMobileLatitude = location.latitude + rcOrMobileLongitude = location.longitude + updateCalculations() + updateStates() + } + + override fun onStatusChanged(provider: String, status: Int, extras: Bundle) { + // Do nothing + } + + override fun onProviderEnabled(provider: String) { + // Do nothing + } + + override fun onProviderDisabled(provider: String) { + // Do nothing + } + //endregion + + //region Helpers + private fun updateGPSData(data: RcGPSInfo) { + if (data.isValid) { + // Update the center type to be the RC/Mobile device type + centerTypeProcessor.onNext(CenterType.RC_MOBILE_GPS) + + // Update location using received location of the RC + rcOrMobileLatitude = data.location.latitude + rcOrMobileLongitude = data.location.longitude + + // Stop updating mobile device location once RC location is received + MobileGPSLocationUtil.getInstance()?.removeLocationListener(this) + updateCalculations() + } + } + + private fun updateCalculations() { + calculateAircraftAngleAndDistanceFromCenterLocation() + calculateAngleAndDistanceBetweenRCAndHome() + } + + private fun calculateAircraftAngleAndDistanceFromCenterLocation() { + val tempCalculatedLocation: FloatArray + val latestAircraftState = AircraftState(0.0f, 0.0f) + if (centerTypeProcessor.value == CenterType.HOME_GPS) { + if (LocationUtil.checkLatitude(homeLocationProcessor.value.latitude) && LocationUtil.checkLongitude(homeLocationProcessor.value.longitude)) { + tempCalculatedLocation = LocationUtil.calculateAngleAndDistance( + homeLocationProcessor.value.latitude, + homeLocationProcessor.value.longitude, + aircraftLocationProcessor.value.latitude, + aircraftLocationProcessor.value.longitude + ) + latestAircraftState.angle = tempCalculatedLocation[0] + latestAircraftState.distance = tempCalculatedLocation[1] + aircraftStateProcessor.onNext(latestAircraftState) + } + } else if (centerTypeProcessor.value == CenterType.RC_MOBILE_GPS && LocationUtil.checkLatitude(rcOrMobileLatitude) && LocationUtil.checkLongitude( + rcOrMobileLongitude) + ) { + tempCalculatedLocation = LocationUtil.calculateAngleAndDistance( + rcOrMobileLatitude, + rcOrMobileLongitude, + aircraftLocationProcessor.value.latitude, + aircraftLocationProcessor.value.longitude + ) + latestAircraftState.angle = tempCalculatedLocation[0] + latestAircraftState.distance = tempCalculatedLocation[1] + aircraftStateProcessor.onNext(latestAircraftState) + + } + } + + private fun calculateAngleAndDistanceBetweenRCAndHome() { + if (centerTypeProcessor.value != CenterType.HOME_GPS) { + val tempCalculatedLocation = LocationUtil.calculateAngleAndDistance( + rcOrMobileLatitude, + rcOrMobileLongitude, + homeLocationProcessor.value.latitude, + homeLocationProcessor.value.longitude + ) + val latestCurrentLocationState = CurrentLocationState(0.0f, 0.0f) + latestCurrentLocationState.angle = tempCalculatedLocation[0] + latestCurrentLocationState.distance = tempCalculatedLocation[1] + currentLocationStateProcessor.onNext(latestCurrentLocationState) + } + } + + private fun getDisplayRotation(): Int { + var rotation = 0 + if (windowManager != null) { + rotation = windowManager.defaultDisplay.rotation + } + if (DJIDeviceUtil.isDJIDevice()) { + rotation = (rotation + 1) % 4 // DJI device default offset is 90, which is modified to support the turn screen function. + } + return rotation + } + //endregion + + //region Customization + /** + * Get the gimbal index for which the model is reacting. + * + * @return current gimbal index. + */ + fun getGimbalIndex(): ComponentIndexType { + return gimbalIndex + } + + /** + * Set gimbal index to which the model should react. + * + * @param gimbalIndex index of the gimbal. + */ + fun setGimbalIndex(gimbalIndex: ComponentIndexType?) { + if (gimbalIndex != null) { + this.gimbalIndex = gimbalIndex + } + restart() + } + //endregion + + //region Classes + /** + * Enum for the center type used in the calculations + */ + enum class CenterType { + /** + * The center is determined by RC location data or mobile device + * location data + */ + RC_MOBILE_GPS, + + /** + * The center is determined by the home location's data + */ + HOME_GPS + } + + /** + * Class that holds the aircraft's attitude with getters and setters + * for the [roll], [pitch] and [yaw] of the aircraft + */ + data class AircraftAttitude(var roll: Double, var pitch: Double, var yaw: Double) + + /** + * Class that holds the [angle] and [distance] between the aircraft and the + * home/RC/Mobile device's location. + */ + data class AircraftState(var angle: Float, var distance: Float) + + /** + * Class that holds the [angle] and [distance] between current home and RC/Mobile device + * locations + */ + data class CurrentLocationState(var angle: Float, var distance: Float) + + data class CompassWidgetState( + var phoneAzimuth: Float, + var aircraftAttitude: Attitude, + var aircraftState: AircraftState, + var currentLocationState: CurrentLocationState, + var gimbalHeading: Float, + var centerType: CenterType, + ) + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/compass/GimbalYawView.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/compass/GimbalYawView.kt new file mode 100644 index 00000000..52a90293 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/compass/GimbalYawView.kt @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +package dji.v5.ux.core.widget.compass + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Paint +import android.graphics.RectF +import android.util.AttributeSet +import android.view.View +import androidx.annotation.ColorInt +import androidx.annotation.FloatRange +import androidx.annotation.Px +import dji.v5.ux.R +import dji.v5.ux.core.extension.getColor +import dji.v5.ux.core.extension.getDimension + +private const val DEAD_ANGLE = 30 +private const val BLINK_ANGLE = 270 +private const val SHOW_ANGLE = 190 +private const val HIDE_ANGLE = 90 +private const val DURATION_BLINK: Long = 200 + +/** + * Custom view to display the aircraft gimbal's heading + */ +class GimbalYawView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : View(context, attrs, defStyleAttr) { + //region Fields + private val rect = RectF() + private val paint: Paint = Paint() + private var curBlinkColor = 0 + private var beforeShow = false + private var yaw = 0f + private var absYaw = 0f + private var yawStartAngle = 0f + private var yawSweepAngle = 0f + private var invalidStartAngle = 0f + private var invalidSweepAngle = 0f + + /** + * The stroke width for the lines in pixels + */ + @Px + @FloatRange(from = 1.0, to = MAX_LINE_WIDTH.toDouble()) + var strokeWidth = getDimension(R.dimen.uxsdk_gimbal_line_width) + set(@FloatRange(from = 1.0, to = MAX_LINE_WIDTH.toDouble()) strokeWidth) { + field = strokeWidth + postInvalidate() + } + + /** + * The yaw color + */ + @ColorInt + var yawColor = getColor(R.color.uxsdk_blue_material_A400) + set(@ColorInt yawColor) { + field = yawColor + postInvalidate() + } + + /** + * The invalid color + */ + @ColorInt + var invalidColor = getColor(R.color.uxsdk_red) + set(@ColorInt invalidColor) { + field = invalidColor + postInvalidate() + } + + /** + * The blink color + */ + @ColorInt + var blinkColor = getColor(R.color.uxsdk_red_material_900_30_percent) + set(@ColorInt blinkColor) { + field = blinkColor + postInvalidate() + } + //endregion + + //region Constructor + init { + init() + } + + private fun init() { + if (isInEditMode) { + return + } + + paint.strokeWidth = strokeWidth + paint.style = Paint.Style.STROKE + paint.isAntiAlias = true + } + //endregion + + //region UI Logic + + /** + * Set the yaw for the view + * + * @param yaw Yaw of the gimbal + */ + fun setYaw(yaw: Float) { + if (this.yaw != yaw) { + this.yaw = yaw + absYaw = if (yaw >= 0) yaw else 0 - yaw + if (absYaw >= SHOW_ANGLE) { + beforeShow = true + } else if (absYaw < HIDE_ANGLE) { + beforeShow = false + } + yawStartAngle = 0.0f + yawSweepAngle = 0.0f + invalidStartAngle = 0.0f + invalidSweepAngle = DEAD_ANGLE.toFloat() + if (this.yaw < 0) { + yawStartAngle = this.yaw + yawSweepAngle = 0 - this.yaw + } else { + invalidStartAngle = 0 - DEAD_ANGLE.toFloat() + yawSweepAngle = this.yaw + } + postInvalidate() + } + } + + override fun onDraw(canvas: Canvas) { + if (isInEditMode) { + return + } + val width: Float = if (width < height) { + width.toFloat() + } else { + height.toFloat() + } + val halfStroke = strokeWidth / 2.0f + val radius = width / 2 + rect[halfStroke, halfStroke, width - halfStroke] = width - halfStroke + canvas.save() + canvas.translate(radius, radius) + canvas.rotate(-90.0f) + canvas.translate(-radius, -radius) + if (absYaw >= BLINK_ANGLE) { + curBlinkColor = if (curBlinkColor == invalidColor) blinkColor else invalidColor + paint.color = curBlinkColor + canvas.drawArc(rect, invalidStartAngle, invalidSweepAngle, false, paint) + postInvalidateDelayed(DURATION_BLINK) + } else if (beforeShow) { + curBlinkColor = invalidColor + paint.color = invalidColor + canvas.drawArc(rect, invalidStartAngle, invalidSweepAngle, false, paint) + } + paint.color = yawColor + canvas.drawArc(rect, yawStartAngle, yawSweepAngle, false, paint) + canvas.restore() + } + //endregion + + companion object { + + /** + * The maximum width of the lines + */ + const val MAX_LINE_WIDTH = 4 + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/compass/VisualCompassView.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/compass/VisualCompassView.kt new file mode 100644 index 00000000..ef796ce1 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/compass/VisualCompassView.kt @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +package dji.v5.ux.core.widget.compass + +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.util.AttributeSet +import android.view.View +import androidx.annotation.ColorInt +import androidx.annotation.FloatRange +import androidx.annotation.Px +import dji.v5.ux.R +import dji.v5.ux.core.extension.getColor +import dji.v5.ux.core.extension.getDimension +import kotlin.math.ln + +private const val DEFAULT_INTERVAL = 100 +private const val DEFAULT_DISTANCE = 400 +private const val DEFAULT_NUMBER_OF_LINES = 4 + +/** + * Custom view to display the compass view for the aircraft + */ +class VisualCompassView @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : View(context, attrs, defStyleAttr) { + //region Fields + private val paint = Paint() + private var distance = DEFAULT_DISTANCE.toFloat() + + /** + * The interval between the lines + */ + var lineInterval = DEFAULT_INTERVAL + set(interval) { + field = interval + postInvalidate() + } + + /** + * The number of lines to be drawn + */ + var numberOfLines = DEFAULT_NUMBER_OF_LINES + set(lines) { + field = lines + postInvalidate() + } + + /** + * The stroke width for the lines in pixels + */ + @Px + @FloatRange(from = 1.0, to = MAX_LINE_WIDTH.toDouble()) + var strokeWidth = getDimension(R.dimen.uxsdk_line_width) + set(@FloatRange(from = 1.0, to = MAX_LINE_WIDTH.toDouble()) strokeWidth) { + field = strokeWidth + postInvalidate() + } + + /** + * The color for the lines + */ + @get:ColorInt + var lineColor: Int = getColor(R.color.uxsdk_white_47_percent) + set(color) { + field = color + postInvalidate() + } + + //endregion + + //region Constructor + init { + init() + } + + private fun init() { + if (isInEditMode) { + return + } + + paint.isAntiAlias = true + paint.color = getColor(R.color.uxsdk_white_20_percent) + paint.style = Paint.Style.STROKE + if (strokeWidth > MAX_LINE_WIDTH) { + strokeWidth = MAX_LINE_WIDTH.toFloat() + } + paint.strokeWidth = strokeWidth + } + //endregion + + //region UI Logic + override fun onDraw(canvas: Canvas) { + super.onDraw(canvas) + drawObstacleInfo(canvas) + } + + private fun findMod(distance: Float): Float { + val radarRadius = lineInterval * numberOfLines.toFloat() + var result = 0.0f + if (distance > radarRadius) { + result = (ln(distance / (lineInterval * numberOfLines).toDouble()) / ln(2.0)).toFloat() + result -= result.toInt() + } + return result + } + + private fun getVirtualColor(mod: Float): Int { + var color = lineColor + var alpha = Color.alpha(color) + alpha = (alpha * (1.0f - mod)).toInt() + color = Color.argb(alpha, Color.red(lineColor), Color.green(lineColor), Color.blue(lineColor)) + return color + } + + private fun drawDistance(canvas: Canvas) { + val mod = findMod(distance) + val width = width - 2 + val radius = width * 0.5f + val center = radius + 1 + val unitRadius = radius / (4.0f * (mod + 1.0f)) + val vColor = getVirtualColor(mod) + var dRadius: Float + paint.style = Paint.Style.STROKE + paint.color = lineColor + canvas.drawCircle(center, center, radius, paint) + var i = 1 + while (i * unitRadius < radius) { + if (i % 2 == 0) { + paint.color = lineColor + } else { + paint.color = vColor + } + dRadius = i * unitRadius + canvas.drawCircle(center, center, dRadius, paint) + i++ + } + } + + private fun drawObstacleInfo(canvas: Canvas) { + drawDistance(canvas) + } + + /** + * Set the real-world distance that is represented by the length from the center to the edge + * of the view. + */ + fun setDistance(distance: Float) { + if (this.distance != distance) { + this.distance = distance + postInvalidate() + } + } + //endregion + + companion object { + + /** + * The maximum width of the lines + */ + const val MAX_LINE_WIDTH = 4 + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/connection/ConnectionWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/connection/ConnectionWidget.kt new file mode 100644 index 00000000..64f2f1fa --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/connection/ConnectionWidget.kt @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.connection + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.View +import android.widget.ImageView +import androidx.annotation.DrawableRes +import androidx.core.content.res.use +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.SchedulerProvider +import io.reactivex.rxjava3.functions.Consumer +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.widget.FrameLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getDrawable +import dji.v5.ux.core.extension.getDrawableAndUse +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.extension.imageDrawable +import dji.v5.ux.core.widget.connection.ConnectionWidget.ModelState +import dji.v5.ux.core.widget.connection.ConnectionWidget.ModelState.ProductConnected +import dji.v5.ux.core.util.UxErrorHandle + +private const val TAG = "ConnectionWidget" + +/** + * This widget displays the connection status of the app with the product. + */ +open class ConnectionWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : FrameLayoutWidget(context, attrs, defStyleAttr) { + + //region Fields + /** + * Background drawable resource for the connectivity icon + */ + var connectivityIconBackground: Drawable? + get() = connectivityImageView.background + set(value) { + connectivityImageView.background = value + } + + /** + * The icon when the product is connected + */ + var connectedIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_connected) + set(value) { + field = value + checkAndUpdateIcon() + } + + /** + * The icon when the product is disconnected + */ + var disconnectedIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_disconnected) + set(value) { + field = value + checkAndUpdateIcon() + } + + private val widgetModel by lazy { + ConnectionWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()) + } + private val connectivityImageView: ImageView = findViewById(R.id.image_view_connection_status) + //endregion + + //region Constructor + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + View.inflate(context, R.layout.uxsdk_widget_connection, this) + } + + init { + attrs?.let { initAttributes(context, it) } + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe(this::updateUI)) + } + + //endregion + + //region Reactions to model + private fun updateUI(isConnected: Boolean) { + widgetStateDataProcessor.onNext(ProductConnected(isConnected)) + connectivityImageView.imageDrawable = if (isConnected) { + connectedIcon + } else { + disconnectedIcon + } + } + //endregion + + //region private helpers + private fun checkAndUpdateIcon() { + if (!isInEditMode) { + addDisposable(widgetModel.productConnection.lastOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(Consumer { updateUI(it) }, UxErrorHandle.logErrorConsumer(TAG, "product connection"))) + } + } + //endregion + + //region Customizations + override fun getIdealDimensionRatioString(): String { + return getString(R.string.uxsdk_widget_default_ratio) + } + + /** + * Set the resource ID for the icon when the product is disconnected + * + * @param resourceId Integer ID of the drawable resource + */ + fun setDisconnectedIcon(@DrawableRes resourceId: Int) { + disconnectedIcon = getDrawable(resourceId) + } + + /** + * Set the resource ID for the icon when the product is connected + * + * @param resourceId Integer ID of the drawable resource + */ + fun setConnectedIcon(@DrawableRes resourceId: Int) { + connectedIcon = getDrawable(resourceId) + } + + /** + * Set the resource ID for the connectivity icon's background + * + * @param resourceId Integer ID of the background resource + */ + fun setConnectivityIconBackground(@DrawableRes resourceId: Int) { + connectivityImageView.setBackgroundResource(resourceId) + } + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.ConnectionWidget).use { typedArray -> + typedArray.getDrawableAndUse(R.styleable.ConnectionWidget_uxsdk_iconBackground) { + connectivityIconBackground = it + } + typedArray.getDrawableAndUse(R.styleable.ConnectionWidget_uxsdk_connectedIcon) { + connectedIcon = it + } + typedArray.getDrawableAndUse(R.styleable.ConnectionWidget_uxsdk_disconnectedIcon) { + disconnectedIcon = it + } + } + } + //endregion + + //region Hooks + + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines the widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/connection/ConnectionWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/connection/ConnectionWidgetModel.kt new file mode 100644 index 00000000..63d2aebb --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/connection/ConnectionWidgetModel.kt @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.connection + +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore + +/** + * Widget Model for the [ConnectionWidget] + * Since the product connection is received from the base widget model + * this does not need to initialize any keys or return any data. + */ +class ConnectionWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + + //region Lifecycle + override fun inSetup() { + // Nothing to setup + } + + override fun inCleanup() { + // Nothing to clean up + } + + override fun updateStates() { // Nothing to update + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/distancehome/DistanceHomeWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/distancehome/DistanceHomeWidget.kt new file mode 100644 index 00000000..56ddf60d --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/distancehome/DistanceHomeWidget.kt @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.distancehome + +import android.content.Context +import android.util.AttributeSet +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.widget.BaseTelemetryWidget +import dji.v5.ux.core.communication.GlobalPreferencesManager +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getDistanceString +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.util.UnitConversionUtil +import dji.v5.ux.core.widget.distancehome.DistanceHomeWidget.ModelState +import dji.v5.ux.core.widget.distancehome.DistanceHomeWidget.ModelState.DistanceHomeStateUpdated +import dji.v5.ux.core.widget.distancehome.DistanceHomeWidget.ModelState.ProductConnected +import dji.v5.ux.core.widget.distancehome.DistanceHomeWidgetModel.DistanceHomeState +import java.text.DecimalFormat + +/** + * Widget displays the distance between the current location of the aircraft + * and the recorded home point. + */ +open class DistanceHomeWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + widgetTheme: Int = 0 +) : BaseTelemetryWidget( + context, + attrs, + defStyleAttr, + WidgetType.TEXT, + widgetTheme, + R.style.UXSDKDistanceHomeWidget +) { + + //region Fields + override val metricDecimalFormat: DecimalFormat = DecimalFormat("###0.0") + + override val imperialDecimalFormat: DecimalFormat = DecimalFormat("###0") + + private val widgetModel: DistanceHomeWidgetModel by lazy { + DistanceHomeWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + GlobalPreferencesManager.getInstance()) + } + //endregion + + //region Lifecycle + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + addReaction(widgetModel.distanceHomeState + .observeOn(SchedulerProvider.ui()) + .subscribe { updateUI(it) }) + } + //endregion + + //region Reactions to model + private fun updateUI(distanceHomeState: DistanceHomeState) { + widgetStateDataProcessor.onNext(DistanceHomeStateUpdated(distanceHomeState)) + if (distanceHomeState is DistanceHomeState.CurrentDistanceToHome) { + if(distanceHomeState.unitType == UnitConversionUtil.UnitType.IMPERIAL) { + setValueTextViewMinWidthByText("8888") + } else { + setValueTextViewMinWidthByText("888.8") + } + valueString = getDecimalFormat(distanceHomeState.unitType) + .format(distanceHomeState.distance).toString() + unitString = getDistanceString(distanceHomeState.unitType) + } else { + valueString = getString(R.string.uxsdk_string_default_value) + unitString = null + } + } + //endregion + + //region customizations + override fun getIdealDimensionRatioString(): String? = null + + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP) + + //endregion + + //region Hooks + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val boolean: Boolean) : ModelState() + + /** + * Distance to home state update + */ + data class DistanceHomeStateUpdated(val distanceHomeState: DistanceHomeState) : ModelState() + } + //endregion + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/distancehome/DistanceHomeWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/distancehome/DistanceHomeWidgetModel.kt new file mode 100644 index 00000000..e715449c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/distancehome/DistanceHomeWidgetModel.kt @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.distancehome + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.value.common.LocationCoordinate2D +import dji.sdk.keyvalue.key.KeyTools +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.GlobalPreferenceKeys +import dji.v5.ux.core.communication.GlobalPreferencesInterface +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.toDistance +import dji.v5.ux.core.util.DataProcessor +import dji.v5.utils.common.LocationUtil.* +import dji.v5.ux.core.util.UnitConversionUtil +import dji.v5.ux.core.widget.distancehome.DistanceHomeWidgetModel.DistanceHomeState.CurrentDistanceToHome + +/** + * Widget Model for the [DistanceHomeWidget] used to define + * the underlying logic and communication + */ +class DistanceHomeWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, + private val preferencesManager: GlobalPreferencesInterface? +) : WidgetModel(djiSdkModel, keyedStore) { + + private val homeLocationProcessor = DataProcessor.create(LocationCoordinate2D(Double.NaN, Double.NaN)) + private val aircraftLocationProcessor = DataProcessor.create(LocationCoordinate2D(Double.NaN, Double.NaN)) + private val unitTypeDataProcessor: DataProcessor = DataProcessor.create(UnitConversionUtil.UnitType.METRIC) + private val distanceHomeStateProcessor: DataProcessor = DataProcessor.create(DistanceHomeState.ProductDisconnected) + + /** + * Value of the distance to home state of the aircraft + */ + val distanceHomeState: Flowable + get() = distanceHomeStateProcessor.toFlowable() + + override fun inSetup() { + + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyHomeLocation), homeLocationProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAircraftLocation), aircraftLocationProcessor) + + val unitTypeKey = GlobalPreferenceKeys.create(GlobalPreferenceKeys.UNIT_TYPE) + bindDataProcessor(unitTypeKey, unitTypeDataProcessor) + preferencesManager?.setUpListener() + preferencesManager?.let { unitTypeDataProcessor.onNext(it.unitType) } + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + if (checkLatitude(aircraftLocationProcessor.value.latitude) + && checkLongitude(aircraftLocationProcessor.value.longitude) + && checkLatitude(homeLocationProcessor.value.latitude) + && checkLongitude(homeLocationProcessor.value.longitude)) { + distanceHomeStateProcessor.onNext( + CurrentDistanceToHome( + distanceBetween( + homeLocationProcessor.value.latitude, homeLocationProcessor.value.longitude, + aircraftLocationProcessor.value.latitude, aircraftLocationProcessor.value.longitude + ).toDistance(unitTypeDataProcessor.value), + unitTypeDataProcessor.value + ) + ) + } else { + distanceHomeStateProcessor.onNext(DistanceHomeState.LocationUnavailable) + } + } else { + distanceHomeStateProcessor.onNext(DistanceHomeState.ProductDisconnected) + } + } + + override fun inCleanup() { + preferencesManager?.cleanup() + } + + /** + * Class to represent states distance of aircraft from the home point + */ + sealed class DistanceHomeState { + /** + * Product is disconnected + */ + object ProductDisconnected : DistanceHomeState() + + /** + * Product is connected but gps location fix is unavailable + */ + object LocationUnavailable : DistanceHomeState() + + /** + * Reflecting the distance to the home point + */ + data class CurrentDistanceToHome(val distance: Float, val unitType: UnitConversionUtil.UnitType) : + DistanceHomeState() + + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/distancerc/DistanceRCWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/distancerc/DistanceRCWidget.kt new file mode 100644 index 00000000..10873721 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/distancerc/DistanceRCWidget.kt @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.distancerc + +import android.content.Context +import android.util.AttributeSet +import dji.v5.ux.R +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.widget.BaseTelemetryWidget +import dji.v5.ux.core.communication.GlobalPreferencesManager +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getDistanceString +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.util.UnitConversionUtil +import dji.v5.ux.core.widget.distancerc.DistanceRCWidget.ModelState +import dji.v5.ux.core.widget.distancerc.DistanceRCWidget.ModelState.ProductConnected +import dji.v5.ux.core.widget.distancerc.DistanceRCWidgetModel.DistanceRCState +import java.text.DecimalFormat + +/** + * Widget displays the distance between the current location of the aircraft + * and the remote controller location. + */ +open class DistanceRCWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + widgetTheme: Int = 0 +) : BaseTelemetryWidget( + context, + attrs, + defStyleAttr, + WidgetType.TEXT, + widgetTheme, + R.style.UXSDKDistanceRCWidget +) { + + //region Fields + override val metricDecimalFormat: DecimalFormat = DecimalFormat("###0.0") + + override val imperialDecimalFormat: DecimalFormat = DecimalFormat("###0") + + private val widgetModel: DistanceRCWidgetModel by lazy { + DistanceRCWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + GlobalPreferencesManager.getInstance()) + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + addReaction(widgetModel.distanceRCState + .observeOn(SchedulerProvider.ui()) + .subscribe { updateUI(it) }) + } + //endregion + + //region Reactions to model + private fun updateUI(distanceRCState: DistanceRCState) { + widgetStateDataProcessor.onNext(ModelState.DistanceRCStateUpdated(distanceRCState)) + if (distanceRCState is DistanceRCState.CurrentDistanceToRC) { + if(distanceRCState.unitType == UnitConversionUtil.UnitType.IMPERIAL) { + setValueTextViewMinWidthByText("8888") + } else { + setValueTextViewMinWidthByText("888.8") + } + valueString = getDecimalFormat(distanceRCState.unitType) + .format(distanceRCState.distance).toString() + unitString = getDistanceString(distanceRCState.unitType) + } else { + valueString = getString(R.string.uxsdk_string_default_value) + unitString = null + } + } + //endregion + + //region customizations + override fun getIdealDimensionRatioString(): String? = null + + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP) + + //endregion + + //region Hooks + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val boolean: Boolean) : ModelState() + + /** + * Distance RC model state + */ + data class DistanceRCStateUpdated(val distanceRCState: DistanceRCState) : ModelState() + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/distancerc/DistanceRCWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/distancerc/DistanceRCWidgetModel.kt new file mode 100644 index 00000000..5b4fec4d --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/distancerc/DistanceRCWidgetModel.kt @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.distancerc + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.key.RemoteControllerKey +import dji.sdk.keyvalue.value.common.LocationCoordinate2D +import dji.sdk.keyvalue.value.remotecontroller.RcGPSInfo +import dji.sdk.keyvalue.key.KeyTools +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.GlobalPreferenceKeys +import dji.v5.ux.core.communication.GlobalPreferencesInterface +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.toDistance +import dji.v5.ux.core.util.DataProcessor +import dji.v5.utils.common.LocationUtil +import dji.v5.utils.common.LocationUtil.distanceBetween +import dji.v5.ux.core.util.UnitConversionUtil +import dji.v5.ux.core.widget.distancerc.DistanceRCWidgetModel.DistanceRCState.* + +/** + * Widget Model for the [DistanceRCWidget] used to define + * the underlying logic and communication + */ +class DistanceRCWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, + private val preferencesManager: GlobalPreferencesInterface? +) : WidgetModel(djiSdkModel, keyedStore) { + + private val rcGPSDataProcessor: DataProcessor = DataProcessor.create(RcGPSInfo()) + private val unitTypeDataProcessor: DataProcessor = DataProcessor.create(UnitConversionUtil.UnitType.METRIC) + private val aircraftLocationProcessor = DataProcessor.create(LocationCoordinate2D(Double.NaN, Double.NaN)) + private val distanceRCStateProcessor: DataProcessor = DataProcessor.create(ProductDisconnected) + + /** + * Value of the distance to RC state of the aircraft + */ + val distanceRCState: Flowable + get() = distanceRCStateProcessor.toFlowable() + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAircraftLocation), aircraftLocationProcessor) + bindDataProcessor( + KeyTools.createKey( + RemoteControllerKey.KeyRcGPSInfo), rcGPSDataProcessor) + bindDataProcessor(GlobalPreferenceKeys.create(GlobalPreferenceKeys.UNIT_TYPE), unitTypeDataProcessor) + preferencesManager?.setUpListener() + preferencesManager?.let { unitTypeDataProcessor.onNext(it.unitType) } + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + if (LocationUtil.checkLatitude(aircraftLocationProcessor.value.latitude) + && LocationUtil.checkLongitude(aircraftLocationProcessor.value.longitude) + && rcGPSDataProcessor.value.isValid) { + distanceRCStateProcessor.onNext( + CurrentDistanceToRC( + distanceBetween( + aircraftLocationProcessor.value.latitude, + aircraftLocationProcessor.value.longitude, + rcGPSDataProcessor.value.location.latitude, + rcGPSDataProcessor.value.location.longitude + ) + .toDistance(unitTypeDataProcessor.value), + unitTypeDataProcessor.value + ) + ) + } else { + distanceRCStateProcessor.onNext(LocationUnavailable) + } + } else { + distanceRCStateProcessor.onNext(ProductDisconnected) + } + + } + + override fun inCleanup() { + preferencesManager?.cleanup() + } + + /** + * Class to represent states distance of aircraft from the remote controller + */ + sealed class DistanceRCState { + /** + * Product is disconnected + */ + object ProductDisconnected : DistanceRCState() + + /** + * Product is connected but GPS location fix is unavailable + */ + object LocationUnavailable : DistanceRCState() + + /** + * Reflecting the distance to the remote controller + */ + data class CurrentDistanceToRC(val distance: Float, val unitType: UnitConversionUtil.UnitType) : + DistanceRCState() + + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/flightmode/FlightModeWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/flightmode/FlightModeWidget.kt new file mode 100644 index 00000000..218170ea --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/flightmode/FlightModeWidget.kt @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.flightmode + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.PorterDuff +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.widget.ImageView +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.annotation.Dimension +import androidx.annotation.DrawableRes +import androidx.annotation.StyleRes +import androidx.constraintlayout.widget.ConstraintSet +import androidx.core.content.res.use +import dji.v5.utils.common.DisplayUtil +import dji.v5.ux.R +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.SchedulerProvider +import io.reactivex.rxjava3.functions.Consumer +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.util.UxErrorHandle +import dji.v5.ux.core.widget.flightmode.FlightModeWidget.ModelState +import dji.v5.ux.core.widget.flightmode.FlightModeWidget.ModelState.FlightModeUpdated +import dji.v5.ux.core.widget.flightmode.FlightModeWidget.ModelState.ProductConnected +import dji.v5.ux.core.widget.flightmode.FlightModeWidgetModel.FlightModeState + +private const val TAG = "FlightModeWidget" + +/** + * Shows the current flight mode next to a flight mode icon. + */ +open class FlightModeWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ConstraintLayoutWidget(context, attrs, defStyleAttr) { + + //region Fields + private val iconImageView: ImageView = findViewById(R.id.imageview_flight_mode_icon) + private val flightModeTextView: TextView = findViewById(R.id.textview_flight_mode_string) + private val widgetModel by lazy { + FlightModeWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()) + } + + /** + * The color of the icon when the product is connected + */ + @get:ColorInt + var connectedStateIconColor: Int = getColor(R.color.uxsdk_white) + set(@ColorInt value) { + field = value + checkAndUpdateUI() + } + + /** + * The color of the icon when the product is disconnected + */ + @get:ColorInt + var disconnectedStateIconColor: Int = getColor(R.color.uxsdk_gray_58) + set(@ColorInt value) { + field = value + checkAndUpdateUI() + } + + /** + * The color of the text when the product is connected + */ + @get:ColorInt + var connectedStateTextColor: Int = getColor(R.color.uxsdk_white) + set(@ColorInt value) { + field = value + checkAndUpdateUI() + } + + /** + * The color of the text when the product is disconnected + */ + @get:ColorInt + var disconnectedStateTextColor: Int = getColor(R.color.uxsdk_gray_58) + set(@ColorInt value) { + field = value + checkAndUpdateUI() + } + + /** + * Background of the flight mode text + */ + var textBackground: Drawable? + get() = flightModeTextView.background + set(value) { + flightModeTextView.background = value + } + + /** + * Text size for the flight mode + */ + var textSize: Float + @Dimension + get() = flightModeTextView.textSize + set(@Dimension textSize) { + flightModeTextView.textSize = textSize + } + + /** + * Icon for flight mode. When customizing the flight mode icon with an image that is not the + * default 1:1, use the [setIcon] method that takes a String ratio as well. + */ + var icon: Drawable? + get() = iconImageView.imageDrawable + set(value) { + iconImageView.imageDrawable = value + } + + /** + * Background of flight mode icon + */ + var iconBackground: Drawable? + get() = iconImageView.background + set(value) { + iconImageView.background = value + } + //endregion + + //region Constructor + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + inflate(context, R.layout.uxsdk_widget_flight_mode, this) + } + + init { + attrs?.let { initAttributes(context, it) } + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.flightModeState + .observeOn(SchedulerProvider.ui()) + .subscribe { this.updateUI(it) }) + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + + } + //endregion + + //region Reactions to model + private fun updateUI(flightModeState: FlightModeState) { + if (flightModeState is FlightModeState.FlightModeUpdated) { + if (flightModeState.flightModeString.equals("P-GPS")){ + flightModeTextView.text = "" + }else{ + flightModeTextView.text = flightModeState.flightModeString + } + iconImageView.setColorFilter(connectedStateIconColor, PorterDuff.Mode.SRC_IN) + flightModeTextView.setTextColor(connectedStateTextColor) + widgetStateDataProcessor.onNext(FlightModeUpdated(flightModeState.flightModeString)) + } else { + flightModeTextView.text = getString(R.string.uxsdk_string_default_value) + iconImageView.setColorFilter(disconnectedStateIconColor, PorterDuff.Mode.SRC_IN) + flightModeTextView.setTextColor(disconnectedStateTextColor) + } + } + + //endregion + + //region helpers + + private fun checkAndUpdateUI() { + if (!isInEditMode) { + addDisposable(widgetModel.flightModeState + .observeOn(SchedulerProvider.ui()) + .subscribe(Consumer { this.updateUI(it) }, UxErrorHandle.logErrorConsumer(TAG, "Update UI "))) + } + } + //endregion + + //region Customization + override fun getIdealDimensionRatioString(): String? = null + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.WRAP, + heightDimension = WidgetSizeDescription.Dimension.EXPAND) + + /** + * Set text appearance of the flight mode text view + * + * @param textAppearanceResId Style resource for text appearance + */ + fun setTextAppearance(@StyleRes textAppearanceResId: Int) { + flightModeTextView.setTextAppearance(context, textAppearanceResId) + } + + /** + * Set the resource ID for the background of the flight mode text view + * + * @param resourceId Integer ID of the drawable resource for the background + */ + fun setTextBackground(@DrawableRes resourceId: Int) { + textBackground = getDrawable(resourceId) + } + + /** + * Set the resource ID for the flight mode icon. If the ratio of the image is not the default + * 1:1, use the [setIcon] method that takes a String ratio as well. + * + * @param resourceId Integer ID of the drawable resource + */ + fun setIcon(@DrawableRes resourceId: Int) { + icon = getDrawable(resourceId) + } + + /** + * Set the flight mode icon with a custom ratio. + * + * @param drawable The drawable resource + * @param dimensionRatio String indicating the ratio of the custom icon + */ + fun setIcon(drawable: Drawable?, dimensionRatio: String) { + icon = drawable + + val set = ConstraintSet() + set.clone(this) + set.setDimensionRatio(iconImageView.id, dimensionRatio) + set.applyTo(this) + } + + /** + * Set the resource ID for the flight mode icon with a custom ratio. + * + * @param resourceId Integer ID of the drawable resource + * @param dimensionRatio String indicating the ratio of the custom icon + */ + fun setIcon(@DrawableRes resourceId: Int, dimensionRatio: String) { + setIcon(getDrawable(resourceId), dimensionRatio) + } + + /** + * Set the resource ID for the flight mode icon's background + * + * @param resourceId Integer ID of the background resource + */ + fun setIconBackground(@DrawableRes resourceId: Int) { + iconBackground = getDrawable(resourceId) + } + + //Initialize all customizable attributes + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.FlightModeWidget).use { typedArray -> + typedArray.getResourceIdAndUse(R.styleable.FlightModeWidget_uxsdk_textAppearance) { + setTextAppearance(it) + } + typedArray.getDrawableAndUse(R.styleable.FlightModeWidget_uxsdk_icon) { + val flightModeIconDimensionRatio = typedArray.getString( + R.styleable.FlightModeWidget_uxsdk_iconDimensionRatio, + getString(R.string.uxsdk_icon_flight_mode_ratio)) + setIcon(it, flightModeIconDimensionRatio) + } + typedArray.getDrawableAndUse(R.styleable.FlightModeWidget_uxsdk_iconBackground) { + iconBackground = it + } + typedArray.getDrawableAndUse(R.styleable.FlightModeWidget_uxsdk_textBackground) { + textBackground = it + } + typedArray.getDimensionAndUse(R.styleable.FlightModeWidget_uxsdk_textSize) { + textSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.FlightModeWidget_uxsdk_connectedStateIconColor) { + connectedStateIconColor = it + } + typedArray.getColorAndUse(R.styleable.FlightModeWidget_uxsdk_disconnectedStateIconColor) { + disconnectedStateIconColor = it + } + typedArray.getColorAndUse(R.styleable.FlightModeWidget_uxsdk_connectedStateTextColor) { + connectedStateTextColor = it + } + typedArray.getColorAndUse(R.styleable.FlightModeWidget_uxsdk_disconnectedStateTextColor) { + disconnectedStateTextColor = it + } + } + } + //endregion + + //region Hooks + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines the widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Flight mode text update + */ + data class FlightModeUpdated(val flightModeText: String) : ModelState() + } + //endregion + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/flightmode/FlightModeWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/flightmode/FlightModeWidgetModel.kt new file mode 100644 index 00000000..9d63b9dd --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/flightmode/FlightModeWidgetModel.kt @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.flightmode +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.key.KeyTools +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import dji.v5.ux.core.widget.flightmode.FlightModeWidgetModel.FlightModeState.FlightModeUpdated +import dji.v5.ux.core.widget.flightmode.FlightModeWidgetModel.FlightModeState.ProductDisconnected + +/** + * Widget Model for the [FlightModeWidget] used to define + * the underlying logic and communication + */ +class FlightModeWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + + //region Fields + private val flightModeStringProcessor: DataProcessor = DataProcessor.create("") + private val flightModeStateProcessor: DataProcessor = DataProcessor.create(ProductDisconnected) + //endregion + + //region Data + + /** + * Get the flight mode state + */ + val flightModeState: Flowable + get() = flightModeStateProcessor.toFlowable() + + //endregion + + //region Lifecycle + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyFlightModeString), flightModeStringProcessor) + } + + override fun inCleanup() { + // Nothing to clean + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + flightModeStateProcessor.onNext(FlightModeUpdated(flightModeStringProcessor.value)) + } else { + flightModeStateProcessor.onNext(ProductDisconnected) + } + } + + //endregion + + /** + * Class to represent states of flight mode + */ + sealed class FlightModeState { + /** + * When the product is disconnected + */ + object ProductDisconnected : FlightModeState() + + /** + * When the product is connected and current flight mode string + */ + data class FlightModeUpdated(val flightModeString: String) : FlightModeState() + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/fpv/FPVStreamSourceListener.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/fpv/FPVStreamSourceListener.kt new file mode 100644 index 00000000..ad1a08ad --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/fpv/FPVStreamSourceListener.kt @@ -0,0 +1,16 @@ +package dji.v5.ux.core.widget.fpv + +import dji.sdk.keyvalue.value.common.CameraLensType +import dji.sdk.keyvalue.value.common.ComponentIndexType + +/** + * Class Description + * + * @author Hoker + * @date 2022/3/19 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ +interface FPVStreamSourceListener { + fun onStreamSourceUpdated(devicePosition: ComponentIndexType, lensType: CameraLensType) +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/fpv/FPVWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/fpv/FPVWidget.kt new file mode 100644 index 00000000..fd51266d --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/fpv/FPVWidget.kt @@ -0,0 +1,527 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +package dji.v5.ux.core.widget.fpv + +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.Surface +import android.view.SurfaceHolder +import android.view.SurfaceView +import android.view.View +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.annotation.Dimension +import androidx.annotation.FloatRange +import androidx.annotation.StyleRes +import androidx.constraintlayout.widget.Guideline +import androidx.core.content.res.use +import dji.sdk.keyvalue.value.common.CameraLensType +import dji.sdk.keyvalue.value.common.ComponentIndexType +import dji.v5.manager.interfaces.ICameraStreamManager +import dji.v5.utils.common.DisplayUtil +import dji.v5.utils.common.LogPath +import dji.v5.utils.common.LogUtils +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.module.FlatCameraModule +import dji.v5.ux.core.ui.CenterPointView +import dji.v5.ux.core.ui.GridLineView +import dji.v5.ux.core.util.UxErrorHandle +import dji.v5.ux.core.widget.fpv.FPVWidget.ModelState +import io.reactivex.rxjava3.core.Flowable + +private const val TAG = "FPVWidget" +private const val ORIGINAL_SCALE = 1f +private const val LANDSCAPE_ROTATION_ANGLE = 0 + +/** + * This widget shows the video feed from the camera. + */ +open class FPVWidget @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 +) : ConstraintLayoutWidget(context, attrs, defStyleAttr) { + private var viewWidth = 0 + private var viewHeight = 0 + private var rotationAngle = 0 + private var surface: Surface? = null + private var width = -1 + private var height = -1 + private val fpvSurfaceView: SurfaceView = findViewById(R.id.surface_view_fpv) + private val cameraNameTextView: TextView = findViewById(R.id.textview_camera_name) + private val cameraSideTextView: TextView = findViewById(R.id.textview_camera_side) + private val verticalOffset: Guideline = findViewById(R.id.vertical_offset) + private val horizontalOffset: Guideline = findViewById(R.id.horizontal_offset) + private var fpvStateChangeResourceId: Int = INVALID_RESOURCE + + private val cameraSurfaceCallback = object : SurfaceHolder.Callback { + override fun surfaceCreated(holder: SurfaceHolder) { + surface = holder.surface + LogUtils.i(LogPath.SAMPLE, "surfaceCreated: ${widgetModel.getCameraIndex()}") + } + + override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { + this@FPVWidget.width = width + this@FPVWidget.height = height + LogUtils.i(LogPath.SAMPLE, "surfaceChanged: ${widgetModel.getCameraIndex()}", "width:$width", ",height:$height") + updateCameraStream() + } + + override fun surfaceDestroyed(holder: SurfaceHolder) { + width = 0 + height = 0 + LogUtils.i(LogPath.SAMPLE, "surfaceDestroyed: ${widgetModel.getCameraIndex()}") + removeSurfaceBinding() + } + } + + val widgetModel: FPVWidgetModel = FPVWidgetModel( + DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance(), FlatCameraModule() + ) + + /** + * Whether the video feed source's camera name is visible on the video feed. + */ + var isCameraSourceNameVisible = true + set(value) { + field = value + checkAndUpdateCameraName() + } + + /** + * Whether the video feed source's camera side is visible on the video feed. + * Only shown on aircraft that support multiple gimbals. + */ + var isCameraSourceSideVisible = true + set(value) { + field = value + checkAndUpdateCameraSide() + } + + /** + * Whether the grid lines are enabled. + */ + var isGridLinesEnabled = true + set(isGridLinesEnabled) { + field = isGridLinesEnabled + updateGridLineVisibility() + } + + /** + * Whether the center point is enabled. + */ + var isCenterPointEnabled = true + set(isCenterPointEnabled) { + field = isCenterPointEnabled + centerPointView.visibility = if (isCenterPointEnabled) View.VISIBLE else View.GONE + } + + /** + * The text color state list of the camera name text view + */ + var cameraNameTextColors: ColorStateList? + get() = cameraNameTextView.textColors + set(colorStateList) { + cameraNameTextView.setTextColor(colorStateList) + } + + /** + * The text color of the camera name text view + */ + @get:ColorInt + @setparam:ColorInt + var cameraNameTextColor: Int + get() = cameraNameTextView.currentTextColor + set(color) { + cameraNameTextView.setTextColor(color) + } + + /** + * The text size of the camera name text view + */ + @get:Dimension + @setparam:Dimension + var cameraNameTextSize: Float + get() = cameraNameTextView.textSize + set(textSize) { + cameraNameTextView.textSize = textSize + } + + /** + * The background for the camera name text view + */ + var cameraNameTextBackground: Drawable? + get() = cameraNameTextView.background + set(drawable) { + cameraNameTextView.background = drawable + } + + /** + * The text color state list of the camera name text view + */ + var cameraSideTextColors: ColorStateList? + get() = cameraSideTextView.textColors + set(colorStateList) { + cameraSideTextView.setTextColor(colorStateList) + } + + /** + * The text color of the camera side text view + */ + @get:ColorInt + @setparam:ColorInt + var cameraSideTextColor: Int + get() = cameraSideTextView.currentTextColor + set(color) { + cameraSideTextView.setTextColor(color) + } + + /** + * The text size of the camera side text view + */ + @get:Dimension + @setparam:Dimension + var cameraSideTextSize: Float + get() = cameraSideTextView.textSize + set(textSize) { + cameraSideTextView.textSize = textSize + } + + /** + * The background for the camera side text view + */ + var cameraSideTextBackground: Drawable? + get() = cameraSideTextView.background + set(drawable) { + cameraSideTextView.background = drawable + } + + /** + * The vertical alignment of the camera name and side text views + */ + var cameraDetailsVerticalAlignment: Float + @FloatRange(from = 0.0, to = 1.0) get() { + val layoutParams: LayoutParams = verticalOffset.layoutParams as LayoutParams + return layoutParams.guidePercent + } + set(@FloatRange(from = 0.0, to = 1.0) percent) { + val layoutParams: LayoutParams = verticalOffset.layoutParams as LayoutParams + layoutParams.guidePercent = percent + verticalOffset.layoutParams = layoutParams + } + + /** + * The horizontal alignment of the camera name and side text views + */ + var cameraDetailsHorizontalAlignment: Float + @FloatRange(from = 0.0, to = 1.0) get() { + val layoutParams: LayoutParams = horizontalOffset.layoutParams as LayoutParams + return layoutParams.guidePercent + } + set(@FloatRange(from = 0.0, to = 1.0) percent) { + val layoutParams: LayoutParams = horizontalOffset.layoutParams as LayoutParams + layoutParams.guidePercent = percent + horizontalOffset.layoutParams = layoutParams + } + + /** + * The [GridLineView] shown in this widget + */ + val gridLineView: GridLineView = findViewById(R.id.view_grid_line) + + /** + * The [CenterPointView] shown in this widget + */ + val centerPointView: CenterPointView = findViewById(R.id.view_center_point) + + //endregion + + //region Constructor + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + inflate(context, R.layout.uxsdk_widget_fpv, this) + } + + init { + if (!isInEditMode) { + rotationAngle = LANDSCAPE_ROTATION_ANGLE + fpvSurfaceView.holder.addCallback(cameraSurfaceCallback) + } + attrs?.let { initAttributes(context, it) } + } + //endregion + + //region LifeCycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + initializeListeners() + } + + private fun initializeListeners() { + //后面补上 + } + + override fun setVisibility(visibility: Int) { + super.setVisibility(visibility) + fpvSurfaceView.visibility = visibility + } + + override fun onDetachedFromWindow() { + destroyListeners() + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.displayMsgProcessor.toFlowable().observeOn(SchedulerProvider.ui()).subscribe { cameraName: String -> updateCameraName(cameraName) }) + addReaction(widgetModel.cameraSideProcessor.toFlowable().observeOn(SchedulerProvider.ui()).subscribe { cameraSide: String -> updateCameraSide(cameraSide) }) + addReaction(widgetModel.hasVideoViewChanged.observeOn(SchedulerProvider.ui()).subscribe { delayCalculator() }) + } + + override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) { + super.onLayout(changed, l, t, r, b) + if (!isInEditMode) { + setViewDimensions() + delayCalculator() + } + } + + private fun destroyListeners() { + //后面补上 + } + + //endregion + //region Customization + override fun getIdealDimensionRatioString(): String { + return getString(R.string.uxsdk_widget_fpv_ratio) + } + + fun updateVideoSource(source: ComponentIndexType) { + LogUtils.i(LogPath.SAMPLE, "updateVideoSource", source, this) + widgetModel.updateCameraSource(source, CameraLensType.UNKNOWN) + updateCameraStream() + if (source == ComponentIndexType.VISION_ASSIST) { + widgetModel.enableVisionAssist() + } + fpvSurfaceView.invalidate() + } + + fun setOnFPVStreamSourceListener(listener: FPVStreamSourceListener) { + widgetModel.streamSourceListener = listener + } + + fun setSurfaceViewZOrderOnTop(onTop: Boolean) { + fpvSurfaceView.setZOrderOnTop(onTop) + } + + fun setSurfaceViewZOrderMediaOverlay(isMediaOverlay: Boolean) { + fpvSurfaceView.setZOrderMediaOverlay(isMediaOverlay) + } + + //endregion + //region Helpers + private fun setViewDimensions() { + viewWidth = measuredWidth + viewHeight = measuredHeight + } + + private fun delayCalculator() { + //后面补充 + } + + private fun updateCameraName(cameraName: String) { + cameraNameTextView.text = cameraName + if (cameraName.isNotEmpty() && isCameraSourceNameVisible) { + cameraNameTextView.visibility = View.INVISIBLE + } else { + cameraNameTextView.visibility = View.INVISIBLE + } + } + + private fun updateCameraSide(cameraSide: String) { + cameraSideTextView.text = cameraSide + if (cameraSide.isNotEmpty() && isCameraSourceSideVisible) { + cameraSideTextView.visibility = View.INVISIBLE + } else { + cameraSideTextView.visibility = View.INVISIBLE + } + } + + private fun checkAndUpdateCameraName() { + if (!isInEditMode) { + addDisposable( + widgetModel.displayMsgProcessor.toFlowable().firstOrError().observeOn(SchedulerProvider.ui()).subscribe( + { cameraName: String -> updateCameraName(cameraName) }, UxErrorHandle.logErrorConsumer(TAG, "updateCameraName") + ) + ) + } + } + + private fun checkAndUpdateCameraSide() { + if (!isInEditMode) { + addDisposable( + widgetModel.cameraSideProcessor.toFlowable().firstOrError().observeOn(SchedulerProvider.ui()).subscribe( + { cameraSide: String -> updateCameraSide(cameraSide) }, UxErrorHandle.logErrorConsumer(TAG, "updateCameraSide") + ) + ) + } + } + + private fun updateGridLineVisibility() { + gridLineView.visibility = if (isGridLinesEnabled && widgetModel.getCameraIndex() == ComponentIndexType.FPV) View.VISIBLE else View.GONE + } + //endregion + + //region Customization helpers + /** + * Set text appearance of the camera name text view + * + * @param textAppearance Style resource for text appearance + */ + fun setCameraNameTextAppearance(@StyleRes textAppearance: Int) { + cameraNameTextView.setTextAppearance(context, textAppearance) + } + + /** + * Set text appearance of the camera side text view + * + * @param textAppearance Style resource for text appearance + */ + fun setCameraSideTextAppearance(@StyleRes textAppearance: Int) { + cameraSideTextView.setTextAppearance(context, textAppearance) + } + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.FPVWidget).use { typedArray -> + if (!isInEditMode) { + typedArray.getBooleanAndUse(R.styleable.FPVWidget_uxsdk_gridLinesEnabled, true) { + isGridLinesEnabled = it + } + typedArray.getBooleanAndUse(R.styleable.FPVWidget_uxsdk_centerPointEnabled, true) { + isCenterPointEnabled = it + } + } + typedArray.getBooleanAndUse(R.styleable.FPVWidget_uxsdk_sourceCameraNameVisibility, true) { + isCameraSourceNameVisible = it + } + typedArray.getBooleanAndUse(R.styleable.FPVWidget_uxsdk_sourceCameraSideVisibility, true) { + isCameraSourceSideVisible = it + } + typedArray.getResourceIdAndUse(R.styleable.FPVWidget_uxsdk_cameraNameTextAppearance) { + setCameraNameTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.FPVWidget_uxsdk_cameraNameTextSize) { + cameraNameTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.FPVWidget_uxsdk_cameraNameTextColor) { + cameraNameTextColor = it + } + typedArray.getDrawableAndUse(R.styleable.FPVWidget_uxsdk_cameraNameBackgroundDrawable) { + cameraNameTextBackground = it + } + typedArray.getResourceIdAndUse(R.styleable.FPVWidget_uxsdk_cameraSideTextAppearance) { + setCameraSideTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.FPVWidget_uxsdk_cameraSideTextSize) { + cameraSideTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.FPVWidget_uxsdk_cameraSideTextColor) { + cameraSideTextColor = it + } + typedArray.getDrawableAndUse(R.styleable.FPVWidget_uxsdk_cameraSideBackgroundDrawable) { + cameraSideTextBackground = it + } + typedArray.getFloatAndUse(R.styleable.FPVWidget_uxsdk_cameraDetailsVerticalAlignment) { + cameraDetailsVerticalAlignment = it + } + typedArray.getFloatAndUse(R.styleable.FPVWidget_uxsdk_cameraDetailsHorizontalAlignment) { + cameraDetailsHorizontalAlignment = it + } + typedArray.getIntegerAndUse(R.styleable.FPVWidget_uxsdk_gridLineType) { + gridLineView.type = GridLineView.GridLineType.find(it) + } + typedArray.getColorAndUse(R.styleable.FPVWidget_uxsdk_gridLineColor) { + gridLineView.lineColor = it + } + typedArray.getFloatAndUse(R.styleable.FPVWidget_uxsdk_gridLineWidth) { + gridLineView.lineWidth = it + } + typedArray.getIntegerAndUse(R.styleable.FPVWidget_uxsdk_gridLineNumber) { + gridLineView.numberOfLines = it + } + typedArray.getIntegerAndUse(R.styleable.FPVWidget_uxsdk_centerPointType) { + centerPointView.type = CenterPointView.CenterPointType.find(it) + } + typedArray.getColorAndUse(R.styleable.FPVWidget_uxsdk_centerPointColor) { + centerPointView.color = it + } + typedArray.getResourceIdAndUse(R.styleable.FPVWidget_uxsdk_onStateChange) { + fpvStateChangeResourceId = it + } + } + } + + private fun updateCameraStream() { + removeSurfaceBinding() + surface?.let { + widgetModel.putCameraStreamSurface( + it, + width, + height, + ICameraStreamManager.ScaleType.CENTER_INSIDE + ) + } + } + + private fun removeSurfaceBinding() { + if (width <= 0 || height <= 0 || surface == null) { + if (surface != null) { + widgetModel.removeCameraStreamSurface(surface!!) + } + } + } + + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines the widget state updates + */ + sealed class ModelState +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/fpv/FPVWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/fpv/FPVWidgetModel.kt new file mode 100644 index 00000000..19c1119a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/fpv/FPVWidgetModel.kt @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +package dji.v5.ux.core.widget.fpv + +import android.view.Surface +import dji.sdk.keyvalue.key.CameraKey +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.value.camera.CameraType +import dji.sdk.keyvalue.value.camera.CameraVideoStreamSourceType +import dji.sdk.keyvalue.value.camera.VideoResolutionFrameRate +import dji.sdk.keyvalue.value.common.CameraLensType +import dji.sdk.keyvalue.value.common.ComponentIndexType +import dji.v5.et.create +import dji.v5.et.createCamera +import dji.v5.manager.datacenter.MediaDataCenter +import dji.v5.manager.interfaces.ICameraStreamManager +import dji.v5.utils.common.LogUtils +import dji.v5.utils.common.StringUtils +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.ICameraIndex +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.module.FlatCameraModule +import dji.v5.ux.core.util.CameraUtil +import dji.v5.ux.core.util.DataProcessor +import dji.v5.ux.core.util.UxErrorHandle +import io.reactivex.rxjava3.core.Flowable + +/** + * Widget Model for the [FPVWidget] used to define + * the underlying logic and communication + */ +class FPVWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, + private val flatCameraModule: FlatCameraModule, +) : WidgetModel(djiSdkModel, keyedStore), ICameraIndex { + + private var currentLensType = CameraLensType.CAMERA_LENS_DEFAULT + private val streamSourceCameraTypeProcessor = DataProcessor.create(CameraVideoStreamSourceType.UNKNOWN) + private val resolutionAndFrameRateProcessor: DataProcessor = DataProcessor.create(VideoResolutionFrameRate()) + private val cameraTypeProcessor: DataProcessor = DataProcessor.create(CameraType.NOT_SUPPORTED) + private val isMotorOnProcessor: DataProcessor = DataProcessor.create(false) + val displayMsgProcessor: DataProcessor = DataProcessor.create("") + val cameraSideProcessor: DataProcessor = DataProcessor.create("") + private val videoViewChangedProcessor: DataProcessor = DataProcessor.create(false) + var streamSourceListener: FPVStreamSourceListener? = null + private var cameraType: CameraType = CameraType.NOT_SUPPORTED + + /** + * The current camera index. This value should only be used for video size calculation. + * To get the camera side, use [FPVWidgetModel.cameraSide] instead. + */ + private var currentCameraIndex: ComponentIndexType = ComponentIndexType.UNKNOWN + + /** + * Get whether the video view has changed + */ + @get:JvmName("hasVideoViewChanged") + val hasVideoViewChanged: Flowable + get() = videoViewChangedProcessor.toFlowable() + + init { + addModule(flatCameraModule) + } + + override fun getCameraIndex(): ComponentIndexType { + return currentCameraIndex + } + + override fun getLensType(): CameraLensType { + return currentLensType + } + + override fun updateCameraSource(cameraIndex: ComponentIndexType, lensType: CameraLensType) { + if (currentCameraIndex != cameraIndex) { + currentCameraIndex = cameraIndex + restart() + } + } + + //region Lifecycle + override fun inSetup() { + val videoViewChangedConsumer = { _: Any -> videoViewChangedProcessor.onNext(true) } + bindDataProcessor(CameraKey.KeyCameraVideoStreamSource.create(currentCameraIndex), streamSourceCameraTypeProcessor) { + currentLensType = when (it) { + CameraVideoStreamSourceType.WIDE_CAMERA -> CameraLensType.CAMERA_LENS_WIDE + CameraVideoStreamSourceType.ZOOM_CAMERA -> CameraLensType.CAMERA_LENS_ZOOM + CameraVideoStreamSourceType.INFRARED_CAMERA -> CameraLensType.CAMERA_LENS_THERMAL + CameraVideoStreamSourceType.NDVI_CAMERA -> CameraLensType.CAMERA_LENS_MS_NDVI + CameraVideoStreamSourceType.MS_G_CAMERA -> CameraLensType.CAMERA_LENS_MS_G + CameraVideoStreamSourceType.MS_R_CAMERA -> CameraLensType.CAMERA_LENS_MS_R + CameraVideoStreamSourceType.MS_RE_CAMERA -> CameraLensType.CAMERA_LENS_MS_RE + CameraVideoStreamSourceType.MS_NIR_CAMERA -> CameraLensType.CAMERA_LENS_MS_NIR + CameraVideoStreamSourceType.RGB_CAMERA -> CameraLensType.CAMERA_LENS_RGB + else -> CameraLensType.CAMERA_LENS_DEFAULT + } + sourceUpdate() + } + + bindDataProcessor(FlightControllerKey.KeyAreMotorsOn.create(), isMotorOnProcessor) { + updateCameraDisplay() + } + + bindDataProcessor(CameraKey.KeyCameraType.create(currentCameraIndex), cameraTypeProcessor) { + cameraType = it + updateCameraDisplay() + } + + bindDataProcessor(CameraKey.KeyVideoResolutionFrameRate.createCamera(currentCameraIndex, currentLensType), resolutionAndFrameRateProcessor) + + addDisposable( + flatCameraModule.cameraModeDataProcessor.toFlowable() + .doOnNext(videoViewChangedConsumer) + .subscribe({ }, UxErrorHandle.logErrorConsumer(tag, "camera mode: ")) + ) + sourceUpdate() + } + + override fun inCleanup() { + currentLensType = CameraLensType.CAMERA_LENS_DEFAULT + } + + private fun sourceUpdate() { + onStreamSourceUpdated() + updateCameraDisplay() + } + + private fun updateCameraDisplay() { + var msg = "" + if (!CameraUtil.isFPVTypeView(currentCameraIndex)) { + msg = cameraType.name + } + if (currentCameraIndex == ComponentIndexType.VISION_ASSIST) { + if (!isMotorOnProcessor.value) { + msg = StringUtils.getResStr(R.string.uxsdk_assistant_video_empty_text) + } + } + if (currentLensType != CameraLensType.CAMERA_LENS_DEFAULT && currentLensType != CameraLensType.UNKNOWN) { + msg = msg + "_" + currentLensType.name + } + displayMsgProcessor.onNext(msg) + cameraSideProcessor.onNext(currentCameraIndex.name) + } + + public override fun updateStates() { + //无需实现 + } + + fun putCameraStreamSurface( + surface: Surface, + width: Int, + height: Int, + scaleType: ICameraStreamManager.ScaleType + ) { + MediaDataCenter.getInstance().cameraStreamManager.putCameraStreamSurface(currentCameraIndex, surface, width, height, scaleType) + } + + fun removeCameraStreamSurface(surface: Surface) { + MediaDataCenter.getInstance().cameraStreamManager.removeCameraStreamSurface(surface) + } + + fun enableVisionAssist() { + MediaDataCenter.getInstance().cameraStreamManager.enableVisionAssist(true, null) + } + + private fun onStreamSourceUpdated() { + streamSourceListener?.onStreamSourceUpdated(currentCameraIndex, currentLensType) + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/gpssignal/GPSSignalWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/gpssignal/GPSSignalWidget.kt new file mode 100644 index 00000000..56ea3f5f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/gpssignal/GPSSignalWidget.kt @@ -0,0 +1,139 @@ +package dji.v5.ux.core.widget.gpssignal + +import android.content.Context +import android.util.AttributeSet +import android.widget.ImageView +import android.widget.TextView +import androidx.constraintlayout.widget.ConstraintLayout +import dji.v5.manager.aircraft.rtk.RTKCenter +import dji.v5.utils.common.LogUtils +import dji.v5.ux.R +import dji.v5.ux.accessory.RTKEnabledWidgetModel +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.base.widget.FrameLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.popover.PopoverHelper + +/** + * Description : + * + * @author: Byte.Cai + * date : 2022/9/12 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ +class GpsSignalWidget @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, +) : ConstraintLayoutWidget(context, attrs, defStyleAttr) { + private val ivRtkIcon: ImageView = findViewById(R.id.iv_rtk_icon) + private val ivSatelliteIcon: ImageView = findViewById(R.id.iv_satellite_icon) + private val tvSatelliteCount: TextView = findViewById(R.id.tv_satellite_count) + private var rtkOverView: GpsSignalWidgetModel.RtkOverview = GpsSignalWidgetModel.RtkOverview() + private val rootView: ConstraintLayout = findViewById(R.id.root_view) + + private val rtkEnabledWidgetModel by lazy { + RTKEnabledWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance() + ) + } + + private val popover by lazy { + PopoverHelper.showPopover(rootView, GpsSignalPopoverView(context)) + } + + private val gpsSignalWidgetModel by lazy { + GpsSignalWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), RTKCenter.getInstance() + ) + } + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + inflate(context, R.layout.uxsdk_fpv_top_bar_widget_gps_signal, this) + } + + init { + setOnClickListener { + if (!popover.isShowing()) { + popover.show() + } + } + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + gpsSignalWidgetModel.setup() + rtkEnabledWidgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + gpsSignalWidgetModel.cleanup() + rtkEnabledWidgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + + addReaction(gpsSignalWidgetModel.rtkOverview.observeOn(SchedulerProvider.ui()).subscribe { + rtkOverView = it + updateRtkIcon(it) + }) + + addReaction(gpsSignalWidgetModel.gpsSatelliteCount.observeOn(SchedulerProvider.ui()).subscribe { + if (!rtkOverView.rtkHealthy) { + LogUtils.d(logTag, "rtk is not healthy,use gpsSatelliteCount") + tvSatelliteCount.text = it.toString() + } + }) + + addReaction(gpsSignalWidgetModel.rtkSatelliteCount.observeOn(SchedulerProvider.ui()).subscribe { + if (rtkOverView.rtkHealthy) { + LogUtils.d(logTag, "rtk is healthy,use rtkSatelliteCount") + tvSatelliteCount.text = it.toString() + } + }) + addReaction(gpsSignalWidgetModel.gpsSignalLevel.observeOn(SchedulerProvider.ui()).subscribe { + ivSatelliteIcon.setColorFilter(getTintColor(it)) + tvSatelliteCount.setTextColor(getTintColor(it)) + }) + } + + private fun updateRtkIcon(overview: GpsSignalWidgetModel.RtkOverview) { + ivRtkIcon.visibility = if (overview.connected) VISIBLE else GONE + + if (overview.enabled) { + when { + overview.rtkKeepingStatus -> { + ivRtkIcon.setImageResource(R.drawable.uxsdk_ic_fpv_topbar_rtk_caution) + } + overview.rtkHealthy -> { + ivRtkIcon.setImageResource(R.drawable.uxsdk_ic_fpv_topbar_rtk_normal) + } + else -> { + ivRtkIcon.setImageResource(R.drawable.uxsdk_ic_fpv_topbar_rtk_danger) + } + } + } else { + ivRtkIcon.setImageResource(R.drawable.uxsdk_ic_fpv_topbar_rtk_no_open) + } + } + + private fun getTintColor(level: GpsSignalWidgetModel.SignalLevel): Int { + return when (level) { + GpsSignalWidgetModel.SignalLevel.LEVEL_1 -> + resources.getColor(R.color.uxsdk_tips_danger_in_dark) + GpsSignalWidgetModel.SignalLevel.LEVEL_2 -> + resources.getColor(R.color.uxsdk_tips_caution_in_dark) + GpsSignalWidgetModel.SignalLevel.LEVEL_3 -> + resources.getColor(R.color.uxsdk_tips_normal_in_dark) + } + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/gpssignal/GPSSignalWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/gpssignal/GPSSignalWidgetModel.kt new file mode 100644 index 00000000..e198f78f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/gpssignal/GPSSignalWidgetModel.kt @@ -0,0 +1,411 @@ +package dji.v5.ux.core.widget.gpssignal + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.key.RtkMobileStationKey +import dji.sdk.keyvalue.value.flightcontroller.GPSSignalLevel +import dji.sdk.keyvalue.value.rtkbasestation.RTKReferenceStationSource +import dji.sdk.keyvalue.value.rtkbasestation.RTKServiceState +import dji.sdk.keyvalue.value.rtkbasestation.RTKStationConnetState +import dji.v5.common.callback.CommonCallbacks +import dji.v5.common.error.IDJIError +import dji.v5.et.create +import dji.v5.et.listen +import dji.v5.manager.KeyManager +import dji.v5.manager.aircraft.rtk.RTKSystemState +import dji.v5.manager.aircraft.rtk.RTKSystemStateListener +import dji.v5.manager.aircraft.rtk.network.INetworkServiceInfoListener +import dji.v5.manager.aircraft.rtk.station.RTKStationConnectStatusListener +import dji.v5.manager.interfaces.IRTKCenter +import dji.v5.utils.common.LogUtils +import dji.v5.ux.accessory.RTKStartServiceHelper +import dji.v5.ux.accessory.RTKStartServiceHelper.isNetworkRTK +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Flowable + +/** + * Description : + * + * @author: Byte.Cai + * date : 2022/9/8 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ + +class GpsSignalWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, + val rtkCenter: IRTKCenter, +) : WidgetModel(djiSdkModel, keyedStore) { + private var rtkSystemState = RTKSystemState() + private var isRtkModuleAvailable = false + private var rtkServiceState = RTKServiceState.UNKNOWN + private var currentGpsSignalLevel: GPSSignalLevel = GPSSignalLevel.UNKNOWN + + private var baseStationConnectStatus = RTKStationConnetState.UNKNOWN + + // 飞机是否正在使用精度保持功能 + private var isUsingRtkKeeping = false + + // GNSS 卫星数量 + private val gpsSatelliteCountProcessor = DataProcessor.create(0) + + //RTK卫星数 + private val rtkSatelliteCountProcessor = DataProcessor.create(0) + + //GPS信号强度 + private val gpsSignalLevelProcessor = DataProcessor.create(SignalLevel.LEVEL_1) + + //RTK信息封装类 + private val rtkOverviewProcessor = DataProcessor.create(RtkOverview()) + private val rtkSystemStateListener = RTKSystemStateListener { + rtkSystemState = it + updateRtkOverview() + rtkSatelliteCountProcessor.onNext(getRtkSatelliteCount(it)) + updateRTKListener(it.rtkReferenceStationSource) + } + private val connectStatusListener = RTKStationConnectStatusListener { + baseStationConnectStatus = it + updateRtkOverview() + } + + private val networkServiceInfoListener: INetworkServiceInfoListener = object : + INetworkServiceInfoListener { + override fun onServiceStateUpdate(state: RTKServiceState?) { + state?.let { + if (rtkServiceState != state) { + rtkServiceState = state + updateRtkOverview() + } + } + + } + + override fun onErrorCodeUpdate(error: IDJIError?) { + LogUtils.e(tag, "networkServiceInfoListener onErrorCodeUpdate:$error") + } + } + + + val gpsSatelliteCount: Flowable + get() = gpsSatelliteCountProcessor.toFlowable() + + val rtkSatelliteCount: Flowable + get() = rtkSatelliteCountProcessor.toFlowable() + + val rtkOverview: Flowable + get() = rtkOverviewProcessor.toFlowable() + + val gpsSignalLevel: Flowable + get() = gpsSignalLevelProcessor.toFlowable() + + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyGPSSatelliteCount), gpsSatelliteCountProcessor) + rtkCenter.addRTKSystemStateListener(rtkSystemStateListener) + rtkCenter.rtkStationManager.addRTKStationConnectStatusListener(connectStatusListener) + rtkCenter.qxrtkManager.addNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.customRTKManager.addNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.cmccrtkManager.addNetworkRTKServiceInfoListener(networkServiceInfoListener) + FlightControllerKey.KeyGPSSignalLevel.create().listen(this) { + it?.let { + currentGpsSignalLevel = it + updateSignalLevel(it) + } + } + FlightControllerKey.KeyConnection.create().listen(this) { + //飞机断连则重置数据 + if (it == false) { + resetData() + updateRtkOverview() + rtkSatelliteCountProcessor.onNext(0) + gpsSatelliteCountProcessor.onNext(0) + } + + } + RTKStartServiceHelper.rtkModuleAvailable.subscribe { + isRtkModuleAvailable = it + updateRtkOverview() + } + // 飞机是否正在使用精度保持功能 + RtkMobileStationKey.KeyRTKkeepStatus.create().listen(this) { + if (it == null) { + return@listen + } + isUsingRtkKeeping = it + updateRtkOverview() + } + } + + override fun inCleanup() { + rtkCenter.removeRTKSystemStateListener(rtkSystemStateListener) + rtkCenter.qxrtkManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.customRTKManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.cmccrtkManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.rtkStationManager.removeRTKStationConnectStatusListener(connectStatusListener) + KeyManager.getInstance().cancelListen(this) + + } + + fun setRTKEnable(boolean: Boolean) { + rtkCenter.setAircraftRTKModuleEnabled(boolean, object : CommonCallbacks.CompletionCallback { + override fun onSuccess() { + //发现RTK精度保持功能关闭,则一起开启 + if (!rtkSystemState.rtkMaintainAccuracyEnabled && boolean) { + rtkCenter.setRTKMaintainAccuracyEnabled(true, null) + } + updateSignalLevel(currentGpsSignalLevel) + } + + override fun onFailure(djiError: IDJIError) { + //do nothing + } + }) + + } + + private fun updateRTKListener(rtkSource: RTKReferenceStationSource) { + when (rtkSource) { + RTKReferenceStationSource.QX_NETWORK_SERVICE -> { + rtkCenter.customRTKManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.cmccrtkManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.rtkStationManager.removeRTKStationConnectStatusListener(connectStatusListener) + rtkCenter.qxrtkManager.addNetworkRTKServiceInfoListener(networkServiceInfoListener) + } + RTKReferenceStationSource.CUSTOM_NETWORK_SERVICE -> { + rtkCenter.qxrtkManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.cmccrtkManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.rtkStationManager.removeRTKStationConnectStatusListener(connectStatusListener) + rtkCenter.customRTKManager.addNetworkRTKServiceInfoListener(networkServiceInfoListener) + + } + RTKReferenceStationSource.NTRIP_NETWORK_SERVICE -> { + rtkCenter.qxrtkManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.customRTKManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.rtkStationManager.removeRTKStationConnectStatusListener(connectStatusListener) + rtkCenter.cmccrtkManager.addNetworkRTKServiceInfoListener(networkServiceInfoListener) + } + RTKReferenceStationSource.BASE_STATION -> { + rtkCenter.qxrtkManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.customRTKManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.cmccrtkManager.removeNetworkRTKServiceInfoListener(networkServiceInfoListener) + rtkCenter.rtkStationManager.addRTKStationConnectStatusListener(connectStatusListener) + + } + else -> { + //do nothing + } + } + + } + + /** + * 更新RTK概览 + */ + private fun updateRtkOverview() { + var currentRtkState = RtkState.NOT_CONNECT + rtkSystemState.run { + if (isRTKEnabled) { + when { + rtkReferenceStationSource == RTKReferenceStationSource.NONE -> { + //无 + currentRtkState = RtkState.NOT_CONNECT + } + rtkReferenceStationSource == RTKReferenceStationSource.BASE_STATION -> { + //base rtk + currentRtkState = updateBaseRtkState() + } + isNetworkRTK(rtkReferenceStationSource) -> { + //网络RTK + currentRtkState = updateRtcmStatus() + } + } + } else { + currentRtkState = RtkState.NOT_OPEN + } + + val rtkOverview = RtkOverview( + connected = isRtkModuleAvailable, + enabled = isRTKEnabled, + rtkHealthy = rtkHealthy, + rtkState = currentRtkState, + rtkSource = rtkReferenceStationSource, + rtkKeepingStatus = isUsingRtkKeeping + ) + rtkOverviewProcessor.onNext(rtkOverview) + LogUtils.d(tag, "rtkOverview=$rtkOverview") + } + + } + + private fun resetData() { + baseStationConnectStatus = RTKStationConnetState.UNKNOWN + rtkSystemState = RTKSystemState() + isRtkModuleAvailable = false + rtkServiceState = RTKServiceState.UNKNOWN + + } + + private fun updateBaseRtkState(): RtkState { + return if (baseStationConnectStatus == RTKStationConnetState.CONNECTED) { + if (rtkSystemState.rtkHealthy) { + RtkState.CONNECTED + } else { + RtkState.CONVERGING + } + } else { + RtkState.NOT_CONNECT + } + } + + /** + * 更新GPS信号强度LiveData + */ + private fun updateSignalLevel(gpsSignalLevel: GPSSignalLevel) { + gpsSignalLevelProcessor.onNext( + when (gpsSignalLevel) { + GPSSignalLevel.LEVEL_10, + GPSSignalLevel.LEVEL_5, + GPSSignalLevel.LEVEL_4, + -> + SignalLevel.LEVEL_3 + GPSSignalLevel.LEVEL_3 -> + SignalLevel.LEVEL_2 + else -> + SignalLevel.LEVEL_1 + } + ) + } + + + private fun updateRtcmStatus(): RtkState { + return when (rtkServiceState) { + RTKServiceState.RTCM_CONNECTED, + RTKServiceState.RTCM_NORMAL, + RTKServiceState.RTCM_USER_HAS_ACTIVATE, + RTKServiceState.RTCM_USER_ACCOUNT_EXPIRES_SOON, + RTKServiceState.RTCM_USE_DEFAULT_MOUNT_POINT, + RTKServiceState.TRANSMITTING, + -> { + if (rtkSystemState.rtkHealthy) { + RtkState.CONNECTED + } else { + RtkState.CONVERGING + } + } + RTKServiceState.RTCM_AUTH_FAILED, + RTKServiceState.RTCM_USER_NOT_BOUNDED, + RTKServiceState.RTCM_USER_NOT_ACTIVATED, + RTKServiceState.SERVICE_SUSPENSION, + RTKServiceState.ACCOUNT_EXPIRED, + RTKServiceState.RTCM_ILLEGAL_UTC_TIME, + RTKServiceState.NETWORK_NOT_REACHABLE, + RTKServiceState.RTCM_SET_COORDINATE_FAILURE, + RTKServiceState.LOGIN_FAILURE, + RTKServiceState.ACCOUNT_ERROR, + RTKServiceState.CONNECTING, + RTKServiceState.INVALID_REQUEST, + RTKServiceState.SERVER_NOT_REACHABLE, + RTKServiceState.UNKNOWN, + -> { + RtkState.ERROR + } + else -> { + RtkState.NOT_CONNECT + } + } + } + + /** + * 计算RTK的星数。只能只取天线1(主天线)的卫星数作为标准,因为飞控大多数情况也只使用主天线的卫星数来计算。 + */ + private fun getRtkSatelliteCount(rtkSystemState: RTKSystemState): Int { + return if (!rtkSystemState.isRTKEnabled) { + 0 + } else { + rtkSystemState.run { + satelliteInfo?.run { + mobileStationReceiver1Info.map { + it.count + }.sum() + } ?: 0 + } + + } + } + + + /** + * RTK概览状态 + */ + data class RtkOverview( + val connected: Boolean = false, + val enabled: Boolean = false, + val rtkHealthy: Boolean = false, + val rtkState: RtkState = RtkState.NOT_OPEN, + val rtkSource: RTKReferenceStationSource = RTKReferenceStationSource.NONE, + val rtkKeepingStatus: Boolean = false, + ) { + override fun toString(): String { + return "RtkOverview(connected=$connected, enabled=$enabled, rtkHealthy=$rtkHealthy, rtkState=$rtkState, rtkSource=$rtkSource, rtkKeepingStatus=$rtkKeepingStatus)" + } + } + + + /** + * RTK统一状态(包含D-RTK和网络RTK的状态) + */ + enum class RtkState { + /** + * 未开启 + */ + NOT_OPEN, + + /** + * 未连接 + */ + NOT_CONNECT, + + /** + * 收敛中 + */ + CONVERGING, + + /** + * 已连接(已使用) + */ + CONNECTED, + + /** + * 异常 + */ + ERROR + + } + + /** + * 信号强度 + */ + enum class SignalLevel { + /** + * 信号很差,红色,飞行器无法返航 + */ + LEVEL_1, + + /** + * 信号较差,黄色,飞行器大概知道home点,可返航 + */ + LEVEL_2, + + /** + * 信号良好,白色,飞行能正常返航、悬停 + */ + LEVEL_3 + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/gpssignal/GpsSignalPopoverView.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/gpssignal/GpsSignalPopoverView.kt new file mode 100644 index 00000000..db6aa774 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/gpssignal/GpsSignalPopoverView.kt @@ -0,0 +1,252 @@ +package dji.v5.ux.core.widget.gpssignal + +import android.content.Context +import android.util.AttributeSet +import android.view.ViewGroup +import android.widget.CompoundButton +import android.widget.FrameLayout +import android.widget.LinearLayout +import android.widget.Switch +import dji.v5.manager.aircraft.rtk.RTKCenter +import dji.v5.utils.common.LogUtils +import dji.v5.ux.R +import dji.v5.ux.accessory.RTKEnabledWidgetModel + +import dji.v5.ux.accessory.item.TitleValueCell +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.widget.FrameLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.extension.showLongToast +import dji.v5.utils.common.AndUtil +import dji.v5.ux.core.util.UxErrorHandle + +class GpsSignalPopoverView @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0, +) : FrameLayoutWidget(context, attrs, defStyleAttr), CompoundButton.OnCheckedChangeListener { + + private var rtkTitleWrapper: FrameLayout = findViewById(R.id.rtk_title_wrapper) + private var rtkContentWrapper: LinearLayout = findViewById(R.id.rtk_content_wrapper) + private var gpsTitleWrapper: FrameLayout = findViewById(R.id.gps_title_wrapper) + private var gpsContentWrapper: LinearLayout = findViewById(R.id.gps_content_wrapper) + + private var tvGpsSignal: TitleValueCell = findViewById(R.id.tv_gps_signal) + private var tvGpsSatelliteCount: TitleValueCell = findViewById(R.id.tv_gps_satellite_count) + + private var rtkEnabledSwitch: Switch = findViewById(R.id.switch_rtk_enable) + private var tvRtkState: TitleValueCell = findViewById(R.id.tv_rtk_state) + private var tvRtkSatelliteCount: TitleValueCell = findViewById(R.id.tv_rtk_satellite_count) + private var tvRtkSignal: TitleValueCell = findViewById(R.id.tv_rtk_signal) + private var maxWidth = 0 + private var rtkOverview: GpsSignalWidgetModel.RtkOverview = GpsSignalWidgetModel.RtkOverview() + + init { + + rtkEnabledSwitch.setOnCheckedChangeListener(this) + + rtkContentWrapper.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED) + gpsContentWrapper.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED) + maxWidth = rtkContentWrapper.measuredWidth.coerceAtLeast(gpsContentWrapper.measuredWidth) + + + } + + private val rtkEnabledWidgetModel by lazy { + RTKEnabledWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()) + } + + private val gpsSignalWidgetModel by lazy { + GpsSignalWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), RTKCenter.getInstance()) + } + + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + gpsSignalWidgetModel.setup() + rtkEnabledWidgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + gpsSignalWidgetModel.cleanup() + rtkEnabledWidgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + + private fun updateRtkState(overview: GpsSignalWidgetModel.RtkOverview) { + if (overview.connected) { + rtkTitleWrapper.visibility = VISIBLE + rtkContentWrapper.visibility = VISIBLE + gpsTitleWrapper.visibility = VISIBLE + gpsContentWrapper.setBackgroundResource(R.color.uxsdk_fpv_popover_content_background_color) + gpsContentWrapper.layoutParams.width = maxWidth + } else { + rtkTitleWrapper.visibility = GONE + rtkContentWrapper.visibility = GONE + gpsTitleWrapper.visibility = GONE + gpsContentWrapper.setBackgroundResource(R.color.uxsdk_fpv_popover_title_background_color) + gpsContentWrapper.layoutParams.width = ViewGroup.LayoutParams.WRAP_CONTENT + } + setRTKSwitch(overview.enabled) + if (!overview.enabled) { + tvRtkSatelliteCount.value = "- -" + tvRtkSignal.value = "- -" + + tvRtkSignal.setValueTextColor(AndUtil.getResColor(R.color.uxsdk_white)) + tvRtkSatelliteCount.setValueTextColor(AndUtil.getResColor(R.color.uxsdk_white)) + } + + if (overview.rtkKeepingStatus) { + //黄 + tvRtkState.value = AndUtil.getResString(R.string.uxsdk_rtk_keep_status_mode) + tvRtkState.setValueTextColor(AndUtil.getResColor(R.color.uxsdk_zone_warning_enhanced)) + } else { + + when (overview.rtkState) { + GpsSignalWidgetModel.RtkState.NOT_OPEN -> { + //黄 + tvRtkState.value = + AndUtil.getResString(R.string.uxsdk_checklist_manual_rtk_not_open) + tvRtkState.setValueTextColor(AndUtil.getResColor(R.color.uxsdk_zone_warning_enhanced)) + } + + GpsSignalWidgetModel.RtkState.NOT_CONNECT -> { + //黄 + tvRtkState.value = + AndUtil.getResString(R.string.uxsdk_setting_menu_rtk_state_disconnect) + tvRtkState.setValueTextColor(AndUtil.getResColor(R.color.uxsdk_red_in_dark)) + } + + GpsSignalWidgetModel.RtkState.CONVERGING -> { + //黄 + tvRtkState.value = + AndUtil.getResString(R.string.uxsdk_checklist_rtk_status_converging) + tvRtkState.setValueTextColor(AndUtil.getResColor(R.color.uxsdk_zone_warning_enhanced)) + } + + GpsSignalWidgetModel.RtkState.CONNECTED -> { + //绿 + tvRtkState.value = + AndUtil.getResString(R.string.uxsdk_checklist_rtk_status_connected) + tvRtkState.setValueTextColor(AndUtil.getResColor(R.color.uxsdk_green_in_dark)) + } + + GpsSignalWidgetModel.RtkState.ERROR -> { + //红 + tvRtkState.value = AndUtil.getResString(R.string.uxsdk_abnormal) + tvRtkState.setValueTextColor(AndUtil.getResColor(R.color.uxsdk_red_in_dark)) + } + } + } + } + + private fun updateRtKSatelliteCount(count: Int) { + rtkOverview.let { + if (it.enabled) { + LogUtils.i(tag,"updateRtKSatelliteCount,it.enabled=${it.enabled},count=$count") + tvRtkSatelliteCount.value = count.toString() + } + } + + } + + private fun setRTKSwitch(isChecked: Boolean) { + rtkEnabledSwitch.setOnCheckedChangeListener(null) + rtkEnabledSwitch.isChecked = isChecked + rtkEnabledSwitch.setOnCheckedChangeListener(this) + } + + private fun updateGpsSatelliteCount(count: Int) { + tvGpsSatelliteCount.value = count.toString() + } + + private fun updateSignalLevel(level: GpsSignalWidgetModel.SignalLevel) { + tvGpsSignal.setValueTextColor(AndUtil.getResColor(mapSignalLevelToColorRes(level))) + tvGpsSignal.value = AndUtil.getResString(mapSignalLevelToStringRes(level)) + tvGpsSatelliteCount.setValueTextColor(AndUtil.getResColor(mapSignalLevelToColorRes(level))) + + if (rtkOverview.enabled) { + tvRtkSignal.setValueTextColor(AndUtil.getResColor(mapSignalLevelToColorRes(level))) + tvRtkSignal.value = AndUtil.getResString(mapSignalLevelToStringRes(level)) + tvRtkSatelliteCount.setValueTextColor(AndUtil.getResColor(mapSignalLevelToColorRes(level))) + } + } + + + private fun mapSignalLevelToStringRes(level: GpsSignalWidgetModel.SignalLevel): Int { + return when (level) { + GpsSignalWidgetModel.SignalLevel.LEVEL_3 -> { + R.string.uxsdk_fpv_top_bar_gps_signal_state_strong + } + GpsSignalWidgetModel.SignalLevel.LEVEL_2 -> { + R.string.uxsdk_fpv_top_bar_gps_signal_state_normal + } + GpsSignalWidgetModel.SignalLevel.LEVEL_1 -> { + R.string.uxsdk_fpv_top_bar_gps_signal_state_weak + } + } + } + + private fun mapSignalLevelToColorRes(level: GpsSignalWidgetModel.SignalLevel): Int { + return when (level) { + GpsSignalWidgetModel.SignalLevel.LEVEL_3 -> { + R.color.uxsdk_tips_normal_in_dark + } + GpsSignalWidgetModel.SignalLevel.LEVEL_2 -> { + R.color.uxsdk_tips_caution_in_dark + } + GpsSignalWidgetModel.SignalLevel.LEVEL_1 -> { + R.color.uxsdk_tips_danger_in_dark + } + } + } + + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + inflate(context, R.layout.uxsdk_fpv_top_bar_widget_gps_signal_popover_rtk, this) + } + + override fun reactToModelChanges() { + addReaction(gpsSignalWidgetModel.rtkOverview.observeOn(SchedulerProvider.ui()).subscribe { + rtkOverview = it + updateRtkState(it) + }) + addReaction(gpsSignalWidgetModel.gpsSatelliteCount.observeOn(SchedulerProvider.ui()).subscribe { + updateGpsSatelliteCount(it) + }) + addReaction(gpsSignalWidgetModel.rtkSatelliteCount.observeOn(SchedulerProvider.ui()).subscribe { + updateRtKSatelliteCount(it) + }) + addReaction(gpsSignalWidgetModel.gpsSignalLevel.observeOn(SchedulerProvider.ui()).subscribe { + updateSignalLevel(it) + }) + } + + override fun getIdealDimensionRatioString(): String? { + return getString(R.string.uxsdk_widget_rtk_enabled_ratio) + } + + override fun onCheckedChanged(buttonView: CompoundButton?, isChecked: Boolean) { + addDisposable(rtkEnabledWidgetModel.canEnableRTK.firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe({ canEnableRTK: Boolean -> + if (!canEnableRTK) { + setRTKSwitch(!isChecked) + showLongToast(R.string.uxsdk_rtk_enabled_motors_running) + } else { + gpsSignalWidgetModel.setRTKEnable(isChecked) + } + }, UxErrorHandle.logErrorConsumer(tag, "canEnableRTK:"))) + } + + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/BandWidthSelectWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/BandWidthSelectWidget.java new file mode 100644 index 00000000..8fb9d6d0 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/BandWidthSelectWidget.java @@ -0,0 +1,197 @@ +package dji.v5.ux.core.widget.hd; + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.ArrayList; +import java.util.List; + +import dji.sdk.keyvalue.value.airlink.Bandwidth; +import dji.sdk.keyvalue.value.airlink.ChannelSelectionMode; +import dji.sdk.keyvalue.value.airlink.FrequencyBand; +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.TabSelectCell; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; + +/** + * SDR 带宽模式选择 + */ +public class BandWidthSelectWidget extends ConstraintLayoutWidget implements TabSelectCell.OnTabChangeListener{ + private static final String TAG = "BandWidthSelectWidget"; + private Bandwidth mBandwidth = Bandwidth.UNKNOWN; + private List mBandWidthItems = new ArrayList<>(); + private ChannelSelectionMode mChannelMode = ChannelSelectionMode.UNKNOWN; + private FrequencyBand mFrequencyBand = FrequencyBand.UNKNOWN; + + private TabSelectCell sdrBandWidthSelectTab; + + BandWidthSelectWidgetModel widgetModel = new BandWidthSelectWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + + public BandWidthSelectWidget(Context context) { + this(context, null); + } + + public BandWidthSelectWidget(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public BandWidthSelectWidget(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + + initBandwidthItems(); + initBandwidthItemsUI(); + setVisibility(GONE); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + } + + private void updateBandwidthSelect() { + if(mBandwidth != Bandwidth.UNKNOWN) { + int position = findBandwidthPosition(mBandwidth); + if(position >= 0) { + sdrBandWidthSelectTab.setOnTabChangeListener(null); + sdrBandWidthSelectTab.setCurrentTab(position); + sdrBandWidthSelectTab.setOnTabChangeListener(this); + } + } + } + + private int findBandwidthPosition(Bandwidth bandwidth) { + + if (mBandWidthItems.isEmpty()) { + return -1; + } + + DJIBandwidth bandwidthMode = DJIBandwidth.find(bandwidth); + return mBandWidthItems.indexOf(bandwidthMode); + } + + private void initBandwidthItemsUI() { + if(!mBandWidthItems.isEmpty()) { + List items = new ArrayList<>(); + for(DJIBandwidth bandwidth : mBandWidthItems) { + items.add(bandwidth.getName()); + } + int position = findBandwidthPosition(mBandwidth); + position = Math.max(position, 0); + sdrBandWidthSelectTab.setOnTabChangeListener(null); + sdrBandWidthSelectTab.addTabs(position, items); + sdrBandWidthSelectTab.setOnTabChangeListener(this); + } + } + + private void initBandwidthItems() { + mBandWidthItems.clear(); + mBandWidthItems.add(DJIBandwidth.BW_40); + mBandWidthItems.add(DJIBandwidth.BW_20); + mBandWidthItems.add(DJIBandwidth.BW_10); + } + + private void updateVisible() { + if (mChannelMode == ChannelSelectionMode.AUTO + // 1.4G 只有 10M 不能选择 + || mFrequencyBand == FrequencyBand.BAND_1_DOT_4G) { + setVisibility(GONE); + } else { + setVisibility(VISIBLE); + } + } + + @Override + public void onTabChanged(TabSelectCell cell, int oldIndex, int newIndex) { + if (oldIndex == newIndex) { + return; + } + if (newIndex < mBandWidthItems.size()) { + Bandwidth bandwidth = mBandWidthItems.get(newIndex).getValue(); + addDisposable(widgetModel.setBandwidth(bandwidth).subscribe(() -> { + + }, throwable -> { + LogUtils.e(TAG, "setFrequencyBand fail: " + throwable); + updateBandwidthSelect(); + })); + } + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_setting_menu_sdr_band_width_select_layout, this); + sdrBandWidthSelectTab = findViewById(R.id.tsc_setting_menu_sdr_band_width_select); + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.getBandwidth().subscribe(value -> { + mBandwidth = value; + int position = findBandwidthPosition(mBandwidth); + if(position >= 0) { + sdrBandWidthSelectTab.setOnTabChangeListener(null); + sdrBandWidthSelectTab.setCurrentTab(position); + sdrBandWidthSelectTab.setOnTabChangeListener(this); + } + updateBandwidthSelect(); + })); + addReaction(widgetModel.getChannelSelectionMode().subscribe(value -> { + mChannelMode = value; + updateVisible(); + })); + addReaction(widgetModel.getFrequencyBand().subscribe(value -> { + mFrequencyBand = value; + updateVisible(); + })); + } + + public enum DJIBandwidth { + + BW_40("40MHz", Bandwidth.BANDWIDTH_40MHZ), + BW_20("20MHz", Bandwidth.BANDWIDTH_20MHZ), + BW_10("10MHz", Bandwidth.BANDWIDTH_10MHZ), + UNKNOWN("", Bandwidth.UNKNOWN); + private String mName; + private Bandwidth mValue; + + DJIBandwidth(String name, Bandwidth value) { + mName = name; + mValue = value; + } + + public String getName() { + return mName; + } + + public Bandwidth getValue() { + return mValue; + } + + public static DJIBandwidth find(Bandwidth value) { + DJIBandwidth target = UNKNOWN; + for(DJIBandwidth bandwidth : values()) { + if(bandwidth.mValue == value) { + target = bandwidth; + break; + } + } + return target; + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/BandWidthSelectWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/BandWidthSelectWidgetModel.java new file mode 100644 index 00000000..c76f58b4 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/BandWidthSelectWidgetModel.java @@ -0,0 +1,53 @@ +package dji.v5.ux.core.widget.hd; + +import androidx.annotation.NonNull; + +import dji.sdk.keyvalue.key.AirLinkKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.value.airlink.Bandwidth; +import dji.sdk.keyvalue.value.airlink.ChannelSelectionMode; +import dji.sdk.keyvalue.value.airlink.FrequencyBand; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; + +public class BandWidthSelectWidgetModel extends WidgetModel { + private DataProcessor bandwidthDataProcessor = DataProcessor.create(Bandwidth.UNKNOWN); + private DataProcessor channelSelectionModeDataProcessor = DataProcessor.create(ChannelSelectionMode.UNKNOWN); + private DataProcessor frequencyBandDataProcessor = DataProcessor.create(FrequencyBand.UNKNOWN); + + protected BandWidthSelectWidgetModel(@NonNull DJISDKModel djiSdkModel, @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + } + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyBandwidth), bandwidthDataProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyChannelSelectionMode), channelSelectionModeDataProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyFrequencyBand), frequencyBandDataProcessor); + } + + @Override + protected void inCleanup() { + //do nothing + } + + public Flowable getBandwidth() { + return bandwidthDataProcessor.toFlowableOnUI(); + } + + public Flowable getChannelSelectionMode(){ + return channelSelectionModeDataProcessor.toFlowableOnUI(); + } + + public Flowable getFrequencyBand(){ + return frequencyBandDataProcessor.toFlowableOnUI(); + } + + public Completable setBandwidth(Bandwidth value) { + return djiSdkModel.setValue(KeyTools.createKey(AirLinkKey.KeyBandwidth), value); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/BandWidthWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/BandWidthWidget.java new file mode 100644 index 00000000..2235a4d6 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/BandWidthWidget.java @@ -0,0 +1,92 @@ +package dji.v5.ux.core.widget.hd; + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.sdk.keyvalue.value.airlink.Bandwidth; +import dji.sdk.keyvalue.value.airlink.ChannelSelectionMode; +import dji.sdk.keyvalue.value.airlink.FrequencyBand; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.TextCell; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; + +/** + * 信道模式为自动模式时显示带宽分配 + */ +public class BandWidthWidget extends ConstraintLayoutWidget { + private ChannelSelectionMode mChannelMode = ChannelSelectionMode.UNKNOWN; + private FrequencyBand mFrequencyBand = FrequencyBand.UNKNOWN; + + private TextCell bandWidthTextCell; + + BandWidthSelectWidgetModel widgetModel = new BandWidthSelectWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + + public BandWidthWidget(Context context) { + this(context, null); + } + + public BandWidthWidget(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public BandWidthWidget(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + } + + + private void updateVisible() { + if (mChannelMode == ChannelSelectionMode.AUTO || mFrequencyBand == FrequencyBand.BAND_1_DOT_4G) { + setVisibility(VISIBLE); + } else { + setVisibility(GONE); + } + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_setting_menu_sdr_band_width_layout, this); + bandWidthTextCell = findViewById(R.id.tsc_setting_menu_sdr_band_width); + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.getBandwidth().subscribe(bandwidth -> { + if (bandwidth == Bandwidth.BANDWIDTH_10MHZ) { + bandWidthTextCell.setContent("10MHz"); + } else if (bandwidth == Bandwidth.BANDWIDTH_20MHZ) { + bandWidthTextCell.setContent("20MHz"); + } else if(bandwidth == Bandwidth.BANDWIDTH_40MHZ) { + bandWidthTextCell.setContent("40MHz"); + } + })); + addReaction(widgetModel.getChannelSelectionMode().subscribe(value -> { + mChannelMode = value; + updateVisible(); + })); + addReaction(widgetModel.getFrequencyBand().subscribe(value -> { + mFrequencyBand = value; + updateVisible(); + })); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/ChannelContract.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/ChannelContract.java new file mode 100644 index 00000000..f9dba66e --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/ChannelContract.java @@ -0,0 +1,16 @@ +package dji.v5.ux.core.widget.hd; +import java.util.List; + +public class ChannelContract { + interface View { + + void updateSupportDataRates(List bands); + + void initSlaveViews(); + + void updateVideoCameras(boolean enable); + + void updateChannelMode(boolean auto); + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/ChannelSelectWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/ChannelSelectWidget.java new file mode 100644 index 00000000..78414c02 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/ChannelSelectWidget.java @@ -0,0 +1,121 @@ +package dji.v5.ux.core.widget.hd; + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.List; + +import dji.sdk.keyvalue.value.airlink.ChannelSelectionMode; +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.TabSelectCell; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; + +public class ChannelSelectWidget extends ConstraintLayoutWidget implements ChannelContract.View, TabSelectCell.OnTabChangeListener{ + private static final String TAG = "ChannelSelectWidget"; + TabSelectCell mChannelModeTabCell; + private boolean mIsChangingChannelMode; + + ChannelSelectWidgetModel widgetModel = new ChannelSelectWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + + public ChannelSelectWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public ChannelSelectWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public ChannelSelectWidget(@NonNull Context context) { + super(context); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + } + + @Override + public void onTabChanged(TabSelectCell cell, int oldIndex, int newIndex) { + addDisposable(widgetModel.setChannelSelectionMode(newIndex == 0 ? ChannelSelectionMode.AUTO : ChannelSelectionMode.MANUAL).subscribe(() -> { + + }, throwable -> { + LogUtils.e(TAG, "setChannelSelectionMode fail: " + throwable); + onChannelSelectionModeFailed(oldIndex); + onDidSetChannelSelectionMode(); + })); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_setting_menu_sdr_channel_select_layout, this); + mChannelModeTabCell = findViewById(R.id.tsc_setting_menu_channel_select_tab_cell); + mChannelModeTabCell.setOnTabChangeListener(this); + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.getChannelSelectionMode().subscribe(value -> { + updateChannelMode(ChannelSelectionMode.AUTO == value); + })); + } + + @Override + public void updateSupportDataRates(List bands) { + //do nothing + } + + @Override + public void initSlaveViews() { + //do nothing + } + + @Override + public void updateVideoCameras(boolean enable) { + //do nothing + } + + @Override + public void updateChannelMode(boolean auto) { + if (mChannelModeTabCell != null) { + mChannelModeTabCell.setOnTabChangeListener(null); + mChannelModeTabCell.setCurrentTab(auto ? 0 : 1); + mChannelModeTabCell.setOnTabChangeListener(this); + } + } + + private void onDidSetChannelSelectionMode() { + mIsChangingChannelMode = false; + updateChannelModeTabEnable(); + } + + private void updateChannelModeTabEnable() { + if (mChannelModeTabCell != null) { + mChannelModeTabCell.setEnabled(!mIsChangingChannelMode); + } + } + + private void onChannelSelectionModeFailed(int oldIndex) { + if (mChannelModeTabCell != null) { + mChannelModeTabCell.setOnTabChangeListener(null); + mChannelModeTabCell.setCurrentTab(oldIndex); + mChannelModeTabCell.setOnTabChangeListener(ChannelSelectWidget.this); + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/ChannelSelectWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/ChannelSelectWidgetModel.java new file mode 100644 index 00000000..5386a841 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/ChannelSelectWidgetModel.java @@ -0,0 +1,39 @@ +package dji.v5.ux.core.widget.hd; + +import androidx.annotation.NonNull; + +import dji.sdk.keyvalue.key.AirLinkKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.value.airlink.ChannelSelectionMode; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; + +public class ChannelSelectWidgetModel extends WidgetModel { + private DataProcessor channelSelectionModeProcessor = DataProcessor.create(ChannelSelectionMode.UNKNOWN); + + protected ChannelSelectWidgetModel(@NonNull DJISDKModel djiSdkModel, @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + } + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyChannelSelectionMode), channelSelectionModeProcessor); + } + + @Override + protected void inCleanup() { + //do nothing + } + + public Flowable getChannelSelectionMode() { + return channelSelectionModeProcessor.toFlowableOnUI(); + } + + public Completable setChannelSelectionMode(ChannelSelectionMode value) { + return djiSdkModel.setValue(KeyTools.createKey(AirLinkKey.KeyChannelSelectionMode), value); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/FrequencyTabSelectWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/FrequencyTabSelectWidget.java new file mode 100644 index 00000000..611637cd --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/FrequencyTabSelectWidget.java @@ -0,0 +1,179 @@ +package dji.v5.ux.core.widget.hd; + +import android.content.Context; +import android.util.AttributeSet; + +import java.util.ArrayList; +import java.util.List; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import dji.sdk.keyvalue.value.airlink.ChannelSelectionMode; +import dji.sdk.keyvalue.value.airlink.FrequencyBand; +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.TabSelectCell; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; + + +public class FrequencyTabSelectWidget extends ConstraintLayoutWidget implements TabSelectCell.OnTabChangeListener { + private static final String TAG = "FrequencyTabSelectWidget"; + + private TabSelectCell frequencySelectTab; + private FrequencyBand mOcuSyncFrequencyBand = FrequencyBand.BAND_MULTI; + + private List mSupportOcuSyncFrequencyBands; + + private ChannelSelectionMode mChannelSelectionMode; + + private FrequencyTabSelectWidgetModel widgetModel = new FrequencyTabSelectWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + + private String[] mAllFrequencyNames; + + public FrequencyTabSelectWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public FrequencyTabSelectWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public FrequencyTabSelectWidget(@NonNull Context context) { + super(context); + } + + @Override + public void onTabChanged(TabSelectCell cell, int oldIndex, int newIndex) { + if (oldIndex == newIndex) { + return; + } + + if (mSupportOcuSyncFrequencyBands != null && newIndex < mSupportOcuSyncFrequencyBands.size()) { + FrequencyBand newBand = mSupportOcuSyncFrequencyBands.get(newIndex); + if (newBand != mOcuSyncFrequencyBand) { + addDisposable(widgetModel.setFrequencyBand(newBand).subscribe(() -> { + + }, throwable -> { + LogUtils.e(TAG, "setFrequencyBand fail: " + throwable); + frequencySelectTab.setCurrentTab(oldIndex); + })); + } + } + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_setting_menu_frequency_tab_select_layout, this); + frequencySelectTab = findViewById(R.id.tsc_setting_menu_hd_frequency_tab_cell); + frequencySelectTab.setOnTabChangeListener(this); + mAllFrequencyNames = getResources().getStringArray(R.array.uxsdk_sdr_frequency_names); + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.getFrequencyBand().subscribe(value -> { + mOcuSyncFrequencyBand = value; + updateSelection(); + })); + addReaction(widgetModel.getFrequencyBandRange().subscribe(value->{ + mSupportOcuSyncFrequencyBands = value; + List names = new ArrayList<>(); + boolean is1dot4Support = find1dot4Band(mSupportOcuSyncFrequencyBands); + if(mSupportOcuSyncFrequencyBands != null && mAllFrequencyNames != null) { + for (FrequencyBand band : mSupportOcuSyncFrequencyBands) { + if (band.value() < mAllFrequencyNames.length) { + if (band == FrequencyBand.BAND_MULTI + && mChannelSelectionMode != ChannelSelectionMode.AUTO) { + continue; + } + names.add(mAllFrequencyNames[convertOcuSyncBandValue(band, is1dot4Support)]); + } + } + } + frequencySelectTab.addTabs(0, names); + updateSelection(); + })); + addReaction(widgetModel.getChannelSelectionMode().subscribe(value->{ + mChannelSelectionMode = value; + updateSelection(); + })); + addReaction(widgetModel.getConnection().subscribe(isConnected->{ + frequencySelectTab.setEnabled(isConnected); + if (Boolean.TRUE.equals(isConnected)) { + return; + } + frequencySelectTab.setCurrentTab(0); + })); + } + + private void updateSelection() { + if (mSupportOcuSyncFrequencyBands != null) { + for (int i = 0; i < mSupportOcuSyncFrequencyBands.size(); i++) { + FrequencyBand band = mSupportOcuSyncFrequencyBands.get(i); + if (band.value() == mOcuSyncFrequencyBand.value()) { + frequencySelectTab.setCurrentTab(i); + break; + } + } + } + } + + private boolean find1dot4Band(List bands) { + + if (bands != null) { + for (FrequencyBand band : bands) { + if (band == FrequencyBand.BAND_1_DOT_4G) { + return true; + } + } + } + + return false; + } + + + public int convertOcuSyncBandValue(FrequencyBand band, boolean is1Dot4Support) { + if (band == null) { + return 0; + } + + switch (band) { + case BAND_MULTI: + if (is1Dot4Support) { + //三频 + return 5; + } else { + //双频 + return 0; + } + case BAND_2_DOT_4G: + return 1; + case BAND_5_DOT_8G: + return 2; + case BAND_1_DOT_4G: + return 3; + case BAND_5_DOT_7G: + return 4; + default: + return 0; + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/FrequencyTabSelectWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/FrequencyTabSelectWidgetModel.java new file mode 100644 index 00000000..9020dca6 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/FrequencyTabSelectWidgetModel.java @@ -0,0 +1,66 @@ +package dji.v5.ux.core.widget.hd; + +import androidx.annotation.NonNull; + +import java.util.ArrayList; +import java.util.List; + +import dji.sdk.keyvalue.key.AirLinkKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.value.airlink.ChannelSelectionMode; +import dji.sdk.keyvalue.value.airlink.FrequencyBand; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; + +public class FrequencyTabSelectWidgetModel extends WidgetModel { + + private DataProcessor airlinkFrequencyBandMsgDataProcessor = DataProcessor.create(FrequencyBand.UNKNOWN); + private DataProcessor> airlinkFrequencyBandRangeMsgDataProcessor = DataProcessor.create(new ArrayList<>()); + private DataProcessor channelSelectionModeDataProcessor = DataProcessor.create(ChannelSelectionMode.UNKNOWN); + private DataProcessor connectionProcessor = DataProcessor.create(false); + protected FrequencyTabSelectWidgetModel(@NonNull DJISDKModel djiSdkModel, @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + } + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyFrequencyBand), airlinkFrequencyBandMsgDataProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyFrequencyBandRange), airlinkFrequencyBandRangeMsgDataProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyChannelSelectionMode), channelSelectionModeDataProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyConnection), connectionProcessor); + } + + @Override + protected void inCleanup() { + // do nothing + } + + public Completable setFrequencyBand(FrequencyBand value) { + return djiSdkModel.setValue(KeyTools.createKey(AirLinkKey.KeyFrequencyBand), value); + } + + public Completable setChannelSelectionMode(ChannelSelectionMode value) { + return djiSdkModel.setValue(KeyTools.createKey(AirLinkKey.KeyChannelSelectionMode), value); + } + + public Flowable getFrequencyBand() { + return airlinkFrequencyBandMsgDataProcessor.toFlowableOnUI(); + } + + public Flowable getChannelSelectionMode() { + return channelSelectionModeDataProcessor.toFlowableOnUI(); + } + + public Flowable> getFrequencyBandRange() { + return airlinkFrequencyBandRangeMsgDataProcessor.toFlowableOnUI(); + } + + public Flowable getConnection() { + return connectionProcessor.toFlowableOnUI(); + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/HdmiSettingWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/HdmiSettingWidget.java new file mode 100644 index 00000000..4247aa0f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/HdmiSettingWidget.java @@ -0,0 +1,41 @@ +package dji.v5.ux.core.widget.hd; + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.v5.ux.R; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; + +public class HdmiSettingWidget extends ConstraintLayoutWidget { + public HdmiSettingWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public HdmiSettingWidget(@NonNull Context context) { + super(context); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_hdmi_setting_layout, this); + } + + @Override + protected void reactToModelChanges() { + //do nothing + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/InfoWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/InfoWidget.java new file mode 100644 index 00000000..f6af7b18 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/InfoWidget.java @@ -0,0 +1,268 @@ +package dji.v5.ux.core.widget.hd; + +import android.content.Context; +import android.util.AttributeSet; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.ArrayList; +import java.util.List; + +import dji.sdk.keyvalue.value.airlink.Bandwidth; +import dji.sdk.keyvalue.value.airlink.FrequencyInterferenceInfo; +import dji.sdk.keyvalue.value.airlink.SDRHdOffsetParams; +import dji.v5.utils.common.AndUtil; +import dji.v5.utils.common.SDRLinkHelper; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.TextCell; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; + +public class InfoWidget extends ConstraintLayoutWidget { + private SignalInfo mSdrSignal = new SignalInfo();; + + /*** + * + * 计算信号状态 + */ + private List mRssis = new ArrayList<>(); + + /** 中心频点的值, 即24xx.5的形式 */ + private Integer mCurNfIndex = Integer.MAX_VALUE; + /** 频点的范围, 10M范围是+-5, 20M范围是+-10 */ + private int mRangeSize = 5; + private Integer[] mValidRanges; + private SDRHdOffsetParams mOffsetParams; + + /** 频点的起始位置 ***/ + private float mNfStartIndex = 2400.5f; + /** 白色选框最左边, 不一定等于({@link #mCurNfIndex} - {@link #mRangeSize}), 会随着用户拖动的变化而变化 */ + private float mLeftNfIndex = Float.MAX_VALUE; + + private int sdrDownQuality = -1; + private int sdrUpQuality = -1; + private int linkSignalQuality = -1; + private boolean fcConnected = false; + private SignalLevel mSignalLevel = SignalLevel.LEVEL_0; + private TextCell sdrInfoTextCell; + private TextView summaryText ; + private InfoWidgetModel widgetModel = new InfoWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + + public InfoWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public InfoWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public InfoWidget(@NonNull Context context) { + super(context); + } + + @Override + public void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + public void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_setting_menu_sdr_info_text_layout, this); + sdrInfoTextCell = findViewById(R.id.tc_setting_menu_sdr_info_text); + summaryText = findViewById(R.id.summaryText); + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.getBandwidth().subscribe(value -> { + mSdrSignal.bandwidth = value; + summaryText.setText(mSdrSignal.toString()); + })); + + addReaction(widgetModel.getFrequencyInterfaceInfoList().subscribe(value -> { + mRssis = value; + updateAverageValue(); + summaryText.setText(mSdrSignal.toString()); + })); + + addReaction(widgetModel.getFrequencyPointIndexRange().subscribe(value -> { + mValidRanges = new Integer[2]; + mValidRanges[0] = value.getMin(); + mValidRanges[1] = value.getMax(); + onValidRangeChanged(); + summaryText.setText(mSdrSignal.toString()); + })); + + addReaction(widgetModel.getSdrHdOffsetParamsData().subscribe(value -> { + mOffsetParams = value; + updateAverageValue(); + summaryText.setText(mSdrSignal.toString()); + })); + + addReaction(widgetModel.getDynamicDataRate().subscribe(value -> { + mSdrSignal.dataRate = value.floatValue(); + summaryText.setText(mSdrSignal.toString()); + })); + + addReaction(widgetModel.getFrequencyPointIndex().subscribe(value -> { + mCurNfIndex = value; + mLeftNfIndex = (float)mCurNfIndex - mRangeSize; + updateAverageValue(); + summaryText.setText(mSdrSignal.toString()); + })); + + addReaction(widgetModel.getDownLinkQuality().subscribe(value -> { + sdrDownQuality = value; + updateSdrSignalLevelLiveData(); + })); + + addReaction(widgetModel.getUpLinkQuality().subscribe(value -> { + sdrUpQuality = value; + updateSdrSignalLevelLiveData(); + })); + + addReaction(widgetModel.getLinkSignalQuality().subscribe(value -> { + linkSignalQuality = value; + updateSdrSignalLevelLiveData(); + })); + + addReaction(widgetModel.getFcConnection().subscribe(value -> { + fcConnected = value; + updateSdrSignalLevelLiveData(); + })); + } + + public void onValidRangeChanged() { + + if(mSdrSignal.bandwidth == null || mValidRanges == null) { + return; + } + + float selectRange = SDRLinkHelper.RANGE_SIZE_10MHZ; + if(mSdrSignal.bandwidth == Bandwidth.BANDWIDTH_20MHZ) { + selectRange = SDRLinkHelper.RANGE_SIZE_20MHZ; + } else if(mSdrSignal.bandwidth == Bandwidth.BANDWIDTH_40MHZ) { + selectRange = SDRLinkHelper.RANGE_SIZE_40MHZ; + } + + float left = mValidRanges[0]; + if(left != SDRLinkHelper.ORIGINAL_NF_2DOT4G_START_FREQ + && left != SDRLinkHelper.ORIGINAL_NF_5DOT8G_START_FREQ) { + left -= selectRange; + } + + mNfStartIndex = left; + } + + private void updateAverageValue() { + + if(mRssis == null || mCurNfIndex == Float.MAX_VALUE || mLeftNfIndex == Float.MAX_VALUE) { + return; + } + + int rssiStartIndex = (int) ((mLeftNfIndex - mNfStartIndex) / 2); + if(rssiStartIndex < 0) { + rssiStartIndex = 0; + } + float average = 0; + for(int i = rssiStartIndex; i < rssiStartIndex + mRangeSize && i < mRssis.size(); ++i) { + average += mRssis.get(i).getRssi(); + } + average = average / mRangeSize; + + // 计算offset值 + if(mOffsetParams != null) { + average += ((mOffsetParams.getRcLinkOffset().byteValue() > 0 ? mOffsetParams.getRcLinkOffset().byteValue() : 0) + + mOffsetParams.getPathLossOffset().byteValue() + mOffsetParams.getTxPowerOffset().byteValue()); + } + mSdrSignal.strength = average; + } + + private void updateSdrSignalLevelLiveData() { + int value = Integer.min(sdrDownQuality, sdrUpQuality); + if (!fcConnected) { + mSignalLevel = SignalLevel.LEVEL_0; + } else { + if (linkSignalQuality > 0) { + switch (linkSignalQuality) { + case 4: + case 5: + mSignalLevel = SignalLevel.LEVEL_3; + break; + case 3: + mSignalLevel = SignalLevel.LEVEL_2; + break; + case 1: + case 2: + mSignalLevel = SignalLevel.LEVEL_1; + break; + default: + break; + } + } else { + if (value > 60) { + mSignalLevel = SignalLevel.LEVEL_3; + } else if (value <= 60 && value >= 40) { + mSignalLevel = SignalLevel.LEVEL_2; + } else { + mSignalLevel = SignalLevel.LEVEL_1; + } + } + } + setTextCellContent(mSignalLevel); + } + + private void setTextCellContent(SignalLevel level){ + switch (level) { + case LEVEL_1: + sdrInfoTextCell.setContent(getResources().getString(R.string.uxsdk_fpv_top_bar_gps_signal_state_weak)); + sdrInfoTextCell.setContentColor(AndUtil.getResColor(R.color.uxsdk_tips_danger_in_dark)); + break; + case LEVEL_2: + sdrInfoTextCell.setContent(getResources().getString(R.string.uxsdk_fpv_top_bar_gps_signal_state_normal)); + sdrInfoTextCell.setContentColor(AndUtil.getResColor(R.color.uxsdk_tips_caution_in_dark)); + break; + case LEVEL_3: + sdrInfoTextCell.setContent(getResources().getString(R.string.uxsdk_fpv_top_bar_gps_signal_state_strong)); + sdrInfoTextCell.setContentColor(AndUtil.getResColor(R.color.uxsdk_green)); + break; + default: + sdrInfoTextCell.setContent("N/A"); + sdrInfoTextCell.setContentColor(AndUtil.getResColor(R.color.uxsdk_tips_danger_in_dark)); + break; + } + } + + private enum SignalLevel { + /** + * 飞机断开,红色叉叉 + */ + LEVEL_0, + /** + * 红色 + */ + LEVEL_1, + /** + * 黄色 + */ + LEVEL_2, + /** + * 白色 + */ + LEVEL_3 + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/InfoWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/InfoWidgetModel.java new file mode 100644 index 00000000..bb57f633 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/InfoWidgetModel.java @@ -0,0 +1,102 @@ +package dji.v5.ux.core.widget.hd; + +import androidx.annotation.NonNull; + +import java.util.ArrayList; +import java.util.List; + +import dji.sdk.keyvalue.key.AirLinkKey; +import dji.sdk.keyvalue.key.FlightControllerKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.value.airlink.Bandwidth; +import dji.sdk.keyvalue.value.airlink.FrequencyInterferenceInfo; +import dji.sdk.keyvalue.value.airlink.SDRHdOffsetParams; +import dji.sdk.keyvalue.value.common.IntMinMax; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Flowable; + +public class InfoWidgetModel extends WidgetModel { + private DataProcessor bandwidthDataProcessor = DataProcessor.create(Bandwidth.UNKNOWN); + private DataProcessor> frequencyInterfaceInfoProcessor = DataProcessor.create(new ArrayList<>()); + private DataProcessor frequencyPointIndexRangeProcessor = DataProcessor.create(new IntMinMax()); + private DataProcessor sdrHdOffsetParamsDataProcessor = DataProcessor.create(new SDRHdOffsetParams()); + private DataProcessor dynamicDataRateProcessor = DataProcessor.create(0.0); + private DataProcessor frequencyPointIndexProcessor = DataProcessor.create(0); + + private DataProcessor downLinkQualityProcessor = DataProcessor.create(0); + + private DataProcessor upLinkQualityProcessor = DataProcessor.create(0); + + private DataProcessor linkSignalQualityProcessor = DataProcessor.create(0); + + private DataProcessor fcConnectionProcessor = DataProcessor.create(false); + + + + protected InfoWidgetModel(@NonNull DJISDKModel djiSdkModel, @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + } + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyBandwidth), bandwidthDataProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyFrequencyInterference), frequencyInterfaceInfoProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyFrequencyPointRange), frequencyPointIndexRangeProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeySDRHdOffsetParams), sdrHdOffsetParamsDataProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyDynamicDataRate), dynamicDataRateProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyFrequencyPoint), frequencyPointIndexProcessor); + + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyDownLinkQuality), downLinkQualityProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyUpLinkQuality), upLinkQualityProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyLinkSignalQuality), linkSignalQualityProcessor); + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyConnection), fcConnectionProcessor); + } + + @Override + protected void inCleanup() { + // do nothing + } + + public Flowable getBandwidth() { + return bandwidthDataProcessor.toFlowableOnUI(); + } + + public Flowable> getFrequencyInterfaceInfoList() { + return frequencyInterfaceInfoProcessor.toFlowableOnUI(); + } + + public Flowable getFrequencyPointIndexRange() { + return frequencyPointIndexRangeProcessor.toFlowableOnUI(); + } + + public Flowable getSdrHdOffsetParamsData() { + return sdrHdOffsetParamsDataProcessor.toFlowableOnUI(); + } + + public Flowable getDynamicDataRate() { + return dynamicDataRateProcessor.toFlowableOnUI(); + } + + public Flowable getFrequencyPointIndex() { + return frequencyPointIndexProcessor.toFlowableOnUI(); + } + + public Flowable getDownLinkQuality() { + return downLinkQualityProcessor.toFlowableOnUI(); + } + + public Flowable getUpLinkQuality() { + return upLinkQualityProcessor.toFlowableOnUI(); + } + + public Flowable getLinkSignalQuality() { + return linkSignalQualityProcessor.toFlowableOnUI(); + } + + public Flowable getFcConnection() { + return fcConnectionProcessor.toFlowableOnUI(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/SignalInfo.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/SignalInfo.java new file mode 100644 index 00000000..db83279c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/SignalInfo.java @@ -0,0 +1,31 @@ +package dji.v5.ux.core.widget.hd; + +import java.util.Locale; + +import dji.sdk.keyvalue.value.airlink.Bandwidth; +import dji.v5.utils.common.AndUtil; +import dji.v5.ux.R; + +public class SignalInfo { + private static final String FORMAT_STR = "%.2fMbps"; + public float strength; + public Bandwidth bandwidth; + public float dataRate; + + @Override + public String toString() { + + String strengthStr = strength + "dBm"; + String bandwidthStr = ""; + if(bandwidth == Bandwidth.BANDWIDTH_10MHZ) { + bandwidthStr = "10MHz"; + } else if(bandwidth == Bandwidth.BANDWIDTH_20MHZ) { + bandwidthStr = "20MHZ"; + } else if(bandwidth == Bandwidth.BANDWIDTH_40MHZ) { + bandwidthStr = "40MHZ"; + } + String rateStr = String.format(Locale.US, FORMAT_STR, dataRate); + + return AndUtil.getResString(R.string.uxsdk_setting_ui_hd_sdr_channel_state_summary,strengthStr,bandwidthStr,rateStr); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/VideoRateTextWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/VideoRateTextWidget.java new file mode 100644 index 00000000..438dcb63 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/VideoRateTextWidget.java @@ -0,0 +1,68 @@ +package dji.v5.ux.core.widget.hd; + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import java.util.Locale; + +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.TextCell; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; + +/** + * 图传码率显示控件 + */ +public class VideoRateTextWidget extends ConstraintLayoutWidget { + + private String formatStr = "%.2fMbps"; + + private TextCell videoRateTextCell; + + VideoRateTextWidgetModel widgetModel = new VideoRateTextWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + + public VideoRateTextWidget(Context context) { + this(context, null); + } + + public VideoRateTextWidget(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public VideoRateTextWidget(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_setting_menu_sdr_video_rate_text_layout, this); + videoRateTextCell = findViewById(R.id.tc_setting_menu_sdr_video_rate_text); + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.getDynamicDataRate().subscribe(value -> { + float codeRate = value.floatValue(); + videoRateTextCell.setContent(String.format(Locale.US, formatStr, codeRate)); + })); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/VideoRateTextWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/VideoRateTextWidgetModel.java new file mode 100644 index 00000000..edb3f53e --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/VideoRateTextWidgetModel.java @@ -0,0 +1,33 @@ +package dji.v5.ux.core.widget.hd; + +import androidx.annotation.NonNull; + +import dji.sdk.keyvalue.key.AirLinkKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Flowable; + +public class VideoRateTextWidgetModel extends WidgetModel { + private DataProcessor dynamicDataRateProcessor = DataProcessor.create(0.0); + + protected VideoRateTextWidgetModel(@NonNull DJISDKModel djiSdkModel, @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + } + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyDynamicDataRate), dynamicDataRateProcessor); + } + + @Override + protected void inCleanup() { + //do nothing + } + + public Flowable getDynamicDataRate() { + return dynamicDataRateProcessor.toFlowableOnUI(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/ChartLeftYAxisView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/ChartLeftYAxisView.java new file mode 100644 index 00000000..f88ba21a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/ChartLeftYAxisView.java @@ -0,0 +1,46 @@ +package dji.v5.ux.core.widget.hd.frequency; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.util.AttributeSet; + +import dji.v5.ux.R; +import dji.v5.ux.core.base.BaseView; + +/** + * @description : 曲线图左边的纵坐标数字 + */ +public class ChartLeftYAxisView extends BaseView { + + private int[] mAxisValues = new int[]{-70, -90, -110}; + private Paint mPaint; + private float mTxtSize; + private float mChartHeight; + + private float mXOffset = 0; + private float mYOffset = 0; + + public ChartLeftYAxisView(Context context, AttributeSet attrs) { + super(context, attrs); + mTxtSize = getResources().getDimension(R.dimen.uxsdk_text_size_small); + mPaint = new Paint(); + mPaint.setColor(getResources().getColor(android.R.color.white)); + mPaint.setTextSize(mTxtSize); + mPaint.setAntiAlias(true); + + mChartHeight = getResources().getDimension(R.dimen.uxsdk_setting_ui_hd_sdr_chart_height); + mYOffset = mTxtSize / 4f; + mXOffset = (int) getResources().getDimension(R.dimen.uxsdk_4_dp); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + canvas.drawText(String.valueOf(mAxisValues[0]), mXOffset, mChartHeight / 5 + mYOffset, mPaint); + canvas.drawText(String.valueOf(mAxisValues[1]), mXOffset, mChartHeight / 5 * 3 + mYOffset, mPaint); + canvas.drawText(String.valueOf(mAxisValues[2]), mXOffset, mChartHeight + mYOffset, mPaint); + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/ChartRightYAxisView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/ChartRightYAxisView.java new file mode 100644 index 00000000..27f7a3e7 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/ChartRightYAxisView.java @@ -0,0 +1,76 @@ +package dji.v5.ux.core.widget.hd.frequency; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.util.AttributeSet; + +import dji.v5.ux.R; +import dji.v5.ux.core.base.BaseView; + +/** + * @description : sdr图标右边所写的文字 + */ +public class ChartRightYAxisView extends BaseView { + + private String[] mDistanceUnitStr = new String[]{"≈1km", "≈4km", "MHz"}; + // 1km距离对应的nf值 + private int mFirstLineNfValue = -91; + // 4km距离对应nf值 + private int mSecondLineNfValue = -103; + + private float mFirstLinePos = 0; + private float mSecondLinePos = 0; + + private Paint mPaint; + private float mSmallTxtSize; + private float mNormalTxtSize; + private float mChartHeight; + + private float mXOffset = 0; + private float mYOffset = 0; + + public ChartRightYAxisView(Context context, AttributeSet attrs) { + super(context, attrs); + + mSmallTxtSize = getResources().getDimension(R.dimen.uxsdk_12_dp); + mNormalTxtSize = getResources().getDimension(R.dimen.uxsdk_14_dp); + mPaint = new Paint(); + mPaint.setColor(getResources().getColor(android.R.color.white)); + mPaint.setTextSize(mSmallTxtSize); + + mChartHeight = getResources().getDimension(R.dimen.uxsdk_setting_ui_hd_sdr_chart_height); + mYOffset = mSmallTxtSize / 4f; + mXOffset = (int) getResources().getDimension(R.dimen.uxsdk_4_dp); + + mFirstLinePos = mChartHeight * (FreqView.LINE_MAX_VALUE - (mFirstLineNfValue - FreqView.NF_BASE_VALUE)) / FreqView.LINE_MAX_VALUE; + mSecondLinePos = mChartHeight * (FreqView.LINE_MAX_VALUE - (mSecondLineNfValue - FreqView.NF_BASE_VALUE)) / FreqView.LINE_MAX_VALUE; + + } + + /** + * 设置1km线的位置 + * @param _val + */ + public void set1KmNfValue(int _val) { + mFirstLineNfValue = _val; + mSecondLineNfValue = mFirstLineNfValue - 12; + mFirstLinePos = mChartHeight * (FreqView.LINE_MAX_VALUE - (mFirstLineNfValue - FreqView.NF_BASE_VALUE)) / FreqView.LINE_MAX_VALUE; + mSecondLinePos = mChartHeight * (FreqView.LINE_MAX_VALUE - (mSecondLineNfValue - FreqView.NF_BASE_VALUE)) / FreqView.LINE_MAX_VALUE; + postInvalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + mPaint.setColor(getResources().getColor(android.R.color.white)); + mPaint.setTextSize(mSmallTxtSize); + canvas.drawText(String.valueOf(mDistanceUnitStr[0]), mXOffset, mFirstLinePos + mYOffset, mPaint); + canvas.drawText(String.valueOf(mDistanceUnitStr[1]), mXOffset, mSecondLinePos + mYOffset, mPaint); + + mPaint.setColor(getResources().getColor(android.R.color.darker_gray)); + mPaint.setTextSize(mNormalTxtSize); + canvas.drawText(String.valueOf(mDistanceUnitStr[2]), mXOffset, mChartHeight + mYOffset, mPaint); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/DistanceLineView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/DistanceLineView.java new file mode 100644 index 00000000..1a835453 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/DistanceLineView.java @@ -0,0 +1,60 @@ +package dji.v5.ux.core.widget.hd.frequency; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.util.AttributeSet; + +import dji.v5.ux.R; +import dji.v5.ux.core.base.BaseView; + +public class DistanceLineView extends BaseView { + + // 1km距离对应的nf值 + private int mFirstLineNfValue = -91; + // 4km距离对应nf值 + private int mSecondLineNfValue = -103; + + private float mFirstLinePos = 0; + private float mSecondLinePos = 0; + + private Paint mPaint; + private float mChartHeight; + + public DistanceLineView(Context context, AttributeSet attrs) { + super(context, attrs); + + mPaint = new Paint(); + mPaint.setColor(getResources().getColor(android.R.color.darker_gray)); + mPaint.setStrokeWidth(1); + mPaint.setAlpha(125); + mPaint.setAntiAlias(true); + mChartHeight = getResources().getDimension(R.dimen.uxsdk_setting_ui_hd_sdr_chart_height); + + mFirstLinePos = mChartHeight * (FreqView.LINE_MAX_VALUE - (mFirstLineNfValue - FreqView.NF_BASE_VALUE)) / FreqView.LINE_MAX_VALUE; + mSecondLinePos = mChartHeight * (FreqView.LINE_MAX_VALUE - (mSecondLineNfValue - FreqView.NF_BASE_VALUE)) / FreqView.LINE_MAX_VALUE; + } + + /** + * 设置1km线的位置 + * @param _val + */ + public void set1KmNfValue(int _val) { + mFirstLineNfValue = _val; + mSecondLineNfValue = mFirstLineNfValue - 12; + mFirstLinePos = mChartHeight * (FreqView.LINE_MAX_VALUE - (mFirstLineNfValue - FreqView.NF_BASE_VALUE)) / FreqView.LINE_MAX_VALUE; + mSecondLinePos = mChartHeight * (FreqView.LINE_MAX_VALUE - (mSecondLineNfValue - FreqView.NF_BASE_VALUE)) / FreqView.LINE_MAX_VALUE; + postInvalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + canvas.drawLine(0, mFirstLinePos, + canvas.getWidth(), mFirstLinePos, mPaint); + + canvas.drawLine(0, mSecondLinePos, + canvas.getWidth(), mSecondLinePos, mPaint); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/FreqRangeRectView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/FreqRangeRectView.java new file mode 100644 index 00000000..f8da3171 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/FreqRangeRectView.java @@ -0,0 +1,516 @@ +package dji.v5.ux.core.widget.hd.frequency; + +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.os.Handler; +import android.os.Looper; +import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.view.View.OnTouchListener; +import android.view.ViewGroup; +import android.view.ViewParent; +import android.widget.ImageView; +import android.widget.ProgressBar; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.List; +import java.util.Locale; + +import dji.sdk.keyvalue.value.airlink.Bandwidth; +import dji.sdk.keyvalue.value.airlink.ChannelSelectionMode; +import dji.sdk.keyvalue.value.airlink.FrequencyBand; +import dji.sdk.keyvalue.value.airlink.FrequencyInterferenceInfo; +import dji.sdk.keyvalue.value.airlink.SDRHdOffsetParams; +import dji.v5.utils.common.LogUtils; +import dji.v5.utils.common.SDRLinkHelper; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; + +public class FreqRangeRectView extends ConstraintLayoutWidget implements OnTouchListener { + private final static String TAG = FreqRangeRectView.class.getSimpleName(); + + public interface OnRangeChangedListener { + void onRangeChanged(float leftVal, float rightVal, float leftPos, float rightPos, boolean isRectDragging); + void onAverageValChanged(String averageVal); + } + + private ImageView mCenterDown; + private ImageView mCenterUp; + private ProgressBar mAveragePgb; + + /** 当前白色选框是否处于拽托状态 */ + private boolean mIsDragging = false; + /** 拽托白色选框时, 手指的触摸位置*/ + private float mRangeRectTouchX = 0; + + private int mNumNfValues = Integer.MAX_VALUE; + /** 频点的起始位置, 见{@link #mNumNfValues}说明 */ + private float mNfStartIndex = 2400.5f; + /** 频点的范围, 10M范围是+-5, 20M范围是+-10 */ + private int mRangeSize = 5; + /** 在屏幕坐标系下, 两个nf频点间的步长, 以x轴为参考坐标系 */ + private float mWidthInterval = Float.MAX_VALUE; + /** 白色选框中心频点的值, 即24xx.5的形式 */ + private Integer mCurNfIndex = Integer.MAX_VALUE; + /** 白色选框最左边, 不一定等于({@link #mCurNfIndex} - {@link #mRangeSize}), 会随着用户拖动的变化而变化 */ + private float mLeftNfIndex = Float.MAX_VALUE; + + /** 上一次出于2。4G时的频点值 */ + private int mLastNfIndex2dot4G = Integer.MIN_VALUE; + + /** 当前中心频点所处于的x轴位置 */ + private float mCurCenterX = Float.MAX_VALUE; + /** 父view的宽度, 这里指整个sdr曲线图的宽度 */ + private int mParentWidth = Integer.MAX_VALUE; + + private FrequencyBand mCurBandChannelMode = FrequencyBand.UNKNOWN; + private ChannelSelectionMode mCurChannelMode = ChannelSelectionMode.AUTO; + private List mRssis; + + private OnRangeChangedListener mListener; + + private Drawable mNormalBg; + private Drawable mHoverBg; + + + private float mRectX = -1.0f; + private float mUnusedRectX = -1.0f; + private float mAlpha = 1; + private float mLeftX; + private float mRightX; + private Handler mSkipPointHandler; + + FreqRangeRectViewModel widgetModel = new FreqRangeRectViewModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + + public FreqRangeRectView(Context context, AttributeSet attrs) { + super(context, attrs); + mSkipPointHandler = new Handler(Looper.getMainLooper()); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + //do nothing + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.getFrequencyPointIndex().subscribe(value -> { + mCurNfIndex = value; + updatePosition(); + })); + addReaction(widgetModel.getChannelSelectionMode().subscribe(value -> { + mCurChannelMode = value; + updateAllView(); + })); + addReaction(widgetModel.getBandwidth().subscribe(value -> { + mBandwidth = value; + updateAllView(); + })); + addReaction(widgetModel.getFrequencyPointRSSIInfo().subscribe(value -> { + mRssis = value; + updateAverageValue(); + })); + addReaction(widgetModel.getFrequencyPointIndexRange().subscribe(value -> { + mValidRanges = new Integer[2]; + mValidRanges[0] = value.getMin(); + mValidRanges[1] = value.getMax(); + onValidRangeChanged(); + })); + addReaction(widgetModel.getSDRHdOffsetParams().subscribe(value -> { + mOffsetParams = value; + })); + addReaction(widgetModel.getFrequencyBand().subscribe(value -> { + mCurBandChannelMode = value; + onDualBandModeChange(); + updateAllView(); + })); + } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + if(isInEditMode()) { + return; + } + + mCenterDown = (ImageView) findViewById(R.id.sdr_snr_freq_range_center_down); + mCenterUp = (ImageView) findViewById(R.id.sdr_snr_freq_range_center_up); + mAveragePgb = (ProgressBar) findViewById(R.id.sdr_snr_freq_rect_pgb); + + mNormalBg = getResources().getDrawable(R.drawable.uxsdk_freq_range_rect); + mHoverBg = getResources().getDrawable(R.drawable.uxsdk_freq_range_rect_hover); + + setOnTouchListener(this); + mAlpha = getAlpha(); + super.setAlpha(0); //初始化时先隐藏 + updateAllView(); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + } + + public FreqRangeRectView setParentWidth(int _width) { + mParentWidth = _width; + return this; + } + + public FreqRangeRectView setNumValues(int _num) { + mNumNfValues = _num; + return this; + } + + public FreqRangeRectView setWidthInterval(float _interval) { + mWidthInterval = _interval; + return this; + } + + @Override + public boolean onTouch(View v, MotionEvent event) { + + //自动模式或辅控都不能设置频点信息 + if(mCurChannelMode != ChannelSelectionMode.MANUAL) { + return false; + } + + // 处理框体的拖动 + if(event.getAction() == MotionEvent.ACTION_DOWN) { + setParentInterceptTouchEvent(true); + mRangeRectTouchX = event.getRawX(); + mIsDragging = true; + updateRectBg(mIsDragging); + } + else if(event.getAction() == MotionEvent.ACTION_MOVE) { + float curX = event.getRawX(); + float setX = v.getX() + curX - mRangeRectTouchX; + // 处理挪出范围的情况 + if(setX < 0) { + setX = 0; + } else if(setX + v.getWidth() > mParentWidth) { + setX = (float)mParentWidth - v.getWidth(); + } + v.setX(setX); + mRangeRectTouchX = curX; + mLeftNfIndex = convertX2Index(setX); + onRangeChanged(mLeftNfIndex, mLeftNfIndex + mRangeSize * 2, setX, setX + v.getWidth(), mIsDragging); + } else if(event.getAction() == MotionEvent.ACTION_UP + || event.getAction() == MotionEvent.ACTION_CANCEL) { + mIsDragging = false; + + float curX = v.getX(); + // 与频点对齐 + if(curX % mWidthInterval != 0) { + float multiple = curX / mWidthInterval; + float preMulX = multiple * mWidthInterval; + float aftMulX = (multiple + 1) * mWidthInterval; + if(curX - preMulX < aftMulX - curX || multiple + 1 >= (mNumNfValues - 1)) { + curX = preMulX; + } else { + curX = aftMulX; + } + v.setX(curX); + + } + mLeftNfIndex = convertX2Index(curX); + onRangeChanged(mLeftNfIndex, mLeftNfIndex + mRangeSize * 2, curX, curX + v.getWidth(), mIsDragging); + updateAverageValue(); + updateRectBg(mIsDragging); + sendNfIndex2Sdr(curX); + setParentInterceptTouchEvent(false); + } + return true; + } + + //请求禁止父容器拦截触摸事件 + public void setParentInterceptTouchEvent(boolean disallow) { + ViewParent parent = getParent(); + if (parent != null) { + parent.requestDisallowInterceptTouchEvent(disallow); + } + } + + /** + * 自定义时, 白色选框拽托结束后, 设置当前的nf频点值到sdr + * @param leftX + */ + private void sendNfIndex2Sdr(float leftX) { + float centerX = leftX + mRangeSize * mWidthInterval; + float caculNf = convertX2Index(centerX); + final int sendNf = (int) caculNf; + addDisposable(widgetModel.setFrequencyPointIndex(sendNf).subscribe(() -> { + + }, throwable -> { + LogUtils.e(TAG, "setFrequencyPointIndex fail: " + throwable); + })); + } + + public void setOnRangeChangedListener(OnRangeChangedListener l) { + mListener = l; + } + + private Bandwidth mBandwidth; + private Integer[] mValidRanges; + private SDRHdOffsetParams mOffsetParams; + + public void onValidRangeChanged() { + + if(mBandwidth == null || mCurChannelMode == null || mParentWidth == Integer.MAX_VALUE + || mValidRanges == null) { + return; + } + + float selectRange = SDRLinkHelper.RANGE_SIZE_10MHZ; + if(mBandwidth == Bandwidth.BANDWIDTH_20MHZ) { + selectRange = SDRLinkHelper.RANGE_SIZE_20MHZ; + } else if(mBandwidth == Bandwidth.BANDWIDTH_40MHZ) { + selectRange = SDRLinkHelper.RANGE_SIZE_40MHZ; + } + + float left = mValidRanges[0]; + float right = mValidRanges[1]; + if(left != SDRLinkHelper.ORIGINAL_NF_2DOT4G_START_FREQ + && left != SDRLinkHelper.ORIGINAL_NF_5DOT8G_START_FREQ) { + left -= selectRange; + right += selectRange; + } + + mNumNfValues = (int) (right - left); + mWidthInterval = mParentWidth * 1f / (mNumNfValues); + mNfStartIndex = left; + if (null == mCurNfIndex || mCurNfIndex == Integer.MAX_VALUE) { + return; + } + checkCurNfInRange(mCurNfIndex); + + updateAllView(); + } + + private void checkCurNfInRange(float curNfIndex) { + + if (mValidRanges == null) { + return; + } + + if (curNfIndex < mValidRanges[0]) { + addDisposable(widgetModel.setFrequencyPointIndex(mValidRanges[0]).subscribe(() -> { + + }, throwable -> { + LogUtils.e(TAG, "setFrequencyPointIndex fail: " + throwable); + })); + } else if (curNfIndex > mValidRanges[1]) { + addDisposable(widgetModel.setFrequencyPointIndex(mValidRanges[1]).subscribe(() -> { + + }, throwable -> { + LogUtils.e(TAG, "setFrequencyPointIndex fail: " + throwable); + })); + } + } + + private void onDualBandModeChange() { + + if (mCurBandChannelMode == FrequencyBand.BAND_5_DOT_8G) { + mLastNfIndex2dot4G = mCurNfIndex; + } else if (mCurBandChannelMode == FrequencyBand.BAND_2_DOT_4G){ + addDisposable(widgetModel.setFrequencyPointIndex(mLastNfIndex2dot4G).subscribe(() -> { + + }, throwable -> { + LogUtils.e(TAG, "setFrequencyPointIndex fail: " + throwable); + })); + } + updateAllView(); + } + + /** + * 更新白色选框内rssi的平均值, 选框位置改变, 大小改变, rssi改变时都应该更新 + */ + private void updateAverageValue() { + + if(mRssis == null || mCurNfIndex == Float.MAX_VALUE) { + return; + } + + int rssiStartIndex = (int) ((mLeftNfIndex - mNfStartIndex) / 2); + if(rssiStartIndex < 0) { + rssiStartIndex = 0; + } + float averageVal = 0; + for(int i = rssiStartIndex; i < rssiStartIndex + mRangeSize && i < mRssis.size(); ++i) { + averageVal += mRssis.get(i).getRssi(); + } + averageVal = averageVal / mRangeSize; + + // 一下计算offset值 + if(mOffsetParams != null) { + averageVal += ((mOffsetParams.getRcLinkOffset().byteValue() > 0 ? mOffsetParams.getRcLinkOffset() : 0) + + mOffsetParams.getPathLossOffset().byteValue() + mOffsetParams.getTxPowerOffset().byteValue()); + } + // 由于最大值是50, Progress最大值为100, 所以转化成Progress直接乘以2 + mAveragePgb.setProgress((int) ((averageVal - FreqView.NF_BASE_VALUE) * 2)); + if(mListener != null) { + mListener.onAverageValChanged(String.format(Locale.US, "%.1f", averageVal) + "dBm"); + } + } + + private void updateAllView() { + resizeRect(); + updatePosition(); + onChannelModeChanged(); + } + + @Override + public void setAlpha(float alpha) { + super.setAlpha(alpha); + mAlpha = alpha; + } + + private void updatePosition() { + if(mCurNfIndex == null || mCurNfIndex == Integer.MAX_VALUE) { + return; + } + // 各项长度还未初始化 + if(mWidthInterval == Float.MAX_VALUE) { + return; + } + + if(mIsDragging) { + return; + } + Log.i(getClass().getSimpleName(), "convertIndex: " + mCurNfIndex); + mCurCenterX = (mCurNfIndex - mNfStartIndex) * mWidthInterval; + + if(getAlpha() != mAlpha) { + super.setAlpha(mAlpha); + } + setRectBorder(); + } + + private void resizeRect() { + if(mBandwidth == null) { + return; + } + + if(mBandwidth == Bandwidth.BANDWIDTH_10MHZ) { + mRangeSize = SDRLinkHelper.RANGE_SIZE_10MHZ; + } else if(mBandwidth == Bandwidth.BANDWIDTH_20MHZ){ + mRangeSize = SDRLinkHelper.RANGE_SIZE_20MHZ; + } else if(mBandwidth == Bandwidth.BANDWIDTH_40MHZ){ + mRangeSize = SDRLinkHelper.RANGE_SIZE_40MHZ; + } + + // 重新计算框的大小 + setRectBorder(); + } + + private void setRectBorder() { + if(mCurCenterX == Float.MAX_VALUE) { + // 中心线未设置 + return; + } + + // 更新左边频点值 + mLeftNfIndex = (float)mCurNfIndex - mRangeSize; + float leftX = Math.max(mCurCenterX - mRangeSize * mWidthInterval, 0f); + float rightX = mCurCenterX + mRangeSize * mWidthInterval; + onRangeChanged((float)mCurNfIndex - mRangeSize, (float)mCurNfIndex + mRangeSize, leftX, rightX, mIsDragging); + } + + private void reDrawRectBorder(float leftX, float rightX) { + if(mLeftX == leftX && mRightX == rightX) { + return; + } + mLeftX = leftX; + mRightX = rightX; + + this.setX(leftX); + ViewGroup.LayoutParams lp = this.getLayoutParams(); + lp.width = (int) (rightX - leftX); + this.setLayoutParams(lp); + updateAverageValue(); + } + + //屏蔽差值较大的值,防止rect view回跳 + private void onRangeChanged(float leftVal, float rightVal, float leftPos, float rightPos, boolean isRectDragging) { + mSkipPointHandler.removeCallbacksAndMessages(null); + if ((mRectX == -1.0f || Math.abs(leftVal - mRectX) <= 5.0f) || (mUnusedRectX != -1.0f && Math.abs(leftVal - mUnusedRectX) <= 5.0f)) { + + mRectX = leftVal; + if (mListener != null) { + mListener.onRangeChanged(leftVal, rightVal, leftPos, rightPos, isRectDragging); + } + if (!mIsDragging) { + reDrawRectBorder(leftPos, rightPos); + } + } else { + mUnusedRectX = leftVal; + //如果跳跃比较大,而又没有再次更新,则应该取最后的结果显示出来 + mSkipPointHandler.postDelayed(() -> { + onRangeChanged(leftVal, rightVal, leftPos, rightPos, isRectDragging); + }, 1000); + } + } + + /** + * 当前的坐标值转化为频点值 + * @param coordX + * @return + */ + private float convertX2Index(float coordX) { + float caculNf = coordX / mWidthInterval + mNfStartIndex; + return (float) (Math.floor(caculNf) + 0.5); + } + + /** + * 信道模式改变时, 需要改变bg + */ + private void onChannelModeChanged() { + if(mCurChannelMode == null) { + return; + } + + if(mCurChannelMode == ChannelSelectionMode.AUTO ) { + mCenterDown.setVisibility(INVISIBLE); + mCenterUp.setVisibility(INVISIBLE); + mIsDragging = false; + setBackground(mNormalBg); + } else { + mCenterDown.setVisibility(VISIBLE); + mCenterUp.setVisibility(VISIBLE); + // 切换到自定义时闪一下背景 + setBackground(mHoverBg); + postDelayed(() -> setBackground(mNormalBg), 200); + } + + } + + /** + * 根据矩形框的拖动状态, 设置矩形框的hover bg以及水平线的消失和显示 + * @param _isdragging + */ + private void updateRectBg(boolean _isdragging) { + if(_isdragging) { + mAveragePgb.setVisibility(INVISIBLE); + setBackground(mHoverBg); + } else { + mAveragePgb.setVisibility(VISIBLE); + setBackground(mNormalBg); + } + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/FreqRangeRectViewModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/FreqRangeRectViewModel.java new file mode 100644 index 00000000..4e89e799 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/FreqRangeRectViewModel.java @@ -0,0 +1,83 @@ +package dji.v5.ux.core.widget.hd.frequency; + +import androidx.annotation.NonNull; + +import java.util.ArrayList; +import java.util.List; + +import dji.sdk.keyvalue.key.AirLinkKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.value.airlink.Bandwidth; +import dji.sdk.keyvalue.value.airlink.ChannelSelectionMode; +import dji.sdk.keyvalue.value.airlink.FrequencyBand; +import dji.sdk.keyvalue.value.airlink.FrequencyInterferenceInfo; +import dji.sdk.keyvalue.value.airlink.SDRHdOffsetParams; +import dji.sdk.keyvalue.value.common.IntMinMax; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; + +public class FreqRangeRectViewModel extends WidgetModel { + private DataProcessor frequencyPointIndexProcessor = DataProcessor.create(0); + private DataProcessor channelSelectionModeDataProcessor = DataProcessor.create(ChannelSelectionMode.UNKNOWN); + private DataProcessor bandwidthDataProcessor = DataProcessor.create(Bandwidth.UNKNOWN); + private DataProcessor> frequencyPointRSSIInfoDataProcessor = DataProcessor.create(new ArrayList<>()); + private DataProcessor frequencyPointIndexRangeProcessor = DataProcessor.create(new IntMinMax()); + private DataProcessor sdrHdOffsetParamsProcessor = DataProcessor.create(new SDRHdOffsetParams()); + private DataProcessor frequencyBandDataProcessor = DataProcessor.create(FrequencyBand.UNKNOWN); + + protected FreqRangeRectViewModel(@NonNull DJISDKModel djiSdkModel, @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + } + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyFrequencyPoint), frequencyPointIndexProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyChannelSelectionMode), channelSelectionModeDataProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyBandwidth), bandwidthDataProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyFrequencyInterference), frequencyPointRSSIInfoDataProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyFrequencyPointRange), frequencyPointIndexRangeProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeySDRHdOffsetParams), sdrHdOffsetParamsProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyFrequencyBand), frequencyBandDataProcessor); + } + + @Override + protected void inCleanup() { + //do nothing + } + + public Flowable getFrequencyPointIndex() { + return frequencyPointIndexProcessor.toFlowableOnUI(); + } + + public Completable setFrequencyPointIndex(Integer value) { + return djiSdkModel.setValue(KeyTools.createKey(AirLinkKey.KeyFrequencyPoint), value); + } + + public Flowable getChannelSelectionMode() { + return channelSelectionModeDataProcessor.toFlowableOnUI(); + } + + public Flowable getBandwidth() { + return bandwidthDataProcessor.toFlowableOnUI(); + } + + public Flowable> getFrequencyPointRSSIInfo() { + return frequencyPointRSSIInfoDataProcessor.toFlowableOnUI(); + } + + public Flowable getFrequencyPointIndexRange() { + return frequencyPointIndexRangeProcessor.toFlowableOnUI(); + } + + public Flowable getSDRHdOffsetParams() { + return sdrHdOffsetParamsProcessor.toFlowableOnUI(); + } + + public Flowable getFrequencyBand() { + return frequencyBandDataProcessor.toFlowableOnUI(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/FreqRangeTextView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/FreqRangeTextView.java new file mode 100644 index 00000000..8a310a52 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/FreqRangeTextView.java @@ -0,0 +1,55 @@ +package dji.v5.ux.core.widget.hd.frequency; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.util.AttributeSet; +import java.util.Locale; + +import dji.v5.ux.R; +import dji.v5.ux.core.base.BaseView; +public class FreqRangeTextView extends BaseView { + + private float mMinValue = 0; + private float mMaxValue = 0; + private float mPosMinX = 0; + private float mPosMaxX = 0; + + private float mMarginLeft = 0; + + private Paint mPaint; + private float mTxtSize = 30; + // 数字的个数, 如'1'为1个, '1257'为4个 + private int mTxtNum = 6; + + public FreqRangeTextView(Context context, AttributeSet attrs) { + super(context, attrs); + mTxtSize = getResources().getDimension(R.dimen.uxsdk_text_size_small); + mPaint = new Paint(); + mPaint.setColor(getResources().getColor(android.R.color.white)); + mPaint.setTextSize(mTxtSize); + mPaint.setAntiAlias(true); + + mMarginLeft = getResources().getDimension(R.dimen.uxsdk_setting_ui_hd_sdr_chart_left_axis_width); + } + + public void setMinMaxValue(float _min, float _max, float posMin, float posMax) { + mMinValue = _min; + mMaxValue = _max; + mPosMinX = posMin; + mPosMaxX = posMax; + postInvalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + // offset处理居中 + float offset = mTxtSize / 4.0f * mTxtNum; + // 初始化offset之后再+-mTxtSize / 2, 是让文字往两边靠, 让两个文字的间隙变大(10M带宽下可能挨在一起) + canvas.drawText(String.format(Locale.US, "%.1f", mMinValue), mMarginLeft + mPosMinX - offset - mTxtSize / 2, mTxtSize * 1.5f, mPaint); + canvas.drawText(String.format(Locale.US, "%.1f", mMaxValue), mMarginLeft + mPosMaxX - offset + mTxtSize / 2, mTxtSize * 1.5f, mPaint); + + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/FreqView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/FreqView.java new file mode 100644 index 00000000..9f63e271 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/FreqView.java @@ -0,0 +1,389 @@ +package dji.v5.ux.core.widget.hd.frequency; + +import android.content.Context; +import android.graphics.LinearGradient; +import android.graphics.Shader; +import android.util.AttributeSet; +import android.view.View; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.ArrayList; +import java.util.List; + +import dji.sdk.keyvalue.key.AirLinkKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.value.airlink.Bandwidth; +import dji.sdk.keyvalue.value.airlink.ChannelSelectionMode; +import dji.sdk.keyvalue.value.airlink.FrequencyInterferenceInfo; +import dji.v5.common.callback.CommonCallbacks; +import dji.v5.common.error.IDJIError; +import dji.v5.manager.KeyManager; +import dji.v5.utils.common.LogUtils; +import dji.v5.utils.common.SDRLinkHelper; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.charts.model.Line; +import dji.v5.ux.core.base.charts.model.LineChartData; +import dji.v5.ux.core.base.charts.model.PointValue; +import dji.v5.ux.core.base.charts.model.Viewport; +import dji.v5.ux.core.base.charts.view.LineChartView; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; + +public class FreqView extends ConstraintLayoutWidget { + private static final String TAG = "FreqView"; + private LineChartView mSdrSnrLine; + private LineChartData mSnrValues; + private FreqRangeRectView mRangeRect; + private FreqRangeTextView mRangeTv; + private RectCenterTextView mAverageTv; + private TextView mCustomTipTv; + private ChartRightYAxisView mQualityTx; + private DistanceLineView mQualityLine; + + private static final int M_MIN_VALUE_COLOR = 0xff95e33f; + private static final int M_MAX_VALUE_COLOR = 0xfff84242; + + /** 曲线顶端的最大值, 即-60+110, 参考{@link #NF_BASE_VALUE}, 最小值为0 */ + public static final int LINE_MAX_VALUE = 50; + /** NF频点对应的值的最低值为-110, 最高值为-60 */ + public static final int NF_BASE_VALUE = -110; + public static final int NF_MAX_VALUE = -60; + private final int RSSI_VALUE_NUM_2DOT4G = 41; + private final int RSSI_VALUE_NUM_5DOT8G = 62; + private final int RSSI_VALUE_NUM_5DOT7G = 10; + private final int RSSI_VALUE_NUM_1DOT4G = 7; + private final int RSSI_VALUE_NUM_5DOT2G = 51; + private int mNumRssiValues = RSSI_VALUE_NUM_2DOT4G; + /** rssi起始index对应的nf频点 */ + private final float START_INDEX_2DOT4G = 2400f; + private final float START_INDEX_5DOT8G = 5725f; + private final float START_INDEX_5DOT7G = 5650f; + private final float START_INDEX_1DOT4G = 1430f; + private final float START_INDEX_5DOT2G = 5150f; + + private float mRssiStartIndex = START_INDEX_2DOT4G; + /** nf频点的个数, 实际的rssi取值为2400~2482, 但是由于只能设置xxxx.5到sdr, 所以取2400.5~2482.5, 步长为1 */ + private final int NF_VALUE_NUM_2DOT4G = 82; + private final int NF_VALUE_NUM_5DOT8G = 124; + private final int NF_VALUE_NUM_5DOT7G = 20; + private final int NF_VALUE_NUM_1DOT4G = 14; + private final int NF_VALUE_NUM_5DOT2G = 102; + private int mNumNfValues = NF_VALUE_NUM_2DOT4G; + /** 在屏幕坐标系下, 两个nf频点间的步长 */ + private float mWidthInterval = 1; + /** 当前工作频段 0: 2.4G, 1:5.8G */ + private FreqBand mCurFreqBand = FreqBand.FREQ_BAND_2DOT4G; + + private FreqViewModel widgetModel = new FreqViewModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + initView(); + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.getFrequencyPointIndex().subscribe(value -> { + mFreqIndex = value; + onFreqIndexChanged(); + })); + addReaction(widgetModel.getChannelSelectionMode().subscribe(value -> { + mSelectionMode = value; + updateCustomTipVisibility(mSelectionMode); + })); + addReaction(widgetModel.getBandwidth().subscribe(value -> { + mCurBandWidth = value; + })); + KeyManager.getInstance().listen(KeyTools.createKey(AirLinkKey.KeyFrequencyInterference), this, (oldValue, newValue) -> setValues(newValue)); + addReaction(widgetModel.getFrequencyPointIndexRange().subscribe(value -> { + mValidRanges = new Integer[2]; + mValidRanges[0] = value.getMin(); + mValidRanges[1] = value.getMax(); + onValidRangeChanged(); + })); + addReaction(widgetModel.getSDRHdOffsetParams().subscribe(value -> { + mDisOffset = value.getDistOffset().byteValue(); + onDistOffsetChanged(); + })); + addReaction(widgetModel.is5Dot7GSupported().subscribe(value -> { + is5Dot7Supported = value; + })); + } + + private enum FreqBand{ + FREQ_BAND_2DOT4G, + FREQ_BAND_5DOT8G, + FREQ_BAND_1DOT4G, + FREQ_BAND_5DOT7G, + FREQ_BAND_840M, + FREQ_BAND_5DOT2G + } + + + private Bandwidth mCurBandWidth; + private ChannelSelectionMode mSelectionMode; + private Integer[] mValidRanges; + private int mDisOffset = 0; + private Integer mFreqIndex; + private boolean is5Dot7Supported; + public FreqView(Context context) { + this(context, null); + } + + public FreqView(Context context, AttributeSet attrs) { + super(context, attrs); + } + + private void initView() { + View.inflate(getContext(), R.layout.uxsdk_sdr_freq_view, this); + mSdrSnrLine = (LineChartView) findViewById(R.id.sdr_snr_line); + KeyManager.getInstance().getValue(KeyTools.createKey(AirLinkKey.KeyFrequencyPoint), new CommonCallbacks.CompletionCallbackWithParam() { + @Override + public void onSuccess(Integer integer) { + mFreqIndex = integer; + onFreqIndexChanged(); + + initValues(); + + mSdrSnrLine.setLineChartData(mSnrValues); + mSdrSnrLine.setZoomEnabled(false); + mSdrSnrLine.setLineShader( + new LinearGradient(0, + getResources().getDimension(R.dimen.uxsdk_setting_ui_hd_sdr_chart_height), + 0, 0, M_MIN_VALUE_COLOR, M_MAX_VALUE_COLOR, Shader.TileMode.MIRROR)); + // 这样设置才能看到曲线图的整个port + mSdrSnrLine.setViewportCalculationEnabled(true); + } + + @Override + public void onFailure(@NonNull IDJIError error) { + LogUtils.e(TAG,"get frequency point failed: "+error.description()); + } + }); + + + resetViewport(); + + mQualityTx = findViewById(R.id.sdr_quality_value); + mQualityLine = findViewById(R.id.sdr_quality_line); + mCustomTipTv = findViewById(R.id.sdr_custom_alert_tip); + mRangeTv = findViewById(R.id.sdr_freq_range_tv); + mAverageTv = findViewById(R.id.sdr_rect_average_value); + + mRangeRect = findViewById(R.id.sdr_snr_freq_range_rect); + mRangeRect.setOnRangeChangedListener(new FreqRangeRectView.OnRangeChangedListener() { + @Override + public void onRangeChanged(float leftVal, float rightVal, float leftPos, float rightPos, boolean isRectDragging) { + if (!isRectDragging) { + mRangeTv.setMinMaxValue(leftVal + 0.5f, rightVal + 0.5f, leftPos, rightPos); + } else { + mRangeTv.setMinMaxValue(leftVal, rightVal, leftPos, rightPos); + } + mAverageTv.setCenterPos((leftPos + rightPos) / 2f, isRectDragging); + } + + @Override + public void onAverageValChanged(String averageVal) { + mAverageTv.setCenterAverageText(averageVal); + } + + }); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + KeyManager.getInstance().cancelListen(this); + } + + @Override + protected void onLayout(boolean changed, int l, int t, int r, int b) { + super.onLayout(changed, l, t, r, b); + if(isInEditMode()) { + return; + } + if(changed) { + mWidthInterval = mSdrSnrLine.getWidth() * 1f / (mNumNfValues - 1); + mRangeRect.setWidthInterval(mWidthInterval) + .setNumValues(mNumNfValues) + .setParentWidth(mSdrSnrLine.getWidth()) + .onValidRangeChanged(); + + onValidRangeChanged(); + onDistOffsetChanged(); + } + } + + private void initValues() { + List values = new ArrayList(); + values.add(new PointValue(0, 0)); + for (int i = 0; i < mNumRssiValues; ++i) { + values.add(new PointValue(i + 0.5f, 0)); + } + values.add(new PointValue(mNumRssiValues, 0)); + + Line line = new Line(values); + line.setStrokeWidth(2); + line.setHasPoints(false); + + List lines = new ArrayList(); + lines.add(line); + + mSnrValues = new LineChartData(lines); + + } + + private void resetViewport() { + final Viewport v = new Viewport(mSdrSnrLine.getMaximumViewport()); + v.bottom = 0; + v.top = LINE_MAX_VALUE; + v.left = 0; + v.right = mNumRssiValues; + mSdrSnrLine.setMaximumViewport(v); + mSdrSnrLine.setCurrentViewport(v); + } + + private void setValues(List values) { + if (values == null) { + return; + } + mSdrSnrLine.clearAnimation(); + Line line = mSdrSnrLine.getLineChartData().getLines().get(0); + + int rssiValIndex = 0; + int pointIndex = 0; + int size = line.getValues().size(); + for (PointValue value : line.getValues()) { + /** 对首尾值进行了处理, 理由{@link mNumRssiValues}的注释 */ + float y = 0; + if(pointIndex == 0) { + y = (float)values.get(rssiValIndex).getRssi() + 10 - NF_BASE_VALUE; + + } else if(pointIndex == values.size() + 1) { + y = (float)values.get(pointIndex - 2).getRssi() + 10- NF_BASE_VALUE; + } else { + if (rssiValIndex >= size) { + LogUtils.e(TAG,"Illegal state,rssiValIndex >= line.getValues().size(),"); + return; + } + y = (float)values.get(rssiValIndex++).getRssi() - NF_BASE_VALUE; + } + + if( y > NF_MAX_VALUE - NF_BASE_VALUE) { + y = (float)NF_MAX_VALUE - NF_BASE_VALUE; + } + if(y < 0) { + y = 0; + } + value.setTarget(value.getX(), y); + ++pointIndex; + } + + mSdrSnrLine.startDataAnimation(300); + + } + + private void onValidRangeChanged() { + + if(mCurBandWidth == null || mSelectionMode == null || mValidRanges == null) { + return; + } + + float selectRange = SDRLinkHelper.RANGE_SIZE_10MHZ; + if(mCurBandWidth == Bandwidth.BANDWIDTH_20MHZ) { + selectRange = SDRLinkHelper.RANGE_SIZE_20MHZ; + } else if(mCurBandWidth == Bandwidth.BANDWIDTH_40MHZ) { + selectRange = SDRLinkHelper.RANGE_SIZE_40MHZ; + } + + float left = mValidRanges[0]; + float right = mValidRanges[1]; + if(left != SDRLinkHelper.ORIGINAL_NF_2DOT4G_START_FREQ) { + left -= selectRange; + right += selectRange; + } + + final Viewport v = new Viewport(mSdrSnrLine.getMaximumViewport()); + v.bottom = 0; + v.top = LINE_MAX_VALUE; + v.left = (left - mRssiStartIndex) / 2; + v.right = (right - mRssiStartIndex) / 2; + if(v.left < 0) { + v.left = 0; + } + if(v.right > mNumRssiValues) { + v.right = mNumRssiValues; + } + mSdrSnrLine.setMaximumViewport(v); + mSdrSnrLine.setCurrentViewport(v); + + updateCustomTipVisibility(mSelectionMode); + + } + + private void updateCustomTipVisibility(ChannelSelectionMode selectionMode) { + if(selectionMode == ChannelSelectionMode.AUTO) { + mCustomTipTv.setVisibility(GONE); + } else { + mCustomTipTv.setVisibility(VISIBLE); + } + } + + private void onDistOffsetChanged() { + mQualityTx.set1KmNfValue(mDisOffset); + mQualityLine.set1KmNfValue(mDisOffset); + } + + private void onFreqIndexChanged() { + FreqBand old = mCurFreqBand; + + if (SDRLinkHelper.isFrequencyIndexIn2dot4G(mFreqIndex)) { + mCurFreqBand = FreqBand.FREQ_BAND_2DOT4G; + mNumRssiValues = RSSI_VALUE_NUM_2DOT4G; + mRssiStartIndex = START_INDEX_2DOT4G; + mNumNfValues = NF_VALUE_NUM_2DOT4G; + } else if (SDRLinkHelper.isFrequencyIndexIn5dot8G(mFreqIndex) && !is5Dot7Supported) { + mCurFreqBand = FreqBand.FREQ_BAND_5DOT8G; + mNumRssiValues = RSSI_VALUE_NUM_5DOT8G; + mRssiStartIndex = START_INDEX_5DOT8G; + mNumNfValues = NF_VALUE_NUM_5DOT8G; + } else if (SDRLinkHelper.isFrequencyIndex5dot2G(mFreqIndex)) { + mCurFreqBand = FreqBand.FREQ_BAND_5DOT2G; + mNumRssiValues = RSSI_VALUE_NUM_5DOT2G; + mRssiStartIndex = START_INDEX_5DOT2G; + mNumNfValues = NF_VALUE_NUM_5DOT2G; + } else if(SDRLinkHelper.isFrequencyIndexIn5dot7G(mFreqIndex)) { + mCurFreqBand = FreqBand.FREQ_BAND_5DOT7G; + mNumRssiValues = RSSI_VALUE_NUM_5DOT7G; + mRssiStartIndex = START_INDEX_5DOT7G; + mNumNfValues = NF_VALUE_NUM_5DOT7G; + } else if(SDRLinkHelper.isFrequencyIndexIn840M(mFreqIndex) || SDRLinkHelper.isFrequencyIndexIn1dot4G(mFreqIndex)) { + mCurFreqBand = FreqBand.FREQ_BAND_1DOT4G; + mNumRssiValues = RSSI_VALUE_NUM_1DOT4G; + mRssiStartIndex = START_INDEX_1DOT4G; + mNumNfValues = NF_VALUE_NUM_1DOT4G; + } + if (mCurFreqBand != old) { + initValues(); + mSdrSnrLine.setLineChartData(mSnrValues); + resetViewport(); + onValidRangeChanged(); + } + LogUtils.d(TAG,"onFreqIndexChanged mNumRssiValues: "+mNumRssiValues+" mCurFreqBand: "+mCurFreqBand+" old: "+old); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/FreqViewModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/FreqViewModel.java new file mode 100644 index 00000000..0b2b7450 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/FreqViewModel.java @@ -0,0 +1,95 @@ +package dji.v5.ux.core.widget.hd.frequency; + +import androidx.annotation.NonNull; + +import java.util.ArrayList; +import java.util.List; + +import dji.sdk.keyvalue.key.AirLinkKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.value.airlink.Bandwidth; +import dji.sdk.keyvalue.value.airlink.ChannelSelectionMode; +import dji.sdk.keyvalue.value.airlink.FrequencyBand; +import dji.sdk.keyvalue.value.airlink.FrequencyInterferenceInfo; +import dji.sdk.keyvalue.value.airlink.SDRHdOffsetParams; +import dji.sdk.keyvalue.value.common.IntMinMax; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; + +public class FreqViewModel extends WidgetModel { + private DataProcessor frequencyPointIndexProcessor = DataProcessor.create(0); + private DataProcessor channelSelectionModeDataProcessor = DataProcessor.create(ChannelSelectionMode.UNKNOWN); + private DataProcessor bandwidthDataProcessor = DataProcessor.create(Bandwidth.UNKNOWN); + private DataProcessor> frequencyInterfaceInfoProcessor = DataProcessor.create(new ArrayList<>()); + private DataProcessor frequencyPointIndexRangeProcessor = DataProcessor.create(new IntMinMax()); + private DataProcessor sdrHdOffsetParamsProcessor = DataProcessor.create(new SDRHdOffsetParams()); + private DataProcessor frequencyBandDataProcessor = DataProcessor.create(FrequencyBand.UNKNOWN); + private DataProcessor isDualBandSupportedProcessor = DataProcessor.create(false); + private DataProcessor is5Dot7GSupportedProcessor = DataProcessor.create(false); + + protected FreqViewModel(@NonNull DJISDKModel djiSdkModel, @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + } + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyFrequencyInterference), frequencyInterfaceInfoProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyFrequencyPoint), frequencyPointIndexProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyChannelSelectionMode), channelSelectionModeDataProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyBandwidth), bandwidthDataProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyFrequencyPointRange), frequencyPointIndexRangeProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeySDRHdOffsetParams), sdrHdOffsetParamsProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyFrequencyBand), frequencyBandDataProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyIsDualBandSupported), isDualBandSupportedProcessor); + bindDataProcessor(KeyTools.createKey(AirLinkKey.KeyIs5Dot7GSupported), is5Dot7GSupportedProcessor); + } + + @Override + protected void inCleanup() { + // do nothing + } + + public Flowable isDualBandSupported() { + return isDualBandSupportedProcessor.toFlowableOnUI(); + } + + public Flowable is5Dot7GSupported() { + return is5Dot7GSupportedProcessor.toFlowableOnUI(); + } + + public Flowable getFrequencyPointIndex() { + return frequencyPointIndexProcessor.toFlowableOnUI(); + } + + public Completable setFrequencyPointIndex(Integer value) { + return djiSdkModel.setValue(KeyTools.createKey(AirLinkKey.KeyFrequencyPoint), value); + } + + public Flowable getChannelSelectionMode() { + return channelSelectionModeDataProcessor.toFlowableOnUI(); + } + + public Flowable getBandwidth() { + return bandwidthDataProcessor.toFlowableOnUI(); + } + + public Flowable> getFrequencyInterfaceInfoList() { + return frequencyInterfaceInfoProcessor.toFlowableOnUI(); + } + + public Flowable getFrequencyPointIndexRange() { + return frequencyPointIndexRangeProcessor.toFlowableOnUI(); + } + + public Flowable getSDRHdOffsetParams() { + return sdrHdOffsetParamsProcessor.toFlowableOnUI(); + } + + public Flowable getFrequencyBand() { + return frequencyBandDataProcessor.toFlowableOnUI(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/RectCenterTextView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/RectCenterTextView.java new file mode 100644 index 00000000..aaadefb0 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/frequency/RectCenterTextView.java @@ -0,0 +1,60 @@ +package dji.v5.ux.core.widget.hd.frequency; + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.Paint; +import android.util.AttributeSet; + +import dji.v5.ux.R; +import dji.v5.ux.core.base.BaseView; +public class RectCenterTextView extends BaseView { + + private String mAverageVal = "-70dBm"; + private float mPosX = 0; + + private Paint mPaint; + private float mTxtSize = 30; + + private float mMarginLeft = 0; + + public RectCenterTextView(Context context, AttributeSet attrs) { + super(context, attrs); + + mTxtSize = getResources().getDimension(R.dimen.uxsdk_text_size_small); + mPaint = new Paint(); + mPaint.setColor(getResources().getColor(android.R.color.white)); + mPaint.setAntiAlias(true); + mPaint.setTextSize(mTxtSize); + + mMarginLeft = getResources().getDimension(R.dimen.uxsdk_setting_ui_hd_sdr_chart_left_axis_width); + } + + public void setCenterAverageText(String val) { + mAverageVal = val; + postInvalidate(); + } + + /** + * + * @param pos + * @param isRectDragging 如果处于拽托状态, 要使这个view消失 + */ + public void setCenterPos(float pos, boolean isRectDragging) { + mPosX = pos; + if(isRectDragging && getVisibility() != INVISIBLE) { + setVisibility(INVISIBLE); + } else if(!isRectDragging && getVisibility() != VISIBLE) { + setVisibility(VISIBLE); + } + postInvalidate(); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + // offset处理居中 + float offset = mTxtSize / 4.0f * mAverageVal.length(); + canvas.drawText(mAverageVal, mMarginLeft + mPosX - offset, mTxtSize, mPaint); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/interference/HDInterferenceWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/interference/HDInterferenceWidget.java new file mode 100644 index 00000000..75ae3906 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hd/interference/HDInterferenceWidget.java @@ -0,0 +1,33 @@ +package dji.v5.ux.core.widget.hd.interference; + + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.v5.ux.core.base.BaseFrameLayout; +import dji.v5.ux.core.widget.hd.frequency.FreqView; + +public class HDInterferenceWidget extends BaseFrameLayout { + private FreqView mOcuInterferenceView; + public HDInterferenceWidget(@NonNull Context context) { + super(context); + } + + public HDInterferenceWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public HDInterferenceWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + changeInterferenceView(context); + } + + private void changeInterferenceView(Context ctx) { + removeAllViews(); + mOcuInterferenceView = new FreqView(ctx); + addView(mOcuInterferenceView); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/horizontalvelocity/HorizontalVelocityWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/horizontalvelocity/HorizontalVelocityWidget.kt new file mode 100644 index 00000000..5bcf0e34 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/horizontalvelocity/HorizontalVelocityWidget.kt @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.horizontalvelocity + +import android.content.Context +import android.util.AttributeSet +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.widget.BaseTelemetryWidget +import dji.v5.ux.core.communication.GlobalPreferencesManager +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.extension.getVelocityString +import dji.v5.ux.core.widget.horizontalvelocity.HorizontalVelocityWidget.ModelState +import dji.v5.ux.core.widget.horizontalvelocity.HorizontalVelocityWidget.ModelState.HorizontalVelocityStateUpdated +import dji.v5.ux.core.widget.horizontalvelocity.HorizontalVelocityWidget.ModelState.ProductConnected +import dji.v5.ux.core.widget.horizontalvelocity.HorizontalVelocityWidgetModel.HorizontalVelocityState +import java.text.DecimalFormat + +/** + * Widget displays the horizontal velocity of the aircraft. + * + */ +open class HorizontalVelocityWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + widgetTheme: Int = 0 +) : BaseTelemetryWidget( + context, + attrs, + defStyleAttr, + WidgetType.TEXT, + widgetTheme, + R.style.UXSDKHorizontalVelocityWidget +) { + + //region Fields + override val metricDecimalFormat: DecimalFormat = DecimalFormat("###0.0") + + override val imperialDecimalFormat: DecimalFormat = DecimalFormat("###0.0") + + private val widgetModel: HorizontalVelocityWidgetModel by lazy { + HorizontalVelocityWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + GlobalPreferencesManager.getInstance()) + } + //endregion + + //region Constructor + init { + setValueTextViewMinWidthByText("88.8") + } + //endregion + + //region Lifecycle + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + addReaction(widgetModel.horizontalVelocityState + .observeOn(SchedulerProvider.ui()) + .subscribe { updateUI(it) }) + } + + //endregion + + //region Reactions to model + private fun updateUI(horizontalVelocityState: HorizontalVelocityState) { + widgetStateDataProcessor.onNext(HorizontalVelocityStateUpdated(horizontalVelocityState)) + if (horizontalVelocityState is HorizontalVelocityState.CurrentVelocity) { + valueString = getDecimalFormat(horizontalVelocityState.unitType) + .format(horizontalVelocityState.velocity).toString() + unitString = getVelocityString(horizontalVelocityState.unitType) + } else { + valueString = getString(R.string.uxsdk_string_default_value) + unitString = null + } + } + + //endregion + + //region customizations + override fun getIdealDimensionRatioString(): String? = null + + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP) + + //endregion + + //region Hooks + + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val boolean: Boolean) : ModelState() + + /** + * Horizontal velocity state update + */ + data class HorizontalVelocityStateUpdated(val horizontalVelocityState: HorizontalVelocityState) : ModelState() + } + + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/horizontalvelocity/HorizontalVelocityWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/horizontalvelocity/HorizontalVelocityWidgetModel.kt new file mode 100644 index 00000000..7dbb85ac --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/horizontalvelocity/HorizontalVelocityWidgetModel.kt @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.horizontalvelocity + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.value.common.Velocity3D +import dji.sdk.keyvalue.key.KeyTools +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.GlobalPreferenceKeys +import dji.v5.ux.core.communication.GlobalPreferencesInterface +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.toVelocity +import dji.v5.ux.core.util.DataProcessor +import dji.v5.ux.core.util.UnitConversionUtil.UnitType +import dji.v5.ux.core.widget.horizontalvelocity.HorizontalVelocityWidgetModel.HorizontalVelocityState.CurrentVelocity +import dji.v5.ux.core.widget.horizontalvelocity.HorizontalVelocityWidgetModel.HorizontalVelocityState.ProductDisconnected +import kotlin.math.pow +import kotlin.math.sqrt + + +/** + * Widget Model for the [HorizontalVelocityWidget] used to define + * the underlying logic and communication + */ +class HorizontalVelocityWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, + private val preferencesManager: GlobalPreferencesInterface? +) : WidgetModel(djiSdkModel, keyedStore) { + + private val aircraftVelocityProcessor: DataProcessor = DataProcessor.create(Velocity3D()) + private val unitTypeDataProcessor: DataProcessor = DataProcessor.create(UnitType.METRIC) + private val horizontalVelocityStateProcessor: DataProcessor = DataProcessor.create(ProductDisconnected) + + /** + * Get the value of the horizontal velocity state of the aircraft + */ + val horizontalVelocityState: Flowable + get() = horizontalVelocityStateProcessor.toFlowable() + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAircraftVelocity), aircraftVelocityProcessor) + bindDataProcessor(GlobalPreferenceKeys.create(GlobalPreferenceKeys.UNIT_TYPE), unitTypeDataProcessor) + preferencesManager?.setUpListener() + preferencesManager?.let { unitTypeDataProcessor.onNext(it.unitType) } + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + horizontalVelocityStateProcessor.onNext( + CurrentVelocity(calculateHorizontalVelocity(), unitTypeDataProcessor.value) + ) + } else { + horizontalVelocityStateProcessor.onNext(ProductDisconnected) + } + + } + + override fun inCleanup() { + preferencesManager?.cleanup() + } + + private fun calculateHorizontalVelocity(): Float { + return sqrt((aircraftVelocityProcessor.value.x.pow(2) + aircraftVelocityProcessor.value.y.pow(2))) + .toVelocity(unitTypeDataProcessor.value) + .toFloat() + } + + /** + * Class to represent states of horizontal velocity + */ + sealed class HorizontalVelocityState { + /** + * When product is disconnected + */ + object ProductDisconnected : HorizontalVelocityState() + + /** + * When aircraft is moving horizontally + */ + data class CurrentVelocity(val velocity: Float, val unitType: UnitType) : + HorizontalVelocityState() + + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/AttitudeDisplayFpvWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/AttitudeDisplayFpvWidget.kt new file mode 100644 index 00000000..78570a0d --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/AttitudeDisplayFpvWidget.kt @@ -0,0 +1,25 @@ +package dji.v5.ux.core.widget.hsi + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import dji.v5.ux.R + +/** + * Class Description + * + * @author Hoker + * @date 2021/12/2 + * + * Copyright (c) 2021, DJI All Rights Reserved. + */ +class AttitudeDisplayFpvWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : AttitudeDisplayWidget(context, attrs, defStyleAttr) { + + override fun loadLayout(context: Context) { + View.inflate(context, R.layout.uxsdk_fpv_pfd_attitude_display_widget, this) + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/AttitudeDisplayModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/AttitudeDisplayModel.kt new file mode 100644 index 00000000..c8fc8b5b --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/AttitudeDisplayModel.kt @@ -0,0 +1,99 @@ +package dji.v5.ux.core.widget.hsi + +import dji.sdk.keyvalue.key.* +import dji.sdk.keyvalue.value.common.LocationCoordinate2D +import dji.sdk.keyvalue.value.common.Velocity3D +import dji.sdk.keyvalue.value.rtkmobilestation.RTKTakeoffAltitudeInfo +import dji.v5.manager.KeyManager +import dji.v5.manager.aircraft.perception.PerceptionManager +import dji.v5.manager.aircraft.perception.data.ObstacleData +import dji.v5.manager.aircraft.perception.data.PerceptionInfo +import dji.v5.manager.aircraft.perception.listener.ObstacleDataListener +import dji.v5.manager.aircraft.perception.listener.PerceptionInformationListener +import dji.v5.manager.aircraft.perception.radar.RadarInformation +import dji.v5.manager.aircraft.perception.radar.RadarInformationListener +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor + +/** + * Class Description + * + * @author Hoker + * @date 2021/11/26 + * + * Copyright (c) 2021, DJI All Rights Reserved. + */ +open class AttitudeDisplayModel constructor( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, +) : WidgetModel(djiSdkModel, keyedStore) { + private val perceptionManager = PerceptionManager.getInstance() + val velocityProcessor = DataProcessor.create(Velocity3D()) + val altitudeProcessor = DataProcessor.create(0.0) + val goHomeHeightProcessor: DataProcessor = DataProcessor.create(0) + val limitMaxFlightHeightInMeterProcessor = DataProcessor.create(0) + val rtkTakeoffAltitudeInfoProcessor = DataProcessor.create(RTKTakeoffAltitudeInfo()) + + val aircraftLocationDataProcessor = DataProcessor.create(LocationCoordinate2D(Double.NaN, Double.NaN)) + val perceptionInfoProcessor = DataProcessor.create(PerceptionInfo()) + val radarInfoProcessor = DataProcessor.create(RadarInformation()) + val perceptionObstacleDataProcessor = DataProcessor.create(ObstacleData()) + val radarObstacleDataProcessor = DataProcessor.create(ObstacleData()) + + private val perceptionInformationListener = PerceptionInformationListener { + perceptionInfoProcessor.onNext(it) + } + + private val perceptionObstacleDataListener = ObstacleDataListener { + perceptionObstacleDataProcessor.onNext(it) + } + + private val radarObstacleDataListener = ObstacleDataListener { + radarObstacleDataProcessor.onNext(it) + } + private val radarInformationListener = RadarInformationListener { + radarInfoProcessor.onNext(it) + } + + + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAircraftVelocity), velocityProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAltitude), altitudeProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyGoHomeHeight), goHomeHeightProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyHeightLimit), limitMaxFlightHeightInMeterProcessor) + + bindDataProcessor( + KeyTools.createKey( + RtkMobileStationKey.KeyRTKTakeoffAltitudeInfo), rtkTakeoffAltitudeInfoProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAircraftLocation), aircraftLocationDataProcessor) + + + perceptionManager.addPerceptionInformationListener(perceptionInformationListener) + perceptionManager.addObstacleDataListener(perceptionObstacleDataListener) + perceptionManager.radarManager.addRadarInformationListener(radarInformationListener) + perceptionManager.radarManager.addObstacleDataListener(radarObstacleDataListener) + + } + + override fun inCleanup() { + perceptionManager.removePerceptionInformationListener(perceptionInformationListener) + perceptionManager.removeObstacleDataListener(perceptionObstacleDataListener) + perceptionManager.radarManager.removeRadarInformationListener(radarInformationListener) + perceptionManager.radarManager.removeObstacleDataListener(radarObstacleDataListener) + KeyManager.getInstance().cancelListen(this) + + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/AttitudeDisplayWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/AttitudeDisplayWidget.kt new file mode 100644 index 00000000..2d57c683 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/AttitudeDisplayWidget.kt @@ -0,0 +1,140 @@ +package dji.v5.ux.core.widget.hsi + +import android.content.Context +import android.util.AttributeSet +import kotlin.jvm.JvmOverloads +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.ui.hsi.dashboard.AttitudeDashBoard +import android.widget.TextView +import dji.sdk.keyvalue.value.common.LocationCoordinate2D +import dji.sdk.keyvalue.value.common.Velocity3D +import dji.sdk.keyvalue.value.rtkmobilestation.RTKTakeoffAltitudeInfo +import io.reactivex.rxjava3.disposables.CompositeDisposable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import io.reactivex.rxjava3.core.ObservableEmitter +import dji.v5.common.utils.GpsUtils +import dji.v5.common.utils.UnitUtils +import io.reactivex.rxjava3.schedulers.Schedulers +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers +import dji.v5.ux.R +import dji.v5.ux.core.base.SchedulerProvider +import io.reactivex.rxjava3.core.Observable +import java.util.* + +open class AttitudeDisplayWidget @JvmOverloads constructor(context: Context?, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : + ConstraintLayoutWidget( + context!!, attrs, defStyleAttr) { + var mAttitudeDashBoard: AttitudeDashBoard? = null + var mTvAslText: TextView? = null + var mTvAslValue: TextView? = null + var mTvVsText: TextView? = null + var mTvVsValue: TextView? = null + + /** + * 飞行器相对home点的高度 + */ + private var mAltitude = 0.0 + + /** + * home点的高度 + */ + private var mHomePointAltitude = 0.0 + + /** + * 飞行器垂直速度 + */ + private var mSpeedZ = 0f + + /** + * 飞行器二维坐标 + */ + private var mDroneLocation: LocationCoordinate2D? = null + private val mCompositeDisposable = CompositeDisposable() + private val widgetModel = AttitudeDisplayModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()) + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + mAttitudeDashBoard?.setModel(widgetModel) + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + if (!isInEditMode) { + widgetModel.cleanup() + } + } + + private fun updateAltitude() { + mCompositeDisposable.add(Observable.create { emitter: ObservableEmitter -> + val lat = if (mDroneLocation != null) mDroneLocation!!.latitude else Double.NaN + val lon = if (mDroneLocation != null) mDroneLocation!!.longitude else Double.NaN + val aslValue = GpsUtils.egm96Altitude(mHomePointAltitude + mAltitude, lat, lon) + val value = UnitUtils.getValueFromMetricByLength(aslValue.toFloat(), + if (UnitUtils.isMetricUnits()) UnitUtils.UnitType.METRIC else UnitUtils.UnitType.IMPERIAL) + emitter.onNext(value) + emitter.onComplete() + }.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe { aValue: Any? -> + val value = String.format(Locale.US, "%06.1f", aValue) + if (mTvAslValue?.text != value) { + mTvAslValue?.text = value + } + }) + } + + private fun updateSpeed() { + var showSpeedZ = mSpeedZ + if (!java.lang.Float.isNaN(mSpeedZ) && mSpeedZ != 0f) { + showSpeedZ = -mSpeedZ + } + val value = UnitUtils.transFormSpeedIntoDifferentUnit(showSpeedZ) + mTvVsValue?.text = String.format(Locale.US, "%03.1f", value) + } + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + loadLayout(context) + mAttitudeDashBoard = findViewById(R.id.pfd_attitude_dash_board) + mTvAslText = findViewById(R.id.pfd_asl_text) + mTvAslValue = findViewById(R.id.pfd_asl_value) + mTvVsText = findViewById(R.id.pfd_vs_text) + mTvVsValue = findViewById(R.id.pfd_vs_value) + } + + open fun loadLayout(context: Context) { + inflate(context, R.layout.uxsdk_liveview_pfd_attitude_display_widget, this) + } + + override fun reactToModelChanges() { + mCompositeDisposable.add(widgetModel.velocityProcessor.toFlowable().observeOn(SchedulerProvider.ui()).subscribe { velocity3D: Velocity3D -> + mSpeedZ = velocity3D.z.toFloat() + updateSpeed() + }) + //Relative altitude of the aircraft relative to take off location, measured by the barometer, in meters. + mCompositeDisposable.add(widgetModel.altitudeProcessor.toFlowable().observeOn(SchedulerProvider.ui()).subscribe { altitude: Double -> + mAltitude = altitude + updateAltitude() + }) + //RTK起飞高度信息 + mCompositeDisposable.add(widgetModel.rtkTakeoffAltitudeInfoProcessor.toFlowable() + .observeOn(SchedulerProvider.ui()) + .filter { info: RTKTakeoffAltitudeInfo -> Math.abs(mHomePointAltitude - info.altitude.toFloat()) >= 0.001 } + .subscribe { rtkTakeoffAltitudeInfo: RTKTakeoffAltitudeInfo -> + mHomePointAltitude = rtkTakeoffAltitudeInfo.altitude + updateAltitude() + }) + mCompositeDisposable.add(widgetModel.aircraftLocationDataProcessor.toFlowable() + .observeOn(SchedulerProvider.ui()) + .subscribe { locationCoordinate2D: LocationCoordinate2D? -> + mDroneLocation = locationCoordinate2D + if (mDroneLocation != null) { + updateAltitude() + } + }) + } + + override fun getIdealDimensionRatioString(): String? { + return null + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/GimbalPitchBarModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/GimbalPitchBarModel.java new file mode 100644 index 00000000..3f1d48ec --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/GimbalPitchBarModel.java @@ -0,0 +1,101 @@ +package dji.v5.ux.core.widget.hsi; + +import androidx.annotation.NonNull; + +import java.util.ArrayList; +import java.util.List; + +import dji.sdk.keyvalue.key.GimbalKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.value.common.Attitude; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.sdk.keyvalue.value.gimbal.GimbalAttitudeRange; +import dji.v5.manager.KeyManager; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.DataProcessor; + +/** + * Description : + * + * @author: Byte.Cai + * date : 2022/11/1 + *

    + * Copyright (c) 2022, DJI All Rights Reserved. + */ +public class GimbalPitchBarModel extends WidgetModel implements ICameraIndex { + private ComponentIndexType cameraIndex = ComponentIndexType.LEFT_OR_MAIN; + private CameraLensType lensType = CameraLensType.CAMERA_LENS_ZOOM; + private final List> gimbalAttitudeInDegreesProcessorList = new ArrayList<>(); + private final DataProcessor gimbalAttitudeInDegrees0Processor = DataProcessor.create(new Attitude()); + private final DataProcessor gimbalAttitudeInDegrees1Processor = DataProcessor.create(new Attitude()); + private final DataProcessor gimbalAttitudeInDegrees2Processor = DataProcessor.create(new Attitude()); + + + private final List> gimbalAttitudeGimbalAttitudeRangeProcessorList = new ArrayList<>(); + private final DataProcessor gimbalAttitudeGimbalAttitudeRange0Processor = DataProcessor.create(new GimbalAttitudeRange()); + private final DataProcessor gimbalAttitudeGimbalAttitudeRange1Processor = DataProcessor.create(new GimbalAttitudeRange()); + private final DataProcessor gimbalAttitudeGimbalAttitudeRange2Processor = DataProcessor.create(new GimbalAttitudeRange()); + + protected GimbalPitchBarModel(@NonNull DJISDKModel djiSdkModel, @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + } + + + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createKey(GimbalKey.KeyGimbalAttitude, ComponentIndexType.LEFT_OR_MAIN), gimbalAttitudeInDegrees0Processor); + bindDataProcessor(KeyTools.createKey(GimbalKey.KeyGimbalAttitude, ComponentIndexType.RIGHT), gimbalAttitudeInDegrees1Processor); + bindDataProcessor(KeyTools.createKey(GimbalKey.KeyGimbalAttitude, ComponentIndexType.UP), gimbalAttitudeInDegrees2Processor); + gimbalAttitudeInDegreesProcessorList.add(gimbalAttitudeInDegrees0Processor); + gimbalAttitudeInDegreesProcessorList.add(gimbalAttitudeInDegrees1Processor); + gimbalAttitudeInDegreesProcessorList.add(gimbalAttitudeInDegrees2Processor); + + bindDataProcessor(KeyTools.createKey(GimbalKey.KeyGimbalAttitudeRange, ComponentIndexType.LEFT_OR_MAIN),gimbalAttitudeGimbalAttitudeRange0Processor); + bindDataProcessor(KeyTools.createKey(GimbalKey.KeyGimbalAttitudeRange, ComponentIndexType.RIGHT), gimbalAttitudeGimbalAttitudeRange1Processor); + bindDataProcessor(KeyTools.createKey(GimbalKey.KeyGimbalAttitudeRange, ComponentIndexType.UP), gimbalAttitudeGimbalAttitudeRange2Processor); + gimbalAttitudeGimbalAttitudeRangeProcessorList.add(gimbalAttitudeGimbalAttitudeRange0Processor); + gimbalAttitudeGimbalAttitudeRangeProcessorList.add(gimbalAttitudeGimbalAttitudeRange1Processor); + gimbalAttitudeGimbalAttitudeRangeProcessorList.add(gimbalAttitudeGimbalAttitudeRange2Processor); + } + + @Override + protected void inCleanup() { + KeyManager.getInstance().cancelListen(this); + gimbalAttitudeInDegreesProcessorList.clear(); + gimbalAttitudeGimbalAttitudeRangeProcessorList.clear(); + + } + + @NonNull + @Override + public ComponentIndexType getCameraIndex() { + return cameraIndex; + } + + @NonNull + @Override + public CameraLensType getLensType() { + return lensType; + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + this.cameraIndex = cameraIndex; + this.lensType = lensType; + restart(); + } + + public List> getGimbalAttitudeInDegreesProcessorList() { + return gimbalAttitudeInDegreesProcessorList; + } + + public List> getGimbalAttitudeGimbalAttitudeRangeProcessorList() { + return gimbalAttitudeGimbalAttitudeRangeProcessorList; + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/GimbalPitchBarWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/GimbalPitchBarWidget.java new file mode 100644 index 00000000..106cb5dc --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/GimbalPitchBarWidget.java @@ -0,0 +1,636 @@ +package dji.v5.ux.core.widget.hsi; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.Paint; +import android.graphics.RectF; +import android.graphics.Typeface; +import android.graphics.drawable.Drawable; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.util.Log; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import dji.sdk.keyvalue.value.common.CameraLensType; +import dji.sdk.keyvalue.value.common.ComponentIndexType; +import dji.sdk.keyvalue.value.common.DoubleMinMax; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.ICameraIndex; +import dji.v5.ux.core.base.widget.FrameLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.ui.hsi.dashboard.FpvStrokeConfig; +import dji.v5.ux.core.util.FontUtils; +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.disposables.CompositeDisposable; +import io.reactivex.rxjava3.schedulers.Schedulers; + +/** + * 云台Pitch角度展示Widget + *

    + * 注意:GimbalPitchBarWidget必须关联到相机,所以只能使用在主界面,比如DefaultLayoutActivity中 + */ +public class GimbalPitchBarWidget extends FrameLayoutWidget implements ICameraIndex { + protected int mMinValue = -120; + protected int mMaxValue = 120; + protected int mValue = 0; + protected boolean mInvalidDrawable = true; + private Paint mBarPaint; + private Paint mBarStrokePaint; + private Paint mHighlightPaint; + private Paint mInnerPaint; + private Paint mOnBarPaint; + private Paint mTextPaint; + private Paint mTextStrokePaint; + + /** + * 主标尺宽度 + */ + private float mBarWidth; + /** + * 原点宽度 + */ + private float mOriginWidth; + /** + * 原点长度 + */ + private float mOriginLength; + /** + * 刻度条 + */ + private int[] mHighlightValues; + /** + * 文字高亮颜色 + */ + private int mTextHighlightColor; + /** + * 内部的指示条 + */ + private float mInnerWidth; + private int mInnerValue; + private int mInnerMaxValue; + private int mOnBarMaxValue; + private int[] mOnBarColors; + /** + * 叠加的指示条 + */ + @Nullable + private int[] mOnBarIndicator; + + /** + * 整体的边距 + */ + private float mOriginPadding; + /** + * 当前值刻度指示图标 + */ + private Drawable mIndicatorDrawable; + /** + * 元素朝向 + */ + private boolean mAlignLeft; + + /** + * 数值是否在顶部 + */ + private boolean mTextOnTop; + + /** + * 云台指示图标放大倍数 + */ + private float mDrawableSizeFactor = 1.0f; + + /** + * 绘制时存储主标尺的位置不含描边 + */ + private final RectF mBarRect = new RectF(); + /** + * 绘制时候的临时对象,使用前需赋值 + */ + private final RectF mTmpRect = new RectF(); + + private String mText; + private float mTextSize; + private float mTextPadding; + + private FpvStrokeConfig mStrokeConfig; + private ComponentIndexType componentIndexType = ComponentIndexType.UNKNOWN; + private CompositeDisposable compositeDisposable = new CompositeDisposable(); + + private GimbalPitchBarModel widgetModel = new GimbalPitchBarModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + + public GimbalPitchBarWidget(Context context) { + this(context, null); + } + + public GimbalPitchBarWidget(Context context, @Nullable AttributeSet attrs) { + this(context, attrs, 0); + } + + public GimbalPitchBarWidget(Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs); + } + + private int getColor(int colorId) { + return getResources().getColor(colorId); + } + + private float getDimen(int dimenId) { + return getResources().getDimension(dimenId); + } + + /** + * @see #drawBackground(Canvas, RectF) + */ + protected void initParams(Context context, AttributeSet attrs) { + super.setWillNotDraw(false); + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.GimbalPitchBarV2); + // 方向 + mAlignLeft = typedArray.getBoolean(R.styleable.GimbalPitchBarV2_uxsdk_gpb_align_left, false); + // 主标尺 + mMaxValue = typedArray.getInt(R.styleable.GimbalPitchBarV2_uxsdk_gpb_bar_max_value, 0); + mMinValue = typedArray.getInt(R.styleable.GimbalPitchBarV2_uxsdk_gpb_bar_min_value, 0); + mValue = typedArray.getInt(R.styleable.GimbalPitchBarV2_uxsdk_gpb_bar_value, 0); + mText = typedArray.getString(R.styleable.GimbalPitchBarV2_uxsdk_gpb_bar_text); + mTextSize = typedArray.getDimension(R.styleable.GimbalPitchBarV2_uxsdk_gpb_bar_text_size, getDimen(R.dimen.uxsdk_7_dp)); + mTextPadding = typedArray.getDimension(R.styleable.GimbalPitchBarV2_uxsdk_gpb_bar_text_padding, getDimen(R.dimen.uxsdk_2_dp)); + mTextOnTop = typedArray.getBoolean(R.styleable.GimbalPitchBarV2_uxsdk_gpb_bar_text_on_top, false); + mBarWidth = typedArray.getDimension(R.styleable.GimbalPitchBarV2_uxsdk_gpb_bar_width, getDimen(R.dimen.uxsdk_3_dp)); + // 主标尺颜色 + int barColor = typedArray.getColor(R.styleable.GimbalPitchBarV2_uxsdk_gpb_bar_color, getColor(R.color.uxsdk_white_10_percent)); + // 主标尺描边宽度 + float barStrokeWidth = typedArray.getDimension(R.styleable.GimbalPitchBarV2_uxsdk_gpb_bar_stroke_width, getDimen(R.dimen.uxsdk_0_5_dp)); + // 主标尺描边颜色 + int barStrokeColor = typedArray.getColor(R.styleable.GimbalPitchBarV2_uxsdk_gpb_bar_stroke_color, getColor(R.color.uxsdk_black_30_percent)); + // 原点 + mOriginPadding = typedArray.getDimension(R.styleable.GimbalPitchBarV2_uxsdk_gpb_bar_origin_padding, getDimen(R.dimen.uxsdk_2_dp)); + mOriginWidth = typedArray.getDimension(R.styleable.GimbalPitchBarV2_uxsdk_gpb_origin_width, getDimen(R.dimen.uxsdk_1_dp)); + mOriginLength = typedArray.getDimension(R.styleable.GimbalPitchBarV2_uxsdk_gpb_origin_length, getDimen(R.dimen.uxsdk_6_dp)); + int highlightValuesId = typedArray.getResourceId(R.styleable.GimbalPitchBarV2_uxsdk_gpb_highlight_values, 0); + if (highlightValuesId != 0) { + mHighlightValues = getResources().getIntArray(highlightValuesId); + } + /* 高亮刻度 */ + // 刻度条宽度 + float highlightWidth = typedArray.getDimension(R.styleable.GimbalPitchBarV2_uxsdk_gpb_highlight_width, getDimen(R.dimen.uxsdk_0_5_dp)); + // 刻度条颜色 + int highlightColor = typedArray.getColor(R.styleable.GimbalPitchBarV2_uxsdk_gpb_highlight_color, getColor(R.color.uxsdk_white)); + mIndicatorDrawable = typedArray.getDrawable(R.styleable.GimbalPitchBarV2_uxsdk_gpb_indicator_drawable); + mDrawableSizeFactor = typedArray.getFloat(R.styleable.GimbalPitchBarV2_uxsdk_gpb_indicator_drawable_factor, 1.0f); + // 内部指示条 + mInnerWidth = typedArray.getDimension(R.styleable.GimbalPitchBarV2_uxsdk_gpb_inner_width, getDimen(R.dimen.uxsdk_3_dp)); + mInnerValue = typedArray.getInt(R.styleable.GimbalPitchBarV2_uxsdk_gpb_inner_value, 0); + mInnerMaxValue = typedArray.getInt(R.styleable.GimbalPitchBarV2_uxsdk_gpb_inner_max_value, 0); + // 色块指示条 + mOnBarMaxValue = typedArray.getInt(R.styleable.GimbalPitchBarV2_uxsdk_gpb_on_bar_max_value, 0); + int onBarValues = typedArray.getResourceId(R.styleable.GimbalPitchBarV2_uxsdk_gpb_on_bar_values, 0); + if (onBarValues != 0) { + mOnBarIndicator = getResources().getIntArray(onBarValues); + } + int onBarColors = typedArray.getResourceId(R.styleable.GimbalPitchBarV2_uxsdk_gpb_on_bar_colors, 0); + if (onBarColors != 0) { + mOnBarColors = getResources().getIntArray(onBarColors); + } + typedArray.recycle(); + + mTextHighlightColor = getResources().getColor(R.color.uxsdk_yellow_in_light); + + mStrokeConfig = new FpvStrokeConfig(context); + + Typeface typeface = Typeface.create("sans-serif-condensed", Typeface.BOLD); + + // 背景画笔 + Paint barPaint = new Paint(Paint.DITHER_FLAG | Paint.ANTI_ALIAS_FLAG); + barPaint.setStyle(Paint.Style.FILL); + barPaint.setColor(barColor); + mBarPaint = barPaint; + + Paint barStrokePaint = new Paint(Paint.DITHER_FLAG | Paint.ANTI_ALIAS_FLAG); + barStrokePaint.setColor(barStrokeColor); + barStrokePaint.setStyle(Paint.Style.STROKE); + barStrokePaint.setStrokeWidth(barStrokeWidth); + mBarStrokePaint = barStrokePaint; + + Paint highlightPaint = new Paint(Paint.DITHER_FLAG | Paint.ANTI_ALIAS_FLAG); + highlightPaint.setColor(highlightColor); + highlightPaint.setStyle(Paint.Style.FILL); + highlightPaint.setStrokeWidth(highlightWidth); + mHighlightPaint = highlightPaint; + + Paint textPaint = new Paint(Paint.DITHER_FLAG | Paint.ANTI_ALIAS_FLAG); + textPaint.setColor(Color.WHITE); + textPaint.setStyle(Paint.Style.FILL); + textPaint.setStrokeWidth(10); + textPaint.setTextSize(mTextSize); + textPaint.setTypeface(typeface); + mTextPaint = textPaint; + + Paint paint = new Paint(Paint.DITHER_FLAG | Paint.ANTI_ALIAS_FLAG); + paint.setColor(mStrokeConfig.getStrokeDeepColor()); + paint.setStyle(Paint.Style.STROKE); + paint.setStrokeWidth(mStrokeConfig.getStrokeBoldWidth()); + paint.setTextSize(mTextSize); + paint.setTypeface(typeface); + mTextStrokePaint = paint; + + Paint onBarPaint = new Paint(Paint.DITHER_FLAG | Paint.ANTI_ALIAS_FLAG); + onBarPaint.setStyle(Paint.Style.FILL); + mOnBarPaint = onBarPaint; + + Paint innerPaint = new Paint(Paint.DITHER_FLAG | Paint.ANTI_ALIAS_FLAG); + innerPaint.setStyle(Paint.Style.FILL); + innerPaint.setColor(Color.WHITE); + mInnerPaint = innerPaint; + + } + + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + RectF bar = mBarRect; + if (mAlignLeft) { + bar.right = mOriginPadding + mOriginLength + mBarWidth; + } else { + bar.right = getWidth() - (mOriginPadding + mOriginLength) + mBarWidth; + } + bar.left = bar.right - mBarWidth; + bar.top = getPaddingTop(); + bar.bottom = (float) getHeight() - getPaddingBottom(); + + drawBackground(canvas, bar); + if (mMaxValue != mMinValue) { + drawHighlightValues(canvas, bar); + } + drawOnBarIndicator(canvas, bar); + drawInnerIndicator(canvas, bar); + + if (mOriginLength > 0) { + drawOriginValue(canvas, bar); + } + if (mMaxValue != mMinValue) { + drawIndicator(canvas, bar); + } + drawCurrentValue(canvas, bar); + + } + + private void drawCurrentValue(Canvas canvas, RectF bar) { + if (TextUtils.isEmpty(mText)) { + return; + } + float len = mTextPaint.measureText(mText); + float baseline; + float left; + if (mTextOnTop) { + baseline = FontUtils.getDigitalBaselineFromBottom(mTextPaint, bar.top - mTextPadding) - mTextPaint.getFontMetrics().bottom; + } else { + baseline = FontUtils.getDigitalBaselineFromTop(mTextPaint, bar.top); + } + if (mTextOnTop) { + left = (bar.left + bar.right - len) / 2; + if (!mAlignLeft) { + left = Math.min(left, getWidth() - len); + } + } else { + left = mAlignLeft ? bar.right + mTextPadding : bar.left - mTextPadding - len; + } + canvas.drawText(mText, left, baseline, mTextStrokePaint); + canvas.drawText(mText, left, baseline, mTextPaint); + } + + private void drawInnerIndicator(Canvas canvas, RectF rect) { + if (mInnerMaxValue == 0) { + return; + } + int lastValue = mInnerValue; + float centerY = rect.centerY(); + float lastY = centerY - innerValue2Height(rect.height(), lastValue); + float left; + if (mAlignLeft) { + left = rect.right; + } else { + left = rect.left - mInnerWidth; + } + float right = left + mInnerWidth; + canvas.drawRect(left, centerY, right, lastY, mInnerPaint); + } + + private void drawOnBarIndicator(Canvas canvas, RectF rect) { + if (mOnBarMaxValue == 0) { + return; + } + int[] onBarIndicator = mOnBarIndicator; + if (onBarIndicator == null || onBarIndicator.length < 2) { + return; + } + if (mOnBarColors == null || mOnBarColors.length == 0) { + return; + } + float centerY = rect.centerY(); + float lastY = centerY - onBarValue2Height(rect.height(), onBarIndicator[0]); + float currentY; + for (int i = 1; i < onBarIndicator.length; i++) { + currentY = centerY - onBarValue2Height(rect.height(), onBarIndicator[i]); + mOnBarPaint.setColor(mOnBarColors[(i - 1) % mOnBarColors.length]); + canvas.drawRect(rect.left, lastY, rect.right, currentY, mOnBarPaint); + lastY = currentY; + } + } + + private void drawOriginValue(Canvas canvas, RectF rect) { + float barHeight = rect.height(); + float halfStrokeWidth = mBarStrokePaint.getStrokeWidth() / 2; + float y; + if (getMaxValue() == getMinValue()) { + y = rect.centerY(); + } else { + y = indicatorValue2Height(barHeight, 0) + rect.top; + } + float left; + float right; + if (mAlignLeft) { + right = rect.right - halfStrokeWidth; + left = right - Math.max(mOriginLength, rect.width()); + } else { + left = rect.left + halfStrokeWidth; + right = left + Math.max(rect.width(), mOriginLength); + } + float halfWidth = mOriginWidth / 2; + canvas.drawRect(left, y - halfWidth, right, y + halfWidth, mHighlightPaint); + canvas.drawRect(left - halfStrokeWidth, y - halfWidth - halfStrokeWidth, right + halfStrokeWidth, y + halfWidth + halfStrokeWidth, + mBarStrokePaint); + } + + private void drawIndicator(Canvas canvas, RectF rect) { + Drawable drawable = mIndicatorDrawable; + if (drawable == null) { + return; + } + float barHeight = rect.height(); + float y = indicatorValue2Height(barHeight, getValue()) + rect.top; + + float width = drawable.getMinimumWidth() * mDrawableSizeFactor; + float height = drawable.getMinimumHeight() * mDrawableSizeFactor; + int right; + if (mAlignLeft) { + right = (int) (rect.left + width); + } else { + right = (int) rect.right; + } + int left = (int) (right - width); + int top = (int) (y - height / 2f); + int bottom = (int) (top + height); + drawable.setBounds(left, top, right, bottom); + drawable.draw(canvas); + } + + private void drawHighlightValues(Canvas canvas, RectF rect) { + if (mHighlightValues == null) { + return; + } + float barHeight = rect.height(); + float halfStrokeWidth = mBarStrokePaint.getStrokeWidth() / 2; + float halfHighLightWidth = mHighlightPaint.getStrokeWidth() / 2; + for (int highlightValue : mHighlightValues) { + float highlightY = indicatorValue2Height(barHeight, highlightValue) + rect.top; + if (highlightValue != 0 || mOriginLength == 0) { + canvas.drawRect(rect.left + halfStrokeWidth, highlightY - halfStrokeWidth - halfHighLightWidth, rect.right - halfStrokeWidth, + highlightY + halfStrokeWidth + halfHighLightWidth, mBarStrokePaint); + canvas.drawLine(rect.left + halfStrokeWidth, highlightY, rect.right - halfStrokeWidth, highlightY, mHighlightPaint); + } + } + } + + private float indicatorValue2Height(float barHeight, int value) { + return barHeight * (getMaxValue() - value) / (getMaxValue() - getMinValue()); + } + + private float onBarValue2Height(float barHeight, int value) { + return value * barHeight / 2f / mOnBarMaxValue; + } + + private float innerValue2Height(float barHeight, int value) { + return value * barHeight / 2f / mInnerMaxValue; + } + + private void drawBackground(Canvas canvas, RectF bar) { + mTmpRect.set(bar); + float halfStrokeWidth = mBarStrokePaint.getStrokeWidth() / 2f; + mTmpRect.inset(-halfStrokeWidth, -halfStrokeWidth); + canvas.drawRect(mTmpRect, mBarStrokePaint); + canvas.drawRect(bar, mBarPaint); + } + + @Override + protected void onSizeChanged(int w, int h, int oldw, int oldh) { + super.onSizeChanged(w, h, oldw, oldh); + mInvalidDrawable = true; + } + + protected void onValueChanged(int value) { + mTextPaint.setColor(isTextHighLight(value) ? mTextHighlightColor : Color.WHITE); + mText = value + "°"; + } + + /** + * 云台度数是否需要高亮 + */ + private boolean isTextHighLight(int value) { + return value == 0 || value == -45 || value == -90; + } + + public int getOnBarMaxValue() { + return mOnBarMaxValue; + } + + public int[] getOnBarIndicator() { + return mOnBarIndicator; + } + + public void setOnBarIndicator(int[] onBarIndicator) { + mOnBarIndicator = onBarIndicator; + } + + public int[] getHighlightValues() { + return mHighlightValues; + } + + public void setHighlightValues(int[] highlightValues) { + mHighlightValues = highlightValues; + } + + + protected void init(Context context, AttributeSet attrs) { + initParams(context, attrs); + } + + public int getMinValue() { + return mMinValue; + } + + public void setMinValue(int minValue) { + mMinValue = minValue; + mInvalidDrawable = true; + postInvalidate(); + } + + public int getMaxValue() { + return mMaxValue; + } + + public void setMaxValue(int maxValue) { + mMaxValue = maxValue; + mInvalidDrawable = true; + postInvalidate(); + } + + public int getValue() { + return mValue; + } + + public void setValue(int value) { + if (mValue != value) { + mValue = value; + if (mValue > mMaxValue) { + mValue = mMaxValue; + } + if (value < mMinValue) { + mValue = mMinValue; + } + } + onValueChanged(value); + postInvalidate(); + } + + public void setGimbalDrawable(ComponentIndexType cameraIndex) { + int resId; + if (cameraIndex == ComponentIndexType.LEFT_OR_MAIN) { + resId = R.drawable.uxsdk_fpv_hsi_pitch_guide_gimbal_3; + } else if (cameraIndex == ComponentIndexType.RIGHT) { + resId = R.drawable.uxsdk_fpv_hsi_pitch_guide_gimbal_1; + } else if (cameraIndex == ComponentIndexType.UP) { + resId = R.drawable.uxsdk_fpv_hsi_pitch_guide_gimbal_2; + } else { + resId = 0; + } + mIndicatorDrawable = resId == 0 ? null : getResources().getDrawable(resId); + } + + @NonNull + @Override + public ComponentIndexType getCameraIndex() { + return widgetModel.getCameraIndex(); + } + + @NonNull + @Override + public CameraLensType getLensType() { + return widgetModel.getLensType(); + } + + @Override + public void updateCameraSource(@NonNull ComponentIndexType cameraIndex, @NonNull CameraLensType lensType) { + widgetModel.updateCameraSource(cameraIndex, lensType); + + Log.e("testMM", "updateCameraSource" + componentIndexType + "---" + cameraIndex); + if (componentIndexType != cameraIndex) { + componentIndexType = cameraIndex; + onStop(); + onStart(cameraIndex); + + } + } + + + private void startListener() { + if (getCameraIndex().value() >= 3 || widgetModel.getGimbalAttitudeInDegreesProcessorList().size() <= 0) { + return; + } + + compositeDisposable.add(widgetModel.getGimbalAttitudeInDegreesProcessorList().get(getCameraIndex().value()).toFlowable() + .observeOn(AndroidSchedulers.mainThread()) + .map(attitude -> (int) Math.round(attitude.getPitch())) + .subscribeOn(Schedulers.io()) + .subscribe(this::setValue)); + + compositeDisposable.add(widgetModel.getGimbalAttitudeGimbalAttitudeRangeProcessorList().get(getCameraIndex().value()).toFlowable().subscribe(gimbalAttitudeRange -> { + DoubleMinMax pitch = gimbalAttitudeRange.getPitch(); + if (pitch == null){ + return; + } + int pitchMax = (int) Math.round(pitch.getMax()); + int pitchMin = (int) Math.round(pitch.getMin()); + int absMax = Math.abs(pitchMax); + int absMin = Math.abs(pitchMin); + int max = Math.max(absMax, absMin); + int min = -max; + setMaxValue(max); + setMinValue(min); + if (absMax < absMin) { + setHighlightValues(new int[]{30, -45, -90}); + } else { + setHighlightValues(new int[]{-30, 45, 90}); + } + })); + } + + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + startListener(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + onStop(); + } + + private void onStart(ComponentIndexType cameraIndex) { + if (compositeDisposable != null) { + compositeDisposable.clear(); + } else { + compositeDisposable = new CompositeDisposable(); + } + setGimbalDrawable(cameraIndex); + startListener(); + } + + private void onStop() { + if (compositeDisposable != null && !compositeDisposable.isDisposed()) { + compositeDisposable.dispose(); + compositeDisposable = null; + } + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + //do nothing + } + + @Override + protected void reactToModelChanges() { + //do nothing + } + + @Nullable + @Override + public String getIdealDimensionRatioString() { + return null; + } + + + // endregion +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/HorizontalSituationIndicatorWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/HorizontalSituationIndicatorWidget.kt new file mode 100644 index 00000000..24fb7c03 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/HorizontalSituationIndicatorWidget.kt @@ -0,0 +1,63 @@ +package dji.v5.ux.core.widget.hsi + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import android.view.View +import dji.sdk.keyvalue.value.common.CameraLensType +import dji.sdk.keyvalue.value.common.ComponentIndexType +import dji.v5.ux.R +import dji.v5.ux.core.base.ICameraIndex +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.databinding.UxsdkFpvViewHorizontalSituationIndicatorBinding + +/** + * Class Description + * + * @author Hoker + * @date 2021/11/25 + * + * Copyright (c) 2021, DJI All Rights Reserved. + */ +open class HorizontalSituationIndicatorWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, +) : ConstraintLayoutWidget(context, attrs, defStyleAttr), + ICameraIndex { + + private lateinit var binding: UxsdkFpvViewHorizontalSituationIndicatorBinding + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + binding = UxsdkFpvViewHorizontalSituationIndicatorBinding.inflate(LayoutInflater.from(context), this, true) + } + + override fun reactToModelChanges() { +// do nothing + } + + override fun getIdealDimensionRatioString(): String? { + return null + } + + fun setSimpleModeEnable(isEnable: Boolean) { + binding.pfdHsiSpeedDisplay.visibility = if (isEnable) VISIBLE else GONE + binding.pfdHsiAttitudeDisplay.visibility = if (isEnable) VISIBLE else GONE + binding.pfdHsiGimbalPitchDisplay.visibility = if (isEnable) VISIBLE else GONE + } + + sealed class ModelState + + override fun getCameraIndex(): ComponentIndexType { + return binding.pfdHsiGimbalPitchDisplay.getCameraIndex() + } + + override fun getLensType(): CameraLensType { + return binding.pfdHsiGimbalPitchDisplay.getLensType() + + } + + override fun updateCameraSource(cameraIndex: ComponentIndexType, lensType: CameraLensType) { + binding.pfdHsiGimbalPitchDisplay.updateCameraSource(cameraIndex, lensType) + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/PrimaryFlightDisplayModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/PrimaryFlightDisplayModel.kt new file mode 100644 index 00000000..d608131b --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/PrimaryFlightDisplayModel.kt @@ -0,0 +1,41 @@ +package dji.v5.ux.core.widget.hsi + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.value.common.Attitude +import dji.sdk.keyvalue.value.common.Velocity3D +import dji.sdk.keyvalue.key.KeyTools +import dji.v5.utils.common.LogUtils +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor + +/** + * Class Description + * + * @author Hoker + * @date 2021/12/2 + * + * Copyright (c) 2021, DJI All Rights Reserved. + */ +open class PrimaryFlightDisplayModel constructor( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + private val tag = LogUtils.getTag("PrimaryFlightDisplayModel") + val velocityProcessor = DataProcessor.create(Velocity3D()) + val aircraftAttitudeProcessor: DataProcessor = DataProcessor.create(Attitude()) + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAircraftVelocity), velocityProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAircraftAttitude), aircraftAttitudeProcessor) + } + + override fun inCleanup() { +// LogUtils.d(tag,"TODO Method not implemented yet") + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/PrimaryFlightDisplayWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/PrimaryFlightDisplayWidget.kt new file mode 100644 index 00000000..101cf794 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/PrimaryFlightDisplayWidget.kt @@ -0,0 +1,76 @@ +package dji.v5.ux.core.widget.hsi + +import android.content.Context +import android.util.AttributeSet +import android.view.LayoutInflater +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.databinding.UxsdkPrimaryFlightDisplayWidgetBinding +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers + +/** + * Class Description + * + * @author Hoker + * @date 2021/11/25 + * + * Copyright (c) 2021, DJI All Rights Reserved. + */ +open class PrimaryFlightDisplayWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ConstraintLayoutWidget(context, attrs, defStyleAttr) { + + private lateinit var binding: UxsdkPrimaryFlightDisplayWidgetBinding + + private val widgetModel by lazy { + PrimaryFlightDisplayModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()) + } + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + binding = UxsdkPrimaryFlightDisplayWidgetBinding.inflate(LayoutInflater.from(context),this,true) + } + + override fun reactToModelChanges() { + addDisposable(widgetModel.velocityProcessor.toFlowable().observeOn(AndroidSchedulers.mainThread()).subscribe { + binding.fpvAttitude.setSpeedX(it.x.toFloat()) + binding.fpvAttitude.setSpeedY(it.y.toFloat()) + binding.fpvAttitude.setSpeedZ(it.z.toFloat()) + + }) + addDisposable(widgetModel.aircraftAttitudeProcessor.toFlowable().observeOn(AndroidSchedulers.mainThread()).subscribe { + binding.fpvAttitude.setPitch(it.pitch.toFloat()) + binding.fpvAttitude.setRoll(it.roll.toFloat()) + binding.fpvAttitude.setYaw(it.yaw.toFloat()) + + }) + setVideoViewSize(1440, 1080) + } + + //可以通过fpvWidget获取真实的video长宽比 + private fun setVideoViewSize(videoViewWidth: Int, videoViewHeight: Int) { + binding.fpvAttitude.setVideoViewSize(videoViewWidth, videoViewHeight) + } + + override fun getIdealDimensionRatioString(): String? { + return null + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + sealed class ModelState +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/SpeedDisplayFpvWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/SpeedDisplayFpvWidget.kt new file mode 100644 index 00000000..a8878da8 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/SpeedDisplayFpvWidget.kt @@ -0,0 +1,26 @@ +package dji.v5.ux.core.widget.hsi + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import dji.v5.ux.R + +/** + * Class Description + * + * @author Hoker + * @date 2021/12/2 + * + * Copyright (c) 2021, DJI All Rights Reserved. + */ +class SpeedDisplayFpvWidget @JvmOverloads constructor( + ctx: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, +) : SpeedDisplayWidget(ctx, attrs, defStyleAttr) { + + override fun loadLayout(context: Context) { + View.inflate(context, R.layout.uxsdk_fpv_pfd_speed_display_widget, this) + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/SpeedDisplayModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/SpeedDisplayModel.kt new file mode 100644 index 00000000..95dabbf8 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/SpeedDisplayModel.kt @@ -0,0 +1,57 @@ +package dji.v5.ux.core.widget.hsi + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.value.common.Attitude +import dji.sdk.keyvalue.value.common.Velocity3D +import dji.sdk.keyvalue.value.flightcontroller.WindDirection +import dji.sdk.keyvalue.value.flightcontroller.WindWarning +import dji.sdk.keyvalue.key.KeyTools +import dji.v5.manager.KeyManager +import dji.v5.utils.common.LogUtils +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor + +/** + * Class Description + * + * @author Hoker + * @date 2021/11/25 + * + * Copyright (c) 2021, DJI All Rights Reserved. + */ +open class SpeedDisplayModel constructor( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + private val tag = LogUtils.getTag("SpeedDisplayModel") + val velocityProcessor = DataProcessor.create(Velocity3D()) + val aircraftAttitudeProcessor: DataProcessor = DataProcessor.create(Attitude()) + val windSpeedProcessor = DataProcessor.create(0) + val windDirectionProcessor = DataProcessor.create(WindDirection.WINDLESS) + val windWarningProcessor = DataProcessor.create(WindWarning.UNKNOWN) + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAircraftVelocity), velocityProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAircraftAttitude), aircraftAttitudeProcessor) + + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyWindSpeed), windSpeedProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyWindDirection), windDirectionProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyWindWarning), windWarningProcessor) + } + + override fun inCleanup() { + KeyManager.getInstance().cancelListen(this) + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/SpeedDisplayWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/SpeedDisplayWidget.kt new file mode 100644 index 00000000..433dadf2 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/hsi/SpeedDisplayWidget.kt @@ -0,0 +1,191 @@ +package dji.v5.ux.core.widget.hsi + +import android.content.Context + +import dji.v5.ux.core.ui.hsi.FlashTimer.removeListener + +import dji.v5.ux.core.ui.hsi.FlashTimer.addListener +import kotlin.jvm.JvmOverloads +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import android.view.ViewDebug.ExportedProperty +import android.widget.TextView +import dji.v5.ux.core.ui.hsi.dashboard.SpeedDashBoard +import io.reactivex.rxjava3.disposables.CompositeDisposable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.R +import dji.v5.ux.core.ui.hsi.FlashTimer +import io.reactivex.rxjava3.core.Flowable +import dji.v5.common.utils.UnitUtils +import android.graphics.Color +import android.util.AttributeSet +import dji.sdk.keyvalue.value.common.Attitude +import dji.sdk.keyvalue.value.flightcontroller.WindDirection +import dji.sdk.keyvalue.value.flightcontroller.WindWarning +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers +import java.util.* + +open class SpeedDisplayWidget @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0) : + ConstraintLayoutWidget(context, attrs, defStyleAttr) { + @ExportedProperty(category = "dji", formatToHexString = true) + private val mWindTextColor: Int + private var mTvWsValue: TextView? = null + private var mIsAnimating = false + var mSpeedDashBoard: SpeedDashBoard? = null + private val mCompositeDisposable = CompositeDisposable() + private var mListener: FlashTimer.Listener? = null + private val widgetModel = SpeedDisplayModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()) + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + loadLayout(context) + mSpeedDashBoard = findViewById(R.id.pfd_speed_dash_board) + mTvWsValue = findViewById(R.id.pfd_ws_value) + } + + protected open fun loadLayout(context: Context) { + inflate(context, R.layout.uxsdk_liveview_pfd_speed_display_widget, this) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + mSpeedDashBoard?.setModel(widgetModel) + widgetModel.setup() + } + mListener = FlashTimer.Listener { show: Boolean -> + val visible: Int = if (mIsAnimating && !show) { + INVISIBLE + } else { + VISIBLE + } + if (mTvWsValue?.visibility != visible) { + postTvWsVisibility(visible) + } + } + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + mCompositeDisposable.dispose() + // 当 View 在闪烁时,需要移除掉回调 + removeListener(mListener) + if (!isInEditMode) { + widgetModel.cleanup() + } + } + + override fun reactToModelChanges() { + mCompositeDisposable.add( + Flowable.combineLatest( + widgetModel.windSpeedProcessor.toFlowable(), + widgetModel.windDirectionProcessor.toFlowable(), + widgetModel.windWarningProcessor.toFlowable(), + widgetModel.aircraftAttitudeProcessor.toFlowable(), + { windSpeed: Int, fcWindDirectionStatus: WindDirection, fcWindWarning: WindWarning, attitude: Attitude -> + val yaw = attitude.yaw.toFloat() + val aircraftDegree: Float = yaw + if (yaw < 0) 359f else 0f + AndroidSchedulers.mainThread().scheduleDirect { + updateWindStatus(windSpeed.toFloat() / 10, fcWindDirectionStatus, fcWindWarning, aircraftDegree) + } + true + } + ).subscribe() + ) + } + + override fun getIdealDimensionRatioString(): String? { + return null + } + + private fun postTvWsVisibility(visible: Int) { + mTvWsValue?.post { mTvWsValue?.visibility = visible } + } + + private fun updateWindStatus(windSpeed: Float, fcWindDirectionStatus: WindDirection, fcWindWarning: WindWarning, aircraftDegree: Float) { + val value = UnitUtils.transFormSpeedIntoDifferentUnit(windSpeed) + val textStr = String.format(Locale.ENGLISH, "WS %04.1f %s", value, getWindDirectionText(fcWindDirectionStatus, aircraftDegree)) + if (textStr != mTvWsValue?.text.toString()) { + mTvWsValue!!.text = textStr + } + if (fcWindWarning == WindWarning.LEVEL_2) { + mTvWsValue!!.setTextColor(resources.getColor(R.color.uxsdk_pfd_barrier_color)) + } else if (fcWindWarning == WindWarning.LEVEL_1) { + mTvWsValue?.setTextColor(resources.getColor(R.color.uxsdk_pfd_avoidance_color)) + } else { + mTvWsValue?.setTextColor(mWindTextColor) + } + val shouldBlink = fcWindWarning == WindWarning.LEVEL_2 + // 红色需要持续闪烁 + if (shouldBlink && !mIsAnimating) { + mIsAnimating = true + addListener(mListener) + } else if (!shouldBlink && mIsAnimating) { + mIsAnimating = false + removeListener(mListener) + // 使用 post,避免消息队列还存在隐藏的消息 + postTvWsVisibility(VISIBLE) + } + } + + private fun getWindDirectionText(fcWindDirectionStatus: WindDirection, aircraftDegree: Float): String { + if (fcWindDirectionStatus == WindDirection.WINDLESS) { + return " " + } + var toAircraft: WindDirection? = null + var delta = getWindDegree(fcWindDirectionStatus) - aircraftDegree + delta += if (delta >= 0) 0f else 360.toFloat() + var start = 22.5f + val offset = 45f + for (i in 2..8) { + if (delta >= start && delta < start + offset) { + toAircraft = WindDirection.find(i) + break + } + start += offset + } + if (toAircraft == null) { + toAircraft = WindDirection.NORTH + } + return getWindDirectionText(toAircraft) + } + + private fun getWindDirectionText(windDirection: WindDirection): String { + return when (windDirection) { + WindDirection.EAST -> "←" + WindDirection.WEST -> "→" + WindDirection.NORTH -> "↓" + WindDirection.SOUTH -> "↑" + WindDirection.NORTH_EAST -> "↙" + WindDirection.NORTH_WEST -> "↘" + WindDirection.SOUTH_EAST -> "↖" + WindDirection.SOUTH_WEST -> "↗" + WindDirection.WINDLESS -> " " + else -> " " + } + } + + private fun getWindDegree(fcWindDirectionStatus: WindDirection?): Int { + return if (fcWindDirectionStatus == null) { + 0 + } else when (fcWindDirectionStatus) { + WindDirection.EAST -> 90 + WindDirection.WEST -> 270 + WindDirection.SOUTH -> 180 + WindDirection.NORTH_EAST -> 45 + WindDirection.NORTH_WEST -> 315 + WindDirection.SOUTH_EAST -> 135 + WindDirection.SOUTH_WEST -> 225 + WindDirection.NORTH -> 0 + else -> 0 + } + } + + companion object { + private val TAG = SpeedDisplayWidget::class.java.simpleName + } + + init { + val typedArray = context.obtainStyledAttributes(attrs, R.styleable.SpeedDisplayWidget) + mWindTextColor = typedArray.getColor(R.styleable.SpeedDisplayWidget_android_textColor, Color.WHITE) + typedArray.recycle() + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/location/LocationWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/location/LocationWidget.kt new file mode 100644 index 00000000..e89619f4 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/location/LocationWidget.kt @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.location + +import android.content.Context +import android.util.AttributeSet +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.widget.BaseTelemetryWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.widget.location.LocationWidget.ModelState +import dji.v5.ux.core.widget.location.LocationWidget.ModelState.LocationStateUpdated +import dji.v5.ux.core.widget.location.LocationWidgetModel.LocationState +import java.text.DecimalFormat + +/** + * Widget shows location coordinates of the aircraft + */ +open class LocationWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + widgetTheme: Int = 0 +) : BaseTelemetryWidget( + context, + attrs, + defStyleAttr, + WidgetType.TEXT_IMAGE_LEFT, + widgetTheme, + R.style.UXSDKLocationWidget +) { + + //region Fields + override val metricDecimalFormat: DecimalFormat = DecimalFormat("+#00.000000;-#00.000000") + + override val imperialDecimalFormat: DecimalFormat = metricDecimalFormat + + private val widgetModel: LocationWidgetModel by lazy { + LocationWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()) + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ModelState.ProductConnected(it)) }) + addReaction(widgetModel.locationState + .observeOn(SchedulerProvider.ui()) + .subscribe { updateUI(it) }) + } + + //endregion + + //region Reactions to model + private fun updateUI(locationState: LocationState) { + widgetStateDataProcessor.onNext(LocationStateUpdated(locationState)) + valueString = if (locationState is LocationState.CurrentLocation) { + getString(R.string.uxsdk_location_coordinates, metricDecimalFormat.format(locationState.latitude).toString(), metricDecimalFormat.format(locationState.longitude).toString()) + } else { + getString(R.string.uxsdk_location_default) + } + } + //endregion + + //region Customization + override fun getIdealDimensionRatioString(): String? = null + + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP) + //endregion + + //region Hooks + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines widget state updates + */ + + sealed class ModelState { + + /** + * Product connection update + */ + data class ProductConnected(val boolean: Boolean) : ModelState() + + /** + * Location model state + */ + data class LocationStateUpdated(val locationState: LocationState) : ModelState() + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/location/LocationWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/location/LocationWidgetModel.kt new file mode 100644 index 00000000..c857e781 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/location/LocationWidgetModel.kt @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.location + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.value.common.LocationCoordinate2D +import dji.sdk.keyvalue.key.KeyTools +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import dji.v5.utils.common.LocationUtil +import dji.v5.ux.core.widget.location.LocationWidgetModel.LocationState.ProductDisconnected + +/** + * Widget Model for the [LocationWidget] used to define + * the underlying logic and communication + */ +class LocationWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + + val aircraftLocationProcessor = DataProcessor.create(LocationCoordinate2D(Double.NaN, Double.NaN)) + private val locationStateProcessor: DataProcessor = DataProcessor.create(ProductDisconnected) + + /** + * Value of the location state of aircraft + */ + val locationState: Flowable + get() = locationStateProcessor.toFlowable() + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAircraftLocation), aircraftLocationProcessor) + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + if (LocationUtil.checkLatitude(aircraftLocationProcessor.value.latitude) + && LocationUtil.checkLongitude(aircraftLocationProcessor.value.longitude)) { + locationStateProcessor.onNext( + LocationState.CurrentLocation( + aircraftLocationProcessor.value.latitude, + aircraftLocationProcessor.value.longitude + ) + ) + } else { + locationStateProcessor.onNext(LocationState.LocationUnavailable) + } + } else { + locationStateProcessor.onNext(ProductDisconnected) + } + } + + + override fun inCleanup() { + // No code required + } + + /** + * Class to represent states of location widget + */ + sealed class LocationState { + /** + * Product is disconnected + */ + object ProductDisconnected : LocationState() + + /** + * Product is connected but GPS location fix is unavailable + */ + object LocationUnavailable : LocationState() + + /** + * Reflecting the current location + */ + data class CurrentLocation(val latitude: Double, val longitude: Double) : LocationState() + + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/perception/PerceptionStateWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/perception/PerceptionStateWidgetModel.kt new file mode 100644 index 00000000..7da5020b --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/perception/PerceptionStateWidgetModel.kt @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.perception + +import dji.v5.manager.aircraft.perception.data.PerceptionInfo +import dji.v5.manager.aircraft.perception.listener.PerceptionInformationListener +import dji.v5.manager.interfaces.IPerceptionManager +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Flowable + +/** + * Widget Model for the [PerceptionStateWidget] used to define + * the underlying logic and communication + * + * @author: William.Wong + * date : 2022/9/21 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ +class PerceptionStateWidgetModel( + djiSdkModel: DJISDKModel, + val keyedStore: ObservableInMemoryKeyedStore, + val perceptionManager: IPerceptionManager, +) : WidgetModel(djiSdkModel, keyedStore) { + private val perceptionInfoProcessor= DataProcessor.create(PerceptionInfo()) + private val perceptionInfoListener = PerceptionInformationListener { + perceptionInfoProcessor.onNext(it) + } + + val perceptionInfo: Flowable + get() = perceptionInfoProcessor.toFlowable() + + override fun inSetup() { + perceptionManager.addPerceptionInformationListener(perceptionInfoListener) + } + + override fun inCleanup() { + perceptionManager.removePerceptionInformationListener(perceptionInfoListener) + } + + /** + * Obstacle avoidance system switch state + */ + enum class PerceptionSwitchState { + /** + * All enabled + */ + ALL_ENABLED, + + /** + * Only horizontal obstacle avoidance system isn't working + */ + ONLY_HORI_OFF, + + /** + * Only upward obstacle avoidance system isn't working + */ + ONLY_UP_OFF, + + /** + * Only downward obstacle avoidance system isn't working + */ + ONLY_DOWN_OFF, + + /** + * Only horizontal obstacle avoidance system is working + */ + ONLY_HORI_ON, + + /** + * Only upward obstacle avoidance system is working + */ + ONLY_UP_ON, + + /** + * Only downward obstacle avoidance system is working + */ + ONLY_DOWN_ON, + + /** + * All disabled + */ + ALL_DISABLED + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/perception/PerceptionWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/perception/PerceptionWidget.kt new file mode 100644 index 00000000..b08bef78 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/perception/PerceptionWidget.kt @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.perception + +import android.content.Context +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.View +import android.widget.ImageView +import dji.v5.manager.aircraft.perception.data.PerceptionInfo +import dji.v5.manager.aircraft.perception.PerceptionManager +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.widget.FrameLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getDrawable +import dji.v5.ux.core.extension.getString + +/** + * Description :The widget used to show whether the visual obstacle avoidance system is enabled. + * + * @author: William.Wong + * date : 2022/9/21 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ +class PerceptionStateWidget @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 +) : FrameLayoutWidget(context, attrs, defStyleAttr) { + + private val perceptionIconImageView: ImageView = findViewById(R.id.imageview_vision_icon) + + private val widgetModel by lazy { + PerceptionStateWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + PerceptionManager.getInstance() + ) + } + + // Used to represent the state of perception switch + private var perceptionSwitchState = PerceptionStateWidgetModel.PerceptionSwitchState.ALL_DISABLED + + // Used to represent the relationships between the perception switch and images + private val perceptionSwitchStateMap: MutableMap = + mutableMapOf( + PerceptionStateWidgetModel.PerceptionSwitchState.ALL_ENABLED to getDrawable(R.drawable.uxsdk_ic_avoid_normal_all), + PerceptionStateWidgetModel.PerceptionSwitchState.ONLY_HORI_OFF to getDrawable(R.drawable.uxsdk_ic_avoid_only_hori_off), + PerceptionStateWidgetModel.PerceptionSwitchState.ONLY_UP_OFF to getDrawable(R.drawable.uxsdk_ic_avoid_only_up_off), + PerceptionStateWidgetModel.PerceptionSwitchState.ONLY_DOWN_OFF to getDrawable(R.drawable.uxsdk_ic_avoid_only_down_off), + PerceptionStateWidgetModel.PerceptionSwitchState.ONLY_HORI_ON to getDrawable(R.drawable.uxsdk_ic_avoid_only_hori_on), + PerceptionStateWidgetModel.PerceptionSwitchState.ONLY_UP_ON to getDrawable(R.drawable.uxsdk_ic_avoid_only_up_on), + PerceptionStateWidgetModel.PerceptionSwitchState.ONLY_DOWN_ON to getDrawable(R.drawable.uxsdk_ic_avoid_only_down_on), + PerceptionStateWidgetModel.PerceptionSwitchState.ALL_DISABLED to getDrawable(R.drawable.uxsdk_ic_avoid_disable_all) + ) + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + View.inflate(context, R.layout.uxsdk_widget_vision, this) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun getIdealDimensionRatioString() = null + + override fun reactToModelChanges() { + addReaction(widgetModel.perceptionInfo + .observeOn(SchedulerProvider.ui()) + .subscribe { handlePerceptionInfo(it) }) + } + + /** + * This function will determine the current perception switch state and draw image. + */ + private fun handlePerceptionInfo(perceptionInfo: PerceptionInfo) { + // If the vision positioning is disabled, all obstacle avoidance system will stop working + if (!perceptionInfo.isVisionPositioningEnabled) { + perceptionSwitchState = PerceptionStateWidgetModel.PerceptionSwitchState.ALL_DISABLED + perceptionIconImageView.setImageDrawable(perceptionSwitchStateMap[perceptionSwitchState]) + return + } + handleHorizontalPerceptionInfo(perceptionInfo) + handleUpwardPerceptionInfo(perceptionInfo) + handleDownwardPerceptionInfo(perceptionInfo) + handleAllPerceptionInfo(perceptionInfo) + perceptionIconImageView.setImageDrawable(perceptionSwitchStateMap[perceptionSwitchState]) + } + + /** + * This function will determine the the current horizontal system state. + */ + private fun handleHorizontalPerceptionInfo(perceptionInfo: PerceptionInfo) { + if (isPerceptionEnabled(perceptionInfo.isHorizontalObstacleAvoidanceEnabled, + !perceptionInfo.isUpwardObstacleAvoidanceEnabled, + !perceptionInfo.isDownwardObstacleAvoidanceEnabled)) { + perceptionSwitchState = PerceptionStateWidgetModel.PerceptionSwitchState.ONLY_HORI_ON + } else if(!isPerceptionEnabled(perceptionInfo.isHorizontalObstacleAvoidanceEnabled, + perceptionInfo.isUpwardObstacleAvoidanceEnabled, + perceptionInfo.isDownwardObstacleAvoidanceEnabled)) { + perceptionSwitchState = PerceptionStateWidgetModel.PerceptionSwitchState.ONLY_HORI_OFF + } + } + + /** + * This function will determine the the current upward system state. + */ + private fun handleUpwardPerceptionInfo(perceptionInfo: PerceptionInfo) { + if (isPerceptionEnabled(!perceptionInfo.isHorizontalObstacleAvoidanceEnabled, + perceptionInfo.isUpwardObstacleAvoidanceEnabled, + !perceptionInfo.isDownwardObstacleAvoidanceEnabled)) { + perceptionSwitchState = PerceptionStateWidgetModel.PerceptionSwitchState.ONLY_UP_ON + } else if(isPerceptionEnabled(perceptionInfo.isHorizontalObstacleAvoidanceEnabled, + !perceptionInfo.isUpwardObstacleAvoidanceEnabled, + perceptionInfo.isDownwardObstacleAvoidanceEnabled)) { + perceptionSwitchState = PerceptionStateWidgetModel.PerceptionSwitchState.ONLY_UP_OFF + } + } + + /** + * This function will determine the the current downward system state. + */ + private fun handleDownwardPerceptionInfo(perceptionInfo: PerceptionInfo) { + if (isPerceptionEnabled(!perceptionInfo.isHorizontalObstacleAvoidanceEnabled, + !perceptionInfo.isUpwardObstacleAvoidanceEnabled, + perceptionInfo.isDownwardObstacleAvoidanceEnabled)) { + perceptionSwitchState = PerceptionStateWidgetModel.PerceptionSwitchState.ONLY_DOWN_ON + } else if(isPerceptionEnabled(perceptionInfo.isHorizontalObstacleAvoidanceEnabled, + perceptionInfo.isUpwardObstacleAvoidanceEnabled, + !perceptionInfo.isDownwardObstacleAvoidanceEnabled)) { + perceptionSwitchState = PerceptionStateWidgetModel.PerceptionSwitchState.ONLY_DOWN_OFF + } + } + + /** + * This function will determine if all the perception is enabled. + */ + private fun handleAllPerceptionInfo(perceptionInfo: PerceptionInfo) { + if (isPerceptionEnabled(perceptionInfo.isHorizontalObstacleAvoidanceEnabled, + perceptionInfo.isUpwardObstacleAvoidanceEnabled, + perceptionInfo.isDownwardObstacleAvoidanceEnabled)) { + perceptionSwitchState = PerceptionStateWidgetModel.PerceptionSwitchState.ALL_ENABLED + } else if(isPerceptionEnabled(!perceptionInfo.isHorizontalObstacleAvoidanceEnabled, + !perceptionInfo.isUpwardObstacleAvoidanceEnabled, + !perceptionInfo.isDownwardObstacleAvoidanceEnabled)) { + perceptionSwitchState = PerceptionStateWidgetModel.PerceptionSwitchState.ALL_DISABLED + } + } + + /** + * This function will combine each direction's perception switch state. + */ + private fun isPerceptionEnabled(horizontalDirection: Boolean, upwardDirection: Boolean, downwardDirection: Boolean): Boolean { + return horizontalDirection && upwardDirection && downwardDirection + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/radar/MultiAngleRadarSectionViewHolder.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/radar/MultiAngleRadarSectionViewHolder.kt new file mode 100644 index 00000000..9c9de81f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/radar/MultiAngleRadarSectionViewHolder.kt @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.radar + +import android.graphics.drawable.Drawable +import android.view.View +import android.widget.ImageView +import android.widget.TextView + +import androidx.annotation.IdRes + +/** + * Represents a section of the obstacle detection radar that has multiple segments. + */ +class MultiAngleRadarSectionViewHolder( + @IdRes imageIds: IntArray, + @IdRes distanceId: Int, + @IdRes arrowId: Int, + parent: View +) : RadarSectionViewHolder() { + + override val distance: TextView = parent.findViewById(distanceId) + override val arrow: ImageView = parent.findViewById(arrowId) + private val sectorImages: Array = arrayOfNulls(imageIds.size) + + init { + imageIds.forEachIndexed { i, imageId -> + sectorImages[i] = parent.findViewById(imageId) + } + hide() + } + + override fun hide() { + distance.visibility = View.GONE + arrow.visibility = View.GONE + sectorImages.forEach { it?.visibility = View.GONE } + } + + + override fun setImages(images: Array) { + sectorImages.forEachIndexed { index: Int, image: ImageView? -> + if (index < images.size) { + image?.setImageDrawable(images[index]) + } + } + } + +// override fun setSectors(sectors: Array?, unitStr: String?) { +// if (sectors != null && sectors.isNotEmpty()) { +// var distanceValue: Float = Integer.MAX_VALUE.toFloat() +// sectors.forEachIndexed { i, sector -> +// if (sector.obstacleDistanceInMeters < distanceValue) { +// distanceValue = sector.obstacleDistanceInMeters +// } +// val level = sector.warningLevel.value() +// if (level in 0..5) { +// sectorImages[i]?.setImageLevel(level) +// } +// } +// +// val isInvalidOrZero = sectors.all { sector -> +// sector.warningLevel == ObstacleDetectionSectorWarning.INVALID +// } || sectors.all { sector -> +// sector.warningLevel == ObstacleDetectionSectorWarning.LEVEL_1 +// } +// if (isInvalidOrZero) { +// hide() +// } else { +// show() +// super.setDistance(distanceValue.toDouble(), unitStr) +// } +// } else { +// hide() +// } +// } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/radar/RadarSectionViewHolder.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/radar/RadarSectionViewHolder.kt new file mode 100644 index 00000000..8bc1059f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/radar/RadarSectionViewHolder.kt @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +package dji.v5.ux.core.widget.radar + +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.drawable.Drawable +import android.widget.ImageView +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.annotation.DrawableRes +import androidx.annotation.StyleRes +import java.util.* + +/** + * Represents a section of the obstacle detection radar : forward, backward, left, or right. + */ +abstract class RadarSectionViewHolder { + + /** + * The [TextView] representing the distance between the obstacle and the aircraft + */ + abstract val distance: TextView + + /** + * The [ImageView] representing the direction of the obstacle + */ + abstract val arrow: ImageView + + /** + * The text color of the distance text view + */ + @get:ColorInt + var distanceTextColor: Int + get() = distance.currentTextColor + set(color) { + distance.setTextColor(color) + } + + /** + * The text color state list of the distance text view + */ + var distanceTextColors: ColorStateList? + get() = distance.textColors + set(colorStateList) { + distance.setTextColor(colorStateList) + } + + /** + * The background of the distance text view + */ + var distanceTextBackground: Drawable? + get() = distance.background + set(icon) { + distance.background = icon + } + + /** + * The text size of the distance text view + */ + var distanceTextSize: Float + get() = distance.textSize + set(textSize) { + distance.textSize = textSize + } + + /** + * The drawable resource for the arrow icon. The given icon should be pointed up, and each + * radar direction's icon will be rotated to point the corresponding direction. + */ + var distanceArrowIcon: Drawable? + get() = arrow.drawable + set(icon) { + arrow.setImageDrawable(icon) + } + + /** + * The drawable resource for the arrow icon's background + */ + var distanceArrowIconBackground: Drawable? + get() = arrow.background + set(icon) { + arrow.background = icon + } + + /** + * Set the distance of the detected obstacle. + * + * @param distance The distance of the detected obstacle. + * @param unitStr A string representing the units for the distance measurement. + */ + open fun setDistance(distance: Double, unitStr: String?) { + val distanceValue = distance.toFloat() + this.distance.text = String.format(Locale.getDefault(), "%.1f %s", distanceValue, unitStr) + } + + /** + * Set the sectors of a multi-angle radar section. For single-angle radar sections, this + * method has no effect. + * + * @param sectors An array of [ObstacleDetectionSector] representing the sections of a + * multi-angle radar. + * @param unitStr A string representing the units for the distance measurement. + */ +// abstract fun setSectors(sectors: Array?, unitStr: String?) + + /** + * Set the images for this radar section. For single-angle radar sections, only the first + * image in the array is used. For multi-angle radar sections, the images will be + * overlapped to form the sections of the radar. + * + * @param images An array of level-list [Drawable] objects with levels from 0-5 for multi-angle + * radar sections or 0-1 for single-angle radar sections. + */ + abstract fun setImages(images: Array) + + /** + * Hide this radar section. May be shown again if [setSectors] or [setDistance] is called + * afterwards. + */ + abstract fun hide() + + //region Customizations + /** + * Set text appearance of the distance text view + * + * @param context A context object + * @param textAppearanceResId Style resource for text appearance + */ + fun setDistanceTextAppearance(context: Context?, @StyleRes textAppearanceResId: Int) { + distance.setTextAppearance(context, textAppearanceResId) + } + + /** + * Set the resource ID for the background of the distance text view + * + * @param resourceId Integer ID of the text view's background resource + */ + fun setDistanceTextBackground(@DrawableRes resourceId: Int) { + distance.setBackgroundResource(resourceId) + } + + /** + * Set the resource ID for the arrow icon. The given icon should be pointed up, and each + * radar direction's icon will be rotated to point the corresponding direction. + * + * @param resourceId Integer ID of the drawable resource + */ + fun setDistanceArrowIcon(@DrawableRes resourceId: Int) { + arrow.setImageResource(resourceId) + } + + /** + * Set the resource ID for the arrow icon's background + * + * @param resourceId Integer ID of the icon's background resource + */ + fun setDistanceArrowIconBackground(@DrawableRes resourceId: Int) { + arrow.setBackgroundResource(resourceId) + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/radar/RadarWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/radar/RadarWidget.kt new file mode 100644 index 00000000..1944665e --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/radar/RadarWidget.kt @@ -0,0 +1,574 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +package dji.v5.ux.core.widget.radar + +import android.content.Context +import android.util.AttributeSet +import androidx.annotation.* +import dji.v5.utils.common.LogUtils +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.GlobalPreferenceKeys +import dji.v5.ux.core.communication.GlobalPreferencesInterface +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.widget.radar.RadarWidget.ModelState +import dji.v5.ux.core.widget.radar.RadarWidget.ModelState.* + +private const val TAG = "RadarWidget" +private const val ASPECT_RATIO = 17f / 8 + +/** + * Shows the current state of the radar sensors. The forward and backward sensors each have four + * sectors represented by [ObstacleDetectionSector], and the left and right sensors each have + * a single sector. Each sector displays an icon according to its + * [ObstacleDetectionSectorWarning] level. + * + * Each radar section has its own distance indicator which uses the unit set in the UNIT_MODE + * global preferences [GlobalPreferencesInterface.unitType] and the + * [GlobalPreferenceKeys.UNIT_TYPE] UX Key and defaults to m if + * nothing is set. + * + * Additionally, an icon appears in the center when the upwards sensor detects an obstacle. + * + * This widget has a fixed aspect ratio of 17:8. + */ +open class RadarWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ConstraintLayoutWidget(context, attrs, defStyleAttr) { + private val tag = LogUtils.getTag("RadarWidget") +// //region Fields +// private var radarSections: Array = arrayOfNulls(4) +// private var upwardObstacle: ImageView = findViewById(R.id.imageview_upward_obstacle) +// private var soundDisposable: Disposable? = null +// +// private val widgetModel: RadarWidgetModel by lazy { +// RadarWidgetModel(DJISDKModel.getInstance(), +// ObservableInMemoryKeyedStore.getInstance(), +// GlobalPreferencesManager.getInstance()) +// } +// +// /** +// * The images for the forward radar section. The images will be overlapped to form the +// * sections of the radar. An array of level-list [Drawable] objects with levels from 0-5 is +// * recommended. +// */ +// var forwardRadarImages: Array = arrayOf( +// getDrawable(R.drawable.uxsdk_ic_radar_forward_0), +// getDrawable(R.drawable.uxsdk_ic_radar_forward_1), +// getDrawable(R.drawable.uxsdk_ic_radar_forward_2), +// getDrawable(R.drawable.uxsdk_ic_radar_forward_3)) +// set(value) { +// field = value +// radarSections[VisionSensorPosition.NOSE.value()]?.setImages(value) +// } +// +// /** +// * The images for the backward radar section. The images will be overlapped to form the +// * sections of the radar. An array of level-list [Drawable] objects with levels from 0-5 is +// * recommended. +// */ +// var backwardRadarImages: Array = arrayOf( +// getDrawable(R.drawable.uxsdk_ic_radar_backward_0), +// getDrawable(R.drawable.uxsdk_ic_radar_backward_1), +// getDrawable(R.drawable.uxsdk_ic_radar_backward_2), +// getDrawable(R.drawable.uxsdk_ic_radar_backward_3)) +// set(value) { +// field = value +// radarSections[VisionSensorPosition.TAIL.value()]?.setImages(value) +// } +// +// /** +// * The image for the left radar section. A level-list [Drawable] objects with levels from 0-1 +// * is recommended. +// */ +// var leftRadarImage: Drawable? = getDrawable(R.drawable.uxsdk_ic_radar_left) +// set(value) { +// field = value +// radarSections[VisionSensorPosition.LEFT.value()]?.setImages(arrayOf(value)) +// } +// +// /** +// * The image for the right radar section. A level-list [Drawable] objects with levels from 0-1 +// * is recommended. +// */ +// var rightRadarImage: Drawable? = getDrawable(R.drawable.uxsdk_ic_radar_right) +// set(value) { +// field = value +// radarSections[VisionSensorPosition.RIGHT.value()]?.setImages(arrayOf(value)) +// } +// +// /** +// * The text color for the distance text views +// */ +// @get:ColorInt +// @setparam:ColorInt +// var distanceTextColor: Int +// get() = radarSections[0]?.distanceTextColor ?: getColor(R.color.uxsdk_white) +// set(color) { +// radarSections.forEach { it?.distanceTextColor = color } +// } +// +// /** +// * The text color state list of the distance text views +// */ +// var distanceTextColors: ColorStateList? +// get() = radarSections[0]?.distanceTextColors +// set(colors) { +// radarSections.forEach { it?.distanceTextColors = colors } +// } +// +// /** +// * The background of the distance text views +// */ +// var distanceTextBackground: Drawable? +// get() = radarSections[0]?.distanceTextBackground +// set(background) { +// radarSections.forEach { it?.distanceTextBackground = background } +// } +// +// /** +// * The text size of the distance text views +// */ +// @get:Dimension +// @setparam:Dimension +// var distanceTextSize: Float +// get() = radarSections[0]?.distanceTextSize ?: 13f +// set(textSize) { +// radarSections.forEach { it?.distanceTextSize = textSize } +// } +// +// /** +// * The drawable resource for the arrow icons. The given icon should be pointed up, and each +// * radar direction's icon will be rotated to point the corresponding direction. +// */ +// var distanceArrowIcon: Drawable? +// get() = radarSections[0]?.distanceArrowIcon +// set(icon) { +// radarSections.forEach { it?.distanceArrowIcon = icon } +// } +// +// /** +// * The drawable resource for the arrow icon's background +// */ +// var distanceArrowIconBackground: Drawable? +// get() = radarSections[0]?.distanceArrowIconBackground +// set(background) { +// radarSections.forEach { it?.distanceArrowIconBackground = background } +// } +// +// /** +// * The drawable resource for the upward obstacle icon +// */ +// var upwardObstacleIcon: Drawable? +// get() = upwardObstacle.drawable +// set(icon) { +// upwardObstacle.setImageDrawable(icon) +// } +// +// /** +// * The drawable resource for the upward obstacle icon's background +// */ +// var upwardObstacleIconBackground: Drawable? +// get() = upwardObstacle.background +// set(background) { +// upwardObstacle.background = background +// } +// //endregion +// +// //region Constructor +// override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { +// View.inflate(context, R.layout.uxsdk_widget_radar, this) +// } +// +// init { +// val forwardIds = intArrayOf(R.id.imageview_radar_forward_0, +// R.id.imageview_radar_forward_1, +// R.id.imageview_radar_forward_2, +// R.id.imageview_radar_forward_3) +// +// val backwardIds = intArrayOf(R.id.imageview_radar_backward_0, +// R.id.imageview_radar_backward_1, +// R.id.imageview_radar_backward_2, +// R.id.imageview_radar_backward_3) +// +// if(!isInEditMode){ +// radarSections[VisionSensorPosition.NOSE.value()] = +// MultiAngleRadarSectionViewHolder(forwardIds, +// R.id.textview_forward_distance, +// R.id.imageview_forward_arrow, this) +// +// radarSections[VisionSensorPosition.TAIL.value()] = +// MultiAngleRadarSectionViewHolder(backwardIds, +// R.id.textview_backward_distance, +// R.id.imageview_backward_arrow, this) +// +// radarSections[VisionSensorPosition.LEFT.value()] = +// SingleAngleRadarSectionViewHolder(R.id.imageview_radar_left, +// R.id.textview_left_distance, +// R.id.imageview_left_arrow, this) +// +// radarSections[VisionSensorPosition.RIGHT.value()] = +// SingleAngleRadarSectionViewHolder(R.id.imageview_radar_right, +// R.id.textview_right_distance, +// R.id.imageview_right_arrow, this) +// } +// +// attrs?.let { initAttributes(context, it) } +// } +// //endregion +// +// //region Lifecycle +// override fun onAttachedToWindow() { +// super.onAttachedToWindow() +// if (!isInEditMode) { +// widgetModel.setup() +// } +// } +// +// override fun onDetachedFromWindow() { +// if (!isInEditMode) { +// widgetModel.cleanup() +// } +// soundDisposable?.dispose() +// soundDisposable = null +// super.onDetachedFromWindow() +// } +// +// override fun reactToModelChanges() { +// addReaction(reactToUpdateRadarSections()) +// addReaction(widgetModel.ascentLimitedByObstacle +// .observeOn(SchedulerProvider.ui()) +// .subscribe { updateUpwardRadar(it) }) +// addReaction(widgetModel.obstacleAvoidanceLevel +// .observeOn(SchedulerProvider.ui()) +// .subscribe { playAlertSound(it) }) +// addReaction(widgetModel.isRadarEnabled +// .observeOn(SchedulerProvider.ui()) +// .subscribe { updateRadarEnabled(it) }) +// addReaction(widgetModel.productConnection +// .observeOn(SchedulerProvider.ui()) +// .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) +// } +// +// override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { +// super.onMeasure(widthMeasureSpec, heightMeasureSpec) +// var width = MeasureSpec.getSize(widthMeasureSpec) +// var height = MeasureSpec.getSize(heightMeasureSpec) +// if (height * ASPECT_RATIO < width) { +// width = (height * ASPECT_RATIO).toInt() +// } else { +// height = (width / ASPECT_RATIO).toInt() +// } +// setMeasuredDimension(View.resolveSize(width, widthMeasureSpec), View.resolveSize(height, heightMeasureSpec)) +// } +// //endregion +// +// //region Reactions +// private fun reactToUpdateRadarSections(): Disposable { +// return Flowable.combineLatest(widgetModel.visionDetectionState, widgetModel.unitType, +// BiFunction { first: VisionDetectionState, second: UnitConversionUtil.UnitType -> Pair(first, second) }) +// .observeOn(SchedulerProvider.ui()) +// .subscribe(Consumer { values: Pair -> updateRadarSections(values.first, values.second) }, +// RxUtil.logErrorConsumer(TAG, "reactToUpdateRadarSections: ")) +// } +// +// private fun updateRadarSections(state: VisionDetectionState, unitType: UnitConversionUtil.UnitType) { +// val sectors = state.detectionSectors +// if (state.position.value() < radarSections.size) { +// val radarSection = radarSections[state.position.value()] +// val unit: String = if (unitType == UnitConversionUtil.UnitType.IMPERIAL) { +// getString(R.string.uxsdk_unit_feet) +// } else { +// getString(R.string.uxsdk_unit_meters) +// } +// radarSection?.setDistance(state.obstacleDistanceInMeters, unit) +// radarSection?.setSectors(sectors, unit) +// when (state.position) { +// VisionSensorPosition.NOSE -> widgetStateDataProcessor.onNext(NoseStateUpdated(state)) +// VisionSensorPosition.TAIL -> widgetStateDataProcessor.onNext(TailStateUpdated(state)) +// VisionSensorPosition.LEFT -> widgetStateDataProcessor.onNext(LeftStateUpdated(state)) +// VisionSensorPosition.RIGHT -> widgetStateDataProcessor.onNext(RightStateUpdated(state)) +// else -> { +// // Do nothing +// } +// } +// } +// } +// +// private fun updateUpwardRadar(isAscentLimitedByObstacle: Boolean) { +// upwardObstacle.visibility = if (isAscentLimitedByObstacle) View.VISIBLE else View.GONE +// widgetStateDataProcessor.onNext(AscentLimitedUpdated(isAscentLimitedByObstacle)) +// } +// +// private fun updateRadarEnabled(isRadarEnabled: Boolean) { +// if (!isRadarEnabled) { +// radarSections.forEach { +// it?.hide() +// } +// } +// widgetStateDataProcessor.onNext(RadarEnabled(isRadarEnabled)) +// } +// +// private fun playAlertSound(avoidanceLevel: ObstacleAvoidanceLevel) { +// if (avoidanceLevel != ObstacleAvoidanceLevel.NONE) { +// if (soundDisposable == null) { +// soundDisposable = Observable.interval(1, java.util.concurrent.TimeUnit.SECONDS) +// .subscribeOn(SchedulerProvider.io()) +// .observeOn(SchedulerProvider.ui()) +// .subscribe { AudioUtil.playSound(context, getSoundId(avoidanceLevel), true) } +// } +// } else { +// soundDisposable?.dispose() +// soundDisposable = null +// } +// } +// +// @RawRes +// private fun getSoundId(avoidAlertLevel: ObstacleAvoidanceLevel): Int { +// return when (avoidAlertLevel) { +// ObstacleAvoidanceLevel.LEVEL_1 -> R.raw.uxsdk_radar_beep_1000 +// ObstacleAvoidanceLevel.LEVEL_2 -> R.raw.uxsdk_radar_beep_500 +// ObstacleAvoidanceLevel.LEVEL_3 -> R.raw.uxsdk_radar_beep_250 +// else -> 0 +// } +// } +// //endregion +// +// //region Customization +// override fun getIdealDimensionRatioString(): String { +// return getString(R.string.uxsdk_widget_radar_ratio) +// } +// +// /** +// * Set the warning level ranges for the specified product models. +// * +// * @param models The product models for which these level ranges apply. +// * @param levelRanges An array where each number represents the maximum distance in meters for +// * the corresponding warning level. For example [70, 4, 2] would indicate +// * that warning level LEVEL_1 has the range (4-70], warning level LEVEL_2 +// * has the range (2,4], and warning level LEVEL_3 has the range [0,2]. +// * A distance with a value above the largest number in the array will have +// * the warning level INVALID. +// */ +// fun setWarningLevelRanges(models: Array, levelRanges: FloatArray) { +// widgetModel.setWarningLevelRanges(models, levelRanges) +// } +// +// /** +// * Set the resource IDs for the forward radar section. The images will be overlapped to form the +// * sections of the radar. +// * +// * @param resourceIds An array of level-list resource IDs with levels from 0-5. +// */ +// fun setForwardRadarImages(resourceIds: IntArray) { +// forwardRadarImages = resourceIds.map { resourceId: Int -> +// getDrawable(resourceId) +// }.toTypedArray() +// } +// +// /** +// * Set the resource IDs for the backward radar section. The images will be overlapped to form the +// * sections of the radar. +// * +// * @param resourceIds An array of level-list resource IDs with levels from 0-5. +// */ +// fun setBackwardRadarImages(resourceIds: IntArray) { +// backwardRadarImages = resourceIds.map { resourceId: Int -> +// getDrawable(resourceId) +// }.toTypedArray() +// } +// +// /** +// * Set the resource ID for the left radar section. +// * +// * @param resourceId A level-list resource ID with levels from 0-1. +// */ +// fun setLeftRadarImage(@DrawableRes resourceId: Int) { +// leftRadarImage = getDrawable(resourceId) +// } +// +// /** +// * Set the resource ID for the right radar section. +// * +// * @param resourceId A level-list resource ID with levels from 0-1. +// */ +// fun setRightRadarImage(@DrawableRes resourceId: Int) { +// leftRadarImage = getDrawable(resourceId) +// } +// +// /** +// * Set text appearance of the distance text views +// * +// * @param textAppearanceResId Style resource for text appearance +// */ +// fun setDistanceTextAppearance(@StyleRes textAppearanceResId: Int) { +// radarSections.forEach { it?.setDistanceTextAppearance(context, textAppearanceResId) } +// } +// +// /** +// * Set the resource ID for the background of the distance text views +// * +// * @param resourceId Integer ID of the text view's background resource +// */ +// fun setDistanceTextBackground(@DrawableRes resourceId: Int) { +// radarSections.forEach { it?.setDistanceTextBackground(resourceId) } +// } +// +// /** +// * Set the resource ID for the arrow icons. The given icon should be pointed up, and each +// * radar direction's icon will be rotated to point the corresponding direction. +// * +// * @param resourceId Integer ID of the drawable resource +// */ +// fun setDistanceArrowIcon(@DrawableRes resourceId: Int) { +// radarSections.forEach { it?.setDistanceArrowIcon(resourceId) } +// } +// +// /** +// * Set the resource ID for the arrow icon's background +// * +// * @param resourceId Integer ID of the icon's background resource +// */ +// fun setDistanceArrowIconBackground(@DrawableRes resourceId: Int) { +// radarSections.forEach { it?.setDistanceArrowIconBackground(resourceId) } +// } +// +// /** +// * Set the resource ID for the upward obstacle icon +// * +// * @param resourceId Integer ID of the drawable resource +// */ +// fun setUpwardObstacleIcon(@DrawableRes resourceId: Int) { +// upwardObstacleIcon = getDrawable(resourceId) +// } +// +// /** +// * Set the resource ID for the upward obstacle icon's background +// * +// * @param resourceId Integer ID of the icon's background resource +// */ +// fun setUpwardObstacleIconBackground(@DrawableRes resourceId: Int) { +// upwardObstacle.setBackgroundResource(resourceId) +// } +// +// @SuppressLint("Recycle") +// private fun initAttributes(context: Context, attrs: AttributeSet) { +// context.obtainStyledAttributes(attrs, R.styleable.RadarWidget).use { typedArray -> +// typedArray.getDrawableArrayAndUse(R.styleable.RadarWidget_uxsdk_forwardImages) { +// forwardRadarImages = it +// } +// typedArray.getDrawableArrayAndUse(R.styleable.RadarWidget_uxsdk_backwardImages) { +// backwardRadarImages = it +// } +// typedArray.getDrawableAndUse(R.styleable.RadarWidget_uxsdk_leftImage) { +// leftRadarImage = it +// } +// typedArray.getDrawableAndUse(R.styleable.RadarWidget_uxsdk_rightImage) { +// rightRadarImage = it +// } +// typedArray.getDrawableAndUse(R.styleable.RadarWidget_uxsdk_distanceArrowIcon) { +// distanceArrowIcon = it +// } +// typedArray.getDrawableAndUse(R.styleable.RadarWidget_uxsdk_distanceArrowIconBackground) { +// distanceArrowIconBackground = it +// } +// typedArray.getDrawableAndUse(R.styleable.RadarWidget_uxsdk_upwardObstacleIcon) { +// upwardObstacleIcon = it +// } +// typedArray.getDrawableAndUse(R.styleable.RadarWidget_uxsdk_upwardObstacleIconBackground) { +// upwardObstacleIconBackground = it +// } +// typedArray.getDrawableAndUse(R.styleable.RadarWidget_uxsdk_distanceTextBackground) { +// distanceTextBackground = it +// } +// typedArray.getResourceIdAndUse(R.styleable.RadarWidget_uxsdk_distanceTextAppearance) { +// setDistanceTextAppearance(it) +// } +// typedArray.getColorAndUse(R.styleable.RadarWidget_uxsdk_distanceTextColor) { +// distanceTextColor = it +// } +// typedArray.getDimensionAndUse(R.styleable.RadarWidget_uxsdk_distanceTextSize) { +// distanceTextSize = DisplayUtil.pxToSp(context, it) +// } +// } +// } +// //endregion +// +// //region Hooks +// /** +// * Class defines the widget state updates +// */ +// sealed class ModelState { +// /** +// * Product connection update +// */ +// data class ProductConnected(val isConnected: Boolean) : ModelState() +// +// /** +// * Ascent limited update +// */ +// data class AscentLimitedUpdated(val isAscentLimited: Boolean) : ModelState() +// +// /** +// * Radar Enabled +// */ +// data class RadarEnabled(val isRadarEnabled: Boolean) : ModelState() +// +// /** +// * Nose state update +// */ +// data class NoseStateUpdated(val noseState: VisionDetectionState) : ModelState() +// +// /** +// * Tail state update +// */ +// data class TailStateUpdated(val tailState: VisionDetectionState) : ModelState() +// +// /** +// * Right state update +// */ +// data class RightStateUpdated(val rightState: VisionDetectionState) : ModelState() +// +// /** +// * Left state update +// */ +// data class LeftStateUpdated(val leftState: VisionDetectionState) : ModelState() +// +// } + //endregion + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { +// LogUtils.d(tag,"TODO Method not implemented yet") + } + + override fun reactToModelChanges() { +// LogUtils.d(tag,"TODO Method not implemented yet") + } + + override fun getIdealDimensionRatioString(): String? { + return null + } + + sealed class ModelState +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/radar/RadarWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/radar/RadarWidgetModel.kt new file mode 100644 index 00000000..6794d628 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/radar/RadarWidgetModel.kt @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ +package dji.v5.ux.core.widget.radar + +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.GlobalPreferencesInterface +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore + +private const val MM_IN_METER = 1000 +private const val MAX_PERCEPTION_DISTANCE = 45 +private const val DEFAULT_RADAR_DISTANCE = 10f +private const val DEFAULT_AVOIDANCE_DISTANCE = 3f +private const val DEGREES_IN_CIRCLE = 360 +private const val SIDE_RADAR_DANGER_DISTANCE = 3 +private const val SIDE_RADAR_WARNING_DISTANCE = 6 + +/** + * Widget Model for the [RadarWidget] used to define + * the underlying logic and communication + */ +class RadarWidgetModel(djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, + private val preferencesManager: GlobalPreferencesInterface? +) : WidgetModel(djiSdkModel, keyedStore) { + +// //region Fields +// private val visionDetectionStateProcessor: DataProcessor = DataProcessor.create( +// VisionDetectionState.createInstance( +// false, 0.0, +// VisionSystemWarning.UNKNOWN, +// null, +// VisionSensorPosition.UNKNOWN, +// false, +// 0)) +// private val isAscentLimitedByObstacleProcessor: DataProcessor = DataProcessor.create(false) +// private val modelProcessor: DataProcessor = DataProcessor.create(Model.UNKNOWN_AIRCRAFT) +// private val isMotorOnProcessor: DataProcessor = DataProcessor.create(false) +// private val flightModeProcessor: DataProcessor = DataProcessor.create(FlightMode.GPS_ATTI) +// private val radarDistancesProcessor: DataProcessor = DataProcessor.create(intArrayOf()) +// private val horizontalRadarDistanceProcessor: DataProcessor = DataProcessor.create(DEFAULT_RADAR_DISTANCE) +// private val horizontalAvoidanceDistanceProcessor: DataProcessor = DataProcessor.create(DEFAULT_AVOIDANCE_DISTANCE) +// private val unitTypeProcessor: DataProcessor = DataProcessor.create(UnitConversionUtil.UnitType.METRIC) +// private val obstacleAvoidanceLevelProcessor: DataProcessor = DataProcessor.create(ObstacleAvoidanceLevel.NONE) +// private val warningLevelRanges: MutableMap = ConcurrentHashMap() +// //endregion +// +// //region Data +// /** +// * The vision detection state. +// */ +// val visionDetectionState: Flowable +// get() = Flowable.combineLatest(visionDetectionStateProcessor.toFlowable(), +// unitTypeProcessor.toFlowable(), +// isRadarEnabled, +// Function3 { state: VisionDetectionState, +// unitType: UnitConversionUtil.UnitType, +// isRadarEnabled: Boolean -> +// var sectors: Array? = null +// var obstacleDistanceInMeters = 0.0 +// +// if (isRadarEnabled) { +// sectors = state.detectionSectors?.map { sector -> +// ObstacleDetectionSector(sector.warningLevel, +// sector.obstacleDistanceInMeters.toDistance(unitType)) +// }?.toTypedArray() +// obstacleDistanceInMeters = state.obstacleDistanceInMeters.toDistance(unitType) +// +// if (state.position == VisionSensorPosition.TAIL) { +// sectors?.reverse() +// } else if (state.position == VisionSensorPosition.LEFT +// || state.position == VisionSensorPosition.RIGHT) { +// val warningLevel = getSideRadarWarningLevel(state) +// sectors = arrayOf(ObstacleDetectionSector(warningLevel, +// obstacleDistanceInMeters.toFloat())) +// } +// adjustWarningLevels(sectors) +// } +// VisionDetectionState.createInstance(state.isSensorBeingUsed, +// obstacleDistanceInMeters, +// state.systemWarning, +// sectors, +// state.position, +// state.isDisabled, +// state.avoidAlertLevel) +// }) +// +// /** +// * Whether the radar is enabled. The radar is disabled if the product is in sport mode or no +// * product is connected. +// */ +// val isRadarEnabled: Flowable +// get() = Flowable.combineLatest(flightModeProcessor.toFlowable(), +// productConnectionProcessor.toFlowable(), +// BiFunction { flightMode: FlightMode, +// isConnected: Boolean -> +// flightMode != FlightMode.GPS_SPORT && isConnected +// }) +// +// /** +// * The obstacle avoidance level. Will only emit updates if the Model is M200 V2 series or M300 +// * series and the motors are on. +// */ +// val obstacleAvoidanceLevel: Flowable +// get() = Flowable.combineLatest(obstacleAvoidanceLevelProcessor.toFlowable(), +// modelProcessor.toFlowable(), +// isMotorOnProcessor.toFlowable(), +// Function3 { level: ObstacleAvoidanceLevel, +// model: Model, +// isMotorOn: Boolean -> +// if (ProductUtil.isM200V2M300(model) && isMotorOn) { +// level +// } else { +// ObstacleAvoidanceLevel.NONE +// } +// }).distinctUntilChanged() +// +// /** +// * Whether the aircraft's upward sensor has detected an obstacle. +// */ +// val ascentLimitedByObstacle: Flowable +// get() = isAscentLimitedByObstacleProcessor.toFlowable() +// +// /** +// * The unit type of the distance value. +// */ +// val unitType: Flowable +// get() = unitTypeProcessor.toFlowable() +// //endregion +// +// //region Constructor +// init { +// if (preferencesManager != null) { +// unitTypeProcessor.onNext(preferencesManager.unitType) +// } +// } +// //endregion +// +// //region Lifecycle +// override fun inSetup() { +// val visionDetectionStateKey: DJIKey = FlightControllerKey.createFlightAssistantKey(FlightControllerKey.VISION_DETECTION_STATE) +// val isAscentLimitedByObstacleKey: DJIKey = FlightControllerKey.createFlightAssistantKey(FlightControllerKey.IS_ASCENT_LIMITED_BY_OBSTACLE) +// val modelKey: DJIKey = ProductKey.create(ProductKey.MODEL_NAME) +// val isMotorOnKey: DJIKey = FlightControllerKey.create(FlightControllerKey.ARE_MOTOR_ON) +// val flightModeKey: DJIKey = FlightControllerKey.create(FlightControllerKey.FLIGHT_MODE) +// val radarDistancesKey: DJIKey = FlightControllerKey.createFlightAssistantKey(FlightControllerKey.OMNI_PERCEPTION_RADAR_BIRD_VIEW_DISTANCE) +// val horizontalRadarDistanceKey: DJIKey = FlightControllerKey.createFlightAssistantKey(FlightControllerKey.OMNI_HORIZONTAL_RADAR_DISTANCE) +// val horizontalAvoidanceDistanceKey: DJIKey = FlightControllerKey.createFlightAssistantKey(FlightControllerKey.OMNI_HORIZONTAL_AVOIDANCE_DISTANCE) +// bindDataProcessor(visionDetectionStateKey, visionDetectionStateProcessor) { visionDetectionState: Any? -> +// obstacleAvoidanceLevelProcessor.onNext(getObstacleAvoidanceLevel(visionDetectionState as VisionDetectionState)) +// } +// bindDataProcessor(isAscentLimitedByObstacleKey, isAscentLimitedByObstacleProcessor) +// bindDataProcessor(modelKey, modelProcessor) +// bindDataProcessor(isMotorOnKey, isMotorOnProcessor) +// bindDataProcessor(flightModeKey, flightModeProcessor) +// bindDataProcessor(radarDistancesKey, radarDistancesProcessor) { radarDistances: Any? -> +// parsePerceptionInformation(radarDistances as IntArray).forEach { +// visionDetectionStateProcessor.onNext(it) +// } +// val distanceInMeters = getMinDistance(radarDistances).toDouble() / MM_IN_METER +// obstacleAvoidanceLevelProcessor.onNext(getObstacleAvoidanceLevel(distanceInMeters.toFloat())) +// } +// bindDataProcessor(horizontalRadarDistanceKey, horizontalRadarDistanceProcessor) +// bindDataProcessor(horizontalAvoidanceDistanceKey, horizontalAvoidanceDistanceProcessor) +// val unitKey = UXKeys.create(GlobalPreferenceKeys.UNIT_TYPE) +// bindDataProcessor(unitKey, unitTypeProcessor) +// preferencesManager?.setUpListener() +// } +// +// override fun inCleanup() { +// preferencesManager?.cleanup() +// } +// +// override fun updateStates() { +// // Nothing to update +// } +// //endregion +// +// //region Customization +// /** +// * Sets the warning level ranges for the specified product models. +// * +// * @param models The product models for which these level ranges apply. +// * @param levelRanges An array where each number represents the maximum distance in meters for +// * the corresponding warning level. For example [70, 4, 2] would indicate +// * that warning level LEVEL_1 has the range (4-70], warning level LEVEL_2 +// * has the range (2,4], and warning level LEVEL_3 has the range [0,2]. +// * A distance with a value above the largest number in the array will have +// * the warning level INVALID. +// */ +// fun setWarningLevelRanges(models: Array, levelRanges: FloatArray) { +// if (models.isEmpty() || levelRanges.isEmpty()) { +// return +// } +// val ranges = levelRanges.copyOf(levelRanges.size) +// ranges.sortDescending() +// models.forEach { warningLevelRanges[it] = ranges } +// } +// //endregion +// +// //region Helpers +// private fun adjustWarningLevels(sectors: Array?) { +// val currentModel = modelProcessor.value +// if (!warningLevelRanges.containsKey(currentModel) || sectors == null) { +// return +// } +// val currentModelLevelRanges = warningLevelRanges[currentModel] +// if (currentModelLevelRanges != null) { +// sectors.forEachIndexed { i, sector -> +// val distanceInMeters = sector.obstacleDistanceInMeters +// val j = currentModelLevelRanges.indexOfLast { distanceInMeters < it } +// if (j >= 0) { +// sectors[i] = ObstacleDetectionSector(ObstacleDetectionSectorWarning.find(j), distanceInMeters) +// } +// } +// } +// } +// +// private fun getSideRadarWarningLevel(state: VisionDetectionState) : ObstacleDetectionSectorWarning { +// return when { +// state.obstacleDistanceInMeters <= 0 || state.obstacleDistanceInMeters >= SIDE_RADAR_WARNING_DISTANCE -> { +// ObstacleDetectionSectorWarning.UNKNOWN +// } +// state.obstacleDistanceInMeters < SIDE_RADAR_DANGER_DISTANCE -> { +// ObstacleDetectionSectorWarning.LEVEL_2 +// } +// else -> ObstacleDetectionSectorWarning.LEVEL_1 +// } +// } +// +// private fun parsePerceptionInformation(info: IntArray): List { +// val numDegreesPerValue = DEGREES_IN_CIRCLE / info.size +// +// val forwardSlice1 = (323 / numDegreesPerValue)..(359 / numDegreesPerValue) +// val forwardSlice2 = 0..(36 / numDegreesPerValue) +// val rightSlice = (53 / numDegreesPerValue)..(126 / numDegreesPerValue) +// val backwardSlice = (143 / numDegreesPerValue)..(216 / numDegreesPerValue) +// val leftSlice = (233 / numDegreesPerValue)..(306 / numDegreesPerValue) +// return arrayListOf( +// getVisionDetectionState(info.sliceArray(forwardSlice1) + info.sliceArray(forwardSlice2), +// VisionSensorPosition.NOSE), +// getVisionDetectionState(info.sliceArray(rightSlice), +// VisionSensorPosition.RIGHT), +// getVisionDetectionState(info.sliceArray(backwardSlice), +// VisionSensorPosition.TAIL), +// getVisionDetectionState(info.sliceArray(leftSlice), +// VisionSensorPosition.LEFT)) +// } +// +// private fun getVisionDetectionState(distances: IntArray, position: VisionSensorPosition): VisionDetectionState { +// val distanceInMeters = getMinDistance(distances).toDouble() / MM_IN_METER +// val visionSectorState = when (position) { +// VisionSensorPosition.NOSE, VisionSensorPosition.TAIL -> getVisionSectorState(distances) +// else -> null +// } +// +// return VisionDetectionState.createInstance(true, +// distanceInMeters, +// VisionSystemWarning.UNKNOWN, +// visionSectorState, +// position, +// false, +// 0) +// } +// +// private fun getVisionSectorState(distances: IntArray?): Array? { +// if (distances == null || distances.isEmpty()) { +// return null +// } +// +// val slice1 = 0 until (distances.size / 4) +// val slice2 = (distances.size / 4) until (distances.size / 2) +// val slice3 = (distances.size / 2) until (distances.size * 3 / 4) +// val slice4 = (distances.size * 3 / 4) until (distances.size) +// return arrayOf( +// getSector(getMinDistance(distances.sliceArray(slice1)) / MM_IN_METER.toFloat()), +// getSector(getMinDistance(distances.sliceArray(slice2)) / MM_IN_METER.toFloat()), +// getSector(getMinDistance(distances.sliceArray(slice3)) / MM_IN_METER.toFloat()), +// getSector(getMinDistance(distances.sliceArray(slice4)) / MM_IN_METER.toFloat())) +// } +// +// private fun getSector(distanceInMeters: Float): ObstacleDetectionSector { +// val sectorWarningLevel = if (modelProcessor.value == Model.MATRICE_300_RTK) { +// when { +// distanceInMeters < 0 -> ObstacleDetectionSectorWarning.UNKNOWN +// distanceInMeters >= MAX_PERCEPTION_DISTANCE -> ObstacleDetectionSectorWarning.INVALID +// distanceInMeters > horizontalRadarDistanceProcessor.value -> ObstacleDetectionSectorWarning.LEVEL_1 +// distanceInMeters > horizontalAvoidanceDistanceProcessor.value + 2 -> ObstacleDetectionSectorWarning.LEVEL_4 +// else -> ObstacleDetectionSectorWarning.LEVEL_6 +// } +// } else { +// when { +// distanceInMeters < 3 -> ObstacleDetectionSectorWarning.LEVEL_6 +// distanceInMeters < 6 -> ObstacleDetectionSectorWarning.LEVEL_5 +// distanceInMeters < 10 -> ObstacleDetectionSectorWarning.LEVEL_4 +// distanceInMeters < 15 -> ObstacleDetectionSectorWarning.LEVEL_3 +// distanceInMeters < 20 -> ObstacleDetectionSectorWarning.LEVEL_2 +// else -> ObstacleDetectionSectorWarning.LEVEL_1 +// } +// } +// return ObstacleDetectionSector(sectorWarningLevel, distanceInMeters) +// } +// +// private fun getObstacleAvoidanceLevel(distanceInMeters: Float): ObstacleAvoidanceLevel { +// return when { +// distanceInMeters > horizontalRadarDistanceProcessor.value -> ObstacleAvoidanceLevel.NONE +// distanceInMeters >= horizontalRadarDistanceProcessor.value / 3 + horizontalAvoidanceDistanceProcessor.value * 2 / 3 -> ObstacleAvoidanceLevel.LEVEL_1 +// distanceInMeters >= horizontalRadarDistanceProcessor.value / 6 + horizontalAvoidanceDistanceProcessor.value * 5 / 6 -> ObstacleAvoidanceLevel.LEVEL_2 +// else -> ObstacleAvoidanceLevel.LEVEL_3 +// } +// } +// +// private fun getObstacleAvoidanceLevel(visionDetectionState: VisionDetectionState): ObstacleAvoidanceLevel { +// val distanceInMeters = if (visionDetectionState.position == VisionSensorPosition.NOSE +// || visionDetectionState.position == VisionSensorPosition.TAIL) { +// visionDetectionState.detectionSectors?.map { sector: ObstacleDetectionSector -> +// sector.obstacleDistanceInMeters +// }?.toTypedArray()?.min() ?: 0f +// } else { +// visionDetectionState.obstacleDistanceInMeters.toFloat() +// } +// +// return when { +// distanceInMeters < 2.5 -> ObstacleAvoidanceLevel.LEVEL_3 +// distanceInMeters < 5 -> ObstacleAvoidanceLevel.LEVEL_2 +// distanceInMeters < 10 -> ObstacleAvoidanceLevel.LEVEL_1 +// else -> ObstacleAvoidanceLevel.NONE +// } +// } +// +// private fun getMinDistance(distances: IntArray): Int { +// return distances.filter { it in 1..60000 }.min() ?: Int.MAX_VALUE +// } +// //endregion +// +// //region Classes +// /** +// * The proximity of obstacles +// */ +// enum class ObstacleAvoidanceLevel(@get:JvmName("value") val value: Int) { +// +// /** +// * No obstacles are detected +// */ +// NONE(0), +// +// /** +// * Obstacle is detected far away +// */ +// LEVEL_1(1), +// +// /** +// * Obstacle is detected close by +// */ +// LEVEL_2(2), +// +// /** +// * Obstacle is detected very close by +// */ +// LEVEL_3(3); +// +// companion object { +// @JvmStatic +// val values = values() +// +// @JvmStatic +// fun find(value: Int): ObstacleAvoidanceLevel { +// return values.find { it.value == value } ?: NONE +// } +// } +// } + //endregion + + override fun inSetup() { + //暂无实现 + } + + override fun inCleanup() { + //暂无实现 + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/radar/SingleAngleRadarSectionViewHolder.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/radar/SingleAngleRadarSectionViewHolder.kt new file mode 100644 index 00000000..792dd6da --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/radar/SingleAngleRadarSectionViewHolder.kt @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.radar + +import android.graphics.drawable.Drawable +import android.view.View +import android.widget.ImageView +import android.widget.TextView + +import androidx.annotation.IdRes + + +/** + * Represents a section of the obstacle detection radar that has a single segment. + */ +class SingleAngleRadarSectionViewHolder( + @IdRes imageId: Int, + @IdRes distanceId: Int, + @IdRes arrowId: Int, + parent: View +) : RadarSectionViewHolder() { + + override val distance: TextView = parent.findViewById(distanceId) + override val arrow: ImageView = parent.findViewById(arrowId) + private val radarImage: ImageView = parent.findViewById(imageId) + + init { + hide() + } + + override fun hide() { + radarImage.visibility = View.GONE + distance.visibility = View.GONE + arrow.visibility = View.GONE + } + + + override fun setImages(images: Array) { + radarImage.setImageDrawable(images[0]) + } + +// override fun setSectors(sectors: Array?, unitStr: String?) { +// val warningLevel = sectors?.get(0)?.warningLevel +// if (warningLevel == ObstacleDetectionSectorWarning.LEVEL_1 +// || warningLevel == ObstacleDetectionSectorWarning.LEVEL_2) { +// show() +// radarImage.setImageLevel(warningLevel.value()) +// } else { +// hide() +// } +// } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/remainingflighttime/RemainingFlightTimeWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/remainingflighttime/RemainingFlightTimeWidget.kt new file mode 100644 index 00000000..763788bb --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/remainingflighttime/RemainingFlightTimeWidget.kt @@ -0,0 +1,506 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.remainingflighttime + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.* +import android.util.AttributeSet +import android.view.View +import androidx.core.content.res.use +import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.disposables.Disposable +import io.reactivex.rxjava3.functions.BiFunction +import io.reactivex.rxjava3.functions.Consumer +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.widget.FrameLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getColorAndUse +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.util.UxErrorHandle +import dji.v5.ux.core.widget.remainingflighttime.RemainingFlightTimeWidget.ModelState +import dji.v5.ux.core.widget.remainingflighttime.RemainingFlightTimeWidget.ModelState.* +import dji.v5.ux.core.widget.remainingflighttime.RemainingFlightTimeWidgetModel.RemainingFlightTimeData + +/** + * Remaining Flight Time Widget + * + * Widget shows the remaining flight time graphically. Data displayed includes + * + * 1. Battery charge remaining in percentage + * 2. Battery required for the aircraft to return home + * 3. Battery required for the aircraft to land + * 4. Remaining flight time + * 5. Serious low battery threshold level + * 6. Low battery threshold level + */ +open class RemainingFlightTimeWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : FrameLayoutWidget( + context, + attrs, + defStyleAttr +) { + + private val widgetModel by lazy { + RemainingFlightTimeWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()) + } + private val batteryRequiredToLandPaint: Paint = Paint() + private val batteryChargeRemainingPaint: Paint = Paint() + private val batteryRequiredToGoHomePaint: Paint = Paint() + private val flightTimeRoundedBackgroundPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG) + private val flightTimeTextPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG) + private val lowBatteryThresholdDotPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG) + private val seriousLowBatteryThresholdDotPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG) + private val homePointBackgroundPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG) + private val homeLetterPaint: Paint = Paint(Paint.ANTI_ALIAS_FLAG) + private var flightTimeText: String = DISCONNECTED_STRING + private val flightTimeTextBounds: Rect = Rect() + private val homeLetterBounds: Rect = Rect() + private var batteryRequiredToLandPercentage = 0f + private var remainingBatteryChargePercentage = 0f + private var batteryRequiredToGoHomePercentage = 0f + private var seriousLowBatteryThresholdPercentage = 0f + private var lowBatteryThresholdPercentage = 0f + private var viewHeight = 0f + private var usableViewWidth = 0f + private var homeLetterWidth = 0f + + //region customizable fields + + /** + * Color representing flight time available in battery + */ + var batteryChargeRemainingColor: Int + get() = batteryChargeRemainingPaint.color + set(color) { + batteryChargeRemainingPaint.color = color + invalidate() + } + + /** + * Color representing flight time available in battery + * for the aircraft to return home + */ + var batteryToReturnHomeColor: Int + get() = batteryRequiredToGoHomePaint.color + set(color) { + batteryRequiredToGoHomePaint.color = color + invalidate() + } + + /** + * Color representing flight time available in battery + * for the aircraft to land + */ + var batteryRequiredToLandColor: Int + get() = batteryRequiredToLandPaint.color + set(color) { + batteryRequiredToLandPaint.color = color + invalidate() + } + + /** + * Color for the serious low battery level threshold indicator dot + */ + var seriousLowBatteryThresholdDotColor: Int + get() = seriousLowBatteryThresholdDotPaint.color + set(color) { + seriousLowBatteryThresholdDotPaint.color = color + invalidate() + } + + /** + * Color for the low battery level threshold indicator dot + */ + var lowBatteryThresholdDotColor: Int + get() = lowBatteryThresholdDotPaint.color + set(color) { + lowBatteryThresholdDotPaint.color = color + invalidate() + } + + /** + * Color for the flight time text + */ + var flightTimeTextColor: Int + get() = flightTimeTextPaint.color + set(color) { + flightTimeTextPaint.color = color + invalidate() + } + + /** + * Background color for flight time text + */ + var flightTimeBackgroundColor: Int + get() = flightTimeRoundedBackgroundPaint.color + set(color) { + flightTimeRoundedBackgroundPaint.color = color + invalidate() + } + + /** + * Color for home letter + */ + var homeLetterColor: Int + get() = homeLetterPaint.color + set(color) { + homeLetterPaint.color = color + invalidate() + } + + /** + * Background color for home letter + */ + var homeLetterBackgroundColor: Int + get() = homePointBackgroundPaint.color + set(color) { + homePointBackgroundPaint.color = color + invalidate() + } + + //endregion + + //region Lifecycle + + init { + setWillNotDraw(false) + initDefaults() + if (attrs != null) { + initAttributes(context, attrs) + } + } + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + // No Layout to init + } + + override fun onDraw(canvas: Canvas) { + val homeLetter = getString(R.string.uxsdk_home_location_letter) + if (viewHeight == 0f) { // Initialize stuff based on View's dimension + viewHeight = height.toFloat() + // Not getting the whole width so it would not touch the edge of the screen + // This is to leave some room in the end for the rounded white background of FlightTime + usableViewWidth = width.toFloat() + batteryRequiredToLandPaint.strokeWidth = viewHeight / 6f + batteryChargeRemainingPaint.strokeWidth = viewHeight / 6f + batteryRequiredToGoHomePaint.strokeWidth = viewHeight / 6f + flightTimeRoundedBackgroundPaint.strokeWidth = viewHeight / 1.1f + seriousLowBatteryThresholdDotPaint.strokeWidth = viewHeight / 2.4f + lowBatteryThresholdDotPaint.strokeWidth = viewHeight / 2.4f + homePointBackgroundPaint.strokeWidth = viewHeight / 1.6f + flightTimeTextPaint.textSize = viewHeight / 1.5f + homeLetterPaint.textSize = viewHeight / 2.5f + homeLetterWidth = homeLetterPaint.measureText(homeLetter) + homeLetterPaint.getTextBounds(homeLetter, 0, 1, homeLetterBounds) + flightTimeTextPaint.getTextBounds(flightTimeText, 0, 1, flightTimeTextBounds) + } else { + val textWidth = flightTimeTextPaint.measureText(flightTimeText) + val roundedBgWidth = textWidth * 1.55f + // Draw remaining flight time based on battery charge + canvas.drawLine(0f, + viewHeight / 2f, + usableViewWidth * remainingBatteryChargePercentage / 100f - roundedBgWidth / 2, + viewHeight / 2f, + batteryChargeRemainingPaint) + // Draw flight time to go home + if (batteryRequiredToGoHomePercentage <= remainingBatteryChargePercentage) { + canvas.drawLine(0f, + viewHeight / 2f, + usableViewWidth * batteryRequiredToGoHomePercentage / 100f - roundedBgWidth / 2, + viewHeight / 2f, batteryRequiredToGoHomePaint) + } else { + canvas.drawLine(0f, + viewHeight / 2f, + usableViewWidth * remainingBatteryChargePercentage / 100f - roundedBgWidth / 2, + viewHeight / 2f, batteryRequiredToGoHomePaint) + } + + // Draw flight time to land immediately + if (batteryRequiredToLandPercentage <= remainingBatteryChargePercentage) { + canvas.drawLine(0f, + viewHeight / 2f, + usableViewWidth * batteryRequiredToLandPercentage / 100f - roundedBgWidth / 2, + viewHeight / 2f, batteryRequiredToLandPaint) + } else { + canvas.drawLine(0f, + viewHeight / 2f, + usableViewWidth * remainingBatteryChargePercentage / 100f - roundedBgWidth / 2, + viewHeight / 2f, batteryRequiredToLandPaint) + } + // Draw serious low battery level indicator + if (seriousLowBatteryThresholdPercentage <= remainingBatteryChargePercentage) { + canvas.drawPoint(usableViewWidth * seriousLowBatteryThresholdPercentage / 100f - roundedBgWidth / 2, + viewHeight / 2f, seriousLowBatteryThresholdDotPaint) + } + // Draw low battery level indicator + if (lowBatteryThresholdPercentage <= remainingBatteryChargePercentage) { + canvas.drawPoint(usableViewWidth * lowBatteryThresholdPercentage / 100f - roundedBgWidth / 2, + viewHeight / 2f, lowBatteryThresholdDotPaint) + } + + // Draw battery left for time to home point indicator + if (batteryRequiredToGoHomePercentage <= remainingBatteryChargePercentage) { + // Draw H letter background + canvas.drawPoint(usableViewWidth * batteryRequiredToGoHomePercentage / 100f - roundedBgWidth / 2, + viewHeight / 2f, homePointBackgroundPaint) + // Draw H letter + canvas.drawText(homeLetter, + usableViewWidth * batteryRequiredToGoHomePercentage / 100f - homeLetterWidth / 2f - roundedBgWidth / 2, + viewHeight / 2f + homeLetterBounds.height() / 2f, + homeLetterPaint) + } else { + // Draw H letter background + + canvas.drawPoint(usableViewWidth * remainingBatteryChargePercentage / 100f - roundedBgWidth / 2, + viewHeight / 2f, homePointBackgroundPaint) + // Draw H letter + canvas.drawText(homeLetter, + usableViewWidth * remainingBatteryChargePercentage / 100f - homeLetterWidth / 2f - roundedBgWidth / 2, + viewHeight / 2f + homeLetterBounds.height() / 2f, + homeLetterPaint) + } + drawFlightText(canvas, roundedBgWidth, textWidth) + } + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { isProductConnected: Boolean -> updateVisibility(isProductConnected) }) + addReaction(reactToRemainingFlightTimeChange()) + addReaction(widgetModel.isAircraftFlying + .observeOn(SchedulerProvider.io()) + .subscribe { + widgetStateDataProcessor.onNext(AircraftFlyingUpdated(it)) + }) + addReaction(widgetModel.remainingFlightTimeData + .observeOn(SchedulerProvider.io()) + .subscribe { + widgetStateDataProcessor.onNext( + FlightTimeDataUpdated(it)) + }) + } + + override fun getIdealDimensionRatioString(): String { + return getString(R.string.uxsdk_widget_remaining_flight_time_ratio) + } + + //endregion + + //region private methods + + private fun updateVisibility(isProductConnected: Boolean) { + widgetStateDataProcessor.onNext(ProductConnected(isProductConnected)) + visibility = if (isProductConnected) View.VISIBLE else View.GONE + } + + private fun drawFlightText(canvas: Canvas, roundedBgWidth: Float, textWidth: Float) { + flightTimeRoundedBackgroundPaint.strokeCap = Paint.Cap.ROUND + val start = if (usableViewWidth * remainingBatteryChargePercentage / 100f - roundedBgWidth > 0) usableViewWidth * remainingBatteryChargePercentage / 100f - roundedBgWidth / 2 - textWidth / 2.5f else flightTimeRoundedBackgroundPaint.strokeWidth / 2.0f + val end = if (usableViewWidth * remainingBatteryChargePercentage / 100f - roundedBgWidth > 0) usableViewWidth * remainingBatteryChargePercentage / 100f - roundedBgWidth / 2 + textWidth / 2.5f else roundedBgWidth / 2 + textWidth / 2.5f + val textStart = if (usableViewWidth * remainingBatteryChargePercentage / 100f - roundedBgWidth > 0) usableViewWidth * remainingBatteryChargePercentage / 100f - roundedBgWidth / 2 - textWidth / 2 else flightTimeRoundedBackgroundPaint.strokeWidth / 2.5f + canvas.drawPoint(start, + viewHeight / 2f, flightTimeRoundedBackgroundPaint) + canvas.drawPoint(end, viewHeight / 2f, flightTimeRoundedBackgroundPaint) + canvas.drawLine(start, viewHeight / 2f, end, viewHeight / 2f, + flightTimeRoundedBackgroundPaint) + canvas.drawText(flightTimeText, + textStart, + viewHeight / 2f + if (flightTimeTextBounds.height() > homeLetterBounds.height()) flightTimeTextBounds.height() / 2.5f else homeLetterBounds.height() / 1.5f, + flightTimeTextPaint) + } + + + private fun reactToRemainingFlightTimeChange(): Disposable { + return Flowable.combineLatest(widgetModel.isAircraftFlying, + widgetModel.remainingFlightTimeData, + BiFunction { first: Boolean, second: RemainingFlightTimeData -> Pair(first, second) }) + .observeOn(SchedulerProvider.ui()) + .subscribe(Consumer { values: Pair -> onRemainingFlightTimeChange(values.first, values.second) }, + UxErrorHandle.logErrorConsumer(TAG, "react to flight time update: ")) + } + + private fun onRemainingFlightTimeChange(isAircraftFlying: Boolean, + remainingFlightTimeData: RemainingFlightTimeData) { + flightTimeText = if (isAircraftFlying) { + getFormattedString(remainingFlightTimeData.flightTime) + } else { + DISCONNECTED_STRING + } + + batteryRequiredToLandPercentage = remainingFlightTimeData.batteryNeededToLand.toFloat() + batteryRequiredToGoHomePercentage = remainingFlightTimeData.batteryNeededToGoHome.toFloat() + remainingBatteryChargePercentage = remainingFlightTimeData.remainingCharge.toFloat() + seriousLowBatteryThresholdPercentage = remainingFlightTimeData.seriousLowBatteryThreshold.toFloat() + lowBatteryThresholdPercentage = remainingFlightTimeData.lowBatteryThreshold.toFloat() + invalidate() + } + + private fun getFormattedString(flightTime: Int): String { + return if (flightTime / MINUTE_CONVERSION_CONSTANT > 59) { + String.format(HOUR_FLIGHT_TIME_FORMAT_STRING, + flightTime / HOUR_CONVERSION_CONSTANT, + flightTime / HOUR_CONVERSION_CONSTANT % MINUTE_CONVERSION_CONSTANT, + flightTime % HOUR_CONVERSION_CONSTANT % MINUTE_CONVERSION_CONSTANT) + } else { + String.format(MINUTE_FLIGHT_TIME_FORMAT_STRING, + flightTime / MINUTE_CONVERSION_CONSTANT, + flightTime % MINUTE_CONVERSION_CONSTANT) + } + } + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.RemainingFlightTimeWidget).use { typedArray -> + typedArray.getColorAndUse(R.styleable.RemainingFlightTimeWidget_uxsdk_homeLetterBackgroundColor) { + homeLetterBackgroundColor = it + } + typedArray.getColorAndUse(R.styleable.RemainingFlightTimeWidget_uxsdk_homeLetterColor) { + homeLetterColor = it + } + typedArray.getColorAndUse(R.styleable.RemainingFlightTimeWidget_uxsdk_flightTimeBackgroundColor) { + flightTimeBackgroundColor = it + } + typedArray.getColorAndUse(R.styleable.RemainingFlightTimeWidget_uxsdk_flightTimeTextColor) { + flightTimeTextColor = it + } + typedArray.getColorAndUse(R.styleable.RemainingFlightTimeWidget_uxsdk_lowBatteryThresholdColor) { + lowBatteryThresholdDotColor = it + } + typedArray.getColorAndUse(R.styleable.RemainingFlightTimeWidget_uxsdk_seriousLowBatteryThresholdColor) { + seriousLowBatteryThresholdDotColor = it + } + typedArray.getColorAndUse(R.styleable.RemainingFlightTimeWidget_uxsdk_batteryRequiredToLandColor) { + batteryRequiredToLandColor = it + } + typedArray.getColorAndUse(R.styleable.RemainingFlightTimeWidget_uxsdk_batteryRequiredToGoHomeColor) { + batteryToReturnHomeColor = it + } + typedArray.getColorAndUse(R.styleable.RemainingFlightTimeWidget_uxsdk_batteryChargeRemainingColor) { + batteryChargeRemainingColor = it + } + } + } + + private fun initDefaults() { + batteryRequiredToLandPaint.color = Color.RED + batteryRequiredToLandPaint.style = Paint.Style.STROKE + batteryRequiredToLandPaint.strokeCap = Paint.Cap.SQUARE + + batteryChargeRemainingPaint.color = Color.GREEN + batteryChargeRemainingPaint.style = Paint.Style.STROKE + batteryChargeRemainingPaint.strokeCap = Paint.Cap.SQUARE + + batteryRequiredToGoHomePaint.color = Color.YELLOW + batteryRequiredToGoHomePaint.style = Paint.Style.STROKE + batteryRequiredToGoHomePaint.strokeCap = Paint.Cap.SQUARE + + flightTimeRoundedBackgroundPaint.color = Color.WHITE + flightTimeRoundedBackgroundPaint.style = Paint.Style.STROKE + flightTimeRoundedBackgroundPaint.strokeCap = Paint.Cap.ROUND + + flightTimeTextPaint.color = Color.BLACK + flightTimeTextPaint.style = Paint.Style.FILL + + seriousLowBatteryThresholdDotPaint.color = Color.WHITE + seriousLowBatteryThresholdDotPaint.style = Paint.Style.STROKE + seriousLowBatteryThresholdDotPaint.strokeCap = Paint.Cap.ROUND + + lowBatteryThresholdDotPaint.color = Color.WHITE + lowBatteryThresholdDotPaint.style = Paint.Style.STROKE + lowBatteryThresholdDotPaint.strokeCap = Paint.Cap.ROUND + + homeLetterPaint.color = Color.BLACK + homeLetterPaint.style = Paint.Style.FILL + homeLetterPaint.typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD) + + homePointBackgroundPaint.color = Color.YELLOW + homePointBackgroundPaint.style = Paint.Style.STROKE + homePointBackgroundPaint.strokeCap = Paint.Cap.ROUND + } + + //endregion + + //region Hooks + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines the widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Aircraft flying status change update + */ + data class AircraftFlyingUpdated(val isAircraftFlying: Boolean) : ModelState() + + /** + * Remaining flight time data update + */ + data class FlightTimeDataUpdated(val remainingFlightTimeData: RemainingFlightTimeData) : ModelState() + + } + //endregion + + companion object { + private const val TAG = "FlightTimeWidget" + private const val DISCONNECTED_STRING = "--:--" + private const val MINUTE_FLIGHT_TIME_FORMAT_STRING = "%02d:%02d" + private const val HOUR_FLIGHT_TIME_FORMAT_STRING = "%01d:%02d:%02d" + private const val MINUTE_CONVERSION_CONSTANT = 60 + private const val HOUR_CONVERSION_CONSTANT = 3600 + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/remainingflighttime/RemainingFlightTimeWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/remainingflighttime/RemainingFlightTimeWidgetModel.kt new file mode 100644 index 00000000..ff88a87a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/remainingflighttime/RemainingFlightTimeWidgetModel.kt @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.remainingflighttime + +import dji.sdk.keyvalue.key.BatteryKey +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.value.flightcontroller.LowBatteryRTHInfo +import dji.sdk.keyvalue.key.KeyTools +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Flowable + +/** + * Remaining Flight Time Widget Model + * + * + * Widget Model for the [RemainingFlightTimeWidget] used to define the + * underlying logic and communication + */ +class RemainingFlightTimeWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + //region Fields + private val chargeRemainingProcessor: DataProcessor = DataProcessor.create(0) + private val goHomeAssessmentProcessor = DataProcessor.create(LowBatteryRTHInfo()) + + private val seriousLowBatteryThresholdProcessor: DataProcessor = DataProcessor.create(0) + private val lowBatteryThresholdProcessor: DataProcessor = DataProcessor.create(0) + private val remainingFlightProcessor: DataProcessor = DataProcessor.create(0) + private val remainingFlightTimeDataProcessor: DataProcessor = + DataProcessor.create( + RemainingFlightTimeData( + 0, 0, + 0, 0, 0, 0 + ) + ) + private val isAircraftFlyingDataProcessor: DataProcessor = DataProcessor.create(false) + + //endregi\ + + override fun inSetup() { + // For total percentage and flight time + + bindDataProcessor( + KeyTools.createKey( + BatteryKey.KeyChargeRemainingInPercent), chargeRemainingProcessor) + + // For red bar batteryPercentNeededToLand + // For H image and yellow bar batteryPercentNeededToGoHome + // For flight time text remainingFlightTime + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyLowBatteryRTHInfo), goHomeAssessmentProcessor) + + // For white dot on the left + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeySeriousLowBatteryWarningThreshold), seriousLowBatteryThresholdProcessor) + + // For white dot on the right + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyLowBatteryWarningThreshold), lowBatteryThresholdProcessor) + + // To check if aircraft is flying + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyIsFlying), isAircraftFlyingDataProcessor) + } + + override fun inCleanup() { // No Clean up required + } + + override fun updateStates() { + val remainingFlightTimeData = RemainingFlightTimeData( + chargeRemainingProcessor.value, + goHomeAssessmentProcessor.value.batteryPercentNeededToLand, + goHomeAssessmentProcessor.value.batteryPercentNeededToGoHome, + seriousLowBatteryThresholdProcessor.value, + lowBatteryThresholdProcessor.value, + goHomeAssessmentProcessor.value.remainingFlightTime + ) + remainingFlightTimeDataProcessor.onNext(remainingFlightTimeData) + } + + //region Data + /** + * Get the latest data for remaining flight based on battery level + */ + val remainingFlightTimeData: Flowable + get() = remainingFlightTimeDataProcessor.toFlowable() + + /** + * Check to see if aircraft is flying + */ + val isAircraftFlying: Flowable + get() = isAircraftFlyingDataProcessor.toFlowable() + + //endregion + /** + * Class representing data for remaining flight time + */ + data class RemainingFlightTimeData( + /** + * Remaining battery charge in percent + */ + val remainingCharge: Int, + + /** + * Battery charge required to land + */ + val batteryNeededToLand: Int, + + /** + * Battery charge needed to go home + */ + val batteryNeededToGoHome: Int, + + /** + * Serious low battery level threshold + */ + val seriousLowBatteryThreshold: Int, + + /** + * Low battery level threshold + */ + val lowBatteryThreshold: Int, + + /** + * Flight time in micro seconds + */ + val flightTime: Int + ) + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/remotecontrollersignal/RemoteControllerSignalWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/remotecontrollersignal/RemoteControllerSignalWidget.kt new file mode 100644 index 00000000..737cdc83 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/remotecontrollersignal/RemoteControllerSignalWidget.kt @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.remotecontrollersignal + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.PorterDuff +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.widget.ImageView +import androidx.annotation.ColorInt +import androidx.annotation.DrawableRes +import androidx.annotation.IntRange +import androidx.core.content.res.use +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.SchedulerProvider +import io.reactivex.rxjava3.functions.Consumer +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.util.UxErrorHandle +import dji.v5.ux.core.widget.remotecontrollersignal.RemoteControllerSignalWidget.ModelState +import dji.v5.ux.core.widget.remotecontrollersignal.RemoteControllerSignalWidget.ModelState.ProductConnected +import dji.v5.ux.core.widget.remotecontrollersignal.RemoteControllerSignalWidget.ModelState.SignalQualityUpdated + +/** + * This widget shows the strength of the signal between the RC and the aircraft. + */ +open class RemoteControllerSignalWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ConstraintLayoutWidget(context, attrs, defStyleAttr) { + + //region Fields + private val rcIconImageView: ImageView = findViewById(R.id.imageview_rc_icon) + private val rcSignalImageView: ImageView = findViewById(R.id.imageview_rc_signal) + private val widgetModel by lazy { + RemoteControllerSignalWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()) + } + + /** + * The color of the RC icon when the product is connected + */ + @get:ColorInt + var connectedStateIconColor: Int = getColor(R.color.uxsdk_white) + set(@ColorInt value) { + field = value + checkAndUpdateIconColor() + } + + /** + * The color of the RC icon when the product is disconnected + */ + @get:ColorInt + var disconnectedStateIconColor: Int = getColor(R.color.uxsdk_gray_58) + set(@ColorInt value) { + field = value + checkAndUpdateIconColor() + } + + /** + * Drawable for the RC icon + */ + var rcIcon: Drawable? + @JvmName("getRCIcon") + get() = rcIconImageView.drawable + @JvmName("setRCIcon") + set(value) { + rcIconImageView.imageDrawable = value + } + + /** + * Background drawable resource for the RC icon + */ + var rcIconBackground: Drawable? + @JvmName("getRCIconBackground") + get() = rcIconImageView.background + @JvmName("setRCIconBackground") + set(value) { + rcIconImageView.background = value + } + + /** + * Drawable resource for the RC signal icon + */ + var rcSignalIcon: Drawable? + @JvmName("getRCSignalIcon") + get() = rcSignalImageView.drawable + @JvmName("setRCSignalIcon") + set(value) { + rcSignalImageView.imageDrawable = value + } + + /** + * Drawable resource for the RC signal icon's background + */ + var rcSignalIconBackground: Drawable? + @JvmName("getRCSignalIconBackground") + get() = rcSignalImageView.background + @JvmName("setRCSignalIconBackground") + set(value) { + rcSignalImageView.background = value + } + //endregion + + //region Constructor + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + inflate(context, R.layout.uxsdk_widget_remote_controller_signal, this) + } + + init { + attrs?.let { initAttributes(context, it) } + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.rcSignalQuality + .observeOn(SchedulerProvider.ui()) + .subscribe { this.updateRCSignal(it) }) + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { this.updateIconColor(it) }) + } + //endregion + + //region Reactions to model + private fun updateRCSignal(@IntRange(from = 0, to = 100) rcSignalQuality: Int) { + rcSignalImageView.setImageLevel(rcSignalQuality) + widgetStateDataProcessor.onNext(SignalQualityUpdated(rcSignalQuality)) + } + + private fun updateIconColor(isConnected: Boolean) { + if (isConnected) { + rcIconImageView.setColorFilter(connectedStateIconColor, PorterDuff.Mode.SRC_IN) + } else { + rcIconImageView.setColorFilter(disconnectedStateIconColor, PorterDuff.Mode.SRC_IN) + } + widgetStateDataProcessor.onNext(ProductConnected(isConnected)) + } + //endregion + + //region helpers + private fun checkAndUpdateIconColor() { + if (!isInEditMode) { + addDisposable(widgetModel.productConnection.firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(Consumer { this.updateIconColor(it) }, UxErrorHandle.logErrorConsumer(TAG, "Update Icon Color "))) + } + } + //endregion + + //region Customization + override fun getIdealDimensionRatioString() = null + + /** + * Set the [resourceId] for the RC icon + * + * @param resourceId Integer ID of the drawable resource + */ + fun setRCIcon(@DrawableRes resourceId: Int) { + rcIcon = getDrawable(resourceId) + } + + /** + * Set the [resourceId] for the RC icon's background + * + * @param resourceId Integer ID of the background resource + */ + fun setRCIconBackground(@DrawableRes resourceId: Int) { + rcIconBackground = getDrawable(resourceId) + } + + /** + * Set the [resourceId] for the RC signal icon + * + * @param resourceId Integer ID of the drawable resource + */ + fun setRCSignalIcon(@DrawableRes resourceId: Int) { + rcSignalIcon = getDrawable(resourceId) + } + + /** + * Set the [resourceId] for the RC signal icon's background + * + * @param resourceId Integer ID of the background resource + */ + fun setRCSignalIconBackground(@DrawableRes resourceId: Int) { + rcSignalIconBackground = getDrawable(resourceId) + } + + //Initialize all customizable attributes + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.RemoteControllerSignalWidget).use { typedArray -> + typedArray.getDrawableAndUse(R.styleable.RemoteControllerSignalWidget_uxsdk_rcIcon) { + rcIcon = it + } + typedArray.getDrawableAndUse(R.styleable.RemoteControllerSignalWidget_uxsdk_rcSignalIcon) { + this.rcSignalIcon = it + } + connectedStateIconColor = typedArray.getColor(R.styleable.RemoteControllerSignalWidget_uxsdk_connectedStateIconColor, + connectedStateIconColor) + disconnectedStateIconColor = typedArray.getColor(R.styleable.RemoteControllerSignalWidget_uxsdk_disconnectedStateIconColor, + disconnectedStateIconColor) + } + } + //endregion + + //region Hooks + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines the widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Signal quality update + */ + data class SignalQualityUpdated(val signalValue: Int) : ModelState() + } + //endregion + + companion object { + private const val TAG = "RCSignalWidget" + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/remotecontrollersignal/RemoteControllerSignalWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/remotecontrollersignal/RemoteControllerSignalWidgetModel.kt new file mode 100644 index 00000000..c6bacc9c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/remotecontrollersignal/RemoteControllerSignalWidgetModel.kt @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.remotecontrollersignal + +import dji.sdk.keyvalue.key.AirLinkKey +import dji.sdk.keyvalue.key.KeyTools +import dji.v5.utils.common.LogUtils +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor + +/** + * Widget Model for the [RemoteControllerSignalWidget] used to define + * the underlying logic and communication + */ +class RemoteControllerSignalWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + private val tag = LogUtils.getTag("RemoteControllerSignalWidgetModel") + private val upLinkQualityRawProcessor: DataProcessor = DataProcessor.create(0) + + /** + * Get the value of the strength of the signal between the RC and the aircraft. + */ + val rcSignalQuality: Flowable + get() = upLinkQualityRawProcessor.toFlowable() + //endregion + + //region Lifecycle + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + AirLinkKey.KeyUpLinkQualityRaw), upLinkQualityRawProcessor) + } + + override fun inCleanup() { + // Nothing to clean + } + + override fun updateStates() { + //LogUtils.d(tag,"TODO Method not implemented yet") + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/setting/SettingPanelWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/setting/SettingPanelWidget.java new file mode 100644 index 00000000..284ebfe3 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/setting/SettingPanelWidget.java @@ -0,0 +1,372 @@ +package dji.v5.ux.core.widget.setting; + +import android.content.Context; +import android.text.TextUtils; +import android.util.AttributeSet; +import android.view.LayoutInflater; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.fragment.app.FragmentManager; + +import dji.sdk.keyvalue.utils.ProductUtil; +import dji.sdk.keyvalue.value.product.ProductType; +import dji.sdk.keyvalue.value.remotecontroller.RCMode; +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.R; +import dji.v5.ux.accessory.RTKStartServiceHelper; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.ui.setting.SettingFragmentPagerAdapter; +import dji.v5.ux.core.ui.setting.data.MenuBean; +import dji.v5.ux.core.ui.setting.taplayout.TabViewPager; +import dji.v5.ux.core.ui.setting.taplayout.VerticalTabLayout; +import dji.v5.ux.core.ui.setting.ui.MenuFragment; +import dji.v5.ux.core.ui.setting.ui.MenuFragmentFactory; +import dji.v5.ux.core.ui.setting.ui.SettingMenuFragment; +import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers; +import io.reactivex.rxjava3.core.Observable; +import io.reactivex.rxjava3.disposables.CompositeDisposable; +import io.reactivex.rxjava3.disposables.Disposable; + + +/** + * Description : 设置页Panel + * + * @author: Byte.Cai + * date : 2022/11/17 + *

    + * Copyright (c) 2022, DJI All Rights Reserved. + */ +public class SettingPanelWidget extends ConstraintLayoutWidget { + private final String tag = LogUtils.getTag(this); + + private ProductType mProductType = ProductType.UNKNOWN; + private ProductType mPrevProductType = ProductType.UNKNOWN; + private boolean mProductConnected; + private RCMode mCurrentRcMode = RCMode.CHANNEL_A; + + private FragmentManager fm; + private TabViewPager viewPager; + private SettingFragmentPagerAdapter mAdapter; + private List menus = new ArrayList<>(); + private List mFragments = new ArrayList<>(); + private VerticalTabLayout mTabLayout; + private Disposable mRestartDispose; + private CompositeDisposable mCompositeDisposable = new CompositeDisposable(); + + private SettingPanelWidgetModel widgetModel = new SettingPanelWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + + public SettingPanelWidget(Context context) { + this(context, null); + } + + public SettingPanelWidget(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public SettingPanelWidget(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + initializeView(); + showWidgets(); + prepareData(); + + } + + + protected void initializeView() { + LayoutInflater.from(getContext()).inflate(R.layout.uxsdk_panel_layout_setting, this, true); + setDescendantFocusability(FOCUS_AFTER_DESCENDANTS); + mTabLayout = findViewById(R.id.setting_vertical_tabLayout); + viewPager = findViewById(R.id.setting_viewpager); + viewPager.setPagingEnabled(false); + + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + + protected void prepareData() { + mCompositeDisposable.add(widgetModel.getRcModeProcessor().toFlowableOnUI().distinctUntilChanged().subscribe(rcMode -> { + if (rcMode != RCMode.UNKNOWN && rcMode != mCurrentRcMode) { + mCurrentRcMode = rcMode; + updateData(rcMode); + } + })); + + mPrevProductType = widgetModel.getProduceType(); + mCompositeDisposable.add(widgetModel.getProductTypeProcessor().toFlowableOnUI().distinctUntilChanged().subscribe(productType -> mProductType = productType)); + + mProductConnected = widgetModel.getFlightControllerConnectStatus(); + mCompositeDisposable.add(widgetModel.getFlightControllerConnectProcessor().toFlowableOnUI().distinctUntilChanged().subscribe(connection -> { + if (connection != mProductConnected) { + mProductConnected = connection; + if (mProductConnected && mProductType != ProductType.UNKNOWN && mPrevProductType != mProductType) { + delayRestartPanel(); + mPrevProductType = mProductType; + } + } + })); + + mCompositeDisposable.add(RTKStartServiceHelper.INSTANCE.getRtkModuleAvailable().distinctUntilChanged().observeOn(AndroidSchedulers.mainThread()).subscribe(aBoolean -> { + if (isSupportAdvRtk(aBoolean)) { + mAdapter.addRTKPanel(); + } else { + mAdapter.removeRTKPanel(); + } + })); + + mCompositeDisposable.add(widgetModel.getPayloadConnectedStatusMapProcessor().toFlowableOnUI().subscribe(payloadIndexTypeBooleanHashMap -> { + if (payloadIndexTypeBooleanHashMap.isEmpty()) { + mAdapter.removePayloadPanel(); + } else { + mAdapter.addPayloadPanel(); + } + + })); + + } + + + protected void showWidgets() { + fm = ((FragmentActivity) getContext()).getSupportFragmentManager(); + if (isSlaverRcMode(mCurrentRcMode)) { + createSlaverFragments(); + } else { + createMasterFragments(); + } + mAdapter = new SettingFragmentPagerAdapter(fm, menus, mFragments); + viewPager.setAdapter(mAdapter); + mTabLayout.setupWithViewPager(viewPager); + + + //设置展示的默认页面,B控则展示遥控页面 + if (isSlaverRcMode(mCurrentRcMode)) { + setCurrentItem(MenuFragmentFactory.FRAGMENT_TAG_RC); + } else { + //A控展示用户上一次选中的页面 + if (!TextUtils.isEmpty(getCurrentItemFlag())) { + setCurrentItem(getCurrentItemFlag()); + } else { + //否则默认展示飞控设置页 + setCurrentItem(MenuFragmentFactory.FRAGMENT_TAG_AIRCRAFT); + } + } + mAdapter.notifyDataSetChanged(); + + } + + + @Override + protected void onDetachedFromWindow() { + destroy(); + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + } + + private void destroy() { + LogUtils.e(tag, "destroy mFragments.clear()"); + mFragments.clear(); + if (mCompositeDisposable != null && !mCompositeDisposable.isDisposed()) { + mCompositeDisposable.dispose(); + mCompositeDisposable = null; + } + if (mRestartDispose != null && !mRestartDispose.isDisposed()) { + mRestartDispose.dispose(); + } + if (viewPager != null) { + viewPager.clearOnPageChangeListeners(); + } + if (mTabLayout != null) { + mTabLayout.setupWithViewPager(null); + mTabLayout = null; + } + if (mAdapter != null) { + mAdapter.destroy(); + mAdapter = null; + } + fm = null; + mAdapter = null; + + + } + + + private void setMasterFragmentData() { + createMasterFragments(); + if (!TextUtils.isEmpty(getCurrentItemFlag())) { + setCurrentItem(getCurrentItemFlag()); + } else { + setCurrentItem(MenuFragmentFactory.FRAGMENT_TAG_AIRCRAFT); + } + mAdapter.notifyDataSetChanged(); + } + + private void createMasterFragments() { + menus.clear(); + mFragments.clear(); + + menus.add(new MenuBean(R.drawable.uxsdk_ic_setting_drone_active, R.drawable.uxsdk_ic_setting_drone)); + mFragments.add(SettingMenuFragment.newInstance(MenuFragmentFactory.FRAGMENT_TAG_AIRCRAFT)); + + menus.add(new MenuBean(R.drawable.uxsdk_ic_setting_obstacl_avoidance_active, R.drawable.uxsdk_ic_setting_obstacl_avoidance)); + mFragments.add(SettingMenuFragment.newInstance(MenuFragmentFactory.FRAGMENT_TAG_PERCEPTION)); + + menus.add(new MenuBean(R.drawable.uxsdk_ic_setting_rc_active, R.drawable.uxsdk_ic_setting_rc)); + + menus.add(new MenuBean(R.drawable.uxsdk_ic_setting_hd_active, R.drawable.uxsdk_ic_setting_hd)); + + menus.add(new MenuBean(R.drawable.uxsdk_ic_setting_plane_electricity_active, R.drawable.uxsdk_ic_setting_plane_electricity)); + + menus.add(new MenuBean(R.drawable.uxsdk_ic_setting_camera_active, R.drawable.uxsdk_ic_setting_camera)); + + mFragments.add(SettingMenuFragment.newInstance(MenuFragmentFactory.FRAGMENT_TAG_RC)); + + mFragments.add(SettingMenuFragment.newInstance(MenuFragmentFactory.FRAGMENT_TAG_HD)); + + mFragments.add(SettingMenuFragment.newInstance(MenuFragmentFactory.FRAGMENT_TAG_BATTERY)); + + mFragments.add(SettingMenuFragment.newInstance(MenuFragmentFactory.FRAGMENT_TAG_GIMBAL)); + + if (isSupportAdvRtk(false)) { + menus.add(new MenuBean(R.drawable.uxsdk_ic_setting_rtk_active, R.drawable.uxsdk_ic_setting_rtk)); + mFragments.add(SettingMenuFragment.newInstance(MenuFragmentFactory.FRAGMENT_TAG_RTK)); + } + + menus.add(new MenuBean(R.drawable.uxsdk_ic_setting_more_active, R.drawable.uxsdk_ic_setting_more)); + mFragments.add(SettingMenuFragment.newInstance(MenuFragmentFactory.FRAGMENT_TAG_COMMON)); + } + + private void setSlaverFragmentData() { + createSlaverFragments(); + setCurrentItem(MenuFragmentFactory.FRAGMENT_TAG_RC); + mAdapter.notifyDataSetChanged(); + } + + private void createSlaverFragments() { + menus.clear(); + menus.add(new MenuBean(R.drawable.uxsdk_ic_setting_rc_active, R.drawable.uxsdk_ic_setting_rc)); + menus.add(new MenuBean(R.drawable.uxsdk_ic_setting_hd_active, R.drawable.uxsdk_ic_setting_hd)); + menus.add(new MenuBean(R.drawable.uxsdk_ic_setting_plane_electricity_active, R.drawable.uxsdk_ic_setting_plane_electricity)); + menus.add(new MenuBean(R.drawable.uxsdk_ic_setting_camera_active, R.drawable.uxsdk_ic_setting_camera)); + menus.add(new MenuBean(R.drawable.uxsdk_ic_setting_more_active, R.drawable.uxsdk_ic_setting_more)); + + mFragments.clear(); + mFragments.add(SettingMenuFragment.newInstance(MenuFragmentFactory.FRAGMENT_TAG_RC)); + mFragments.add(SettingMenuFragment.newInstance(MenuFragmentFactory.FRAGMENT_TAG_HD)); + mFragments.add(SettingMenuFragment.newInstance(MenuFragmentFactory.FRAGMENT_TAG_BATTERY)); + mFragments.add(SettingMenuFragment.newInstance(MenuFragmentFactory.FRAGMENT_TAG_GIMBAL)); + mFragments.add(SettingMenuFragment.newInstance(MenuFragmentFactory.FRAGMENT_TAG_COMMON)); + } + + public void setCurrentItem(String flag) { + if (mAdapter == null) { + LogUtils.e(tag, "SettingPanel is not ready!"); + return; + } + int result = mAdapter.getSelectIndex(flag); + if (result >= 0) { + viewPager.setCurrentItem(result, true); + } + } + + public String getCurrentItemFlag() { + int result = viewPager.getCurrentItem(); + return mAdapter.getSelectFlag(result); + } + + + private void delayRestartPanel() { + if (mRestartDispose != null && !mRestartDispose.isDisposed()) { + mRestartDispose.dispose(); + } + mRestartDispose = Observable.just(true) + .delay(1, TimeUnit.SECONDS) + .observeOn(AndroidSchedulers.mainThread()) + .subscribe(aBoolean -> { + if (isSlaverRcMode(mCurrentRcMode)) { + setSlaverFragmentData(); + } else { + setMasterFragmentData(); + } + }); + } + + private void updateData(RCMode rcMode) { + if (isSlaverRcMode(rcMode)) { + setSlaverFragmentData(); + } else { + setMasterFragmentData(); + } + } + + private boolean isSlaverRcMode(RCMode mode) { + if (mode != null) { + return mode == RCMode.SLAVE || mode == RCMode.SLAVE_SUB; + } + return false; + } + + + //辅控不支持RTK + private boolean isSupportAdvRtk(Boolean isRTKModuleAvailable) { + return !isSlaverRcMode(mCurrentRcMode) && isRTKModuleAvailable || ProductUtil.isM300Product() || ProductUtil.isM30Product() || ProductUtil.isM350Product()|| ProductUtil.isM400Product(); + } + + @Override + public void onWindowFocusChanged(boolean hasWindowFocus) { + super.onWindowFocusChanged(hasWindowFocus); + } + + + /** + * 返回事件,询问fragment是否要处理返回事件 + */ + public boolean onBackPressed() { + boolean handled = false; + if (mFragments != null) { + for (Fragment fragment : mFragments) { + if (fragment instanceof MenuFragment) { + handled = ((MenuFragment) fragment).onBackPressed(); + if (handled) { + break; + } + } + } + } + + return handled; + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + //do nothing + } + + @Override + protected void reactToModelChanges() { + //do nothing + + } + + @Nullable + @Override + public String getIdealDimensionRatioString() { + return null; + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/setting/SettingPanelWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/setting/SettingPanelWidgetModel.kt new file mode 100644 index 00000000..d92c3259 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/setting/SettingPanelWidgetModel.kt @@ -0,0 +1,72 @@ +package dji.v5.ux.core.widget.setting + +import dji.sdk.keyvalue.key.* +import dji.sdk.keyvalue.value.product.ProductType +import dji.sdk.keyvalue.value.remotecontroller.RCMode +import dji.v5.et.create +import dji.v5.et.get +import dji.v5.manager.KeyManager +import dji.v5.manager.aircraft.payload.PayloadCenter +import dji.v5.manager.aircraft.payload.PayloadIndexType +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor + +/** + * Description : + * + * @author: Byte.Cai + * date : 2022/11/17 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ +class SettingPanelWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, +) : WidgetModel(djiSdkModel, keyedStore) { + private val payloadConnectStatusMap = HashMap() + val productTypeProcessor = DataProcessor.create(ProductType.UNKNOWN) + val flightControllerConnectProcessor = DataProcessor.create(false) + val rcModeProcessor = DataProcessor.create(RCMode.UNKNOWN) + val payloadConnectedStatusMapProcessor = DataProcessor.create(payloadConnectStatusMap) + + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + ProductKey.KeyProductType), productTypeProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyConnection), flightControllerConnectProcessor) + bindDataProcessor( + KeyTools.createKey( + RemoteControllerKey.KeyRcMachineMode), rcModeProcessor) + + PayloadCenter.getInstance().payloadManager.forEach { + it.value.addPayloadBasicInfoListener { payloadBasicInfo -> + run { + if (payloadBasicInfo.isConnected) { + payloadConnectStatusMap[it.key] = true + } else { + payloadConnectStatusMap.remove(it.key) + } + payloadConnectedStatusMapProcessor.onNext(payloadConnectStatusMap) + + } + } + } + } + + override fun inCleanup() { + KeyManager.getInstance().cancelListen(this) + } + + fun getFlightControllerConnectStatus(): Boolean { + return FlightControllerKey.KeyConnection.create().get(false) + } + + fun getProduceType(): ProductType { + return ProductKey.KeyProductType.create().get(ProductType.UNKNOWN) + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/setting/SettingWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/setting/SettingWidget.kt new file mode 100644 index 00000000..2dbc1792 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/setting/SettingWidget.kt @@ -0,0 +1,36 @@ +package dji.v5.ux.core.widget.setting + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import dji.v5.ux.R +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget + +/** + * Description : 左上角设置页的入口Widget + * + * @author: Byte.Cai + * date : 2022/11/17 + * + * Copyright (c) 2022, DJI All Rights Reserved. + */ + + +class SettingWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, +) : ConstraintLayoutWidget(context, attrs, defStyleAttr) { + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + View.inflate(context, R.layout.uxsdk_widget_setting, this) + } + + override fun reactToModelChanges() { + //do nothing + } + + override fun getIdealDimensionRatioString(): String? { + return null + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/simulator/SimulatorIndicatorWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/simulator/SimulatorIndicatorWidget.kt new file mode 100644 index 00000000..709b1423 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/simulator/SimulatorIndicatorWidget.kt @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.simulator + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.PorterDuff +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.util.Pair +import android.view.View +import androidx.annotation.DrawableRes +import androidx.core.content.res.use +import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.disposables.Disposable +import io.reactivex.rxjava3.functions.Consumer +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.widget.IconButtonWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.util.UxErrorHandle +import dji.v5.ux.core.widget.simulator.SimulatorIndicatorWidget.ModelState +import dji.v5.ux.core.widget.simulator.SimulatorIndicatorWidget.ModelState.ProductConnected +import dji.v5.ux.core.widget.simulator.SimulatorIndicatorWidget.ModelState.SimulatorStateUpdated + +/** + * Simulator Indicator Widget will display the current state of the simulator + * + * Simulator Indicator Widget has two states + * Active - Green icon indicates currently simulator is running on the device + * Inactive - White icon indicates simulator is currently turned off on the device + */ +open class SimulatorIndicatorWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : IconButtonWidget( + context, + attrs, + defStyleAttr +), View.OnClickListener { + + //region Fields + private var stateChangeResourceId: Int = INVALID_RESOURCE + private val widgetModel by lazy { + SimulatorIndicatorWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance() + ) + } + + /** + * The drawable resource for the simulator active icon + */ + var simulatorActiveIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_simulator_active) + set(value) { + field = value + checkAndUpdateIcon() + } + + /** + * The drawable resource for the simulator inactive icon + */ + var simulatorInactiveIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_simulator) + set(value) { + field = value + checkAndUpdateIcon() + } + + //endregion + + //region Lifecycle + init { + attrs?.let { initAttributes(context, it) } + connectedStateIconColor = getColor(R.color.uxsdk_white) + } + + override fun reactToModelChanges() { + addReaction(reactToSimulatorStateChange()) + addReaction(widgetModel.isSimulatorActive + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(SimulatorStateUpdated(it)) }) + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + } + + override fun getIdealDimensionRatioString(): String { + return getString(R.string.uxsdk_widget_default_ratio) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun checkAndUpdateIconColor() { + if (!isInEditMode) { + addDisposable(reactToSimulatorStateChange()) + } + } + + //endregion + + //region private Methods + + + private fun reactToSimulatorStateChange(): Disposable { + return Flowable.combineLatest(widgetModel.productConnection, widgetModel.isSimulatorActive, + { first: Boolean, second: Boolean -> Pair(first, second) }) + .observeOn(SchedulerProvider.ui()) + .subscribe( + Consumer { values: Pair -> updateUI(values.first, values.second) }, + UxErrorHandle.logErrorConsumer(TAG, "react to Focus Mode Change: ") + ) + } + + private fun updateUI(isConnected: Boolean, isActive: Boolean) { + if (isConnected && isActive) { + foregroundImageView.imageDrawable = simulatorActiveIcon + foregroundImageView.clearColorFilter() + } else if (isConnected) { + foregroundImageView.imageDrawable = simulatorInactiveIcon + foregroundImageView.setColorFilter(connectedStateIconColor, PorterDuff.Mode.SRC_IN) + + } else { + foregroundImageView.imageDrawable = simulatorInactiveIcon + foregroundImageView.setColorFilter(disconnectedStateIconColor, PorterDuff.Mode.SRC_IN) + + } + } + + + private fun checkAndUpdateIcon() { + if (!isInEditMode) { + addDisposable(reactToSimulatorStateChange()) + } + } + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.SimulatorIndicatorWidget).use { typedArray -> + typedArray.getResourceIdAndUse(R.styleable.SimulatorIndicatorWidget_uxsdk_onStateChange) { + stateChangeResourceId = it + } + typedArray.getDrawableAndUse(R.styleable.SimulatorIndicatorWidget_uxsdk_simulatorActiveDrawable) { + simulatorActiveIcon = it + } + typedArray.getDrawableAndUse(R.styleable.SimulatorIndicatorWidget_uxsdk_simulatorInactiveDrawable) { + simulatorInactiveIcon = it + } + } + } + //endregion + + //region customizations + + /** + * Set the resource ID for the simulator active icon + * + * @param resourceId Integer ID of the drawable resource + */ + fun setSimulatorActiveIcon(@DrawableRes resourceId: Int) { + simulatorActiveIcon = getDrawable(resourceId) + } + + /** + * Set the resource ID for the simulator inactive icon + * + * @param resourceId Integer ID of the drawable resource + */ + fun setSimulatorInactiveIcon(@DrawableRes resourceId: Int) { + simulatorInactiveIcon = getDrawable(resourceId) + } + + //endregion + + //region Hooks + + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines the widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Simulator State update + */ + data class SimulatorStateUpdated(val isActive: Boolean) : ModelState() + } + //endregion + + companion object { + private const val TAG = "SimulatorIndWidget" + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/simulator/SimulatorIndicatorWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/simulator/SimulatorIndicatorWidgetModel.kt new file mode 100644 index 00000000..487edf74 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/simulator/SimulatorIndicatorWidgetModel.kt @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.simulator + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.key.KeyTools +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor + +/** + * Simulator Indicator Widget Model + * + * + * Widget Model for the [SimulatorIndicatorWidget] used to define the + * underlying logic and communication + */ +class SimulatorIndicatorWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + + private val isSimulatorStartedProcessor: DataProcessor = DataProcessor.create(false) + + /** + * Check if the simulator is running + */ + val isSimulatorActive: Flowable + get() = isSimulatorStartedProcessor.toFlowable() + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyIsSimulatorStarted), isSimulatorStartedProcessor) + } + + override fun inCleanup() { + // No Clean up required + } + + override fun updateStates() { + // No States + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/systemstatus/SystemStatusWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/systemstatus/SystemStatusWidget.kt new file mode 100644 index 00000000..56f7e395 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/systemstatus/SystemStatusWidget.kt @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.systemstatus + +import android.annotation.SuppressLint +import android.content.Context +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.util.Pair +import android.view.animation.Animation +import android.view.animation.AnimationUtils +import android.widget.ImageView +import android.widget.TextView +import androidx.annotation.ColorInt +import androidx.annotation.Dimension +import androidx.annotation.StyleRes +import androidx.core.content.res.use +import dji.v5.manager.diagnostic.DJIDeviceStatus +import dji.v5.manager.diagnostic.WarningLevel +import dji.v5.utils.common.DisplayUtil +import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.disposables.Disposable +import io.reactivex.rxjava3.functions.Consumer +import io.reactivex.rxjava3.processors.PublishProcessor +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.GlobalPreferencesManager +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.util.UxErrorHandle +import dji.v5.ux.core.util.UnitConversionUtil +import dji.v5.ux.core.widget.systemstatus.SystemStatusWidget.ModelState +import dji.v5.ux.core.widget.systemstatus.SystemStatusWidget.ModelState.ProductConnected +import dji.v5.ux.core.widget.systemstatus.SystemStatusWidget.ModelState.SystemStatusUpdated +import java.util.* + +private const val TAG = "SystemStatusWidget" + +/** + * This widget shows the system status of the aircraft. + * + * The WarningStatusItem received by this widget contains the message to be + * displayed, the warning level and the urgency of the message. + * + * The color of the background changes depending on the severity of the + * status as determined by the WarningLevel. The UI also reacts + * to the urgency of the message by causing the background to blink. + */ +open class SystemStatusWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ConstraintLayoutWidget(context, attrs, defStyleAttr){ + //region Fields + private val systemStatusTextView: TextView = findViewById(R.id.textview_system_status) + private val systemStatusBackgroundImageView: ImageView = findViewById(R.id.imageview_system_status_background) + private val blinkAnimation: Animation = AnimationUtils.loadAnimation(context, R.anim.uxsdk_anim_blink) + protected val uiUpdateStateProcessor: PublishProcessor = PublishProcessor.create() + + private val widgetModel by lazy { + SystemStatusWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + GlobalPreferencesManager.getInstance() + ) + } + + private val textColorMap: MutableMap by lazy { + if (isInEditMode) { + mutableMapOf() + } else { + mutableMapOf( + WarningLevel.SERIOUS_WARNING to getColor(R.color.uxsdk_status_error), + WarningLevel.WARNING to getColor(R.color.uxsdk_status_warning), + WarningLevel.NORMAL to getColor(R.color.uxsdk_status_good), + WarningLevel.UNKNOWN to getColor(R.color.uxsdk_status_offline) + ) + } + } + + private val backgroundDrawableMap: MutableMap = mutableMapOf() + + /** + * The text size of the system status message text view + */ + var systemStatusMessageTextSize: Float + @Dimension + get() = systemStatusTextView.textSize + set(@Dimension textSize) { + systemStatusTextView.textSize = textSize + } + + /** + * The default mode determines the default text color and image background settings. + */ + var defaultMode = DefaultMode.COLOR + set(value) { + field = value + if (value == DefaultMode.COLOR) { + setSystemStatusMessageTextColor(WarningLevel.SERIOUS_WARNING, getColor(R.color.uxsdk_status_error)) + setSystemStatusMessageTextColor(WarningLevel.WARNING, getColor(R.color.uxsdk_status_warning)) + setSystemStatusMessageTextColor(WarningLevel.NORMAL, getColor(R.color.uxsdk_status_good)) + setSystemStatusMessageTextColor(WarningLevel.UNKNOWN, getColor(R.color.uxsdk_status_offline)) + + setSystemStatusBackgroundDrawable(null) + } else { + setSystemStatusMessageTextColor(getColor(R.color.uxsdk_white)) + setSystemStatusBackgroundDrawable(WarningLevel.SERIOUS_WARNING, getDrawable(R.drawable.uxsdk_gradient_error)) + setSystemStatusBackgroundDrawable(WarningLevel.WARNING, getDrawable(R.drawable.uxsdk_gradient_warning)) + setSystemStatusBackgroundDrawable(WarningLevel.NORMAL, getDrawable(R.drawable.uxsdk_gradient_good)) + setSystemStatusBackgroundDrawable(WarningLevel.UNKNOWN, getDrawable(R.drawable.uxsdk_gradient_offline)) + } + } + + private var stateChangeResourceId: Int = 0 + + //endregion + + //region Constructor + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + inflate(context, R.layout.uxsdk_widget_system_status, this) + } + + init { + systemStatusTextView.isSelected = true //Required for horizontal scrolling in textView + attrs?.let { initAttributes(context, it) } + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.systemStatus + .observeOn(SchedulerProvider.ui()) + .subscribe { updateUI(it) }) + addReaction(reactToCompassError()) + addReaction(widgetModel.warningStatusMessageData + .observeOn(SchedulerProvider.ui()) + .subscribe { updateMessage(it) }) + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + } + + //endregion + + //region Reactions to model + private fun updateUI(status: DJIDeviceStatus) { + systemStatusTextView.textColor = getSystemStatusMessageTextColor(status.warningLevel()) + systemStatusBackgroundImageView.imageDrawable = getSystemStatusBackgroundDrawable(status.warningLevel()) + blinkBackground(status.warningLevel() == WarningLevel.SERIOUS_WARNING) + widgetStateDataProcessor.onNext(SystemStatusUpdated(status)) + } + + private fun updateMessage(messageData: SystemStatusWidgetModel.WarningStatusMessageData) { + if (isMaxHeightMessage(messageData.message)){ + systemStatusTextView.text =messageData.message + " - " + formatMaxHeight(messageData.maxHeight, messageData.unitType) + }else{ + val str:String = if (messageData.message.contains("(GPS)")){ + messageData.message.replace("(GPS)", "").trim() + }else if(messageData.message.contains("(GPS)")){ + messageData.message.replace("(GPS)", "").trim() + }else{ + messageData.message + } + systemStatusTextView.text =str + + } + } + + private fun isMaxHeightMessage(text: String?): Boolean { + return DJIDeviceStatus.IN_NFZ_MAX_HEIGHT.statusCode().equals(text) + } + + private fun formatMaxHeight(maxHeight: Float, unitType: UnitConversionUtil.UnitType): String? { + val maxHeightStr: String = + if (unitType == UnitConversionUtil.UnitType.IMPERIAL) { + resources.getString(R.string.uxsdk_value_feet, String.format(Locale.US, "%.0f", maxHeight)) + } else { + resources.getString(R.string.uxsdk_value_meters, String.format(Locale.US, "%.0f", maxHeight)) + } + return getString(R.string.uxsdk_max_flight_height_limit, maxHeightStr) + } + + private fun blinkBackground(isUrgentMessage: Boolean) { + if (isUrgentMessage) { + systemStatusBackgroundImageView.startAnimation(blinkAnimation) + } else { + systemStatusBackgroundImageView.clearAnimation() + } + } + + private fun reactToCompassError(): Disposable { + return Flowable.combineLatest(widgetModel.systemStatus, widgetModel.isMotorOn + ) { first: DJIDeviceStatus, second: Boolean -> Pair(first, second) } + .observeOn(SchedulerProvider.ui()) + .subscribe( + Consumer { values: Pair -> updateVoiceNotification(values.first, values.second) }, + UxErrorHandle.logErrorConsumer(TAG, "react to Compass Error: ") + ) + } + + private fun updateVoiceNotification(statusItem: DJIDeviceStatus, isMotorOn: Boolean) { + if (isMotorOn && statusItem == DJIDeviceStatus.COMPASS_ERROR) { + addDisposable(widgetModel.sendVoiceNotification().subscribe()) + } + } + + private fun checkAndUpdateUI() { + if (!isInEditMode) { + addDisposable(widgetModel.systemStatus.firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(Consumer { this.updateUI(it) }, UxErrorHandle.logErrorConsumer(TAG, "Update UI ")) + ) + } + } + + //endregion + + //region Customization + override fun getIdealDimensionRatioString(): String? = null + + override val widgetSizeDescription: WidgetSizeDescription = WidgetSizeDescription( + WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.EXPAND + ) + //endregion + + //region Customization Helpers + /** + * Set text appearance of the system status message text view + * + * @param textAppearance Style resource for text appearance + */ + fun setSystemStatusMessageTextAppearance(@StyleRes textAppearance: Int) { + systemStatusTextView.setTextAppearance(context, textAppearance) + } + + /** + * Set the text color of the system status message for the given warning level. + * + * @param level The level for which to set the system status message text color. + * @param color The color of the system status message text. + */ + fun setSystemStatusMessageTextColor(level: WarningLevel, @ColorInt color: Int) { + textColorMap[level] = color + checkAndUpdateUI() + } + + /** + * Set the text color of the system status message for all warning levels. + * + * @param color The color of the system status message text. + */ + fun setSystemStatusMessageTextColor(@ColorInt color: Int) { + textColorMap[WarningLevel.SERIOUS_WARNING] = color + textColorMap[WarningLevel.WARNING] = color + textColorMap[WarningLevel.NORMAL] = color + textColorMap[WarningLevel.UNKNOWN] = color + checkAndUpdateUI() + } + + /** + * Get the text color of the system status message for the given warning level. + * + * @param level The level for which to get the system status message text color. + * @return The color of the system status message text. + */ + @ColorInt + fun getSystemStatusMessageTextColor(level: WarningLevel): Int { + return (textColorMap[level]?.let { it } ?: getColor(R.color.uxsdk_status_offline)) + } + + /** + * Set the background drawable of the system status message for the given warning level. + * + * @param level The level for which to set the system status message background drawable. + * @param background The background of the system status message. + */ + fun setSystemStatusBackgroundDrawable(level: WarningLevel, background: Drawable?) { + backgroundDrawableMap[level] = background + checkAndUpdateUI() + } + + /** + * Set the background drawable of the system status message for all warning levels. + * + * @param background The background of the system status message. + */ + fun setSystemStatusBackgroundDrawable(background: Drawable?) { + backgroundDrawableMap[WarningLevel.SERIOUS_WARNING] = background + backgroundDrawableMap[WarningLevel.WARNING] = background + backgroundDrawableMap[WarningLevel.NORMAL] = background + backgroundDrawableMap[WarningLevel.UNKNOWN] = background + checkAndUpdateUI() + } + + /** + * Get the background drawable of the system status message for the given warning level. + * + * @param level The level for which to get the system status message background drawable. + * @return The background drawable of the system status message. + */ + fun getSystemStatusBackgroundDrawable(level: WarningLevel): Drawable? { + return backgroundDrawableMap[level] + } + + //Initialize all customizable attributes + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.SystemStatusWidget).use { typedArray -> + typedArray.getIntegerAndUse(R.styleable.SystemStatusWidget_uxsdk_defaultMode) { + defaultMode = DefaultMode.find(it) + } + typedArray.getResourceIdAndUse(R.styleable.SystemStatusWidget_uxsdk_systemStatusMessageTextAppearance) { + setSystemStatusMessageTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.SystemStatusWidget_uxsdk_systemStatusMessageTextSize) { + systemStatusMessageTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.SystemStatusWidget_uxsdk_systemStatusMessageErrorTextColor) { + setSystemStatusMessageTextColor(WarningLevel.SERIOUS_WARNING, it) + } + typedArray.getColorAndUse(R.styleable.SystemStatusWidget_uxsdk_systemStatusMessageWarningTextColor) { + setSystemStatusMessageTextColor(WarningLevel.WARNING, it) + } + typedArray.getColorAndUse(R.styleable.SystemStatusWidget_uxsdk_systemStatusMessageGoodTextColor) { + setSystemStatusMessageTextColor(WarningLevel.NORMAL, it) + } + typedArray.getColorAndUse(R.styleable.SystemStatusWidget_uxsdk_systemStatusMessageOfflineTextColor) { + setSystemStatusMessageTextColor(WarningLevel.UNKNOWN, it) + } + typedArray.getDrawableAndUse(R.styleable.SystemStatusWidget_uxsdk_systemStatusErrorBackgroundDrawable) { + setSystemStatusBackgroundDrawable(WarningLevel.SERIOUS_WARNING, it) + } + typedArray.getDrawableAndUse(R.styleable.SystemStatusWidget_uxsdk_systemStatusWarningBackgroundDrawable) { + setSystemStatusBackgroundDrawable(WarningLevel.WARNING, it) + } + typedArray.getDrawableAndUse(R.styleable.SystemStatusWidget_uxsdk_systemStatusGoodBackgroundDrawable) { + setSystemStatusBackgroundDrawable(WarningLevel.NORMAL, it) + } + typedArray.getDrawableAndUse(R.styleable.SystemStatusWidget_uxsdk_systemStatusOfflineBackgroundDrawable) { + setSystemStatusBackgroundDrawable(WarningLevel.UNKNOWN, it) + } + typedArray.getResourceIdAndUse(R.styleable.SystemStatusWidget_uxsdk_onStateChange) { + stateChangeResourceId = it + } + } + } + + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Get the [UIState] updates + */ + fun getUIStateUpdates(): Flowable { + return uiUpdateStateProcessor.onBackpressureBuffer() + } + + /** + * Class defines widget UI states + */ + sealed class UIState { + + /** + * Widget click update + */ + object WidgetClicked : UIState() + } + + /** + * Class defines the widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * System status update + */ + data class SystemStatusUpdated(val status: DJIDeviceStatus) : ModelState() + } + + /** + * Sets the mode for the default image backgrounds and text colors. + */ + enum class DefaultMode(@get:JvmName("value") val value: Int) { + /** + * The text color updates to match the [WarningLevel] and there is no image background. + */ + COLOR(0), + + /** + * The text is white and the background image is a gradient which updates to match the + * [WarningLevel]. + */ + GRADIENT(1); + + companion object { + @JvmStatic + val values = values() + + @JvmStatic + fun find(value: Int): DefaultMode { + return values.find { it.value == value } ?: COLOR + } + } + } + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/systemstatus/SystemStatusWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/systemstatus/SystemStatusWidgetModel.kt new file mode 100644 index 00000000..213975f0 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/systemstatus/SystemStatusWidgetModel.kt @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.systemstatus + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.key.KeyTools +import dji.v5.manager.diagnostic.DJIDeviceStatus +import dji.v5.manager.diagnostic.DJIDeviceStatusChangeListener +import dji.v5.manager.diagnostic.DeviceStatusManager +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.* +import dji.v5.ux.core.model.VoiceNotificationType +import dji.v5.ux.core.util.DataProcessor +import dji.v5.ux.core.util.UnitConversionUtil +import io.reactivex.rxjava3.core.Completable + +/** + * Widget Model for the [SystemStatusWidget] used to define + * the underlying logic and communication + */ +class SystemStatusWidgetModel( + djiSdkModel: DJISDKModel, + private val keyedStore: ObservableInMemoryKeyedStore, + private val preferencesManager: GlobalPreferencesInterface? +) : WidgetModel(djiSdkModel, keyedStore) { + + //region Fields + private val systemStatusProcessor: DataProcessor = DataProcessor.create( + DJIDeviceStatus.NORMAL) + private val areMotorsOnDataProcessor: DataProcessor = DataProcessor.create(false) + private val maxHeightProcessor: DataProcessor = DataProcessor.create(0) + private val unitTypeProcessor: DataProcessor = DataProcessor.create(UnitConversionUtil.UnitType.METRIC) + private val warningStatusMessageProcessor: DataProcessor = DataProcessor.create(WarningStatusMessageData("", 0f, UnitConversionUtil.UnitType.METRIC)) + private val sendVoiceNotificationKey: UXKey = UXKeys.create(MessagingKeys.SEND_VOICE_NOTIFICATION) + //endregion + + private val deviceStatusChangeListener = DJIDeviceStatusChangeListener { _, to -> + systemStatusProcessor.onNext(to) + updateStates() + } + + //region Data + /** + * Get the system status of the aircraft as a WarningStatusItem. + */ + val systemStatus: Flowable + get() = systemStatusProcessor.toFlowable() + + /** + * Get whether the motors are on. + */ + val isMotorOn: Flowable + get() = areMotorsOnDataProcessor.toFlowable() + + /** + * Get the data required for displaying the warning status message. + */ + val warningStatusMessageData: Flowable + get() = warningStatusMessageProcessor.toFlowable() + + //endregion + + //region Actions + /** + * Send a voice notification. + * + * @return Completable representing the success/failure of the set action. + */ + fun sendVoiceNotification(): Completable { + val notificationType = VoiceNotificationType.ATTI + return keyedStore.setValue(sendVoiceNotificationKey, notificationType) + } + //endregion + + //region LifeCycle + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAreMotorsOn), areMotorsOnDataProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyFlightLimitHeight), maxHeightProcessor) + val unitKey = UXKeys.create(GlobalPreferenceKeys.UNIT_TYPE) + bindDataProcessor(unitKey, unitTypeProcessor) + + preferencesManager?.setUpListener() + + DeviceStatusManager.getInstance().addDJIDeviceStatusChangeListener(deviceStatusChangeListener) + } + + override fun inCleanup() { + preferencesManager?.cleanup() + DeviceStatusManager.getInstance().removeDJIDeviceStatusChangeListener(deviceStatusChangeListener) + } + + override fun updateStates() { + warningStatusMessageProcessor.onNext( + WarningStatusMessageData( + systemStatusProcessor.value.description(), + getMaxHeight(maxHeightProcessor.value.toFloat(), unitTypeProcessor.value), + unitTypeProcessor.value + ) + ) + } + + init { + if (preferencesManager != null) { + unitTypeProcessor.onNext(preferencesManager.unitType) + } + } + //endregion + + //region Helpers + private fun getMaxHeight(maxHeight: Float, unitType: UnitConversionUtil.UnitType): Float { + return if (unitType == UnitConversionUtil.UnitType.IMPERIAL) { + UnitConversionUtil.convertMetersToFeet(maxHeight) + } else { + maxHeight + } + } + //endregion + + //region Classes + /** + * Class representing data for displaying a warning status message + */ + data class WarningStatusMessageData( + /** + * Warning Status Message + */ + val message: String, + + /** + * Max height of a height-limited no-fly zone + */ + val maxHeight: Float, + + /** + * Unit type for the height + */ + val unitType: UnitConversionUtil.UnitType + ) + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/useraccount/UserAccountLoginWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/useraccount/UserAccountLoginWidget.java new file mode 100644 index 00000000..21f284a8 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/useraccount/UserAccountLoginWidget.java @@ -0,0 +1,697 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.useraccount; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.Drawable; +import android.util.AttributeSet; +import android.view.View; +import android.view.View.OnClickListener; +import android.widget.ImageView; +import android.widget.TextView; + +import androidx.annotation.ColorInt; +import androidx.annotation.Dimension; +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.StyleRes; +import androidx.fragment.app.FragmentActivity; + +import java.util.HashMap; +import java.util.Map; + +import dji.v5.manager.account.LoginInfo; +import dji.v5.manager.account.LoginState; +import dji.v5.manager.account.UserAccountManager; +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.SchedulerProvider; +import dji.v5.ux.core.base.UXSDKError; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; + +/** + * User Account Login Widget + *

    + * Widget will display the current login status of the user's DJI account. + * Tapping on the widget will provide the option to login or logout of the DJI account. + */ +public class UserAccountLoginWidget extends ConstraintLayoutWidget implements OnClickListener { + //region Fields + private static final String TAG = "LoginWidget"; + private TextView widgetStateTextView; + private ImageView widgetActionImageView; + private ImageView widgetUserImageView; + private TextView widgetMessageTextView; + private View widgetDivider; + private UserAccountLoginWidgetModel widgetModel; + private Map widgetStateTextColorMap; + private Map widgetMessageTextColorMap; + private Map widgetActionIconMap; + private Map widgetUserIconMap; + private LoginInfo currentLoginInfo = new LoginInfo(); + + //endregion + + //region Lifecycle + public UserAccountLoginWidget(Context context) { + super(context); + } + + public UserAccountLoginWidget(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public UserAccountLoginWidget(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_widget_user_account_login, this); + setBackgroundResource(R.drawable.uxsdk_background_black_rectangle); + widgetDivider = findViewById(R.id.widget_divider); + widgetStateTextView = findViewById(R.id.textview_widget_status); + widgetActionImageView = findViewById(R.id.imageview_widget_status); + widgetUserImageView = findViewById(R.id.imageview_widget_user); + widgetMessageTextView = findViewById(R.id.textview_widget_message); + widgetStateTextColorMap = new HashMap<>(); + widgetMessageTextColorMap = new HashMap<>(); + widgetActionIconMap = new HashMap<>(); + widgetUserIconMap = new HashMap<>(); + + if (!isInEditMode()) { + widgetModel = new UserAccountLoginWidgetModel(DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + UserAccountManager.getInstance()); + } + setOnClickListener(this); + initDefaults(); + + if (attrs != null) { + initAttributes(context, attrs); + } + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.getUserAccountInformation().observeOn(SchedulerProvider.ui()).subscribe(loginInfo -> { + if (loginInfo != null) { + currentLoginInfo = loginInfo; + updateUI(); + } + } + + )); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + if (!isInEditMode()) { + widgetModel.cleanup(); + } + super.onDetachedFromWindow(); + } + + @Override + public void onClick(View v) { + if (currentLoginInfo.getLoginState() == LoginState.LOGGED_IN) { + logoutUser(); + } else { + loginUser(); + } + } + + @NonNull + @Override + public String getIdealDimensionRatioString() { + return getResources().getString(R.string.uxsdk_widget_user_account_login_ratio); + } + + + private void loginUser() { + Context ctx = getContext(); + if (!(ctx instanceof FragmentActivity) || ((FragmentActivity) ctx).isFinishing()) { + LogUtils.e(TAG, "Context is not activity or had finish: " + ctx); + } else { + addDisposable(widgetModel.loginUser((FragmentActivity) ctx) + .observeOn(SchedulerProvider.ui()) + .subscribe(() -> { + }, error -> { + LogUtils.e(TAG, "login error:" + error); + })); + } + + } + + private void logoutUser() { + addDisposable(widgetModel.logoutUser().observeOn(SchedulerProvider.ui()).subscribe(() -> { + }, error -> { + if (error instanceof UXSDKError) { + LogUtils.e(TAG, error.toString()); + } + })); + } + + private void updateUI() { + if (currentLoginInfo == null) { + LogUtils.e(TAG, "currentLoginInfo == null"); + return; + } + switch (currentLoginInfo.getLoginState()) { + case LOGGED_IN: + widgetStateTextView.setText(currentLoginInfo.getAccount()); + widgetMessageTextView.setText(getResources().getString(R.string.uxsdk_user_login_widget_logged_in)); + break; + case NOT_LOGGED_IN: + widgetStateTextView.setText(getResources().getString(R.string.uxsdk_user_login_widget_login)); + widgetMessageTextView.setText(getResources().getString(R.string.uxsdk_user_login_widget_not_logged_in)); + break; + case TOKEN_OUT_OF_DATE: + widgetStateTextView.setText(getResources().getString(R.string.uxsdk_user_login_widget_refresh)); + widgetMessageTextView.setText(getResources().getString(R.string.uxsdk_user_login_widget_token)); + break; + case UNKNOWN: + default: + return; + } + + widgetMessageTextView.setTextColor(getWidgetMessageTextColor(currentLoginInfo.getLoginState())); + widgetActionImageView.setImageDrawable(getActionIcon(currentLoginInfo.getLoginState())); + widgetUserImageView.setImageDrawable(getUserIcon(currentLoginInfo.getLoginState())); + widgetStateTextView.setTextColor(getWidgetStateTextColor(currentLoginInfo.getLoginState())); + } + + private void initAttributes(Context context, AttributeSet attrs) { + TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.UserAccountLoginWidget); + initActionIcon(typedArray); + initStateText(typedArray); + initMessageTest(typedArray); + typedArray.recycle(); + } + + private void initStateText(TypedArray typedArray) { + int textAppearance = typedArray.getResourceId(R.styleable.UserAccountLoginWidget_uxsdk_stateTextAppearance, INVALID_RESOURCE); + if (textAppearance != INVALID_RESOURCE) { + setWidgetStateTextAppearance(textAppearance); + } + + int color = typedArray.getColor(R.styleable.UserAccountLoginWidget_uxsdk_stateTextColorLoggedIn, INVALID_COLOR); + if (color != INVALID_COLOR) { + setWidgetStateTextColor(LoginState.LOGGED_IN, color); + } + color = typedArray.getColor(R.styleable.UserAccountLoginWidget_uxsdk_stateTextColorNotLoggedIn, INVALID_COLOR); + if (color != INVALID_COLOR) { + setWidgetStateTextColor(LoginState.NOT_LOGGED_IN, color); + } + color = typedArray.getColor(R.styleable.UserAccountLoginWidget_uxsdk_stateTextColorTokenOutOfDate, INVALID_COLOR); + if (color != INVALID_COLOR) { + setWidgetStateTextColor(LoginState.TOKEN_OUT_OF_DATE, color); + } + + setWidgetStateTextEnabled(typedArray.getBoolean(R.styleable.UserAccountLoginWidget_uxsdk_stateTextEnabled, + true)); + } + + private void initMessageTest(TypedArray typedArray) { + int textAppearance = typedArray.getResourceId(R.styleable.UserAccountLoginWidget_uxsdk_messageTextAppearance, INVALID_RESOURCE); + if (textAppearance != INVALID_RESOURCE) { + setWidgetMessageTextAppearance(textAppearance); + } + int color = typedArray.getColor(R.styleable.UserAccountLoginWidget_uxsdk_messageTextColorLoggedIN, INVALID_COLOR); + if (color != INVALID_COLOR) { + setWidgetMessageTextColor(LoginState.LOGGED_IN, color); + } + color = typedArray.getColor(R.styleable.UserAccountLoginWidget_uxsdk_messageTextColorNotLoggedIn, INVALID_COLOR); + if (color != INVALID_COLOR) { + setWidgetMessageTextColor(LoginState.NOT_LOGGED_IN, color); + } + color = typedArray.getColor(R.styleable.UserAccountLoginWidget_uxsdk_messageTextColorTokenOutOfDate, INVALID_COLOR); + if (color != INVALID_COLOR) { + setWidgetMessageTextColor(LoginState.TOKEN_OUT_OF_DATE, color); + } + setWidgetMessageTextSize(typedArray.getDimension(R.styleable.UserAccountLoginWidget_uxsdk_messageTextSize, + getResources().getDimension(R.dimen.uxsdk_user_account_message_text_size))); + setWidgetMessageBackground(typedArray.getDrawable(R.styleable.UserAccountLoginWidget_uxsdk_messageTextBackground)); + setWidgetStateTextSize(typedArray.getDimension(R.styleable.UserAccountLoginWidget_uxsdk_messageTextSize, + getResources().getDimension(R.dimen.uxsdk_user_account_state_text_size))); + if (typedArray.getDrawable(R.styleable.UserAccountLoginWidget_uxsdk_messageTextBackground) != null) { + setWidgetStateBackground(typedArray.getDrawable(R.styleable.UserAccountLoginWidget_uxsdk_messageTextBackground)); + } + initActionIcon(typedArray); + setMessageTextEnabled(typedArray.getBoolean(R.styleable.UserAccountLoginWidget_uxsdk_messageTextEnabled, + true)); + } + + private void initActionIcon(TypedArray typedArray) { + Drawable drawable = typedArray.getDrawable(R.styleable.UserAccountLoginWidget_uxsdk_actionIconLoggedIn); + if (drawable != null) { + setActionIcon(LoginState.LOGGED_IN, drawable); + } + + drawable = typedArray.getDrawable(R.styleable.UserAccountLoginWidget_uxsdk_actionIconNotLoggedIn); + if (drawable != null) { + setActionIcon(LoginState.NOT_LOGGED_IN, drawable); + } + + drawable = typedArray.getDrawable(R.styleable.UserAccountLoginWidget_uxsdk_actionIconTokenOutOfDate); + if (drawable != null) { + setActionIcon(LoginState.TOKEN_OUT_OF_DATE, drawable); + } + drawable = typedArray.getDrawable(R.styleable.UserAccountLoginWidget_uxsdk_userIconLoggedIn); + if (drawable != null) { + setUserIcon(LoginState.LOGGED_IN, drawable); + } + + drawable = typedArray.getDrawable(R.styleable.UserAccountLoginWidget_uxsdk_userIconNotLoggedIn); + if (drawable != null) { + setUserIcon(LoginState.NOT_LOGGED_IN, drawable); + } + + drawable = typedArray.getDrawable(R.styleable.UserAccountLoginWidget_uxsdk_userIconTokenOutOfDate); + if (drawable != null) { + setUserIcon(LoginState.TOKEN_OUT_OF_DATE, drawable); + } + + if (typedArray.getDrawable(R.styleable.UserAccountLoginWidget_uxsdk_userIconBackground) != null) { + setUserIconBackground(typedArray.getDrawable(R.styleable.UserAccountLoginWidget_uxsdk_userIconBackground)); + } + if (typedArray.getDrawable(R.styleable.UserAccountLoginWidget_uxsdk_actionIconBackground) != null) { + setActionIconBackground(typedArray.getDrawable(R.styleable.UserAccountLoginWidget_uxsdk_actionIconBackground)); + } + setUserIconEnabled(typedArray.getBoolean(R.styleable.UserAccountLoginWidget_uxsdk_userIconEnabled, true)); + setActionIconEnabled(typedArray.getBoolean(R.styleable.UserAccountLoginWidget_uxsdk_actionIconEnabled, true)); + } + + private void initDefaults() { + if (isInEditMode()) { + return; + } + setWidgetStateTextColor(LoginState.NOT_LOGGED_IN, getResources().getColor(R.color.uxsdk_white_80_percent)); + setWidgetStateTextColor(LoginState.LOGGED_IN, getResources().getColor(R.color.uxsdk_white_80_percent)); + setWidgetStateTextColor(LoginState.TOKEN_OUT_OF_DATE, getResources().getColor(R.color.uxsdk_white_80_percent)); + setWidgetStateTextColor(LoginState.UNKNOWN, getResources().getColor(R.color.uxsdk_white_80_percent)); + + setWidgetMessageTextColor(LoginState.NOT_LOGGED_IN, getResources().getColor(R.color.uxsdk_red_material_800)); + setWidgetMessageTextColor(LoginState.LOGGED_IN, getResources().getColor(R.color.uxsdk_green_material_400)); + setWidgetMessageTextColor(LoginState.TOKEN_OUT_OF_DATE, getResources().getColor(R.color.uxsdk_yellow_500)); + setWidgetMessageTextColor(LoginState.UNKNOWN, getResources().getColor(R.color.uxsdk_red_material_800)); + + setUserIcon(LoginState.NOT_LOGGED_IN, getResources().getDrawable(R.drawable.uxsdk_ic_person)); + setUserIcon(LoginState.LOGGED_IN, getResources().getDrawable(R.drawable.uxsdk_ic_person)); + setUserIcon(LoginState.TOKEN_OUT_OF_DATE, getResources().getDrawable(R.drawable.uxsdk_ic_person)); + setUserIcon(LoginState.UNKNOWN, getResources().getDrawable(R.drawable.uxsdk_ic_person)); + + setActionIcon(LoginState.NOT_LOGGED_IN, getResources().getDrawable(R.drawable.uxsdk_ic_person_log_in)); + setActionIcon(LoginState.LOGGED_IN, getResources().getDrawable(R.drawable.uxsdk_ic_person_log_out)); + setActionIcon(LoginState.TOKEN_OUT_OF_DATE, getResources().getDrawable(R.drawable.uxsdk_ic_person_log_out)); + setActionIcon(LoginState.UNKNOWN, getResources().getDrawable(R.drawable.uxsdk_ic_person_log_in)); + + setWidgetStateTextSize(getResources().getDimension(R.dimen.uxsdk_user_account_state_text_size)); + setWidgetMessageTextSize(getResources().getDimension(R.dimen.uxsdk_user_account_message_text_size)); + } + + //endregion + + //region customizations + + /** + * Set the color of the widget state text based on user login state + * + * @param userAccountState {@link LoginState} for which the color should be used + * @param color integer value of color to be used for the user login state + */ + public void setWidgetStateTextColor(@NonNull LoginState userAccountState, @ColorInt int color) { + widgetStateTextColorMap.put(userAccountState, color); + updateUI(); + } + + /** + * Get the color of the widget state text + * + * @param userAccountState {@link LoginState} for which the color is being used + * @return integer value representing the color + */ + @ColorInt + public int getWidgetStateTextColor(@NonNull LoginState userAccountState) { + return widgetStateTextColorMap.get(userAccountState); + } + + /** + * Set text appearance of the widget state text + * + * @param textAppearance style resource id for the text appearance + */ + public void setWidgetStateTextAppearance(@StyleRes int textAppearance) { + widgetStateTextView.setTextAppearance(getContext(), textAppearance); + } + + /** + * Get the current background of the widget state text + * + * @return Drawable representing widget state text background + */ + @Nullable + public Drawable getWidgetStateBackground() { + return widgetStateTextView.getBackground(); + } + + /** + * Set the background resource of the widget state text + * + * @param resourceId to be used as background of widget state text + */ + public void setWidgetStateBackground(@DrawableRes int resourceId) { + setWidgetStateBackground(getResources().getDrawable(resourceId)); + } + + /** + * Set the background of the widget state text + * + * @param drawable drawable to be used as the background of widget state text + */ + public void setWidgetStateBackground(@Nullable Drawable drawable) { + widgetStateTextView.setBackground(drawable); + } + + /** + * Get the current text size of the widget state text + * + * @return float value representing text size + */ + @Dimension + public float getWidgetStateTextSize() { + return widgetStateTextView.getTextSize(); + } + + /** + * Set the text size of widget state text + * + * @param textSize float value for size of widget state text + */ + public void setWidgetStateTextSize(@Dimension float textSize) { + widgetStateTextView.setTextSize(textSize); + } + + /** + * Set the color of the widget message text based on user login state + * + * @param userAccountState {@link LoginState} for which the color should be used + * @param color integer value of color to be used for the message text + */ + public void setWidgetMessageTextColor(@NonNull LoginState userAccountState, @ColorInt int color) { + widgetMessageTextColorMap.put(userAccountState, color); + updateUI(); + } + + /** + * Get the color of the widget message text + * + * @param userAccountState {@link LoginState} for which the color is being used + * @return integer value representing the color + */ + @ColorInt + public int getWidgetMessageTextColor(@NonNull LoginState userAccountState) { + return widgetMessageTextColorMap.get(userAccountState); + } + + /** + * Set text appearance of the widget message text + * + * @param textAppearance style resource id for the text appearance + */ + public void setWidgetMessageTextAppearance(@StyleRes int textAppearance) { + widgetMessageTextView.setTextAppearance(getContext(), textAppearance); + } + + /** + * Get the current background of the widget message text + * + * @return Drawable representing widget message text background + */ + @Nullable + public Drawable getWidgetMessageBackground() { + return widgetMessageTextView.getBackground(); + } + + /** + * Set the background resource of the widget message text + * + * @param resourceId to be used as background of widget message text + */ + public void setWidgetMessageBackground(@DrawableRes int resourceId) { + setWidgetMessageBackground(getResources().getDrawable(resourceId)); + } + + /** + * Set the background of the widget message text + * + * @param drawable Drawable to be used as the background of widget message text + */ + public void setWidgetMessageBackground(@Nullable Drawable drawable) { + widgetMessageTextView.setBackground(drawable); + } + + /** + * Get the current text size of the widget message text + * + * @return float value representing text size + */ + @Dimension + public float getWidgetMessageTextSize() { + return widgetMessageTextView.getTextSize(); + } + + /** + * Set the text size of widget message text + * + * @param textSize float value for size of widget message text + */ + public void setWidgetMessageTextSize(@Dimension float textSize) { + widgetMessageTextView.setTextSize(textSize); + } + + /** + * Set icon for the action based on {@link LoginState} + * + * @param userAccountState {@link LoginState} for which icon should be used + * @param resourceId resource id for the icon + */ + public void setActionIcon(@NonNull LoginState userAccountState, @DrawableRes int resourceId) { + setActionIcon(userAccountState, getResources().getDrawable(resourceId)); + } + + /** + * Set icon for the action based on {@link LoginState} + * + * @param userAccountState {@link LoginState} for which icon should be used + * @param drawable drawable for the icon + */ + public void setActionIcon(@NonNull LoginState userAccountState, @Nullable Drawable drawable) { + widgetActionIconMap.put(userAccountState, drawable); + updateUI(); + } + + /** + * Get current icon for the action based on {@link LoginState} + * + * @param userAccountState {@link LoginState} for which icon is used + * @return drawable used as action icon + */ + public Drawable getActionIcon(@NonNull LoginState userAccountState) { + return widgetActionIconMap.get(userAccountState); + } + + /** + * Get current background of action icon + * + * @return drawable used as background of icon + */ + public Drawable getActionIconBackground() { + return widgetActionImageView.getBackground(); + } + + /** + * Set the background of the action icon + * + * @param resourceId to be used as background of action icon + */ + public void setActionIconBackground(@DrawableRes int resourceId) { + setActionIconBackground(getResources().getDrawable(resourceId)); + } + + /** + * Set the background of the action icon + * + * @param drawable to be used as background of action icon + */ + public void setActionIconBackground(@Nullable Drawable drawable) { + widgetActionImageView.setBackground(drawable); + } + + /** + * Set icon for the user based on {@link LoginState} + * + * @param userAccountState {@link LoginState} for which icon should be used + * @param resourceId resource id for the icon + */ + public void setUserIcon(@NonNull LoginState userAccountState, @DrawableRes int resourceId) { + setUserIcon(userAccountState, getResources().getDrawable(resourceId)); + } + + /** + * Set icon for the user based on {@link LoginState} + * + * @param userAccountState {@link LoginState} for which icon should be used + * @param drawable drawable for the icon + */ + public void setUserIcon(@NonNull LoginState userAccountState, @Nullable Drawable drawable) { + widgetUserIconMap.put(userAccountState, drawable); + updateUI(); + } + + /** + * Get current icon for the user based on {@link LoginState} + * + * @param userAccountState {@link LoginState} for which icon is used + * @return drawable used as user icon + */ + public Drawable getUserIcon(@NonNull LoginState userAccountState) { + return widgetUserIconMap.get(userAccountState); + } + + /** + * Get current background of user icon + * + * @return drawable used as background of icon + */ + public Drawable getUserIconBackground() { + return widgetUserImageView.getBackground(); + } + + /** + * Set the background of the user icon + * + * @param resourceId to be used as background of user icon + */ + public void setUserIconBackground(@DrawableRes int resourceId) { + setUserIconBackground(getResources().getDrawable(resourceId)); + } + + /** + * Set the background of the user icon + * + * @param drawable to be used as background of user icon + */ + public void setUserIconBackground(@Nullable Drawable drawable) { + widgetUserImageView.setBackground(drawable); + } + + /** + * Check if action icon is enabled + * + * @return boolean value true - visible false - not visible + */ + public boolean isActionIconEnabled() { + return widgetActionImageView.getVisibility() == VISIBLE; + } + + /** + * Enable action icon to show/hide user icon + * + * @param isEnabled boolean flag true - visible false - not visible + */ + public void setActionIconEnabled(boolean isEnabled) { + widgetActionImageView.setVisibility(isEnabled ? VISIBLE : GONE); + widgetDivider.setVisibility(isEnabled ? VISIBLE : GONE); + } + + /** + * Check if user icon is enabled + * + * @return boolean value true - visible false - not visible + */ + public boolean isUserIconEnabled() { + return widgetUserImageView.getVisibility() == VISIBLE; + } + + /** + * Enable user icon to show/hide user icon + * + * @param isEnabled boolean flag true - visible false - not visible + */ + public void setUserIconEnabled(boolean isEnabled) { + widgetUserImageView.setVisibility(isEnabled ? VISIBLE : GONE); + widgetDivider.setVisibility(isEnabled ? VISIBLE : GONE); + } + + /** + * Check if message text is enabled + * + * @return boolean value true - visible false - not visible + */ + public boolean isMessageTextEnabled() { + return widgetMessageTextView.getVisibility() == VISIBLE; + } + + /** + * Enable widget message text to show/hide message state text + */ + public void setMessageTextEnabled(boolean isEnabled) { + widgetMessageTextView.setVisibility(isEnabled ? VISIBLE : GONE); + } + + /** + * Check if widget state text is enabled + * + * @return boolean value true - visible false - not visible + */ + public boolean isWidgetStateTextEnabled() { + return widgetStateTextView.getVisibility() == VISIBLE; + } + + /** + * Enable widget state text to show/hide widget state text + * + * @param isEnabled boolean flag true - visible false - not visible + */ + public void setWidgetStateTextEnabled(boolean isEnabled) { + widgetStateTextView.setVisibility(isEnabled ? VISIBLE : GONE); + } + // + // //endregion + + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/useraccount/UserAccountLoginWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/useraccount/UserAccountLoginWidgetModel.java new file mode 100644 index 00000000..792fd17c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/useraccount/UserAccountLoginWidgetModel.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.useraccount; + + +import androidx.annotation.NonNull; +import androidx.fragment.app.FragmentActivity; + +import dji.v5.common.callback.CommonCallbacks; +import dji.v5.common.error.IDJIError; +import dji.v5.manager.account.LoginInfo; +import dji.v5.manager.account.LoginInfoUpdateListener; +import dji.v5.manager.interfaces.IUserAccountManager; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.UXSDKError; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; + +/** + * User Account Login Widget Model + *

    + * Widget Model for {@link UserAccountLoginWidget} used to define the + * underlying logic and communication + */ +public class UserAccountLoginWidgetModel extends WidgetModel { + + //region Fields + private DataProcessor loginInfoDataProcessor; + private IUserAccountManager userAccountManager; + private LoginInfoUpdateListener loginInfoUpdateListener = loginInfo -> loginInfoDataProcessor.onNext(loginInfo); + + + //endregion + + public UserAccountLoginWidgetModel(@NonNull DJISDKModel djiSdkModel, + @NonNull ObservableInMemoryKeyedStore keyedStore, + @NonNull IUserAccountManager userAccountManager) { + super(djiSdkModel, keyedStore); + this.userAccountManager = userAccountManager; + loginInfoDataProcessor = DataProcessor.create(new LoginInfo()); + } + + + @Override + protected void inSetup() { + if (userAccountManager != null) { + userAccountManager.addLoginInfoUpdateListener(loginInfoUpdateListener); + } + } + + @Override + protected void inCleanup() { + userAccountManager.removeLoginInfoUpdateListener(loginInfoUpdateListener); + } + + @Override + protected void updateStates() { + //empty + } + + + //region Data + + /** + * Get user account information + * + * @return Flowable of type UserAccountInformation + */ + public Flowable getUserAccountInformation() { + return loginInfoDataProcessor.toFlowable(); + } + + + //endregion + + //region Actions + + /** + * Log into user account + * + * @param context for showing logging pop up + * @return completable indicating the success or failure + */ + public Completable loginUser(@NonNull FragmentActivity context) { + + return Completable.create(emitter -> userAccountManager.logInDJIUserAccount(context, false, new CommonCallbacks.CompletionCallback() { + @Override + public void onSuccess() { + emitter.onComplete(); + } + + @Override + public void onFailure(@NonNull IDJIError error) { + if (!emitter.isDisposed()) { + UXSDKError uxsdkError = new UXSDKError(error); + emitter.onError(uxsdkError); + } + } + })); + } + + /** + * Log out the current logged in user account + * + * @return completable indicating the success or failure + */ + public Completable logoutUser() { + return Completable.create(emitter -> userAccountManager.logOutDJIUserAccount(new CommonCallbacks.CompletionCallback() { + @Override + public void onSuccess() { + emitter.onComplete(); + } + + @Override + public void onFailure(@NonNull IDJIError error) { + emitter.onError(new UXSDKError(error)); + } + })); + } + + //endregion + + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/verticalvelocity/VerticalVelocityWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/verticalvelocity/VerticalVelocityWidget.kt new file mode 100644 index 00000000..2d651fbc --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/verticalvelocity/VerticalVelocityWidget.kt @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.verticalvelocity + +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.TypedArray +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import androidx.annotation.DrawableRes +import androidx.core.content.res.use +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.widget.BaseTelemetryWidget +import dji.v5.ux.core.communication.GlobalPreferencesManager +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.getDrawable +import dji.v5.ux.core.extension.getDrawableAndUse +import dji.v5.ux.core.extension.getString +import dji.v5.ux.core.extension.getVelocityString +import dji.v5.ux.core.util.UnitConversionUtil.UnitType +import dji.v5.ux.core.widget.verticalvelocity.VerticalVelocityWidget.ModelState +import dji.v5.ux.core.widget.verticalvelocity.VerticalVelocityWidgetModel.VerticalVelocityState +import java.text.DecimalFormat + +/** + * Widget displays the vertical velocity of the aircraft. + * + */ +open class VerticalVelocityWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + widgetTheme: Int = 0 +) : BaseTelemetryWidget( + context, + attrs, + defStyleAttr, + WidgetType.TEXT_IMAGE_RIGHT, + widgetTheme, + R.style.UXSDKVerticalVelocityWidget +) { + + + //region Fields + /** + * Icon for upward velocity + */ + var upwardVelocityIcon: Drawable = getDrawable(R.drawable.uxsdk_ic_arrow_up) + + /** + * Icon for downward velocity + */ + var downwardVelocityIcon: Drawable = getDrawable(R.drawable.uxsdk_ic_arrow_down) + + private val widgetModel: VerticalVelocityWidgetModel by lazy { + VerticalVelocityWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + GlobalPreferencesManager.getInstance()) + } + + override val metricDecimalFormat: DecimalFormat = DecimalFormat("###0.0") + + override val imperialDecimalFormat: DecimalFormat = DecimalFormat("###0.0") + //endregion + + //region Constructor + init { + initThemeAttributes(context, widgetTheme) + initAttributes(context, attrs) + setValueTextViewMinWidthByText("88.8") + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ModelState.ProductConnected(it)) }) + addReaction(widgetModel.verticalVelocityState + .observeOn(SchedulerProvider.ui()) + .subscribe { updateUI(it) }) + } + //endregion + + //region Customization + override fun getIdealDimensionRatioString(): String? = null + + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP) + + /** + * Set the icon for upward velocity + * + * @param resourceId Integer ID of the icon + */ + fun setUpwardVelocityIcon(@DrawableRes resourceId: Int) { + upwardVelocityIcon = getDrawable(resourceId) + } + + /** + * Set the icon for downward velocity + * + * @param resourceId Integer ID of the icon + */ + fun setDownwardVelocityIcon(@DrawableRes resourceId: Int) { + downwardVelocityIcon = getDrawable(resourceId) + } + + @SuppressLint("Recycle") + private fun initThemeAttributes(context: Context, widgetTheme: Int) { + val verticalVelocityAttributeArray: IntArray = R.styleable.VerticalVelocityWidget + context.obtainStyledAttributes(widgetTheme, verticalVelocityAttributeArray).use { + initAttributesByTypedArray(it) + } + } + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet?) { + context.obtainStyledAttributes(attrs, R.styleable.VerticalVelocityWidget, 0, defaultStyle).use { + initAttributesByTypedArray(it) + } + } + + private fun initAttributesByTypedArray(typedArray: TypedArray) { + typedArray.getDrawableAndUse(R.styleable.VerticalVelocityWidget_uxsdk_upward_velocity_icon) { + upwardVelocityIcon = it + } + typedArray.getDrawableAndUse(R.styleable.VerticalVelocityWidget_uxsdk_downward_velocity_icon) { + downwardVelocityIcon = it + } + } + //endregion + + //region Reactions to model + private fun updateUI(verticalVelocityState: VerticalVelocityState) { + widgetStateDataProcessor.onNext(ModelState.VerticalVelocityStateUpdated(verticalVelocityState)) + when (verticalVelocityState) { + VerticalVelocityState.ProductDisconnected -> updateToDisconnectedState() + is VerticalVelocityState.Idle -> updateVelocityState(0.0, verticalVelocityState.unitType, null) + is VerticalVelocityState.UpwardVelocity -> updateVelocityState(verticalVelocityState.velocity, verticalVelocityState.unitType, upwardVelocityIcon) + is VerticalVelocityState.DownwardVelocity -> updateVelocityState(verticalVelocityState.velocity, verticalVelocityState.unitType, downwardVelocityIcon) + } + + } + + private fun updateVelocityState(velocity: Double, unitType: UnitType, icon: Drawable?) { + widgetIcon = icon + valueString = getDecimalFormat(unitType).format(velocity).toString() + unitString = getVelocityString(unitType) + } + + private fun updateToDisconnectedState() { + unitString = null + widgetIcon = null + valueString = getString(R.string.uxsdk_string_default_value) + } + //endregion + + //region Hooks + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val boolean: Boolean) : ModelState() + + /** + * Vertical velocity state update + */ + data class VerticalVelocityStateUpdated(val verticalVelocityState: VerticalVelocityState) : ModelState() + } + //endregion + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/verticalvelocity/VerticalVelocityWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/verticalvelocity/VerticalVelocityWidgetModel.kt new file mode 100644 index 00000000..08ffcc40 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/verticalvelocity/VerticalVelocityWidgetModel.kt @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.verticalvelocity + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.value.common.Velocity3D +import dji.sdk.keyvalue.key.KeyTools +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.GlobalPreferenceKeys +import dji.v5.ux.core.communication.GlobalPreferencesInterface +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.toVelocity +import dji.v5.ux.core.util.DataProcessor +import dji.v5.ux.core.util.UnitConversionUtil.UnitType +import dji.v5.ux.core.widget.verticalvelocity.VerticalVelocityWidgetModel.VerticalVelocityState.* +import kotlin.math.abs + +/** + * Widget Model for the [VerticalVelocityWidget] used to define + * the underlying logic and communication + */ +class VerticalVelocityWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, + private val preferencesManager: GlobalPreferencesInterface? +) : WidgetModel(djiSdkModel, keyedStore) { + + private val velocityProcessor = DataProcessor.create(Velocity3D()) + private val unitTypeDataProcessor: DataProcessor = DataProcessor.create(UnitType.METRIC) + private val verticalVelocityStateProcessor: DataProcessor = DataProcessor.create(ProductDisconnected) + + /** + * Value of the vertical velocity state of the aircraft + */ + val verticalVelocityState: Flowable + get() = verticalVelocityStateProcessor.toFlowable() + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAircraftVelocity), velocityProcessor) + bindDataProcessor(GlobalPreferenceKeys.create(GlobalPreferenceKeys.UNIT_TYPE), unitTypeDataProcessor) + preferencesManager?.setUpListener() + preferencesManager?.let { unitTypeDataProcessor.onNext(it.unitType) } + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + when { + velocityProcessor.value.z < 0 -> { + verticalVelocityStateProcessor.onNext( + UpwardVelocity( + abs(velocityProcessor.value.z).toVelocity(unitTypeDataProcessor.value), + unitTypeDataProcessor.value + ) + ) + } + velocityProcessor.value.z > 0 -> { + verticalVelocityStateProcessor.onNext( + DownwardVelocity( + abs(velocityProcessor.value.z).toVelocity(unitTypeDataProcessor.value), + unitTypeDataProcessor.value + ) + ) + } + else -> { + verticalVelocityStateProcessor.onNext(Idle(unitTypeDataProcessor.value)) + } + } + } else { + verticalVelocityStateProcessor.onNext(ProductDisconnected) + } + } + + override fun inCleanup() { + preferencesManager?.cleanup() + } + + /** + * Class to represent states of vertical velocity + */ + sealed class VerticalVelocityState { + /** + * When product is disconnected + */ + object ProductDisconnected : VerticalVelocityState() + + /** + * When aircraft is not moving vertically + */ + data class Idle(val unitType: UnitType) : VerticalVelocityState() + + /** + * When aircraft is moving in upward direction + */ + data class UpwardVelocity(val velocity: Double, val unitType: UnitType) : + VerticalVelocityState() + + /** + * When aircraft is moving in downward direction + */ + data class DownwardVelocity(val velocity: Double, val unitType: UnitType) : + VerticalVelocityState() + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/videosignal/VideoSignalWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/videosignal/VideoSignalWidget.kt new file mode 100644 index 00000000..ca954719 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/videosignal/VideoSignalWidget.kt @@ -0,0 +1,412 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.videosignal + +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.ColorStateList +import android.graphics.PorterDuff +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.util.Pair +import android.view.View +import android.widget.ImageView +import android.widget.TextView +import androidx.annotation.* +import androidx.annotation.IntRange +import androidx.core.content.res.use +import dji.sdk.keyvalue.value.airlink.FrequencyBand +import dji.v5.utils.common.DisplayUtil +import dji.v5.utils.common.SDRLinkHelper +import io.reactivex.rxjava3.core.Flowable +import io.reactivex.rxjava3.disposables.Disposable +import io.reactivex.rxjava3.functions.Consumer +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.widget.videosignal.VideoSignalWidget.ModelState.* +import dji.v5.ux.core.util.UxErrorHandle + +/** + * This widget shows the strength of the video signal between the + * aircraft and the app through the RC. + */ +open class VideoSignalWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ConstraintLayoutWidget(context, attrs, defStyleAttr) { + + //region Fields + private val videoIconImageView: ImageView = findViewById(R.id.imageview_video_icon) + private val videoSignalImageView: ImageView = findViewById(R.id.imageview_video_signal) + private val frequencyBandTextView: TextView = findViewById(R.id.textview_frequency_band) + private val widgetModel: VideoSignalWidgetModel by lazy { + VideoSignalWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance() + ) + } + + /** + * The color of the video display icon when the product is connected + */ + @get:ColorInt + var connectedStateIconColor: Int = getColor(R.color.uxsdk_white) + set(@ColorInt value) { + field = value + checkAndUpdateIconColor() + } + + /** + * The color of the video display icon when the product is disconnected + */ + @get:ColorInt + var disconnectedStateIconColor: Int = getColor(R.color.uxsdk_gray_58) + set(@ColorInt value) { + field = value + checkAndUpdateIconColor() + } + + /** + * Icon for video + */ + var videoIcon: Drawable? + get() = videoIconImageView.imageDrawable + set(value) { + videoIconImageView.imageDrawable = value + } + + /** + * Background of the video icon + */ + var videoIconBackground: Drawable? + get() = videoIconImageView.background + set(value) { + videoIconImageView.background = value + } + + /** + * Icon for the video signal strength + */ + var videoSignalIcon: Drawable? + get() = videoSignalImageView.imageDrawable + set(value) { + videoSignalImageView.imageDrawable = value + } + + /** + * Background of the video signal strength icon + */ + var videoSignalIconBackground: Drawable? + get() = videoSignalImageView.background + set(value) { + videoSignalImageView.background = value + } + + /** + * ColorStateList for the frequency band text + */ + var textColors: ColorStateList? + get() = frequencyBandTextView.textColorStateList + set(value) { + frequencyBandTextView.textColorStateList = value + } + + /** + * Color for the frequency band text + */ + var textColor: Int + @ColorInt + get() = frequencyBandTextView.textColor + set(@ColorInt value) { + frequencyBandTextView.textColor = value + } + + /** + * Size for the frequency band text + */ + var textSize: Float + @Dimension + get() = frequencyBandTextView.textSize + set(@Dimension textSize) { + frequencyBandTextView.textSize = textSize + } + + /** + * Background for the frequency band text + */ + var textBackground: Drawable? + get() = frequencyBandTextView.background + set(drawable) { + frequencyBandTextView.background = drawable + } + //endregion + + //region Constructor + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + View.inflate(context, R.layout.uxsdk_widget_video_signal, this) + } + + init { + attrs?.let { initAttributes(context, it) } + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { this.updateIconColor(it) }) + addReaction(widgetModel.videoSignalQuality + .observeOn(SchedulerProvider.ui()) + .subscribe { this.updateVideoSignal(it) }) + addReaction(widgetModel.airlinkFrequencyBand + .observeOn(SchedulerProvider.ui()) + .subscribe { this.updateWifiFrequencyBandText(it) }) + addReaction(reactToOcuSyncFrequencyStateChange()) + + } + //endregion + + //region Reactions to model + private fun updateVideoSignal(@IntRange(from = 0, to = 100) videoSignalQuality: Int) { + widgetStateDataProcessor.onNext(VideoSignalQualityUpdated(videoSignalQuality)) + videoSignalImageView.setImageLevel(videoSignalQuality) + } + + private fun updateIconColor(isConnected: Boolean) { + widgetStateDataProcessor.onNext(ProductConnected(isConnected)) + if (isConnected) { + videoIconImageView.setColorFilter(connectedStateIconColor, PorterDuff.Mode.SRC_IN) + } else { + videoIconImageView.setColorFilter(disconnectedStateIconColor, PorterDuff.Mode.SRC_IN) + frequencyBandTextView.text = "" + } + } + //endregion + + //region helpers + + private fun checkAndUpdateIconColor() { + if (!isInEditMode) { + addDisposable(widgetModel.productConnection.firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(Consumer { this.updateIconColor(it) }, UxErrorHandle.logErrorConsumer(TAG, "Update Icon Color ")) + ) + } + } + + private fun updateWifiFrequencyBandText(frequencyBandType: FrequencyBand) { + widgetStateDataProcessor.onNext(AirlinkFrequencyBandUpdated(frequencyBandType)) + if (frequencyBandType != FrequencyBand.UNKNOWN) { + frequencyBandTextView.text = when (frequencyBandType) { + FrequencyBand.BAND_2_DOT_4G -> FREQUENCY_BAND_2_DOT_4_GHZ + FrequencyBand.BAND_1_DOT_4G -> FREQUENCY_BAND_2_DOT_4_GHZ + FrequencyBand.BAND_MULTI -> FREQUENCY_BAND_5_GHZ + else -> "" + } + } + } + + private fun reactToOcuSyncFrequencyStateChange(): Disposable { + return Flowable.combineLatest( + widgetModel.airlinkFrequencyBand, + widgetModel.ocuSyncFrequencyPointIndex, + { ocuSyncFrequencyBand, signalQuality -> Pair.create(ocuSyncFrequencyBand, signalQuality) }) + .observeOn(SchedulerProvider.ui()) + .subscribe { values -> + widgetStateDataProcessor.onNext(AirlinkFrequencyBandUpdated(values.first)) + if (values.first != FrequencyBand.UNKNOWN) { + frequencyBandTextView.text = when (values.first) { + FrequencyBand.BAND_2_DOT_4G -> FREQUENCY_BAND_2_DOT_4_GHZ + FrequencyBand.BAND_5_DOT_8G -> FREQUENCY_BAND_5_DOT_8_GHZ + FrequencyBand.BAND_MULTI -> getAutoFrequencyBandStr(values.second) + else -> "" + } + } + + } + } + + private fun getAutoFrequencyBandStr(ocuFrequencyPoint: Int): String { + return if (ocuFrequencyPoint > SDRLinkHelper.ORIGINAL_NF_2DOT4G_START_FREQ && ocuFrequencyPoint < SDRLinkHelper.ORIGINAL_NF_5DOT8G_START_FREQ) { + FREQUENCY_BAND_2_DOT_4_GHZ + } else if (ocuFrequencyPoint > SDRLinkHelper.ORIGINAL_NF_5DOT8G_START_FREQ) { + FREQUENCY_BAND_5_DOT_8_GHZ + } else { + "" + } + } + + //endregion + + //region Customization + override fun getIdealDimensionRatioString() = null + + /** + * Set the resource ID for the video display icon + * + * @param resourceId Integer ID of the drawable resource + */ + fun setVideoIcon(@DrawableRes resourceId: Int) { + videoIcon = getDrawable(resourceId) + } + + /** + * Set the resource ID for the video display icon's background + * + * @param resourceId Integer ID of the background resource + */ + fun setVideoIconBackground(@DrawableRes resourceId: Int) { + videoIconBackground = getDrawable(resourceId) + } + + /** + * Set the resource ID for the video signal icon + * + * @param resourceId Integer ID of the drawable resource + */ + fun setVideoSignalIcon(@DrawableRes resourceId: Int) { + videoSignalIcon = getDrawable(resourceId) + } + + + /** + * Set the resource ID for the video signal icon's background + * + * @param resourceId Integer ID of the background resource + */ + fun setVideoSignalIconBackground(@DrawableRes resourceId: Int) { + videoSignalIconBackground = getDrawable(resourceId) + } + + /** + * Set text appearance of the frequency band text view + * + * @param textAppearance Style resource for text appearance + */ + fun setTextAppearance(@StyleRes textAppearance: Int) { + frequencyBandTextView.setTextAppearance(context, textAppearance) + } + //endregion + + //region Customization Helpers + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.VideoSignalWidget).use { typedArray -> + typedArray.getDrawableAndUse(R.styleable.VideoSignalWidget_uxsdk_videoIcon) { + videoIcon = it + } + + typedArray.getDrawableAndUse(R.styleable.VideoSignalWidget_uxsdk_videoSignalIcon) { + videoSignalIcon = it + } + + typedArray.getResourceIdAndUse(R.styleable.VideoSignalWidget_uxsdk_frequencyBandTextAppearance) { + setTextAppearance(it) + } + + typedArray.getDimensionAndUse(R.styleable.VideoSignalWidget_uxsdk_frequencyBandTextSize) { + textSize = DisplayUtil.pxToSp(context, it) + } + + typedArray.getColorAndUse(R.styleable.VideoSignalWidget_uxsdk_frequencyBandTextColor) { + textColor = it + } + + typedArray.getDrawableAndUse(R.styleable.VideoSignalWidget_uxsdk_frequencyBandBackgroundDrawable) { + textBackground = it + } + + connectedStateIconColor = typedArray.getColor( + R.styleable.VideoSignalWidget_uxsdk_connectedStateIconColor, + connectedStateIconColor + ) + disconnectedStateIconColor = typedArray.getColor( + R.styleable.VideoSignalWidget_uxsdk_disconnectedStateIconColor, + disconnectedStateIconColor + ) + } + } + //endregion + + //region Hooks + + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines the widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Video signal quality / strength update + */ + data class VideoSignalQualityUpdated(val signalQuality: Int) : ModelState() + + /** + * WiFi frequency band update + */ + data class AirlinkFrequencyBandUpdated(val frequencyBandType: FrequencyBand) : + ModelState() + } + + //endregion + + companion object { + private const val TAG = "VideoSignalWidget" + private const val FREQUENCY_BAND_2_DOT_4_GHZ = "2.4G" + private const val FREQUENCY_BAND_5_GHZ = "5G" + private const val FREQUENCY_BAND_5_DOT_7_GHZ = "5.7G" + private const val FREQUENCY_BAND_5_DOT_8_GHZ = "5.8G" + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/videosignal/VideoSignalWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/videosignal/VideoSignalWidgetModel.kt new file mode 100644 index 00000000..26c8f822 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/videosignal/VideoSignalWidgetModel.kt @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.videosignal + +import dji.sdk.keyvalue.key.AirLinkKey +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.value.airlink.FrequencyBand +import dji.v5.utils.common.LogUtils +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor + +/** + * Widget Model for the [VideoSignalWidget] used to define + * the underlying logic and communication + */ +class VideoSignalWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, keyedStore) { + + //region Fields + private val tag = LogUtils.getTag("VideoSignalWidgetModel") + private val videoSignalQualityProcessor: DataProcessor = DataProcessor.create(0) + private val airlinkFrequencyBandProcessor: DataProcessor = DataProcessor.create(FrequencyBand.UNKNOWN) + + private var signalValue: Int = 0 + private val ocuFrequencyPointIndexProcessor: DataProcessor = DataProcessor.create(0) + //endregion + + //region Data + /** + * Get the value of the strength of the video signal as an integer. + */ + val videoSignalQuality: Flowable + get() = videoSignalQualityProcessor.toFlowable() + + val ocuSyncFrequencyPointIndex: Flowable + get() = ocuFrequencyPointIndexProcessor.toFlowable() + + val airlinkFrequencyBand: Flowable + get() = airlinkFrequencyBandProcessor.toFlowable() + + //region Lifecycle + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + AirLinkKey.KeyFrequencyPoint), ocuFrequencyPointIndexProcessor) + bindDataProcessor( + KeyTools.createKey( + AirLinkKey.KeyDownLinkQualityRaw), videoSignalQualityProcessor) + bindDataProcessor( + KeyTools.createKey( + AirLinkKey.KeyFrequencyBand), airlinkFrequencyBandProcessor) + } + + override fun inCleanup() { + // Nothing to clean + } + + override fun updateStates() { +// LogUtils.d(tag,"TODO Method not implemented yet") + } + + override fun onProductConnectionChanged(isConnected: Boolean) { + if (!isConnected) { + signalValue = 0 + } + } +} +//endregion diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/vps/VPSWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/vps/VPSWidget.kt new file mode 100644 index 00000000..8d428ed3 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/vps/VPSWidget.kt @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.vps + +import android.annotation.SuppressLint +import android.content.Context +import android.content.res.TypedArray +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import androidx.annotation.DrawableRes +import androidx.core.content.res.use +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.WidgetSizeDescription +import dji.v5.ux.core.base.widget.BaseTelemetryWidget +import dji.v5.ux.core.communication.GlobalPreferencesManager +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.widget.vps.VPSWidget.ModelState +import dji.v5.ux.core.widget.vps.VPSWidgetModel.VPSState +import java.text.DecimalFormat + +private const val MIN_VPS_HEIGHT = 1.2f + +/** + * Shows the status of the vision positioning system + * as well as the height of the aircraft as received from the + * vision positioning system if available. + */ +open class VPSWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0, + widgetTheme: Int = 0 +) : BaseTelemetryWidget( + context, + attrs, + defStyleAttr, + WidgetType.TEXT_IMAGE_RIGHT, + widgetTheme, + R.style.UXSDKVPSWidget +) { + + //region Fields + override val metricDecimalFormat: DecimalFormat = DecimalFormat("###0.0") + + override val imperialDecimalFormat: DecimalFormat = DecimalFormat("###0") + + /** + * Icon for VPS enabled + */ + var vpsEnabledIcon: Drawable = getDrawable(R.drawable.uxsdk_ic_vps_enabled) + + /** + * Icon for VPS disabled + */ + var vpsDisabledIcon: Drawable = getDrawable(R.drawable.uxsdk_ic_vps_disabled) + + private val widgetModel: VPSWidgetModel by lazy { + VPSWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + GlobalPreferencesManager.getInstance()) + } + //endregion + + //region Constructor + init { + initThemeAttributes(context, widgetTheme) + initAttributes(context, attrs) + setValueTextViewMinWidthByText("88.8") + } + //endregion + + //region Lifecycle + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ModelState.ProductConnected(it)) }) + addReaction(widgetModel.vpsState + .observeOn(SchedulerProvider.ui()) + .subscribe { updateUI(it) }) + } + //endregion + + //region Reaction to model + private fun updateUI(vpsState: VPSState) { + widgetStateDataProcessor.onNext(ModelState.VPSStateUpdated(vpsState)) + when (vpsState) { + VPSState.ProductDisconnected, + VPSState.Disabled -> updateToDisconnectedState() + is VPSState.Enabled -> updateVPSState(vpsState) + } + } + + private fun updateVPSState(vpsState: VPSState.Enabled) { + widgetIcon = vpsEnabledIcon + unitString = getDistanceString(vpsState.unitType) + valueString = getDecimalFormat(vpsState.unitType).format(vpsState.height) + valueTextColor = if (vpsState.height > MIN_VPS_HEIGHT.toDistance(vpsState.unitType)) { + normalValueColor + } else { + errorValueColor + } + } + + private fun updateToDisconnectedState() { + unitString = null + widgetIcon = vpsDisabledIcon + valueString = getString(R.string.uxsdk_string_default_value) + valueTextColor = normalValueColor + } + //endregion + + //region Customization + override fun getIdealDimensionRatioString(): String? = null + + + override val widgetSizeDescription: WidgetSizeDescription = + WidgetSizeDescription(WidgetSizeDescription.SizeType.OTHER, + widthDimension = WidgetSizeDescription.Dimension.EXPAND, + heightDimension = WidgetSizeDescription.Dimension.WRAP) + + /** + * Set the icon for VPS enabled + * + * @param resourceId Integer ID of the icon + */ + fun setVPSEnabledIcon(@DrawableRes resourceId: Int) { + vpsEnabledIcon = getDrawable(resourceId) + } + + /** + * Set the icon for VPS disabled + * + * @param resourceId Integer ID of the icon + */ + fun setVPSDisabledIcon(@DrawableRes resourceId: Int) { + vpsDisabledIcon = getDrawable(resourceId) + } + + @SuppressLint("Recycle") + private fun initThemeAttributes(context: Context, widgetTheme: Int) { + val vpsAttributeArray: IntArray = R.styleable.VPSWidget + context.obtainStyledAttributes(widgetTheme, vpsAttributeArray).use { + initAttributesByTypedArray(it) + } + } + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet?) { + context.obtainStyledAttributes(attrs, R.styleable.VPSWidget, 0, defaultStyle).use { + initAttributesByTypedArray(it) + } + } + + private fun initAttributesByTypedArray(typedArray: TypedArray) { + typedArray.getDrawableAndUse(R.styleable.VPSWidget_uxsdk_vpsEnabledIcon) { + vpsEnabledIcon = it + } + typedArray.getDrawableAndUse(R.styleable.VPSWidget_uxsdk_vpsDisabledIcon) { + vpsDisabledIcon = it + } + } + + //endregion + + //region Hooks + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines widget state updates + */ + sealed class ModelState { + + /** + * Product connection update + */ + data class ProductConnected(val boolean: Boolean) : ModelState() + + /** + * VPS model state + */ + data class VPSStateUpdated(val vpsState: VPSState) : ModelState() + } + //endregion + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/vps/VPSWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/vps/VPSWidgetModel.kt new file mode 100644 index 00000000..ef508648 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/core/widget/vps/VPSWidgetModel.kt @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.core.widget.vps + +import dji.sdk.keyvalue.key.FlightAssistantKey +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.key.KeyTools +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.GlobalPreferenceKeys +import dji.v5.ux.core.communication.GlobalPreferencesInterface +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.toDistance +import dji.v5.ux.core.util.DataProcessor +import dji.v5.ux.core.util.UnitConversionUtil +import io.reactivex.rxjava3.core.Flowable + +/** + * Widget Model for the [VPSWidget] used to define + * the underlying logic and communication + */ +class VPSWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, + private val preferencesManager: GlobalPreferencesInterface? +) : WidgetModel(djiSdkModel, keyedStore) { + + private val unitTypeDataProcessor: DataProcessor = DataProcessor.create(UnitConversionUtil.UnitType.METRIC) + private val visionPositioningEnabledProcessor: DataProcessor = DataProcessor.create(false) + private val ultrasonicBeingUsedProcessor: DataProcessor = DataProcessor.create(false) + private val rawUltrasonicHeightProcessor: DataProcessor = DataProcessor.create(0) + private val vpsStateProcessor: DataProcessor = DataProcessor.create(VPSState.ProductDisconnected) + + /** + * Get the current VPS state + */ + val vpsState: Flowable + get() = vpsStateProcessor.toFlowable() + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightAssistantKey.KeyVisionPositioningEnabled), visionPositioningEnabledProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyIsUltrasonicUsed), ultrasonicBeingUsedProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyUltrasonicHeight), rawUltrasonicHeightProcessor) + + val unitTypeKey = GlobalPreferenceKeys.create(GlobalPreferenceKeys.UNIT_TYPE) + bindDataProcessor(unitTypeKey, unitTypeDataProcessor) + preferencesManager?.setUpListener() + preferencesManager?.let { unitTypeDataProcessor.onNext(it.unitType) } + } + + override fun updateStates() { + if (productConnectionProcessor.value) { + if (ultrasonicBeingUsedProcessor.value + && visionPositioningEnabledProcessor.value) { + vpsStateProcessor.onNext( + VPSState.Enabled( + rawUltrasonicHeightProcessor.value.toFloat().toDistance(unitTypeDataProcessor.value), + unitTypeDataProcessor.value + ) + ) + } else { + vpsStateProcessor.onNext(VPSState.Disabled) + } + } else { + vpsStateProcessor.onNext(VPSState.ProductDisconnected) + } + } + + override fun inCleanup() { + preferencesManager?.cleanup() + } + + /** + * Class to represent states of VPS + */ + sealed class VPSState { + + /** + * When product is disconnected + */ + object ProductDisconnected : VPSState() + + /** + * Vision disabled or ultrasonic is not being used + */ + object Disabled : VPSState() + + /** + * Current VPS height + */ + data class Enabled(val height: Float, val unitType: UnitConversionUtil.UnitType) : + VPSState() + + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/DistanceLimitWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/DistanceLimitWidget.java new file mode 100644 index 00000000..6e265e9f --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/DistanceLimitWidget.java @@ -0,0 +1,190 @@ +package dji.v5.ux.flight.flightparam; + + +import static dji.sdk.keyvalue.value.flightcontroller.GoHomePathMode.HEIGHT_FIXED; +import static dji.sdk.keyvalue.value.flightcontroller.GoHomePathMode.UNKNOWN; +import static dji.v5.ux.core.base.SchedulerProvider.ui; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.View; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.sdk.keyvalue.value.flightcontroller.FailsafeAction; +import dji.sdk.keyvalue.value.flightcontroller.GoHomePathMode; +import dji.v5.ux.R; +import dji.v5.ux.accessory.DescSpinnerCell; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.EditorCell; +import dji.v5.ux.core.base.SchedulerProvider; +import dji.v5.ux.core.base.SwitcherCell; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.ViewUtil; +import io.reactivex.rxjava3.core.CompletableObserver; +import io.reactivex.rxjava3.disposables.Disposable; +import io.reactivex.rxjava3.functions.Consumer; + +public class DistanceLimitWidget extends ConstraintLayoutWidget implements EditorCell.OnValueChangedListener { + + private DistanceLimitWidgetModel widgetModel = new DistanceLimitWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + + private EditorCell mGoHomeEditCell; + + private EditorCell mMaxHeightEditCell; + private EditorCell mMaxRadiusEditorCell; + private SwitcherCell mMaxRadiusCell; + private TextView mRTHTipTv; + private int maxHeight = 500; + private static final int ALARM_HEIGHT = 120; + private static final int CONFIRM_ALARM_HEIGHT = 500; + public DistanceLimitWidget(@NonNull Context context) { + super(context); + } + + public DistanceLimitWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public DistanceLimitWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_setting_menu_limit_distance_set_layout, this); + mGoHomeEditCell = findViewById(R.id.setting_menu_aircraft_goHomeAttitude); + mGoHomeEditCell.setOnValueChangedListener(this); + mMaxHeightEditCell = findViewById(R.id.setting_menu_aircraft_maxHeight); + mMaxHeightEditCell.setOnValueChangedListener(this); + mMaxRadiusEditorCell = findViewById(R.id.setting_menu_aircraft_maxRadius); + mMaxRadiusEditorCell.setOnValueChangedListener(this); + mMaxRadiusCell = findViewById(R.id.setting_menu_aircraft_maxRadius_switch); + mRTHTipTv = findViewById(R.id.setting_menu_aircraft_go_home_mode_desc); + + mMaxRadiusCell.setOnCheckedChangedListener((cell, isChecked) -> { + widgetModel.setDistanceLimitEnabled(isChecked).subscribe(); + if(isChecked) { + mMaxRadiusEditorCell.setVisibility(VISIBLE); + } else { + mMaxRadiusEditorCell.setVisibility(GONE); + } + }); + + } + + + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.getGoHomeHeight().observeOn(ui()).subscribe(this::updateGoHomeHeight)); + addReaction(widgetModel.getHomeLimitHeight().observeOn(ui()).subscribe(this::updateHeightLimit)); + addReaction(widgetModel.getDistanceLimit().observeOn(ui()).subscribe(this::updateDistanceLimit)); + addReaction(widgetModel.getDistanceLimitEnabled().observeOn(ui()).subscribe(this::updateDistanceLimitEnable)); + addReaction(widgetModel.getGoHomePathMode().observeOn(ui()).subscribe(this::updateGoHomeMode)); + } + + private void updateGoHomeMode(GoHomePathMode goHomePathMode) { + // 别的飞机可能没有智能返航功能,如果是UNKNOWN的话,认为是旧的设定高度返航模式,提示设定高度返航的文案 + if (goHomePathMode == HEIGHT_FIXED || goHomePathMode == UNKNOWN) { + mRTHTipTv.setText(R.string.uxsdk_setting_menu_flyc_smart_rth_set_altitude); + } else { + mRTHTipTv.setText(R.string.uxsdk_setting_menu_flyc_smart_rth_smart_altitude); + } + } + + private void updateDistanceLimitEnable(Boolean isChecked) { + mMaxRadiusCell.setChecked(isChecked); + if(isChecked) { + mMaxRadiusEditorCell.setVisibility(VISIBLE); + } else { + mMaxRadiusEditorCell.setVisibility(GONE); + } + } + + private void updateDistanceLimit(Integer integer) { + mMaxRadiusEditorCell.setValue(integer); + } + + private void updateHeightLimit(Integer integer) { + maxHeight = integer; + mMaxHeightEditCell.setValue(integer); + } + + private void updateGoHomeHeight(Integer integer) { + mGoHomeEditCell.setValue(integer); + } + + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + } + + + @Override + public void onValueChanged(EditorCell cell, int inputValue, int validValue) { + if (inputValue > cell.getMaxValue() || inputValue < cell.getMinValue()) { + ViewUtil.showToast(getContext() , R.string.uxsdk_setting_menu_setting_fail , Toast.LENGTH_SHORT); + return; + } + if (cell.getId() == R.id.setting_menu_aircraft_goHomeAttitude) { + if (inputValue > maxHeight) { + ViewUtil.showToast(getContext() , R.string.uxsdk_setting_menu_flyc_gohome_altitude_limit , Toast.LENGTH_SHORT); + return; + } + widgetModel.setGoHomeHeight( inputValue).observeOn(ui()).subscribe(getFinishObserve()); + } else if(cell.getId() == R.id.setting_menu_aircraft_maxHeight) { + checkMaxFlightHeight(inputValue); + widgetModel.setHeightLimit( inputValue).observeOn(ui()).subscribe(getFinishObserve()); + } else if(cell.getId() == R.id.setting_menu_aircraft_maxRadius){ + widgetModel.setDistanceLimit(inputValue).observeOn(ui()).subscribe(getFinishObserve()); + } + + } + + private void checkMaxFlightHeight(int inputValue) { + if(inputValue <= CONFIRM_ALARM_HEIGHT && inputValue > ALARM_HEIGHT){ + ViewUtil.showToast(getContext() , getContext().getString(R.string.uxsdk_setting_menu_flyc_limit_high_notice) , Toast.LENGTH_LONG); + }else if (inputValue > CONFIRM_ALARM_HEIGHT){ + ViewUtil.showToast(getContext() , getContext().getString(R.string.uxsdk_setting_menu_flyc_limit_high_notice_above_500) , Toast.LENGTH_LONG); + } + + + } + + private CompletableObserver getFinishObserve(){ + return new CompletableObserver() { + @Override + public void onSubscribe(@io.reactivex.rxjava3.annotations.NonNull Disposable d) { + //do nothing + } + + @Override + public void onComplete() { + ViewUtil.showToast(getContext(), R.string.uxsdk_setting_menu_setting_success , Toast.LENGTH_SHORT); + } + + @Override + public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) { + //add log + } + }; + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/DistanceLimitWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/DistanceLimitWidgetModel.java new file mode 100644 index 00000000..4315b8cb --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/DistanceLimitWidgetModel.java @@ -0,0 +1,81 @@ +package dji.v5.ux.flight.flightparam; + + +import androidx.annotation.NonNull; + +import dji.sdk.keyvalue.key.FlightControllerKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.value.flightcontroller.GoHomePathMode; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Completable; +import io.reactivex.rxjava3.core.Flowable; + +public class DistanceLimitWidgetModel extends WidgetModel { + + private final DataProcessor goHomeHeightDataProcessor = DataProcessor.create(500); + private final DataProcessor heightLimitDataProcessor = DataProcessor.create(500); + private final DataProcessor distanceLimitDataProcessor = DataProcessor.create(5000); + private final DataProcessor distanceLimitEnableDataProcessor = DataProcessor.create(false); + private final DataProcessor goHomePathModeProcessor = DataProcessor.create(GoHomePathMode.UNKNOWN); + + protected DistanceLimitWidgetModel(@NonNull DJISDKModel djiSdkModel, @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + } + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyGoHomeHeight), goHomeHeightDataProcessor); + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyHeightLimit), heightLimitDataProcessor); + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyDistanceLimit) , distanceLimitDataProcessor); + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyDistanceLimitEnabled) , distanceLimitEnableDataProcessor); + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyGoHomePathMode) , goHomePathModeProcessor); + } + + @Override + protected void inCleanup() { + //do nothing + } + + public Flowable getGoHomePathMode(){ + return goHomePathModeProcessor.toFlowable(); + } + + public Flowable getGoHomeHeight(){ + return goHomeHeightDataProcessor.toFlowable(); + } + + + public Completable setGoHomeHeight(int value) { + return djiSdkModel.setValue(KeyTools.createKey(FlightControllerKey.KeyGoHomeHeight) , value); + } + + + public Flowable getHomeLimitHeight(){ + return heightLimitDataProcessor.toFlowable(); + } + + public Completable setHeightLimit(int value) { + return djiSdkModel.setValue(KeyTools.createKey(FlightControllerKey.KeyHeightLimit) , value); + } + + + public Flowable getDistanceLimit(){ + return distanceLimitDataProcessor.toFlowable(); + } + + public Completable setDistanceLimit(int value) { + return djiSdkModel.setValue(KeyTools.createKey(FlightControllerKey.KeyDistanceLimit) , value); + } + + public Flowable getDistanceLimitEnabled(){ + return distanceLimitEnableDataProcessor.toFlowable(); + } + + public Completable setDistanceLimitEnabled(boolean value) { + return djiSdkModel.setValue(KeyTools.createKey(FlightControllerKey.KeyDistanceLimitEnabled) , value); + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/FlightModeWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/FlightModeWidget.java new file mode 100644 index 00000000..3b9b0368 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/FlightModeWidget.java @@ -0,0 +1,54 @@ +package dji.v5.ux.flight.flightparam; + + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.sdk.keyvalue.value.flightcontroller.FailsafeAction; +import dji.v5.ux.R; +import dji.v5.ux.accessory.DescSpinnerCell; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.SchedulerProvider; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; + +public class FlightModeWidget extends ConstraintLayoutWidget { + + public FlightModeWidget(@NonNull Context context) { + super(context); + } + + public FlightModeWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public FlightModeWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_widget_flight_fpa, this); + + } + + @Override + protected void reactToModelChanges() { + //add log + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + } + + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/FpaView.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/FpaView.java new file mode 100644 index 00000000..b68678a8 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/FpaView.java @@ -0,0 +1,292 @@ +package dji.v5.ux.flight.flightparam; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.LinearLayout; +import android.widget.TextView; +import android.widget.Toast; + +import androidx.annotation.NonNull; + +import java.util.Arrays; + +import dji.sdk.keyvalue.key.FlightControllerKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.key.RemoteControllerKey; +import dji.sdk.keyvalue.value.flightcontroller.ControlChannelMapping; +import dji.sdk.keyvalue.value.remotecontroller.RemoteControllerType; +import dji.v5.common.callback.CommonCallbacks; +import dji.v5.common.error.IDJIError; +import dji.v5.manager.KeyManager; +import dji.v5.utils.common.AndUtil; +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.base.SwitcherCell; +import dji.v5.ux.core.base.TabSelectCell; +import dji.v5.ux.core.util.ViewUtil; + +/* + * Copyright (c) 2017, DJI All Rights Reserved. + */ + +/** + *

    Created by luca on 2017/6/13.

    + */ + +public class FpaView extends LinearLayout implements SwitcherCell.OnCheckedChangedListener, TabSelectCell.OnTabChangeListener { + private static final String TAG = "FpaView"; + private TextView mDescView; + private SwitcherCell mSwitcherCell; + private TabSelectCell mFlycModeTabCell; + private View mDividerTv; + + private int[] modeDrawable = new int[]{R.drawable.uxsdk_setting_ui_flyc_smart_controller_rc_mode_aps,R.drawable.uxsdk_setting_ui_flyc_smart_controller_rc_mode}; + + public FpaView(Context context) { + this(context, null); + } + + public FpaView(Context context, AttributeSet attrs) { + this(context, attrs, 0); + } + + public FpaView(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + LayoutInflater.from(context).inflate(R.layout.uxsdk_setting_menu_flyc_mode, this, true); + setOrientation(VERTICAL); + modeDrawable[0] = getRes(R.drawable.uxsdk_setting_ui_flyc_m3e_rc_mode_ans, R.drawable.uxsdk_setting_ui_flyc_c_plus_rc_mode_aps, R.drawable.uxsdk_setting_ui_flyc_smart_controller_rc_mode_aps); + modeDrawable[1] = getRes(R.drawable.uxsdk_setting_ui_flyc_m3e_rc_mode_tns, R.drawable.uxsdk_setting_ui_flyc_rc_plus_rc_mode, R.drawable.uxsdk_setting_ui_flyc_smart_controller_rc_mode); + + mDescView = findViewById(R.id.setting_ui_flyc_mode); + mSwitcherCell = findViewById(R.id.setting_ui_flyc_mode_switch); + mFlycModeTabCell = findViewById(R.id.setting_ui_flyc_mode_tab); + mDividerTv = findViewById(R.id.setting_ui_flyc_mode_divider); + } + +// public void setPresenter(FlycMenuContract.Presenter presenter) { +// +// } + + @Override + protected void onFinishInflate() { + super.onFinishInflate(); + + mFlycModeTabCell.addTabs(0, Arrays.asList(getResources().getStringArray(getRes(R.array.uxsdk_flight_mode_rc510, R.array.uxsdk_flight_mode_smart_controller, R.array.uxsdk_flight_mode)))); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + KeyManager.getInstance().listen(KeyTools.createKey(FlightControllerKey.KeyMultipleFlightModeEnabled), this, (oldValue, open) -> { + LogUtils.d( TAG, "MultipleFlightModeEnabled = " + open); + mSwitcherCell.setOnCheckedChangedListener(null); + mSwitcherCell.setChecked(Boolean.TRUE.equals(open)); + mSwitcherCell.setOnCheckedChangedListener(FpaView.this); + updateView(Boolean.TRUE.equals(open)); + }); + + } + + @Override + protected void onDetachedFromWindow() { + KeyManager.getInstance().cancelListen(this); + super.onDetachedFromWindow(); + } + + @Override + public void onCheckedChanged(SwitcherCell cell, final boolean isChecked) { + + KeyManager.getInstance().setValue(KeyTools.createKey(FlightControllerKey.KeyMultipleFlightModeEnabled), isChecked, new CommonCallbacks.CompletionCallback() { + @Override + public void onSuccess() { + //关闭允许切换飞行模式开关时,将飞行档位切换至三角架模式 T/P/S + if (!isChecked && mFlycModeTabCell.getCurrentTab() == 1) { + setTripodFlycMode(); + } + } + + @Override + public void onFailure(@NonNull IDJIError error) { + mSwitcherCell.setOnCheckedChangedListener(null); + mSwitcherCell.setChecked(!isChecked); + mSwitcherCell.setOnCheckedChangedListener(FpaView.this); + } + }); + + } + + @Override + public void onTabChanged(TabSelectCell cell, int oldIndex, int newIndex) { + if(oldIndex == newIndex){ + return; + } + if (newIndex == 1) { + //姿态模式 A/P/S + showAttiFlycModeDialog(oldIndex); + } else { + //切换至三角架模式 T/P/S + setTripodFlycMode(); + } + } + + /** + * 切换至 T/P/S 飞行档位 + */ + private void setTripodFlycMode() { + + KeyManager.getInstance().setValue(KeyTools.createKey(FlightControllerKey.KeyCustomFunctionMode), ControlChannelMapping.TRIPOD, new CommonCallbacks.CompletionCallback() { + @Override + public void onSuccess() { + updateFlycModeDescView(0); + } + + @Override + public void onFailure(@NonNull IDJIError error) { + setTabCellCurrentTab(1); + ViewUtil.showToast(getContext() ,AndUtil.getResString(R.string.uxsdk_setting_menu_setting_fail)); + } + }); + + } + + /** + * 根据不同机型显示不同布局与文案 + * + * @param open 切换飞行模式开关,false则不显示具体内容,true则显示具体详情 + */ + private void updateView(boolean open) { + //UI控件显示与隐藏 + setVisibility(View.VISIBLE); + int visible = open ? VISIBLE : GONE; + mSwitcherCell.setBottomDividerEnable(!open); + mDescView.setVisibility(visible); + mDividerTv.setVisibility(visible); + mFlycModeTabCell.setVisibility(GONE); + updateFlycModeValue(); + } + + /** + * 通过飞行模式配置表获取当前飞行模式 + */ + private void updateFlycModeValue() { + + KeyManager.getInstance().getValue(KeyTools.createKey(FlightControllerKey.KeyCustomFunctionMode), new CommonCallbacks.CompletionCallbackWithParam() { + @Override + public void onSuccess(ControlChannelMapping config) { + updateFlycModeView(config); + } + + @Override + public void onFailure(@NonNull IDJIError error) { + //add log + } + }); + + } + + private void updateFlycModeView(ControlChannelMapping channelMapping) { + //从飞机获取的飞行模式配置表,刷新页面内容 + int currentTab = channelMapping == ControlChannelMapping.ATTITUDE_NORMAL ? 1 : 0; + setTabCellCurrentTab(currentTab); + mFlycModeTabCell.setVisibility(mSwitcherCell.isChecked() ? VISIBLE : GONE); + //根据T/P/S或A/P/S显示不同的描述文案 + updateFlycModeDescView(currentTab); + } + + /** + * 切换为A/P/S时弹出dialog提示用户同意免责协议方可切换 + * + * @param oldIndex + */ + private void showAttiFlycModeDialog(int oldIndex) { + LogUtils.d(TAG , "curIndex " + oldIndex); + KeyManager.getInstance().setValue(KeyTools.createKey(FlightControllerKey.KeyCustomFunctionMode), ControlChannelMapping.ATTITUDE_NORMAL, new CommonCallbacks.CompletionCallback() { + @Override + public void onSuccess() { + ViewUtil.showToast(getContext() , R.string.uxsdk_setting_menu_desc_omni_perception_downwards , Toast.LENGTH_SHORT); + updateFlycModeDescView(1); + } + + @Override + public void onFailure(@NonNull IDJIError error) { + setTabCellCurrentTab(0); + ViewUtil.showToast(getContext() , AndUtil.getResString(R.string.uxsdk_setting_menu_setting_fail)); + } + }); + //需用户同意方可设置为 A/P/S 模式 +// final PilotDialog attiFlycModeDialog = new PilotDialog.Builder(getContext()) +// .title(AndUtil.getResString(getRes(R.string.setting_menu_flyc_mode_atti_dialog_title_n_mode_rc511, R.string.setting_menu_flyc_mode_atti_dialog_title_n_mode, R.string.setting_menu_flyc_mode_atti_dialog_title))) +// .content(R.string.setting_menu_flyc_mode_atti_dialog_content) +// .negativeText(AndUtil.getResString(R.string.app_cancel)) +// .onNegative((dialog, which) -> { +// setTabCellCurrentTab(oldIndex); +// }).positiveText(AndUtil.getResString(R.string.setting_menu_flyc_mode_atti_dialog_confirm)) +// .positiveEnable(false) +// .onPositive((dialog, which) -> { +// //发送切换为 S/P/A 模式命令 +// mCompositeDisposable.add(Pilot2Repo.FlightController().CustomFunctionMode().setValueAsync(ControlChannelMapping.ATTITUDE_NORMAL).subscribe(resultWrapper -> { +// if (resultWrapper.isSucceed()) { +// updateFlycModeDescView(1); +// } else { +// setTabCellCurrentTab(0); +// ToastBox.showToast(AndUtil.getResString(R.string.setting_menu_setting_fail)); +// } +// })); +// }).cancelable(false) +// .checkBoxPrompt(AndUtil.getResString(R.string.setting_menu_flyc_mode_atti_dialog_notice), false, (dialog, buttonView, isChecked) -> { +// //仅同意免责声明后方可切换 +// dialog.setPositiveEnable(isChecked); +// }) +// .build(); +// attiFlycModeDialog.show(); + } + + private void setTabCellCurrentTab(int index) { + mFlycModeTabCell.setOnTabChangeListener(null); + mFlycModeTabCell.setCurrentTab(index); + mFlycModeTabCell.setOnTabChangeListener(this); + } + + /** + * 根据A/P/S或T/P/S档位的不同展示不同的文案和图片 + * + * @param index + */ + private void updateFlycModeDescView(int index) { + if (index == 1) { + mDescView.setCompoundDrawablesWithIntrinsicBounds(modeDrawable[0], 0, 0, 0); + mDescView.setText(getRes(R.string.uxsdk_setting_menu_flyc_mode_atti_n_mode_rc511, R.string.uxsdk_setting_menu_flyc_mode_atti_n_mode, R.string.uxsdk_setting_menu_flyc_mode_atti)); + } else { + mDescView.setCompoundDrawablesWithIntrinsicBounds(modeDrawable[1], 0, 0, 0); + mDescView.setText(getRes(R.string.uxsdk_setting_menu_flyc_mode_n_rc511, R.string.uxsdk_setting_menu_flyc_mode_n, R.string.uxsdk_setting_menu_flyc_mode_m300)); + } + } + + public static T getRes(@NonNull T rcPlusRes, @NonNull T smartControllerRes) { + RemoteControllerType curType = KeyManager.getInstance().getValue(KeyTools.createKey(RemoteControllerKey.KeyRemoteControllerType) , RemoteControllerType.UNKNOWN); + switch (curType) { + case DJI_RC_PRO: + case DJI_RC_PLUS: + return rcPlusRes; + case M300_RTK_RC: + default: + return smartControllerRes; + } + } + + public static T getRes(@NonNull T m3eRes, @NonNull T rcPlusRes, @NonNull T smartControllerRes) { + RemoteControllerType curType = KeyManager.getInstance().getValue(KeyTools.createKey(RemoteControllerKey.KeyRemoteControllerType) , RemoteControllerType.UNKNOWN); + + switch (curType) { + case DJI_RC_PRO: + return m3eRes; + case DJI_RC_PLUS: + return rcPlusRes; + case M300_RTK_RC: + default: + return smartControllerRes; + } + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/GoHomeModeWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/GoHomeModeWidgetModel.java new file mode 100644 index 00000000..e90bfdc1 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/GoHomeModeWidgetModel.java @@ -0,0 +1,55 @@ +package dji.v5.ux.flight.flightparam; + +import androidx.annotation.NonNull; + +import dji.sdk.keyvalue.key.FlightControllerKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.key.ProductKey; +import dji.sdk.keyvalue.value.flightcontroller.GoHomePathMode; +import dji.sdk.keyvalue.value.product.ProductType; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Flowable; + + +public class GoHomeModeWidgetModel extends WidgetModel { + + private final DataProcessor goHomePathModeDataProcessor = DataProcessor.create(GoHomePathMode.UNKNOWN); + private final DataProcessor productTypeProcessor = DataProcessor.create(ProductType.UNKNOWN); + + + protected GoHomeModeWidgetModel(@NonNull DJISDKModel djiSdkModel, @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + } + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createKey(ProductKey.KeyProductType), productTypeProcessor); + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyGoHomePathMode), goHomePathModeDataProcessor); + + } + + @Override + protected void inCleanup() { + //do nothing + } + + @NonNull + public Flowable goHomePathModeFlowable() { + return goHomePathModeDataProcessor.toFlowable(); + } + + @NonNull Flowable getProductTypeFlowable() { + return productTypeProcessor.toFlowable(); + } + //todo checkvalue + boolean isSupportGoHomeMode(){ + return productTypeProcessor.getValue() == ProductType.DJI_MAVIC_3_ENTERPRISE_SERIES; + } + + public Flowable setGoHomePathMode(GoHomePathMode value) { + return djiSdkModel.setValue(KeyTools.createKey(FlightControllerKey.KeyGoHomePathMode) ,value).toFlowable(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/HomePointWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/HomePointWidget.java new file mode 100644 index 00000000..2d5f4e8c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/HomePointWidget.java @@ -0,0 +1,208 @@ +package dji.v5.ux.flight.flightparam; + + +import android.content.Context; +import android.location.Location; +import android.util.AttributeSet; +import android.view.View; +import android.widget.ImageView; +import android.widget.Toast; + +import androidx.annotation.DrawableRes; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import dji.sdk.keyvalue.value.common.LocationCoordinate2D; +import dji.sdk.keyvalue.value.remotecontroller.RCMode; +import dji.sdk.keyvalue.value.remotecontroller.RcGPSInfo; +import dji.v5.common.utils.GpsUtils; +import dji.v5.utils.common.LocationUtil; +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.R; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.SchedulerProvider; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.ViewUtil; +import io.reactivex.rxjava3.core.CompletableObserver; +import io.reactivex.rxjava3.disposables.Disposable; + +public class HomePointWidget extends ConstraintLayoutWidget { + + private HomeSetWidgetModel widgetModel = new HomeSetWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + private ImageView rcAHomePointIv; + private ImageView rcBHomePointIv; + + public HomePointWidget(@NonNull Context context) { + super(context); + } + + public HomePointWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public HomePointWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_setting_menu_aircraft_home_set_layout, this); + findViewById(R.id.setting_menu_flyc_homepoint_now).setOnClickListener(view -> prepareToSetHomePoint(0)); + + rcAHomePointIv = findViewById(R.id.setting_menu_flyc_homepoint_rc_a); + rcAHomePointIv.setOnClickListener(view -> prepareToSetHomePoint(1)); + + rcBHomePointIv = findViewById(R.id.setting_menu_flyc_homepoint_rc_b); + rcBHomePointIv.setOnClickListener(view -> prepareToSetHomePoint(2)); + + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.getProductConnection().observeOn(SchedulerProvider.ui()).subscribe(connected -> { + if (!connected) { + updateHomePointViewWithSingleRc(); + } + })); + } + + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + } + + + /** + * 设置返航点 + * + * @param index 0:飞机位置 1:A控位置 2:B控位置 + */ + public void prepareToSetHomePoint(final int index) { + if (index == 0) { + // 设置飞机位置为返航点 + setAircraftHome(); + + } else if (!widgetModel.isSupportMultiRc()) { + //不支持双控,默认为只能设置当前遥控器为返航点。 + prepareToSetCurRcHomePoint(); + + } else { + //支持双控,需要判断 + RCMode mode = index == 1 ? RCMode.CHANNEL_A : RCMode.CHANNEL_B; + if (widgetModel.isCurrentRc(mode)) { + // 设置当前遥控器位置为返航点 + prepareToSetCurRcHomePoint(); + } else { + // 设置另外一个遥控器位置为返航点 + setRcHome(widgetModel.getOtherRcLocation(), false); + } + } + } + + private void setAircraftHome() { + + widgetModel.setHomeLocationUseingAircraftLoc().subscribe(new CompletableObserver() { + @Override + public void onSubscribe(@io.reactivex.rxjava3.annotations.NonNull Disposable d) { + // do something + } + + @Override + public void onComplete() { + ViewUtil.showToast(getContext(), R.string.uxsdk_fpv_toast_homepoint_setting_drone, Toast.LENGTH_SHORT); + } + + @Override + public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) { + ViewUtil.showToast(getContext(), R.string.uxsdk_fpv_toast_homepoint_setting_failed, Toast.LENGTH_SHORT); + } + }); + } + + private void prepareToSetCurRcHomePoint() { + Location location = LocationUtil.getLastLocation(); + if (location == null) { + RcGPSInfo gpsInfo = widgetModel.getRcGPSInfo(); + if (gpsInfo == null || !gpsInfo.getIsValid()) { + ViewUtil.showToast(getContext(), R.string.uxsdk_fpv_toast_homepoint_gps_weak, Toast.LENGTH_SHORT); + return; + } + location = GpsUtils.convertToLocation(gpsInfo); + } + + final Location newLocation = location; + int distance = widgetModel.checkRcGpsValid(location.getLatitude(), location.getLongitude(), location.getAccuracy()); + if (distance == -1) { + ViewUtil.showToast(getContext(), R.string.uxsdk_fpv_toast_homepoint_gps_weak, Toast.LENGTH_SHORT); + } else { + setRcHome(newLocation, true); + } + } + + private void setRcHome(Location location, boolean isCurrentRc) { + if (location == null) { + return; + } + LogUtils.i("RcHome", "isCurrentRc keep " + isCurrentRc); + LocationCoordinate2D location2D = new LocationCoordinate2D(location.getLatitude(), location.getLongitude()); + if (!GpsUtils.isValid(location2D.getLatitude(), location2D.getLongitude())) { + ViewUtil.showToast(getContext(), R.string.uxsdk_fpv_toast_homepoint_setting_failed, Toast.LENGTH_SHORT); + return; + } + widgetModel.setHomeLocation(location2D).subscribe(new CompletableObserver() { + @Override + public void onSubscribe(@io.reactivex.rxjava3.annotations.NonNull Disposable d) { + //do nothing + } + + @Override + public void onComplete() { + ViewUtil.showToast(getContext() , R.string.uxsdk_fpv_toast_homepoint_setting_current_rc, Toast.LENGTH_SHORT); + + } + + @Override + public void onError(@io.reactivex.rxjava3.annotations.NonNull Throwable e) { + ViewUtil.showToast(getContext(), R.string.uxsdk_fpv_toast_homepoint_setting_failed, Toast.LENGTH_SHORT); + } + }); + } + + private void selectHomePointView(ImageView view, @DrawableRes int iconRes) { + if (view == null) { + return; + } + view.setVisibility(View.VISIBLE); + view.setImageResource(iconRes); + } + + private void hideHomePointView(ImageView view) { + if (view == null) { + return; + } + view.setVisibility(View.GONE); + } + + private void updateHomePointViewWithSingleRc() { + if (widgetModel.isChannelA()) { + selectHomePointView(rcAHomePointIv, R.drawable.uxsdk_ic_fpv_setting_rc_a); + hideHomePointView(rcBHomePointIv); + } else if (widgetModel.isChannelB()) { + selectHomePointView(rcBHomePointIv, R.drawable.uxsdk_ic_fpv_setting_rc_b); + hideHomePointView(rcAHomePointIv); + } + } + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/HomeSetWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/HomeSetWidgetModel.java new file mode 100644 index 00000000..dd92fe8a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/HomeSetWidgetModel.java @@ -0,0 +1,116 @@ +package dji.v5.ux.flight.flightparam; + +import android.location.Location; + +import androidx.annotation.NonNull; +import dji.sdk.keyvalue.key.FlightControllerKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.key.ProductKey; +import dji.sdk.keyvalue.key.RemoteControllerKey; +import dji.sdk.keyvalue.value.common.LocationCoordinate2D; +import dji.sdk.keyvalue.value.product.ProductType; +import dji.sdk.keyvalue.value.remotecontroller.RCMode; +import dji.sdk.keyvalue.value.remotecontroller.RcGPSInfo; +import dji.v5.common.utils.GpsUtils; +import dji.v5.manager.KeyManager; +import dji.v5.utils.common.LocationUtil; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Completable; + +import static dji.v5.ux.map.MapWidgetModel.INVALID_COORDINATE; + +/** + * @author feel.feng + * @time 2023/08/11 11:20 + * @description: + */ +public class HomeSetWidgetModel extends WidgetModel { + private final DataProcessor productTypeProcessor = DataProcessor.create(ProductType.UNKNOWN); + + // private final DataProcessor productConnectDataProcessor = DataProcessor.create(false); + + private final DataProcessor rcModeDataProcessor = DataProcessor.create(RCMode.UNKNOWN); + private final DataProcessor rcGPSInfoDataProcessor = DataProcessor.create(new RcGPSInfo()); + + public final DataProcessor homeLocationDataProcessor = + DataProcessor.create(new LocationCoordinate2D(INVALID_COORDINATE, INVALID_COORDINATE)); + + protected HomeSetWidgetModel(@NonNull DJISDKModel djiSdkModel, @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + } + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createKey(RemoteControllerKey.KeyRcMachineMode), rcModeDataProcessor); + bindDataProcessor(KeyTools.createKey(ProductKey.KeyProductType), productTypeProcessor); + //addDisposable(RxUtil.addListener(KeyTools.createKey(ProductKey.KeyConnection), this).subscribe(productConnectDataProcessor::onNext)); + + bindDataProcessor(KeyTools.createKey(RemoteControllerKey.KeyRcGPSInfo), rcGPSInfoDataProcessor); + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyHomeLocation), homeLocationDataProcessor); + + + } + + @Override + protected void inCleanup() { + //do nothing + } + + public RcGPSInfo getRcGPSInfo() { + return rcGPSInfoDataProcessor.getValue(); + } + + boolean isSupportMultiRc() { + ProductType curType = productTypeProcessor.getValue(); + return curType == ProductType.M30_SERIES || curType == ProductType.M350_RTK || curType == ProductType.M300_RTK || curType == ProductType.DJI_MATRICE_400; + } + + boolean isCurrentRc(RCMode mode) { + return rcModeDataProcessor.getValue() == mode; + } + + public Completable setHomeLocationUseingAircraftLoc() { + return djiSdkModel.performActionWithOutResult(KeyTools.createKey(FlightControllerKey.KeyHomeLocationUsingCurrentAircraftLocation)); + } + + public int checkRcGpsValid(final double latitude, final double longitude, final double accuracy) { + if (!GpsUtils.checkLatitude(latitude) + || !GpsUtils.checkLongitude(longitude) + || !isFineAccuracy((float) accuracy, 60)) { + return -1; + } + LocationCoordinate2D homeLocation = homeLocationDataProcessor.getValue(); + if (GpsUtils.isValid(homeLocation.getLatitude(), homeLocation.getLongitude())) { + return (int) GpsUtils.distance(latitude, longitude, homeLocation.getLatitude(), homeLocation.getLongitude()); + } else { + return -1; + } + } + + public Completable setHomeLocation(LocationCoordinate2D locationCoordinate2D) { + return djiSdkModel.setValue(KeyTools.createKey(FlightControllerKey.KeyHomeLocation), locationCoordinate2D); + } + + + private boolean isFineAccuracy(float accuracy, float meter) { + return 0.0F < accuracy && accuracy <= meter; + } + + public boolean isChannelB() { + return RCMode.CHANNEL_B == KeyManager.getInstance().getValue(KeyTools.createKey(RemoteControllerKey.KeyRcMachineMode), RCMode.UNKNOWN); + } + + /** + * 是否为A控,非双控机型返回false + */ + public boolean isChannelA() { + return RCMode.CHANNEL_A == KeyManager.getInstance().getValue(KeyTools.createKey(RemoteControllerKey.KeyRcMachineMode), RCMode.UNKNOWN); + } + + public Location getOtherRcLocation() { + return LocationUtil.getLastLocation(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/ImuCompassSensorWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/ImuCompassSensorWidget.java new file mode 100644 index 00000000..a5721f1c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/ImuCompassSensorWidget.java @@ -0,0 +1,61 @@ +package dji.v5.ux.flight.flightparam; + + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.v5.ux.R; +import dji.v5.ux.accessory.DescSpinnerCell; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; + +public class ImuCompassSensorWidget extends ConstraintLayoutWidget { + + LostActionWidgetModel widgetModel = new LostActionWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + DescSpinnerCell spinnerCell; + public ImuCompassSensorWidget(@NonNull Context context) { + super(context); + } + + public ImuCompassSensorWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public ImuCompassSensorWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_setting_menu_imu_campass_sensor_layout, this); + + } + + @Override + protected void reactToModelChanges() { + //do something + } + + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + } + + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/LedWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/LedWidget.java new file mode 100644 index 00000000..6caf4a6d --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/LedWidget.java @@ -0,0 +1,49 @@ +package dji.v5.ux.flight.flightparam; + + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.v5.ux.R; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; + +public class LedWidget extends ConstraintLayoutWidget { + + public LedWidget(@NonNull Context context) { + super(context); + } + + public LedWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public LedWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_widget_common_led, this); + + } + + @Override + protected void reactToModelChanges() { + //add log + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + } + + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/LostActionWidget.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/LostActionWidget.java new file mode 100644 index 00000000..4d4e5e0c --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/LostActionWidget.java @@ -0,0 +1,73 @@ +package dji.v5.ux.flight.flightparam; + + +import android.content.Context; +import android.util.AttributeSet; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import dji.sdk.keyvalue.value.flightcontroller.FailsafeAction; +import dji.v5.utils.common.LogUtils; +import dji.v5.ux.R; +import dji.v5.ux.accessory.DescSpinnerCell; +import dji.v5.ux.cameracore.widget.cameracapture.CameraCaptureWidgetModel; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.SchedulerProvider; +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import io.reactivex.rxjava3.functions.Consumer; + +public class LostActionWidget extends ConstraintLayoutWidget { + + LostActionWidgetModel widgetModel = new LostActionWidgetModel(DJISDKModel.getInstance(), ObservableInMemoryKeyedStore.getInstance()); + DescSpinnerCell spinnerCell; + public LostActionWidget(@NonNull Context context) { + super(context); + } + + public LostActionWidget(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + } + + public LostActionWidget(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + protected void initView(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + inflate(context, R.layout.uxsdk_widget_flight_lost_action, this); + spinnerCell = findViewById(R.id.setting_menu_aircraft_failSafe); + spinnerCell.addOnItemSelectedListener(position -> { + FailsafeAction value = FailsafeAction.find(position); + widgetModel.setLostAction(value).subscribe(); + }); + } + + @Override + protected void reactToModelChanges() { + addReaction(widgetModel.getLostActionFlowable().observeOn(SchedulerProvider.ui()).subscribe(this::updateSelection)); + } + + private void updateSelection(FailsafeAction failsafeAction) { + spinnerCell.select(failsafeAction.value()); + } + + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (!isInEditMode()) { + widgetModel.setup(); + } + } + + @Override + protected void onDetachedFromWindow() { + super.onDetachedFromWindow(); + if (!isInEditMode()) { + widgetModel.cleanup(); + } + } + + +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/LostActionWidgetModel.java b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/LostActionWidgetModel.java new file mode 100644 index 00000000..b9677a2a --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/LostActionWidgetModel.java @@ -0,0 +1,45 @@ +package dji.v5.ux.flight.flightparam; + +import androidx.annotation.NonNull; + +import dji.sdk.keyvalue.key.FlightControllerKey; +import dji.sdk.keyvalue.key.KeyTools; +import dji.sdk.keyvalue.value.flightcontroller.FailsafeAction; +import dji.v5.ux.core.base.DJISDKModel; +import dji.v5.ux.core.base.WidgetModel; +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore; +import dji.v5.ux.core.util.DataProcessor; +import io.reactivex.rxjava3.core.Flowable; + +/** + * @author feel.feng + * @time 2023/08/11 11:20 + * @description: + */ +public class LostActionWidgetModel extends WidgetModel { + private final DataProcessor lostActionDataprocesser = DataProcessor.create(FailsafeAction.UNKNOWN); + + protected LostActionWidgetModel(@NonNull DJISDKModel djiSdkModel, @NonNull ObservableInMemoryKeyedStore uxKeyManager) { + super(djiSdkModel, uxKeyManager); + } + + @Override + protected void inSetup() { + bindDataProcessor(KeyTools.createKey(FlightControllerKey.KeyFailsafeAction), lostActionDataprocesser); + } + + @Override + protected void inCleanup() { + //do nothing + } + + + public Flowable setLostAction(FailsafeAction value){ + return djiSdkModel.setValue(KeyTools.createKey(FlightControllerKey.KeyFailsafeAction) ,value).toFlowable(); + } + + @NonNull + public Flowable getLostActionFlowable(){ + return lostActionDataprocesser.toFlowable(); + } +} diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/ReturnHomeModeWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/ReturnHomeModeWidget.kt new file mode 100644 index 00000000..16462c1b --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/flightparam/ReturnHomeModeWidget.kt @@ -0,0 +1,119 @@ +package dji.v5.ux.flight.flightparam + +import android.content.Context +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.LayoutInflater +import android.widget.LinearLayout +import android.widget.TextView + +import dji.sdk.keyvalue.value.flightcontroller.GoHomePathMode +import dji.v5.utils.common.AndUtil +import dji.v5.utils.common.LogUtils +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.SchedulerProvider +import dji.v5.ux.core.base.TabSelectCell +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import io.reactivex.rxjava3.disposables.CompositeDisposable + +import io.reactivex.rxjava3.kotlin.addTo + +class ReturnHomeModeWidget @JvmOverloads constructor( + context: Context, attrs: AttributeSet? = null +) : LinearLayout(context, attrs), TabSelectCell.OnTabChangeListener { + + companion object { + private const val TAG = "GoHomeModeWidgetModel" + } + + private val goHomeModeTab: TabSelectCell + private val goHomeModeTv: TextView + + private val goHomeHeightNearGroundDrawable: Drawable? + private val goHomeHeightFixedDrawable: Drawable? + + private val compositeDisposable = CompositeDisposable() + + private val widgetModel = GoHomeModeWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance()) + init { + LayoutInflater.from(context).inflate(R.layout.uxsdk_setting_menu_aircraft_go_home_mode_layout, this) + orientation = VERTICAL + + goHomeModeTab = findViewById(R.id.setting_menu_aircraft_go_home_mode) + goHomeModeTv = findViewById(R.id.setting_menu_aircraft_go_home_mode_desc) + + val width = context.resources.getDimensionPixelSize(R.dimen.uxsdk_setting_menu_perception_pic_cac_width) + val height = context.resources.getDimensionPixelSize(R.dimen.uxsdk_setting_menu_perception_pic_cac_height) + goHomeHeightNearGroundDrawable = context.getDrawable(R.drawable.uxsdk_setting_ui_go_home_mode_height_near_ground) + goHomeHeightFixedDrawable = context.getDrawable(R.drawable.uxsdk_setting_ui_go_home_mode_height_fixed) + + goHomeHeightNearGroundDrawable?.setBounds(0, 0, width, height) + goHomeHeightFixedDrawable?.setBounds(0, 0, width, height) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + registerGoHomeMode() + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + unregisterGoHomeMode() + super.onDetachedFromWindow() + } + + private fun registerGoHomeMode() { + goHomeModeTab.setOnTabChangeListener(this) + widgetModel.goHomePathModeFlowable().observeOn(SchedulerProvider.ui()) + + .subscribe { + val isSupport = widgetModel.isSupportGoHomeMode + if (isSupport) { + visibility = VISIBLE + } else { + visibility = GONE + return@subscribe + } + val currentDrawable: Drawable? + val value: Int + LogUtils.i(TAG, "goHomeMode >> $it") + if (it == GoHomePathMode.HEIGHT_NEAR_GROUND) { + visibility = VISIBLE + goHomeModeTv.text = AndUtil.getResString(R.string.uxsdk_setting_menu_flyc_smart_rth_smart_altitude_des) + currentDrawable = goHomeHeightNearGroundDrawable + value = 1 + } else { + visibility = VISIBLE + goHomeModeTv.text = AndUtil.getResString(R.string.uxsdk_setting_menu_flyc_smart_rth_preset_altitude_des) + currentDrawable = goHomeHeightFixedDrawable + value = 0 + } + goHomeModeTv.setCompoundDrawables(currentDrawable, null, null, null) + goHomeModeTab.currentTab = value + }.addTo(compositeDisposable) + } + + private fun unregisterGoHomeMode() { + goHomeModeTab.setOnTabChangeListener(null) + compositeDisposable.clear() + } + + override fun onTabChanged(cell: TabSelectCell?, oldIndex: Int, newIndex: Int) { + val goHomePathMode = if (newIndex == 1) GoHomePathMode.HEIGHT_NEAR_GROUND else GoHomePathMode.HEIGHT_FIXED + widgetModel.setGoHomePathMode(goHomePathMode) + .subscribe { + LogUtils.i(TAG, "onTabChanged >> $it") + goHomeModeTab.currentTab = oldIndex + } + .addTo(compositeDisposable) + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/returnhome/ReturnHomeWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/returnhome/ReturnHomeWidget.kt new file mode 100644 index 00000000..ae9931c9 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/returnhome/ReturnHomeWidget.kt @@ -0,0 +1,694 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.flight.returnhome + +import android.annotation.SuppressLint +import android.content.Context +import android.content.DialogInterface +import android.content.res.ColorStateList +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.View +import androidx.annotation.ColorInt +import androidx.annotation.Dimension +import androidx.annotation.DrawableRes +import androidx.annotation.StyleRes +import androidx.core.content.res.use +import dji.v5.utils.common.DisplayUtil +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.SchedulerProvider +import io.reactivex.rxjava3.disposables.Disposable +import io.reactivex.rxjava3.functions.Consumer +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.UXSDKError +import dji.v5.ux.core.base.widget.IconButtonWidget +import dji.v5.ux.core.base.widget.IconButtonWidget.UIState.* +import dji.v5.ux.core.communication.GlobalPreferencesManager +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.ui.SlidingDialog +import dji.v5.ux.core.util.UxErrorHandle +import dji.v5.ux.core.util.UnitConversionUtil +import dji.v5.ux.R +import dji.v5.ux.flight.returnhome.ReturnHomeWidget.ModelState +import dji.v5.ux.flight.returnhome.ReturnHomeWidget.ModelState.* +import dji.v5.ux.flight.returnhome.ReturnHomeWidgetModel.ReturnHomeState +import java.text.DecimalFormat + +private const val TAG = "ReturnHomeWidget" +private const val RETURN_TO_HOME_DISTANCE_THRESHOLD = 20 +private const val RETURN_HOME_AT_CURRENT_ALTITUDE_MINIMUM = 3 + +/** + * A button that performs actions related to returning home. There are two possible states for the + * widget: ready to return home, and returning home in progress. Clicking the button when the + * aircraft is ready to return home will open a dialog to confirm returning to home. + */ +open class ReturnHomeWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : IconButtonWidget(context, attrs, defStyleAttr), View.OnClickListener { + //region Fields + private var slidingDialog: SlidingDialog? = null + private val decimalFormat = DecimalFormat("#.#") + + private val widgetModel: ReturnHomeWidgetModel by lazy { + ReturnHomeWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + GlobalPreferencesManager.getInstance()) + } + + private val description: String + get() { + val (distanceToHome, currentHeight, goToHomeHeight, unitType) = widgetModel.distanceToHome + return if (distanceToHome < RETURN_TO_HOME_DISTANCE_THRESHOLD) { + if (distanceToHome > RETURN_HOME_AT_CURRENT_ALTITUDE_MINIMUM && widgetModel.isRTHAtCurrentAltitudeEnabled) { + getString(R.string.uxsdk_return_home_at_current_altitude) + } else { + getString(R.string.uxsdk_return_home_inner_desc) + } + } else { +// if (widgetModel.flyZoneReturnToHomeState == FlyZoneReturnToHomeState.NEAR_NO_FLY_ZONE) { +// getString(R.string.uxsdk_return_home_near_nfz) +// } else if (ProductUtil.isProductWiFiConnected()) { +// getString(R.string.uxsdk_return_home_wifi) +// } else { + context.getString(R.string.uxsdk_return_home_below_desc, + getHeightString(goToHomeHeight, unitType), + getHeightString(currentHeight, unitType)) +// } + } + } + + /** + * The alpha of the image when the widget is disabled or pressed + */ + var disabledAlpha = 0.38f + + /** + * The alpha of the image when the widget is enabled + */ + var enabledAlpha = 1.0f + + /** + * The theme of the dialog + */ + @get:StyleRes + @setparam:StyleRes + var dialogTheme = R.style.UXSDKTakeOffDialogTheme + set(value) { + field = value + initDialog() + } + + /** + * Cancel return home action icon drawable + */ + var cancelReturnHomeActionIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_cancel_landing) + set(drawable) { + field = drawable + checkAndUpdateReturnHomeState() + } + + /** + * Return home action icon + */ + var returnHomeActionIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_return_home) + set(drawable) { + field = drawable + checkAndUpdateReturnHomeState() + } + + /** + * Dialog icon drawable + */ + var returnHomeDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_return_home_yellow) + + /** + * The text size of the title for the dialog shown by this widget + */ + var dialogTitleTextSize: Float + @Dimension + get() = slidingDialog?.dialogTitleTextSize + ?: DisplayUtil.pxToSp(context, getDimension(R.dimen.uxsdk_text_size_normal_medium)) + set(@Dimension textSize) { + slidingDialog?.dialogTitleTextSize = textSize + } + + /** + * The color of the title for the dialog shown by this widget + */ + @ColorInt + var dialogTitleTextColor: Int = getColor(R.color.uxsdk_yellow) + + /** + * The background of the title for the dialog shown by this widget + */ + var dialogTitleBackground: Drawable? + get() = slidingDialog?.dialogTitleBackground + set(value) { + slidingDialog?.dialogTitleBackground = value + } + + /** + * The text size of the message for the dialog shown by this widget + */ + var dialogMessageTextSize: Float + get() = slidingDialog?.dialogMessageTextSize + ?: DisplayUtil.pxToSp(context, getDimension(R.dimen.uxsdk_text_size_normal_medium)) + set(value) { + slidingDialog?.dialogMessageTextSize = value + } + + /** + * The text color of the message for the dialog shown by this widget + */ + var dialogMessageTextColor: Int + @ColorInt + get() = slidingDialog?.dialogMessageTextColor ?: getColor(R.color.uxsdk_white) + set(@ColorInt color) { + slidingDialog?.dialogMessageTextColor = color + } + + /** + * The background of the message for the dialog shown by this widget + */ + var dialogMessageBackground: Drawable? + get() = slidingDialog?.dialogMessageBackground + set(value) { + slidingDialog?.dialogMessageBackground = value + } + + /** + * The text size of the cancel button for the dialog shown by this widget + */ + var dialogCancelTextSize: Float + @Dimension + get() = slidingDialog?.cancelTextSize + ?: DisplayUtil.pxToSp(context, getDimension(R.dimen.uxsdk_text_size_normal_medium)) + set(@Dimension textSize) { + slidingDialog?.cancelTextSize = textSize + } + + /** + * The text color of the cancel button for the dialog shown by this widget + */ + var dialogCancelTextColor: Int + @ColorInt + get() = slidingDialog?.cancelTextColor ?: getColor(R.color.uxsdk_white) + set(@ColorInt color) { + slidingDialog?.cancelTextColor = color + } + + /** + * The text colors of the cancel button for the dialog shown by this widget + */ + var dialogCancelTextColors: ColorStateList? + get() = slidingDialog?.cancelTextColors + ?: ColorStateList.valueOf(getColor(R.color.uxsdk_white)) + set(colors) { + slidingDialog?.cancelTextColors = colors + } + + /** + * The background of the cancel button for the dialog shown by this widget + */ + var dialogCancelBackground: Drawable? + get() = slidingDialog?.cancelBackground + set(value) { + slidingDialog?.cancelBackground = value + } + + /** + * The text size of the slider message for the dialog shown by this widget + */ + var dialogSliderMessageTextSize: Float + @Dimension + get() = slidingDialog?.actionMessageTextSize + ?: DisplayUtil.pxToSp(context, getDimension(R.dimen.uxsdk_text_size_normal)) + set(@Dimension textSize) { + slidingDialog?.actionMessageTextSize = textSize + } + + /** + * The text color of the slider message for the dialog shown by this widget + */ + var dialogSliderMessageTextColor: Int + @ColorInt + get() = slidingDialog?.actionMessageTextColor + ?: getColor(R.color.uxsdk_slider_text) + set(@ColorInt color) { + slidingDialog?.actionMessageTextColor = color + } + + /** + * The background of the slider message for the dialog shown by this widget + */ + var dialogSliderMessageBackground: Drawable? + get() = slidingDialog?.actionMessageBackground + set(value) { + slidingDialog?.actionMessageBackground = value + } + + /** + * The icon to the right of the slider message for the dialog shown by this widget + */ + var dialogSliderIcon: Drawable? + get() = slidingDialog?.actionIcon + set(icon) { + slidingDialog?.actionIcon = icon + } + + /** + * The color of the slider thumb for the dialog shown by this widget + */ + var dialogSliderThumbColor: Int + @ColorInt + get() = slidingDialog?.actionSliderThumbColor ?: getColor(R.color.uxsdk_white) + set(@ColorInt color) { + slidingDialog?.actionSliderThumbColor = color + } + + /** + * The color of the slider thumb when selected for the dialog shown by this widget + */ + var dialogSliderThumbSelectedColor: Int + @ColorInt + get() = slidingDialog?.actionSliderThumbSelectedColor + ?: getColor(R.color.uxsdk_slider_thumb_selected) + set(@ColorInt color) { + slidingDialog?.actionSliderThumbSelectedColor = color + } + + /** + * The fill color of the slider for the dialog shown by this widget + */ + var dialogSliderFillColor: Int + @ColorInt + get() = slidingDialog?.actionSliderFillColor ?: getColor(R.color.uxsdk_slider_filled) + set(@ColorInt color) { + slidingDialog?.actionSliderFillColor = color + } + + /** + * The background of the dialog shown by this widget + */ + var dialogBackground: Drawable? + get() = slidingDialog?.background + ?: getDrawable(R.drawable.uxsdk_background_black_rectangle) + set(background) { + slidingDialog?.background = background + } + + //endregion + + //region Lifecycle + init { + setOnClickListener(this) + initDialog() + attrs?.let { initAttributes(context, it) } + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.returnHomeState + .observeOn(SchedulerProvider.ui()) + .subscribe { returnHomeState: ReturnHomeState -> updateReturnHomeState(returnHomeState) }) + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + } + + override fun getIdealDimensionRatioString(): String = getString(R.string.uxsdk_widget_default_ratio) + + override fun onClick(view: View?) { + super.onClick(view) + val drawable = foregroundImageView.drawable + drawable?.let { + when (it) { + returnHomeActionIcon -> showConfirmDialog(description) + else -> addDisposable(cancelReturnToHome()) + } + } + } + //endregion + + //region private helpers + private fun initDialog() { + if (!isInEditMode) { + slidingDialog = SlidingDialog(context, dialogTheme) + slidingDialog?.setOnEventListener(object : SlidingDialog.OnEventListener { + override fun onCancelClick(dialog: DialogInterface?) { + slidingDialog?.dismiss() + uiUpdateStateProcessor.onNext(DialogActionCancelled(null)) + } + + override fun onSlideChecked(dialog: DialogInterface?, checked: Boolean) { + if (checked) { + addDisposable(returnToHome()) + slidingDialog?.dismiss() + uiUpdateStateProcessor.onNext(DialogActionConfirmed(null)) + } + } + + override fun onCheckBoxChecked(dialog: DialogInterface?, checked: Boolean) { + // no checkbox used + } + }) + + slidingDialog?.setOnDismissListener { uiUpdateStateProcessor.onNext(DialogDismissed(null)) } + } + } + + private fun showConfirmDialog(msg: String) { + slidingDialog?.setDialogTitleRes(R.string.uxsdk_return_to_home_header) + ?.setDialogTitleTextColor(dialogTitleTextColor) + ?.setDialogMessage(msg) + ?.setActionMessageRes(R.string.uxsdk_return_to_home_action) + ?.setDialogIcon(returnHomeDialogIcon) + ?.show() + uiUpdateStateProcessor.onNext(DialogDisplayed(null)) + } + + private fun returnToHome(): Disposable { + return widgetModel.performReturnHomeAction() + .subscribeOn(SchedulerProvider.io()) + .subscribe({ + widgetStateDataProcessor.onNext(ReturnHomeStartSucceeded) + }) { error: Throwable -> + if (error is UXSDKError) { + widgetStateDataProcessor.onNext(ReturnHomeStartFailed(error)) + } + } + } + + private fun cancelReturnToHome(): Disposable { + return widgetModel.performCancelReturnHomeAction() + .subscribeOn(SchedulerProvider.io()) + .subscribe({ + widgetStateDataProcessor.onNext(ReturnHomeCancelSucceeded) + }) { error: Throwable -> + if (error is UXSDKError) { + widgetStateDataProcessor.onNext(ReturnHomeCancelFailed(error)) + } + } + } + + private fun getHeightString(height: Float, unitType: UnitConversionUtil.UnitType): String { + val resourceString = + if (unitType == UnitConversionUtil.UnitType.IMPERIAL) { + R.string.uxsdk_value_feet + } else { + R.string.uxsdk_value_meters + } + return resources.getString(resourceString, decimalFormat.format(height)) + } + + private fun updateReturnHomeState(returnHomeState: ReturnHomeState) { + widgetStateDataProcessor.onNext(ReturnHomeStateUpdated(returnHomeState)) + foregroundImageView.setImageDrawable( + when (returnHomeState) { + ReturnHomeState.READY_TO_RETURN_HOME, + ReturnHomeState.RETURN_HOME_DISABLED -> returnHomeActionIcon + ReturnHomeState.RETURNING_TO_HOME, + ReturnHomeState.FORCED_RETURNING_TO_HOME -> cancelReturnHomeActionIcon + else -> null + }) + isEnabled = !(returnHomeState == ReturnHomeState.RETURN_HOME_DISABLED || + returnHomeState == ReturnHomeState.FORCED_RETURNING_TO_HOME) + visibility = + if (returnHomeState == ReturnHomeState.AUTO_LANDING || + returnHomeState == ReturnHomeState.DISCONNECTED) { + View.GONE + } else { + View.VISIBLE + } + updateImageAlpha() + } + + private fun updateImageAlpha() { + if (foregroundImageView.imageDrawable == cancelReturnHomeActionIcon) { + foregroundImageView.isEnabled = isEnabled + if (isPressed) { + foregroundImageView.alpha = disabledAlpha + } else { + foregroundImageView.alpha = enabledAlpha + } + return + } + + if ((isPressed || isFocused) || !isEnabled) { + foregroundImageView.alpha = disabledAlpha + } else { + foregroundImageView.alpha = enabledAlpha + } + } + + private fun checkAndUpdateReturnHomeState() { + if (!isInEditMode) { + addDisposable(widgetModel.returnHomeState.firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(Consumer { this.updateReturnHomeState(it) }, + UxErrorHandle.logErrorConsumer(TAG, "Update Return Home State "))) + } + } + + override fun checkAndUpdateIconColor() { + // do nothing + } + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.ReturnHomeWidget).use { typedArray -> + typedArray.getFloatAndUse(R.styleable.ReturnHomeWidget_uxsdk_disabledAlpha) { + disabledAlpha = it + } + typedArray.getFloatAndUse(R.styleable.ReturnHomeWidget_uxsdk_enabledAlpha) { + enabledAlpha = it + } + typedArray.getResourceIdAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogTheme) { + dialogTheme = it + } + typedArray.getDrawableAndUse(R.styleable.ReturnHomeWidget_uxsdk_returnHomeDrawable) { + returnHomeActionIcon = it + } + typedArray.getDrawableAndUse(R.styleable.ReturnHomeWidget_uxsdk_cancelReturnHomeDrawable) { + cancelReturnHomeActionIcon = it + } + typedArray.getDrawableAndUse(R.styleable.ReturnHomeWidget_uxsdk_returnHomeDialogIcon) { + returnHomeDialogIcon = it + } + typedArray.getResourceIdAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogTitleTextAppearance) { + setDialogTitleTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogTitleTextSize) { + dialogTitleTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogTitleTextColor) { + dialogTitleTextColor = it + } + typedArray.getDrawableAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogTitleBackground) { + dialogTitleBackground = it + } + typedArray.getResourceIdAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogMessageTextAppearance) { + setDialogMessageTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogMessageTextSize) { + dialogMessageTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogMessageTextColor) { + dialogMessageTextColor = it + } + typedArray.getDrawableAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogMessageBackground) { + dialogMessageBackground = it + } + typedArray.getResourceIdAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogCancelTextAppearance) { + setDialogCancelTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogCancelTextSize) { + dialogCancelTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogCancelTextColor) { + dialogCancelTextColor = it + } + typedArray.getDrawableAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogCancelBackground) { + dialogCancelBackground = it + } + typedArray.getResourceIdAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogSliderMessageTextAppearance) { + setDialogSliderMessageTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogSliderMessageTextSize) { + dialogSliderMessageTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogSliderMessageTextColor) { + dialogSliderMessageTextColor = it + } + typedArray.getDrawableAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogSliderMessageBackground) { + dialogSliderMessageBackground = it + } + typedArray.getDrawableAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogSliderIcon) { + dialogSliderIcon = it + } + typedArray.getColorAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogSliderThumbColor) { + dialogSliderThumbColor = it + } + typedArray.getColorAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogSliderThumbSelectedColor) { + dialogSliderThumbSelectedColor = it + } + typedArray.getColorAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogSliderFillColor) { + dialogSliderFillColor = it + } + typedArray.getDrawableAndUse(R.styleable.ReturnHomeWidget_uxsdk_dialogBackground) { + dialogBackground = it + } + } + } + //endregion + + //region Customization + /** + * Set return home action drawable resource + * + * @param resourceId resource id of return home action icon + */ + fun setReturnHomeActionIcon(@DrawableRes resourceId: Int) { + returnHomeActionIcon = getDrawable(resourceId) + } + + /** + * Set cancel return home action icon drawable + * + * @param resourceId resource id of cancel return home action + */ + fun setCancelReturnHomeActionIcon(@DrawableRes resourceId: Int) { + cancelReturnHomeActionIcon = getDrawable(resourceId) + } + + /** + * Set return home dialog icon drawable + * + * @param resourceId resource id of return home dialog icon + */ + fun setReturnHomeDialogIcon(@DrawableRes resourceId: Int) { + returnHomeDialogIcon = getDrawable(resourceId) + } + + /** + * Set the text appearance of the title for the dialog shown by this widget + * + * @param textAppearance Style resource for text appearance + */ + fun setDialogTitleTextAppearance(@StyleRes textAppearance: Int) { + slidingDialog?.setDialogTitleTextAppearance(textAppearance) + } + + /** + * Set the text appearance of the message for the dialog shown by this widget + * + * @param textAppearance Style resource for text appearance + */ + fun setDialogMessageTextAppearance(@StyleRes textAppearance: Int) { + slidingDialog?.setDialogMessageTextAppearance(textAppearance) + } + + /** + * Set the text appearance of the cancel button for the dialog shown by this widget + * + * @param textAppearance Style resource for text appearance + */ + fun setDialogCancelTextAppearance(@StyleRes textAppearance: Int) { + slidingDialog?.setCancelTextAppearance(textAppearance) + } + + /** + * Set the text appearance of the slider message for the dialog shown by this widget + * + * @param textAppearance Style resource for text appearance + */ + fun setDialogSliderMessageTextAppearance(@StyleRes textAppearance: Int) { + slidingDialog?.setActionMessageTextAppearance(textAppearance) + } + //endregion + + //region Hooks + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines the widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Return Home State update + */ + data class ReturnHomeStateUpdated(val state: ReturnHomeState) : ModelState() + + /** + * Return to Home started successfully + */ + object ReturnHomeStartSucceeded : ModelState() + + /** + * Return to Home not started due to error + */ + data class ReturnHomeStartFailed(val error: UXSDKError) : ModelState() + + /** + * Return to Home canceled successfully + */ + object ReturnHomeCancelSucceeded : ModelState() + + /** + * Return to Home not canceled due to error + */ + data class ReturnHomeCancelFailed(val error: UXSDKError) : ModelState() + } + + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/returnhome/ReturnHomeWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/returnhome/ReturnHomeWidgetModel.kt new file mode 100644 index 00000000..58a4a614 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/returnhome/ReturnHomeWidgetModel.kt @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.flight.returnhome + +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.key.DJIKey +import dji.sdk.keyvalue.key.RemoteControllerKey +import dji.sdk.keyvalue.value.common.LocationCoordinate2D +import dji.sdk.keyvalue.value.flightcontroller.FCAutoRTHReason +import dji.sdk.keyvalue.value.flightcontroller.FCFlightMode +import dji.sdk.keyvalue.value.remotecontroller.RCMode +import dji.sdk.keyvalue.key.KeyTools +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.GlobalPreferenceKeys +import dji.v5.ux.core.communication.GlobalPreferencesInterface +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.communication.UXKeys +import dji.v5.ux.core.util.DataProcessor +import dji.v5.utils.common.LocationUtil +import dji.v5.ux.core.util.UnitConversionUtil +import io.reactivex.rxjava3.core.Completable +import io.reactivex.rxjava3.core.Flowable + +/** + * Widget Model for the [ReturnHomeWidget] used to define + * the underlying logic and communication + */ +class ReturnHomeWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, + private val preferencesManager: GlobalPreferencesInterface? +) : WidgetModel(djiSdkModel, keyedStore) { + + //region Fields + private val isGoingHomeDataProcessor: DataProcessor = DataProcessor.create(false) + private val isFlyingDataProcessor: DataProcessor = DataProcessor.create(false) + private val isAutoLandingDataProcessor: DataProcessor = DataProcessor.create(false) + private val areMotorsOnDataProcessor: DataProcessor = DataProcessor.create(false) + private val returnHomeDataProcessor: DataProcessor = DataProcessor.create(ReturnHomeState.DISCONNECTED) + private val isCancelReturnToHomeDisabledProcessor: DataProcessor = DataProcessor.create(false) + private val rcModeDataProcessor: DataProcessor = DataProcessor.create(RCMode.UNKNOWN) + + // private val flyZoneReturnToHomeStateProcessor: DataProcessor = DataProcessor.create(FlyZoneReturnToHomeState.UNKNOWN) + private val flightModeProcessor: DataProcessor = DataProcessor.create(FCFlightMode.UNKNOWN) + private val autoRTHReasonProcessor: DataProcessor = DataProcessor.create(FCAutoRTHReason.UNKNOWN) + private val unitTypeProcessor: DataProcessor = DataProcessor.create(UnitConversionUtil.UnitType.METRIC) + //endregion + + //region Data + /** + * Get the return home state + */ + val returnHomeState: Flowable + get() = returnHomeDataProcessor.toFlowable().distinctUntilChanged() + + /** + * Get the distance from the aircraft to the home point + */ + val distanceToHome: ReturnHomeDistance + get() { + val goHomeHeightKey: DJIKey = KeyTools.createKey( + FlightControllerKey.KeyGoHomeHeight + ) + val homeLocationKey: DJIKey = KeyTools.createKey( + FlightControllerKey.KeyHomeLocation + ) + val currentHeightKey: DJIKey = KeyTools.createKey( + FlightControllerKey.KeyAltitude + ) + val aircraftLocationKey: DJIKey = KeyTools.createKey( + FlightControllerKey.KeyAircraftLocation + ) + var currentHeight = 0f + var goHomeHeight = 0f + var homeLatitude = Double.NaN + var homeLongitude = Double.NaN + var aircraftLocationLat = 0.0 + var aircraftLocationLong = 0.0 + val unitType = unitTypeProcessor.value + + djiSdkModel.getCacheValue(currentHeightKey)?.let { + currentHeight = it.toFloat() + } + djiSdkModel.getCacheValue(goHomeHeightKey)?.let { + goHomeHeight = it.toFloat() + } + djiSdkModel.getCacheValue(homeLocationKey)?.let { + homeLatitude = it.latitude + homeLongitude = it.longitude + } + djiSdkModel.getCacheValue(aircraftLocationKey)?.let { + aircraftLocationLat = it.latitude + aircraftLocationLong = it.longitude + } + var distanceToHome = 0f + if (!homeLatitude.isNaN() && !homeLongitude.isNaN()) { + distanceToHome = distanceBetween(homeLatitude, homeLongitude, aircraftLocationLat, aircraftLocationLong) + } + return ReturnHomeDistance(distanceToHome, currentHeight, goHomeHeight, unitType) + } + + /** + * Get whether returning to home at the current altitude is enabled + */ + val isRTHAtCurrentAltitudeEnabled: Boolean + get() { +// val rthAtCurrentHeightKey = FlightControllerKey.create(FlightControllerKey.CONFIG_RTH_IN_CURRENT_ALTITUDE) +// var isRTHAtCurrentAltitudeEnabled = true +// djiSdkModel.getCacheValue(rthAtCurrentHeightKey)?.let { +// isRTHAtCurrentAltitudeEnabled = it as Boolean +// } +// return isRTHAtCurrentAltitudeEnabled + return true + } + + /** + * Get the latest [FlyZoneReturnToHomeState] + */ +// val flyZoneReturnToHomeState: FlyZoneReturnToHomeState +// get() = flyZoneReturnToHomeStateProcessor.value + //endregion + + //region Constructor + init { + if (preferencesManager != null) { + unitTypeProcessor.onNext(preferencesManager.unitType) + } + } + //endregion + + //region Actions + /** + * Performs return to home action + */ + fun performReturnHomeAction(): Completable { + return djiSdkModel.performActionWithOutResult( + KeyTools.createKey( + FlightControllerKey.KeyStartGoHome + ) + ) + } + + /** + * Performs cancel return to home action + */ + fun performCancelReturnHomeAction(): Completable { + return djiSdkModel.performActionWithOutResult( + KeyTools.createKey( + FlightControllerKey.KeyStopGoHome + ) + ) + } + + //endregion + + //region Lifecycle + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyIsFlying + ), isFlyingDataProcessor + ) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyIsInLandingMode + ), isAutoLandingDataProcessor + ) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAreMotorsOn + ), areMotorsOnDataProcessor + ) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyFCFlightMode + ), flightModeProcessor + ) { + isGoingHomeDataProcessor.onNext(it == FCFlightMode.GO_HOME || it == FCFlightMode.AUTO_LANDING) + } + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAutoRTHReason + ), autoRTHReasonProcessor + ) { + isCancelReturnToHomeDisabledProcessor.onNext(it == FCAutoRTHReason.MC_PROTECT_GOHOME) + } + bindDataProcessor( + KeyTools.createKey( + RemoteControllerKey.KeyRcMachineMode + ), rcModeDataProcessor + ) +// val flyZoneReturnToHomeState: DJIKey = FlightControllerKey.create(FlightControllerKey.RETURN_TO_HOME_STATE) +// bindDataProcessor(flyZoneReturnToHomeState, flyZoneReturnToHomeStateProcessor) + val unitKey = UXKeys.create(GlobalPreferenceKeys.UNIT_TYPE) + bindDataProcessor(unitKey, unitTypeProcessor) + preferencesManager?.setUpListener() + } + + override fun inCleanup() { + preferencesManager?.cleanup() + } + + override fun updateStates() { + if (!productConnectionProcessor.value) { + returnHomeDataProcessor.onNext(ReturnHomeState.DISCONNECTED) + } else if (!isFlyingDataProcessor.value + || !areMotorsOnDataProcessor.value) { + returnHomeDataProcessor.onNext(ReturnHomeState.RETURN_HOME_DISABLED) + } else if (isAutoLandingDataProcessor.value) { + returnHomeDataProcessor.onNext(ReturnHomeState.AUTO_LANDING) + } else if (isGoingHomeDataProcessor.value && !isAutoLandingDataProcessor.value) { + if (isCancelReturnHomeDisabled()) { + returnHomeDataProcessor.onNext(ReturnHomeState.FORCED_RETURNING_TO_HOME) + } else { + returnHomeDataProcessor.onNext(ReturnHomeState.RETURNING_TO_HOME) + } + } else { + returnHomeDataProcessor.onNext(ReturnHomeState.READY_TO_RETURN_HOME) + } + } + + private fun isCancelReturnHomeDisabled(): Boolean { + return isCancelReturnToHomeDisabledProcessor.value || + rcModeDataProcessor.value == RCMode.SLAVE + } + //endregion + + //region Helpers for unit testing + private fun distanceBetween( + latitude1: Double, + longitude1: Double, + latitude2: Double, + longitude2: Double + ): Float { + return LocationUtil.distanceBetween(latitude1, longitude1, latitude2, longitude2) + } + //endregion + + //region Classes + /** + * The state of the aircraft + */ + enum class ReturnHomeState { + /** + * The aircraft is ready to return to home + */ + READY_TO_RETURN_HOME, + + /** + * The aircraft cannot return to home + */ + RETURN_HOME_DISABLED, + + /** + * The aircraft has started returning to home + */ + RETURNING_TO_HOME, + + /** + * The aircraft has started returning to home and it cannot be canceled + */ + FORCED_RETURNING_TO_HOME, + + /** + * The aircraft has started auto landing + */ + AUTO_LANDING, + + /** + * The aircraft is disconnected + */ + DISCONNECTED + } + + /** + * The measurements describing the return to home behavior + * + * @property distanceToHome The distance to home in meters + * @property currentHeight The current height of the aircraft in [unitType] + * @property goToHomeHeight The height at which the aircraft will return to home in [unitType] + * @property unitType The unit type of [currentHeight] and [goToHomeHeight] + */ + data class ReturnHomeDistance( + val distanceToHome: Float, + val currentHeight: Float, + val goToHomeHeight: Float, + val unitType: UnitConversionUtil.UnitType + ) + + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/takeoff/TakeOffWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/takeoff/TakeOffWidget.kt new file mode 100644 index 00000000..cc9ef876 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/takeoff/TakeOffWidget.kt @@ -0,0 +1,1030 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.flight.takeoff + +import android.annotation.SuppressLint +import android.content.Context +import android.content.DialogInterface +import android.content.res.ColorStateList +import android.graphics.drawable.Drawable +import android.util.AttributeSet +import android.view.View +import androidx.annotation.ColorInt +import androidx.annotation.Dimension +import androidx.annotation.DrawableRes +import androidx.annotation.StyleRes +import androidx.core.content.res.use +import dji.v5.utils.common.DisplayUtil +import io.reactivex.rxjava3.core.Flowable +import dji.v5.ux.core.base.SchedulerProvider +import io.reactivex.rxjava3.disposables.Disposable +import io.reactivex.rxjava3.functions.Consumer +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.UXSDKError +import dji.v5.ux.core.base.widget.IconButtonWidget +import dji.v5.ux.core.base.widget.IconButtonWidget.UIState.* +import dji.v5.ux.core.communication.GlobalPreferencesManager +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.extension.* +import dji.v5.ux.core.ui.SlidingDialog +import dji.v5.ux.core.util.UxErrorHandle +import dji.v5.ux.core.util.UnitConversionUtil +import dji.v5.ux.R +import dji.v5.ux.flight.takeoff.TakeOffWidget.ModelState +import dji.v5.ux.flight.takeoff.TakeOffWidget.ModelState.* +import dji.v5.ux.flight.takeoff.TakeOffWidget.DialogType.* +import dji.v5.ux.flight.takeoff.TakeOffWidgetModel.TakeOffLandingState +import java.text.DecimalFormat + +private const val TAG = "TakeOffWidget" + +/** + * A button that performs actions related to takeoff and landing. There are three possible states + * for the widget: ready to take off, ready to land, and landing in progress. Clicking the + * button in each of these states will open a dialog to confirm take off, landing, and landing + * cancellation, respectively. + * + * Additionally, this widget will show a dialog if landing is in progress, but it is currently + * unsafe to land. The dialog will prompt the user whether or not they want to cancel landing. + */ +open class TakeOffWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : IconButtonWidget(context, attrs, defStyleAttr) { + //region Fields + private var slidingDialog: SlidingDialog? = null + private val decimalFormat = DecimalFormat("#.#") + private var dialogType: DialogType? = null + + private val widgetModel by lazy { + TakeOffWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance(), + GlobalPreferencesManager.getInstance()) + } + + /** + * The alpha of the image when the widget is disabled or pressed + */ + var disabledAlpha = 0.38f + + /** + * The alpha of the image when the widget is enabled + */ + var enabledAlpha = 1.0f + + /** + * The theme of the dialogs + */ + @get:StyleRes + @setparam:StyleRes + var dialogTheme = R.style.UXSDKTakeOffDialogTheme + set(value) { + field = value + initDialog() + } + + /** + * Takeoff icon drawable + */ + var takeOffActionIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_takeoff) + set(drawable) { + field = drawable + checkAndUpdateTakeOffLandingState() + } + + /** + * Land action icon + */ + var landActionIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_land) + set(drawable) { + field = drawable + checkAndUpdateTakeOffLandingState() + } + + /** + * Cancel land action icon drawable + */ + var cancelLandActionIcon: Drawable? = getDrawable(R.drawable.uxsdk_cancel_landing_selector) + set(drawable) { + field = drawable + checkAndUpdateTakeOffLandingState() + } + + /** + * Takeoff dialog icon drawable + */ + var takeOffDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_takeoff_yellow) + + /** + * Landing dialog icon drawable + */ + var landingDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_land_yellow) + + /** + * Landing Confirmation dialog icon drawable + */ + var landingConfirmationDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_land_yellow) + + /** + * Unsafe To Land dialog icon drawable + */ + var unsafeToLandDialogIcon: Drawable? = getDrawable(R.drawable.uxsdk_ic_land_yellow) + + /** + * The text size of the title for all the dialogs shown by this widget + */ + var dialogTitleTextSize: Float + @Dimension + get() = slidingDialog?.dialogTitleTextSize + ?: DisplayUtil.pxToSp(context, getDimension(R.dimen.uxsdk_text_size_normal_medium)) + set(@Dimension textSize) { + slidingDialog?.dialogTitleTextSize = textSize + } + + /** + * The color of the title for all the dialogs shown by this widget + */ + @ColorInt + var dialogTitleTextColor: Int = getColor(R.color.uxsdk_yellow) + + /** + * The background of the title for all the dialogs shown by this widget + */ + var dialogTitleBackground: Drawable? + get() = slidingDialog?.dialogTitleBackground + set(value) { + slidingDialog?.dialogTitleBackground = value + } + + /** + * The text size of the message for all the dialogs shown by this widget + */ + var dialogMessageTextSize: Float = DisplayUtil.pxToSp(context, getDimension(R.dimen.uxsdk_text_size_normal_medium)) + + /** + * The text size of the precision takeoff message for the takeoff dialog + */ + var dialogPrecisionMessageTextSize: Float = DisplayUtil.pxToSp(context, getDimension(R.dimen.uxsdk_text_size_small)) + + /** + * The text color of the message for all the dialogs shown by this widget + */ + var dialogMessageTextColor: Int + @ColorInt + get() = slidingDialog?.dialogMessageTextColor ?: getColor(R.color.uxsdk_white) + set(@ColorInt color) { + slidingDialog?.dialogMessageTextColor = color + } + + /** + * The background of the message for all the dialogs shown by this widget + */ + var dialogMessageBackground: Drawable? + get() = slidingDialog?.dialogMessageBackground + set(value) { + slidingDialog?.dialogMessageBackground = value + } + + /** + * The text size of the precision takeoff checkbox for the takeoff dialog + */ + var dialogCheckBoxMessageTextSize: Float + @Dimension + get() = slidingDialog?.checkBoxMessageTextSize + ?: DisplayUtil.pxToSp(context, getDimension(R.dimen.uxsdk_text_size_normal_medium)) + set(@Dimension textSize) { + slidingDialog?.checkBoxMessageTextSize = textSize + } + + /** + * The text color of the precision takeoff checkbox for the takeoff dialog + */ + var dialogCheckBoxMessageTextColor: Int + @ColorInt + get() = slidingDialog?.checkBoxMessageTextColor ?: getColor(R.color.uxsdk_white) + set(@ColorInt color) { + slidingDialog?.checkBoxMessageTextColor = color + } + + /** + * The background of the precision takeoff checkbox for the takeoff dialog + */ + var dialogCheckBoxMessageBackground: Drawable? + get() = slidingDialog?.checkBoxMessageBackground + set(value) { + slidingDialog?.checkBoxMessageBackground = value + } + + /** + * The text size of the cancel button for all the dialogs shown by this widget + */ + var dialogCancelTextSize: Float + @Dimension + get() = slidingDialog?.cancelTextSize + ?: DisplayUtil.pxToSp(context, getDimension(R.dimen.uxsdk_text_size_normal_medium)) + set(@Dimension textSize) { + slidingDialog?.cancelTextSize = textSize + } + + /** + * The text color of the cancel button for all the dialogs shown by this widget + */ + var dialogCancelTextColor: Int + @ColorInt + get() = slidingDialog?.cancelTextColor ?: getColor(R.color.uxsdk_white) + set(@ColorInt color) { + slidingDialog?.cancelTextColor = color + } + + /** + * The text colors of the cancel button for all the dialogs shown by this widget + */ + var dialogCancelTextColors: ColorStateList? + get() = slidingDialog?.cancelTextColors + ?: ColorStateList.valueOf(getColor(R.color.uxsdk_white)) + set(colors) { + slidingDialog?.cancelTextColors = colors + } + + /** + * The background of the cancel button for all the dialogs shown by this widget + */ + var dialogCancelBackground: Drawable? + get() = slidingDialog?.cancelBackground + set(value) { + slidingDialog?.cancelBackground = value + } + + /** + * The text size of the slider message for all the dialogs shown by this widget + */ + var dialogSliderMessageTextSize: Float + @Dimension + get() = slidingDialog?.actionMessageTextSize + ?: DisplayUtil.pxToSp(context, getDimension(R.dimen.uxsdk_text_size_normal)) + set(@Dimension textSize) { + slidingDialog?.actionMessageTextSize = textSize + } + + /** + * The text color of the slider message for all the dialogs shown by this widget + */ + var dialogSliderMessageTextColor: Int + @ColorInt + get() = slidingDialog?.actionMessageTextColor + ?: getColor(R.color.uxsdk_slider_text) + set(@ColorInt color) { + slidingDialog?.actionMessageTextColor = color + } + + /** + * The background of the slider message for all the dialogs shown by this widget + */ + var dialogSliderMessageBackground: Drawable? + get() = slidingDialog?.actionMessageBackground + set(value) { + slidingDialog?.actionMessageBackground = value + } + + /** + * The icon to the right of the slider message for all the dialogs shown by this widget + */ + var dialogSliderIcon: Drawable? + get() = slidingDialog?.actionIcon + set(icon) { + slidingDialog?.actionIcon = icon + } + + /** + * The color of the slider thumb for all the dialogs shown by this widget + */ + var dialogSliderThumbColor: Int + @ColorInt + get() = slidingDialog?.actionSliderThumbColor ?: getColor(R.color.uxsdk_white) + set(@ColorInt color) { + slidingDialog?.actionSliderThumbColor = color + } + + /** + * The color of the slider thumb when selected for all the dialogs shown by this widget + */ + var dialogSliderThumbSelectedColor: Int + @ColorInt + get() = slidingDialog?.actionSliderThumbSelectedColor + ?: getColor(R.color.uxsdk_slider_thumb_selected) + set(@ColorInt color) { + slidingDialog?.actionSliderThumbSelectedColor = color + } + + /** + * The fill color of the slider for all the dialogs shown by this widget + */ + var dialogSliderFillColor: Int + @ColorInt + get() = slidingDialog?.actionSliderFillColor ?: getColor(R.color.uxsdk_slider_filled) + set(@ColorInt color) { + slidingDialog?.actionSliderFillColor = color + } + + /** + * The background of all the dialogs shown by this widget + */ + var dialogBackground: Drawable? + get() = slidingDialog?.background + ?: getDrawable(R.drawable.uxsdk_background_black_rectangle) + set(background) { + slidingDialog?.background = background + } + + //endregion + + //region Lifecycle + init { + setOnClickListener(this) + initDialog() + attrs?.let { initAttributes(context, it) } + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + } + } + + override fun onDetachedFromWindow() { + if (!isInEditMode) { + widgetModel.cleanup() + } + super.onDetachedFromWindow() + } + + override fun reactToModelChanges() { + addReaction(widgetModel.takeOffLandingState + .observeOn(SchedulerProvider.ui()) + .subscribe { updateTakeOffStatus(it) }) + addReaction(widgetModel.productConnection + .observeOn(SchedulerProvider.ui()) + .subscribe { widgetStateDataProcessor.onNext(ProductConnected(it)) }) + } + + override fun onClick(view: View?) { + super.onClick(view) + val current = foregroundImageView.drawable + current?.let { + when (it) { + cancelLandActionIcon -> performCancelLandAction() + landActionIcon -> showLandingDialog() + else -> showTakeOffDialog() + } + } + } + + //endregion + + //region private helpers + private fun initDialog() { + if (!isInEditMode) { + slidingDialog = SlidingDialog(context, dialogTheme) + slidingDialog?.setOnEventListener(object : SlidingDialog.OnEventListener { + + var checkBoxChecked: Boolean = false + + override fun onCancelClick(dialog: DialogInterface?) { + slidingDialog?.dismiss() + addDisposable(widgetModel.takeOffLandingState.firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(Consumer { takeOffLandingState: TakeOffLandingState -> + if (takeOffLandingState == TakeOffLandingState.WAITING_FOR_LANDING_CONFIRMATION) { + performCancelLandAction() + } + uiUpdateStateProcessor.onNext(DialogActionCancelled(dialogType)) + }, UxErrorHandle.logErrorConsumer(TAG, "Update takeoff Landing State"))) + } + + override fun onSlideChecked(dialog: DialogInterface?, checked: Boolean) { + if (checked) { + performOnSlideChecked(checkBoxChecked) + } + } + + override fun onCheckBoxChecked(dialog: DialogInterface?, checked: Boolean) { + uiUpdateStateProcessor.onNext(DialogCheckboxCheckChanged(dialogType)) + checkBoxChecked = checked +// updateTakeOffDialogMessage() + } + }) + + slidingDialog?.setOnDismissListener { uiUpdateStateProcessor.onNext(DialogDismissed(dialogType)) } + + } + } + + private fun performOnSlideChecked(checkBoxChecked: Boolean) { + val current = foregroundImageView.drawable + if (current == landActionIcon) { + addDisposable(performLandingAction()) + } else if (current == cancelLandActionIcon) { + addDisposable(performLandingConfirmationAction()) + } else { + if (checkBoxChecked) { + addDisposable(performPrecisionTakeOffAction()) + } else { + addDisposable(performTakeOffAction()) + } + } + slidingDialog?.dismiss() + uiUpdateStateProcessor.onNext(DialogActionConfirmed(dialogType)) + } + + private fun performTakeOffAction(): Disposable { + return widgetModel.performTakeOffAction() + .subscribe({ + widgetStateDataProcessor.onNext(TakeOffStartSucceeded) + }) { error: Throwable -> + if (error is UXSDKError) { + widgetStateDataProcessor.onNext(TakeOffStartFailed(error)) + } + } + } + + private fun performPrecisionTakeOffAction(): Disposable { + return widgetModel.performPrecisionTakeOffAction() + .subscribe({ + widgetStateDataProcessor.onNext(PrecisionTakeOffStartSucceeded) + }) { error: Throwable -> + if (error is UXSDKError) { + widgetStateDataProcessor.onNext(PrecisionTakeOffStartFailed(error)) + } + } + } + + private fun performLandingAction(): Disposable { + return widgetModel.performLandingAction() + .subscribe({ + widgetStateDataProcessor.onNext(LandingStartSucceeded) + }) { error: Throwable -> + if (error is UXSDKError) { + widgetStateDataProcessor.onNext(LandingStartFailed(error)) + } + } + } + + private fun performLandingConfirmationAction(): Disposable { + return widgetModel.performLandingConfirmationAction() + .subscribe({ + widgetStateDataProcessor.onNext(LandingConfirmSucceeded) + }) { error: Throwable -> + if (error is UXSDKError) { + widgetStateDataProcessor.onNext(LandingConfirmFailed(error)) + } + } + } + + private fun performCancelLandAction(): Disposable { + return widgetModel.performCancelLandingAction() + .observeOn(SchedulerProvider.ui()) + .subscribe({ + slidingDialog?.dismiss() + widgetStateDataProcessor.onNext(LandingCancelSucceeded) + }) { error: Throwable -> + if (error is UXSDKError) { + widgetStateDataProcessor.onNext(LandingCancelFailed(error)) + } + } + } + + private fun showDialog() { + slidingDialog?.let { + it.setDialogTitleTextColor(dialogTitleTextColor) + .setDialogMessageTextSize( + if (it.checkBoxChecked) { + dialogPrecisionMessageTextSize + } else { + dialogMessageTextSize + }) + .show() + } + } + + private fun showTakeOffDialog() { + slidingDialog?.setDialogTitleRes(R.string.uxsdk_take_off_header) + ?.setActionMessageRes(R.string.uxsdk_take_off_action) + ?.setDialogIcon(takeOffDialogIcon) + ?.setCheckBoxMessageRes(R.string.uxsdk_precision_takeoff) + showDialog() + uiUpdateStateProcessor.onNext(DialogDisplayed(TakeOff)) + dialogType = TakeOff + + updateCheckBoxVisibility() + updateTakeOffDialogMessage() + } + + private fun updateCheckBoxVisibility() { +// addDisposable(widgetModel.isPrecisionTakeoffSupported +// .observeOn(SchedulerProvider.ui()) +// .subscribe(Consumer { +// slidingDialog?.setCheckBoxVisibility(it) +// if (!it) { +// slidingDialog?.setCheckBoxChecked(false) +// } +// }, RxUtil.logErrorConsumer(TAG, "Update Precision Takeoff Check Box "))) + slidingDialog?.setCheckBoxChecked(true) + } + + private fun updateTakeOffDialogMessage() { + if (slidingDialog?.checkBoxChecked == true) { + val takeOffHeightString = getHeightString(widgetModel.precisionTakeOffHeight) + slidingDialog?.setDialogMessage(resources.getString(R.string.uxsdk_precision_takeoff_message, + takeOffHeightString)) + ?.setDialogMessageTextSize(dialogPrecisionMessageTextSize) + } else { + addDisposable(widgetModel.isInAttiMode.firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(Consumer { isInAttiMode: Boolean -> + val takeOffHeightString = getHeightString(widgetModel.takeOffHeight) + slidingDialog?.setDialogMessage( + if (isInAttiMode) { + resources.getString(R.string.uxsdk_take_off_atti_message, takeOffHeightString) + } else { + resources.getString(R.string.uxsdk_take_off_message, takeOffHeightString) + }) + ?.setDialogMessageTextSize(dialogMessageTextSize) + }, UxErrorHandle.logErrorConsumer(TAG, "Update Takeoff Message "))) + } + } + + private fun getHeightString(height: TakeOffWidgetModel.Height): String { + val resourceString = + if (height.unitType == UnitConversionUtil.UnitType.IMPERIAL) { + R.string.uxsdk_value_feet + } else { + R.string.uxsdk_value_meters + } + return resources.getString(resourceString, decimalFormat.format(height.height)) + } + + private fun showLandingDialog() { + slidingDialog?.setDialogTitleRes(R.string.uxsdk_land_header) + ?.setDialogMessageRes(R.string.uxsdk_land_message) + ?.setDialogIcon(landingDialogIcon) + ?.setActionMessageRes(R.string.uxsdk_land_action) + ?.setCheckBoxVisibility(false) + ?.setCheckBoxChecked(false) + showDialog() + uiUpdateStateProcessor.onNext(DialogDisplayed(Landing)) + dialogType = Landing + } + + private fun showLandingConfirmationDialog() { + slidingDialog?.setDialogTitleRes(R.string.uxsdk_land_confirmation_header) + ?.setDialogIcon(landingConfirmationDialogIcon) + ?.setActionMessageRes(R.string.uxsdk_land_action) + ?.setCheckBoxVisibility(false) + ?.setCheckBoxChecked(false) + showDialog() + uiUpdateStateProcessor.onNext(DialogDisplayed(LandingConfirmation)) + dialogType = LandingConfirmation + + updateLandingConfirmationDialogMessage() + } + + private fun updateLandingConfirmationDialogMessage() { + val landHeightString = getHeightString(widgetModel.landHeight) + slidingDialog?.setDialogMessage(resources.getString(R.string.uxsdk_land_confirmation_message, landHeightString)) + } + + private fun showUnsafeToLandDialog() { + slidingDialog?.setDialogTitleRes(R.string.uxsdk_unsafe_to_land_header) + ?.setDialogMessageRes(R.string.uxsdk_unsafe_to_land_message) + ?.setDialogIcon(unsafeToLandDialogIcon) + ?.setActionMessageRes(R.string.uxsdk_unsafe_to_land_action) + ?.setCheckBoxVisibility(false) + ?.setCheckBoxChecked(false) + showDialog() + uiUpdateStateProcessor.onNext(DialogDisplayed(UnsafeToLand)) + dialogType = UnsafeToLand + } + + private fun updateTakeOffStatus(takeOffLandingState: TakeOffLandingState) { + widgetStateDataProcessor.onNext(TakeOffLandingStateUpdated(takeOffLandingState)) + foregroundImageView.setImageDrawable( + when (takeOffLandingState) { + TakeOffLandingState.READY_TO_TAKE_OFF, + TakeOffLandingState.TAKE_OFF_DISABLED -> takeOffActionIcon + TakeOffLandingState.READY_TO_LAND, + TakeOffLandingState.LAND_DISABLED -> landActionIcon + TakeOffLandingState.AUTO_LANDING, + TakeOffLandingState.FORCED_AUTO_LANDING, + TakeOffLandingState.WAITING_FOR_LANDING_CONFIRMATION, + TakeOffLandingState.UNSAFE_TO_LAND -> cancelLandActionIcon + else -> null + }) + isEnabled = !(takeOffLandingState == TakeOffLandingState.TAKE_OFF_DISABLED || + takeOffLandingState == TakeOffLandingState.LAND_DISABLED || + takeOffLandingState == TakeOffLandingState.FORCED_AUTO_LANDING) + visibility = + if (takeOffLandingState == TakeOffLandingState.RETURNING_TO_HOME || + takeOffLandingState == TakeOffLandingState.DISCONNECTED) { + View.GONE + } else { + View.VISIBLE + } + updateImageAlpha() + + when (takeOffLandingState) { + TakeOffLandingState.UNSAFE_TO_LAND -> showUnsafeToLandDialog() + TakeOffLandingState.WAITING_FOR_LANDING_CONFIRMATION -> showLandingConfirmationDialog() + TakeOffLandingState.READY_TO_TAKE_OFF, + TakeOffLandingState.TAKE_OFF_DISABLED -> slidingDialog?.dismiss() + else -> { + //do nothing + } + } + } + + private fun updateImageAlpha() { + if (foregroundImageView.imageDrawable == cancelLandActionIcon) { + foregroundImageView.isEnabled = isEnabled + if (isPressed) { + foregroundImageView.alpha = disabledAlpha + } else { + foregroundImageView.alpha = enabledAlpha + } + return + } + + if ((isPressed || isFocused) || !isEnabled) { + foregroundImageView.alpha = disabledAlpha + } else { + foregroundImageView.alpha = enabledAlpha + } + } + + private fun checkAndUpdateTakeOffLandingState() { + if (!isInEditMode) { + addDisposable(widgetModel.takeOffLandingState.firstOrError() + .observeOn(SchedulerProvider.ui()) + .subscribe(Consumer { this.updateTakeOffStatus(it) }, + UxErrorHandle.logErrorConsumer(TAG, "Update Take Off Landing State "))) + } + } + + override fun checkAndUpdateIconColor() { + // do nothing + } + + @SuppressLint("Recycle") + private fun initAttributes(context: Context, attrs: AttributeSet) { + context.obtainStyledAttributes(attrs, R.styleable.TakeOffWidget).use { typedArray -> + typedArray.getFloatAndUse(R.styleable.TakeOffWidget_uxsdk_disabledAlpha) { + disabledAlpha = it + } + typedArray.getFloatAndUse(R.styleable.TakeOffWidget_uxsdk_enabledAlpha) { + enabledAlpha = it + } + typedArray.getResourceIdAndUse(R.styleable.TakeOffWidget_uxsdk_dialogTheme) { + dialogTheme = it + } + typedArray.getDrawableAndUse(R.styleable.TakeOffWidget_uxsdk_takeOffActionDrawable) { + takeOffActionIcon = it + } + typedArray.getDrawableAndUse(R.styleable.TakeOffWidget_uxsdk_landActionDrawable) { + landActionIcon = it + } + typedArray.getDrawableAndUse(R.styleable.TakeOffWidget_uxsdk_cancelLandActionDrawable) { + cancelLandActionIcon = it + } + typedArray.getDrawableAndUse(R.styleable.TakeOffWidget_uxsdk_takeOffDialogIcon) { + takeOffDialogIcon = it + } + typedArray.getDrawableAndUse(R.styleable.TakeOffWidget_uxsdk_landingDialogIcon) { + landingDialogIcon = it + } + typedArray.getDrawableAndUse(R.styleable.TakeOffWidget_uxsdk_landingConfirmationDialogIcon) { + landingConfirmationDialogIcon = it + } + typedArray.getDrawableAndUse(R.styleable.TakeOffWidget_uxsdk_unsafeToLandDialogIcon) { + unsafeToLandDialogIcon = it + } + typedArray.getResourceIdAndUse(R.styleable.TakeOffWidget_uxsdk_dialogTitleTextAppearance) { + setDialogTitleTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.TakeOffWidget_uxsdk_dialogTitleTextSize) { + dialogTitleTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.TakeOffWidget_uxsdk_dialogTitleTextColor) { + dialogTitleTextColor = it + } + typedArray.getDrawableAndUse(R.styleable.TakeOffWidget_uxsdk_dialogTitleBackground) { + dialogTitleBackground = it + } + typedArray.getResourceIdAndUse(R.styleable.TakeOffWidget_uxsdk_dialogMessageTextAppearance) { + setDialogMessageTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.TakeOffWidget_uxsdk_dialogMessageTextSize) { + dialogMessageTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getDimensionAndUse(R.styleable.TakeOffWidget_uxsdk_dialogPrecisionMessageTextSize) { + dialogPrecisionMessageTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.TakeOffWidget_uxsdk_dialogMessageTextColor) { + dialogMessageTextColor = it + } + typedArray.getDrawableAndUse(R.styleable.TakeOffWidget_uxsdk_dialogMessageBackground) { + dialogMessageBackground = it + } + typedArray.getResourceIdAndUse(R.styleable.TakeOffWidget_uxsdk_dialogCheckBoxMessageTextAppearance) { + setDialogCheckBoxMessageTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.TakeOffWidget_uxsdk_dialogCheckBoxMessageTextSize) { + dialogCheckBoxMessageTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.TakeOffWidget_uxsdk_dialogCheckBoxMessageTextColor) { + dialogCheckBoxMessageTextColor = it + } + typedArray.getDrawableAndUse(R.styleable.TakeOffWidget_uxsdk_dialogCheckBoxMessageBackground) { + dialogCheckBoxMessageBackground = it + } + typedArray.getResourceIdAndUse(R.styleable.TakeOffWidget_uxsdk_dialogCancelTextAppearance) { + setDialogCancelTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.TakeOffWidget_uxsdk_dialogCancelTextSize) { + dialogCancelTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.TakeOffWidget_uxsdk_dialogCancelTextColor) { + dialogCancelTextColor = it + } + typedArray.getDrawableAndUse(R.styleable.TakeOffWidget_uxsdk_dialogCancelBackground) { + dialogCancelBackground = it + } + typedArray.getResourceIdAndUse(R.styleable.TakeOffWidget_uxsdk_dialogSliderMessageTextAppearance) { + setDialogSliderMessageTextAppearance(it) + } + typedArray.getDimensionAndUse(R.styleable.TakeOffWidget_uxsdk_dialogSliderMessageTextSize) { + dialogSliderMessageTextSize = DisplayUtil.pxToSp(context, it) + } + typedArray.getColorAndUse(R.styleable.TakeOffWidget_uxsdk_dialogSliderMessageTextColor) { + dialogSliderMessageTextColor = it + } + typedArray.getDrawableAndUse(R.styleable.TakeOffWidget_uxsdk_dialogSliderMessageBackground) { + dialogSliderMessageBackground = it + } + typedArray.getDrawableAndUse(R.styleable.TakeOffWidget_uxsdk_dialogSliderIcon) { + dialogSliderIcon = it + } + typedArray.getColorAndUse(R.styleable.TakeOffWidget_uxsdk_dialogSliderThumbColor) { + dialogSliderThumbColor = it + } + typedArray.getColorAndUse(R.styleable.TakeOffWidget_uxsdk_dialogSliderThumbSelectedColor) { + dialogSliderThumbSelectedColor = it + } + typedArray.getColorAndUse(R.styleable.TakeOffWidget_uxsdk_dialogSliderFillColor) { + dialogSliderFillColor = it + } + typedArray.getDrawableAndUse(R.styleable.TakeOffWidget_uxsdk_dialogBackground) { + dialogBackground = it + } + } + } + //endregion + + //region Customizations + /** + * Set takeoff icon drawable + * + * @param resourceId resource id of takeoff icon + */ + fun setTakeOffActionIcon(@DrawableRes resourceId: Int) { + takeOffActionIcon = getDrawable(resourceId) + } + + /** + * Set land action icon drawable + * + * @param resourceId resource id of land action icon + */ + fun setLandActionIcon(@DrawableRes resourceId: Int) { + landActionIcon = getDrawable(resourceId) + } + + /** + * Set cancel land action icon drawable + * + * @param resourceId resource id of cancel land action + */ + fun setCancelLandActionIcon(@DrawableRes resourceId: Int) { + cancelLandActionIcon = getDrawable(resourceId) + } + + /** + * Set takeoff dialog icon drawable + * + * @param resourceId resource id of takeoff dialog icon + */ + fun setTakeOffDialogIcon(@DrawableRes resourceId: Int) { + takeOffDialogIcon = getDrawable(resourceId) + } + + /** + * Set landing dialog icon drawable + * + * @param resourceId resource id of landing dialog icon + */ + fun setLandingDialogIcon(@DrawableRes resourceId: Int) { + landingDialogIcon = getDrawable(resourceId) + } + + /** + * Set landing confirmation dialog icon drawable + * + * @param resourceId resource id of landing confirmation dialog icon + */ + fun setLandingConfirmationDialogIcon(@DrawableRes resourceId: Int) { + landingConfirmationDialogIcon = getDrawable(resourceId) + } + + /** + * Set unsafe to land dialog icon drawable + * + * @param resourceId resource id of unsafe to land dialog icon + */ + fun setUnsafeToLandDialogIcon(@DrawableRes resourceId: Int) { + unsafeToLandDialogIcon = getDrawable(resourceId) + } + + /** + * Set the text appearance of the title for all the dialogs shown by this widget + * + * @param textAppearance Style resource for text appearance + */ + fun setDialogTitleTextAppearance(@StyleRes textAppearance: Int) { + slidingDialog?.setDialogTitleTextAppearance(textAppearance) + } + + /** + * Set the text appearance of the message for all the dialogs shown by this widget + * + * @param textAppearance Style resource for text appearance + */ + fun setDialogMessageTextAppearance(@StyleRes textAppearance: Int) { + slidingDialog?.setDialogMessageTextAppearance(textAppearance) + } + + /** + * Set the text appearance of the precision checkbox message for the takeoff dialog + * + * @param textAppearance Style resource for text appearance + */ + fun setDialogCheckBoxMessageTextAppearance(@StyleRes textAppearance: Int) { + slidingDialog?.setCheckBoxMessageTextAppearance(textAppearance) + } + + /** + * Set the text appearance of the cancel button for all the dialogs shown by this widget + * + * @param textAppearance Style resource for text appearance + */ + fun setDialogCancelTextAppearance(@StyleRes textAppearance: Int) { + slidingDialog?.setCancelTextAppearance(textAppearance) + } + + /** + * Set the text appearance of the slider message for all the dialogs shown by this widget + * + * @param textAppearance Style resource for text appearance + */ + fun setDialogSliderMessageTextAppearance(@StyleRes textAppearance: Int) { + slidingDialog?.setActionMessageTextAppearance(textAppearance) + } + //endregion + + //region Hooks + /** + * Get the [ModelState] updates + */ + @SuppressWarnings + override fun getWidgetStateUpdate(): Flowable { + return super.getWidgetStateUpdate() + } + + /** + * Class defines the widget state updates + */ + sealed class ModelState { + /** + * Product connection update + */ + data class ProductConnected(val isConnected: Boolean) : ModelState() + + /** + * Takeoff Landing State update + */ + data class TakeOffLandingStateUpdated(val state: TakeOffLandingState) : ModelState() + + /** + * Takeoff started successfully + */ + object TakeOffStartSucceeded : ModelState() + + /** + * Takeoff not started due to error + */ + data class TakeOffStartFailed(val error: UXSDKError) : ModelState() + + /** + * Precision Takeoff started successfully + */ + object PrecisionTakeOffStartSucceeded : ModelState() + + /** + * Precision Takeoff not started due to error + */ + data class PrecisionTakeOffStartFailed(val error: UXSDKError) : ModelState() + + /** + * Landing started successfully + */ + object LandingStartSucceeded : ModelState() + + /** + * Landing not started due to error + */ + data class LandingStartFailed(val error: UXSDKError) : ModelState() + + /** + * Landing confirmed successfully + */ + object LandingConfirmSucceeded : ModelState() + + /** + * Landing not confirmed due to error + */ + data class LandingConfirmFailed(val error: UXSDKError) : ModelState() + + /** + * Landing canceled successfully + */ + object LandingCancelSucceeded : ModelState() + + /** + * Landing not canceled due to error + */ + data class LandingCancelFailed(val error: UXSDKError) : ModelState() + } + + /** + * The type of dialog shown + */ + sealed class DialogType { + + /** + * The takeoff dialog, which is shown when the widget is clicked and the aircraft is ready + * to take off. + */ + object TakeOff : DialogType() + + /** + * The landing dialog, which is shown when the widget is clicked and the aircraft is ready + * to land. + */ + object Landing : DialogType() + + /** + * The landing confirmation dialog, which is shown when the aircraft has paused + * auto-landing and is waiting for confirmation before continuing. + */ + object LandingConfirmation : DialogType() + + /** + * The unsafe to land dialog, which is shown when the aircraft is auto-landing and has + * determined it is unsafe to land. + */ + object UnsafeToLand : DialogType() + } + + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/takeoff/TakeOffWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/takeoff/TakeOffWidgetModel.kt new file mode 100644 index 00000000..dd1793c4 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/flight/takeoff/TakeOffWidgetModel.kt @@ -0,0 +1,369 @@ +/* + * Copyright (c) 2018-2020 DJI + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +package dji.v5.ux.flight.takeoff + +import dji.sdk.keyvalue.key.FlightAssistantKey +import dji.sdk.keyvalue.key.FlightControllerKey +import dji.sdk.keyvalue.key.ProductKey +import dji.sdk.keyvalue.key.RemoteControllerKey +import dji.sdk.keyvalue.value.flightassistant.LandingProtectionState +import dji.sdk.keyvalue.value.flightcontroller.FCAutoRTHReason +import dji.sdk.keyvalue.value.flightcontroller.FCFlightMode +import dji.sdk.keyvalue.value.product.ProductType +import dji.sdk.keyvalue.value.remotecontroller.RCMode +import dji.sdk.keyvalue.key.KeyTools +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.GlobalPreferenceKeys +import dji.v5.ux.core.communication.GlobalPreferencesInterface +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.communication.UXKeys +import dji.v5.ux.core.util.DataProcessor +import dji.v5.ux.core.util.UnitConversionUtil +import io.reactivex.rxjava3.core.Completable +import io.reactivex.rxjava3.core.Flowable + +private const val TAKEOFF_HEIGHT: Float = 1.2f +private const val PRECISION_TAKEOFF_HEIGHT: Float = 6f +private const val LAND_HEIGHT: Float = 0.3f + +/** + * Widget Model for the [TakeOffWidget] used to define + * the underlying logic and communication + */ +class TakeOffWidgetModel( + djiSdkModel: DJISDKModel, + keyedStore: ObservableInMemoryKeyedStore, + private val preferencesManager: GlobalPreferencesInterface? +) : WidgetModel(djiSdkModel, keyedStore) { + + //region Fields + private val isFlyingDataProcessor: DataProcessor = DataProcessor.create(false) + private val isAutoLandingDataProcessor: DataProcessor = DataProcessor.create(false) + private val isLandingConfNeededDataProcessor: DataProcessor = DataProcessor.create(false) + private val forceLandingHeightDataProcessor: DataProcessor = DataProcessor.create(0) + private val areMotorsOnDataProcessor: DataProcessor = DataProcessor.create(false) + private val isGoingHomeDataProcessor: DataProcessor = DataProcessor.create(false) + private val flightModeStringDataProcessor: DataProcessor = DataProcessor.create("") + private val isCancelAutoLandingDisabledProcessor: DataProcessor = DataProcessor.create(false) + private val autoRTHReasonProcessor: DataProcessor = DataProcessor.create(FCAutoRTHReason.UNKNOWN) + private val rcModeDataProcessor: DataProcessor = DataProcessor.create(RCMode.UNKNOWN) + private val productModelProcessor: DataProcessor = DataProcessor.create(ProductType.UNKNOWN) + private val unitTypeProcessor: DataProcessor = DataProcessor.create(UnitConversionUtil.UnitType.METRIC) + private val landingProtectionStateDataProcessor: DataProcessor = DataProcessor.create(LandingProtectionState.UNKNOWN) + private val flightModeProcessor: DataProcessor = DataProcessor.create(FCFlightMode.UNKNOWN) + + private val takeOffLandingStateDataProcessor: DataProcessor = + DataProcessor.create(TakeOffLandingState.DISCONNECTED) + private val isInAttiModeDataProcessor: DataProcessor = + DataProcessor.create(false) + //endregion + + //region Data + /** + * Get the takeoff landing state + */ + val takeOffLandingState: Flowable + get() = takeOffLandingStateDataProcessor.toFlowable().distinctUntilChanged() + + /** + * Get whether the product is in ATTI mode + */ + val isInAttiMode: Flowable + get() = isInAttiModeDataProcessor.toFlowable() + + /** + * Get the height the aircraft will reach after takeoff + */ + val takeOffHeight: Height + get() = getHeightFromValue(TAKEOFF_HEIGHT) + + /** + * Get the height the aircraft will reach after a precision takeoff + */ + val precisionTakeOffHeight: Height + get() = getHeightFromValue(PRECISION_TAKEOFF_HEIGHT) + + /** + * Get the current height of the aircraft while waiting for landing confirmation + */ + val landHeight: Height + get() = getHeightFromValue(getLandHeight()) + //endregion + + //region Constructor + init { + if (preferencesManager != null) { + unitTypeProcessor.onNext(preferencesManager.unitType) + } + } + //endregion + + //region Actions + /** + * Performs take off action + */ + fun performTakeOffAction(): Completable { + return djiSdkModel.performActionWithOutResult( + KeyTools.createKey( + FlightControllerKey.KeyStartTakeoff)) + .onErrorResumeNext { error: Throwable -> + if (areMotorsOnDataProcessor.value) { + return@onErrorResumeNext Completable.complete() + } else { + return@onErrorResumeNext Completable.error(error) + } + } + } + + /** + * Performs precision take off action + */ + fun performPrecisionTakeOffAction(): Completable { + return djiSdkModel.performActionWithOutResult( + KeyTools.createKey( + FlightControllerKey.KeyStartTakeoff)) + .onErrorResumeNext { error: Throwable -> + if (areMotorsOnDataProcessor.value) { + return@onErrorResumeNext Completable.complete() + } else { + return@onErrorResumeNext Completable.error(error) + } + } + } + + /** + * Performs landing action + */ + fun performLandingAction(): Completable { + return djiSdkModel.performActionWithOutResult( + KeyTools.createKey( + FlightControllerKey.KeyStartAutoLanding)) + } + + /** + * Performs cancel landing action + */ + fun performCancelLandingAction(): Completable { + return djiSdkModel.performActionWithOutResult( + KeyTools.createKey( + FlightControllerKey.KeyStopAutoLanding)) + } + + /** + * Performs the landing confirmation action. This allows aircraft to land when + * landing confirmation is received. + */ + fun performLandingConfirmationAction(): Completable { + return djiSdkModel.performActionWithOutResult( + KeyTools.createKey( + FlightControllerKey.KeyConfirmLanding)) + } + + //endregion + + //region Lifecycle + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyIsFlying), isFlyingDataProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyIsInLandingMode), isAutoLandingDataProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyIsLandingConfirmationNeeded), isLandingConfNeededDataProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyTouchDownConfirmLimitHeight), forceLandingHeightDataProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyFlightModeString), flightModeStringDataProcessor) { value: Any -> + isInAttiModeDataProcessor.onNext((value as String).contains("atti", ignoreCase = true)) + } + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAreMotorsOn), areMotorsOnDataProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyFCFlightMode), flightModeProcessor) { + isGoingHomeDataProcessor.onNext(it == FCFlightMode.GO_HOME || it == FCFlightMode.AUTO_LANDING) + } + bindDataProcessor( + KeyTools.createKey( + FlightControllerKey.KeyAutoRTHReason), autoRTHReasonProcessor) { + isCancelAutoLandingDisabledProcessor.onNext( + it == FCAutoRTHReason.WARNING_POWER_LANDING + || it == FCAutoRTHReason.SMART_POWER_LANDING + || it == FCAutoRTHReason.LOW_VOLTAGE_LANDING + || it == FCAutoRTHReason.SERIOUS_LOW_VOLTAGE_LANDING + || it == FCAutoRTHReason.NO_FLY_ZONE_LANDING + || it == FCAutoRTHReason.BATTERY_FORCE_LANDING + ) + } + bindDataProcessor( + KeyTools.createKey( + RemoteControllerKey.KeyRcMachineMode), rcModeDataProcessor) + bindDataProcessor( + KeyTools.createKey( + ProductKey.KeyProductType), productModelProcessor) + val unitKey = UXKeys.create(GlobalPreferenceKeys.UNIT_TYPE) + bindDataProcessor(unitKey, unitTypeProcessor) + bindDataProcessor( + KeyTools.createKey( + FlightAssistantKey.KeyLandingProtectionState), landingProtectionStateDataProcessor) + preferencesManager?.setUpListener() + } + + override fun inCleanup() { + preferencesManager?.cleanup() + } + + override fun updateStates() { + if (!productConnectionProcessor.value) { + takeOffLandingStateDataProcessor.onNext(TakeOffLandingState.DISCONNECTED) + } else if (isAutoLandingDataProcessor.value) { + updateAutoLandingData() + } else if (isGoingHomeDataProcessor.value && !isAutoLandingDataProcessor.value) { + takeOffLandingStateDataProcessor.onNext(TakeOffLandingState.RETURNING_TO_HOME) + } else if (!areMotorsOnDataProcessor.value) { + if (rcModeDataProcessor.value == RCMode.SLAVE) { + takeOffLandingStateDataProcessor.onNext(TakeOffLandingState.TAKE_OFF_DISABLED) + } else { + takeOffLandingStateDataProcessor.onNext(TakeOffLandingState.READY_TO_TAKE_OFF) + } + } else { + if (rcModeDataProcessor.value == RCMode.SLAVE) { + takeOffLandingStateDataProcessor.onNext(TakeOffLandingState.LAND_DISABLED) + } else { + takeOffLandingStateDataProcessor.onNext(TakeOffLandingState.READY_TO_LAND) + } + } + } + + private fun updateAutoLandingData() { + if (isLandingConfNeededDataProcessor.value) { + takeOffLandingStateDataProcessor.onNext(TakeOffLandingState.WAITING_FOR_LANDING_CONFIRMATION) + } else if (isCancelAutoLandingDisabled()) { + takeOffLandingStateDataProcessor.onNext(TakeOffLandingState.FORCED_AUTO_LANDING) + } else if (landingProtectionStateDataProcessor.value == LandingProtectionState.NOT_SAFE_TO_LAND) { + takeOffLandingStateDataProcessor.onNext(TakeOffLandingState.UNSAFE_TO_LAND) + } else { + takeOffLandingStateDataProcessor.onNext(TakeOffLandingState.AUTO_LANDING) + } + } + + private fun isCancelAutoLandingDisabled(): Boolean { + return isCancelAutoLandingDisabledProcessor.value || + rcModeDataProcessor.value == RCMode.SLAVE + } + + private fun getHeightFromValue(value: Float): Height { + return Height( + if (unitTypeProcessor.value == UnitConversionUtil.UnitType.IMPERIAL) { + UnitConversionUtil.convertMetersToFeet(value) + } else { + value + }, + unitTypeProcessor.value + ) + } + + private fun getLandHeight(): Float { + return if (forceLandingHeightDataProcessor.value != Int.MIN_VALUE) { + forceLandingHeightDataProcessor.value * 0.1f + } else { + LAND_HEIGHT + } + } + //endregion + + //region Classes + /** + * The state of the aircraft + */ + enum class TakeOffLandingState { + /** + * The aircraft is ready to take off + */ + READY_TO_TAKE_OFF, + + /** + * The aircraft is currently flying and is ready to land + */ + READY_TO_LAND, + + /** + * The aircraft has started auto landing + */ + AUTO_LANDING, + + /** + * The aircraft has started auto landing and it cannot be canceled + */ + FORCED_AUTO_LANDING, + + /** + * The aircraft has paused auto landing and is waiting for confirmation before continuing + */ + WAITING_FOR_LANDING_CONFIRMATION, + + /** + * The aircraft has determined it is unsafe to land while auto landing is in progress + */ + UNSAFE_TO_LAND, + + /** + * The aircraft is returning to its home point + */ + RETURNING_TO_HOME, + + /** + * The aircraft cannot take off + */ + TAKE_OFF_DISABLED, + + /** + * The aircraft cannot land + */ + LAND_DISABLED, + + /** + * The aircraft is disconnected + */ + DISCONNECTED + } + + /** + * Represents a height and the height's unit. + * + * @property height The current height of the aircraft in [unitType] + * @property unitType The unit type of [height] + */ + data class Height( + val height: Float, + val unitType: UnitConversionUtil.UnitType + ) + //endregion +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/gimbal/GimbalFineTuneWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/gimbal/GimbalFineTuneWidget.kt new file mode 100644 index 00000000..75b577b4 --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/gimbal/GimbalFineTuneWidget.kt @@ -0,0 +1,160 @@ +package dji.v5.ux.gimbal + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import android.widget.ImageView +import android.widget.TextView +import androidx.core.content.ContextCompat +import dji.sdk.keyvalue.value.common.ComponentIndexType +import dji.sdk.keyvalue.value.gimbal.PostureFineTuneAxis +import dji.v5.utils.common.AndUtil +import dji.v5.utils.common.LogUtils +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.IGimbalIndex +import dji.v5.ux.core.base.SchedulerProvider.ui +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import java.util.Locale + +/** + * This widget is used to manually fine-tune the gimbal + */ +open class GimbalFineTuneWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ConstraintLayoutWidget(context, attrs, defStyleAttr), View.OnClickListener, IGimbalIndex { + + companion object { + private val TAG = "GimbalFineTuneWidget" + private val GIMBAL_PITCH_FINE_TUNE = PostureFineTuneAxis.PITCH_AXIS + private val GIMBAL_ROLL_FINE_TUNE = PostureFineTuneAxis.ROLL_AXIS + private val GIMBAL_YAW_FINE_TUNE = PostureFineTuneAxis.YAW_AXIS + } + + private val widgetModel = GimbalFineTuneWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance() + ) + + private val pitchTv: TextView = findViewById(R.id.fpv_left_tv) + private val rollTv: TextView = findViewById(R.id.fpv_middle_tv) + private val yawTv: TextView = findViewById(R.id.fpv_right_tv) + private val imgMinus: ImageView = findViewById(R.id.fpv_gimbal_finetune_minus_img) + private val tvValue: TextView = findViewById(R.id.fpv_gimbal_finetune_value_tv) + private val imgPlus: ImageView = findViewById(R.id.fpv_gimbal_finetune_plus_img) + + var rollDegree: Double = 0.0 + var pitchDegree: Double = 0.0 + var yawDegree: Double = 0.0 + var currentAxis: PostureFineTuneAxis = PostureFineTuneAxis.PITCH_AXIS + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + inflate(context, R.layout.uxsdk_gimbal_fine_tune, this) + setBackgroundResource(R.drawable.uxsdk_background_black_rectangle) + val padding = AndUtil.dip2px(getContext(), 16f) + setPadding(padding, padding, padding, padding) + } + + override fun onAttachedToWindow() { + super.onAttachedToWindow() + if (!isInEditMode) { + widgetModel.setup() + pitchTv.setOnClickListener(this) + rollTv.setOnClickListener(this) + yawTv.setOnClickListener(this) + imgMinus.setOnClickListener(this) + imgPlus.setOnClickListener(this) + tvValue.setOnClickListener(this) + updateViewForType(currentAxis) + } + + } + + override fun onDetachedFromWindow() { + super.onDetachedFromWindow() + if (!isInEditMode) { + widgetModel.cleanup() + } + } + + override fun reactToModelChanges() { + //Roll微调角度 + addReaction(widgetModel.rollAdjustDegree().observeOn(ui()).subscribe { degree: Double -> + rollDegree = degree + updateViewForType(currentAxis) + }) + + //Pitch微调角度 + addReaction(widgetModel.pitchAdjustDegree().observeOn(ui()).subscribe { degree: Double -> + pitchDegree = degree + updateViewForType(currentAxis) + }) + //Yaw微调角度 + addReaction(widgetModel.yawAdjustDegree().observeOn(ui()).subscribe { degree: Double -> + yawDegree = degree + updateViewForType(currentAxis) + }) + } + + override fun onClick(v: View) { + val id = v.id + if (R.id.fpv_left_tv == id) { + updateViewForType(GIMBAL_PITCH_FINE_TUNE) + } else if (R.id.fpv_middle_tv == id) { + updateViewForType(GIMBAL_ROLL_FINE_TUNE) + } else if (R.id.fpv_right_tv == id) { + updateViewForType(GIMBAL_YAW_FINE_TUNE) + } else if (R.id.fpv_gimbal_finetune_minus_img == id) { + widgetModel.fineTunePosture(currentAxis, -0.1).subscribe() + } else if (R.id.fpv_gimbal_finetune_plus_img == id) { + widgetModel.fineTunePosture(currentAxis, 0.1).subscribe() + } else if (R.id.fpv_gimbal_finetune_value_tv == id) { + widgetModel.fineTunePosture(currentAxis, 0.0).subscribe() + } + } + + private fun updateViewForType(type: PostureFineTuneAxis) { + currentAxis = type + pitchTv.setTextColor(ContextCompat.getColor(context, R.color.uxsdk_fpv_white_50)) + rollTv.setTextColor(ContextCompat.getColor(context, R.color.uxsdk_fpv_white_50)) + yawTv.setTextColor(ContextCompat.getColor(context, R.color.uxsdk_fpv_white_50)) + when (type) { + GIMBAL_PITCH_FINE_TUNE -> { + pitchTv.setTextColor(ContextCompat.getColor(context, R.color.uxsdk_setting_ui_btn_hover)) + imgMinus.setImageResource(R.drawable.fpv_pitch_down_normal) + imgPlus.setImageResource(R.drawable.fpv_pitch_up_normal) + tvValue.text = String.format(Locale.US, "%.1f", if (-pitchDegree == -0.0) 0.0 else -pitchDegree) + } + + GIMBAL_ROLL_FINE_TUNE -> { + rollTv.setTextColor(ContextCompat.getColor(context, R.color.uxsdk_setting_ui_btn_hover)) + imgMinus.setImageResource(R.drawable.fpv_roll_leftarrow_normal) + imgPlus.setImageResource(R.drawable.fpv_roll_rightarrow_normal) + tvValue.text = String.format(Locale.US, "%.1f", if (rollDegree == -0.0) 0.0 else rollDegree) + } + + GIMBAL_YAW_FINE_TUNE -> { + yawTv.setTextColor(ContextCompat.getColor(context, R.color.uxsdk_setting_ui_btn_hover)) + imgMinus.setImageResource(R.drawable.fpv_yaw_right) + imgPlus.setImageResource(R.drawable.fpv_yaw_left) + tvValue.text = String.format(Locale.US, "%.1f", if (-yawDegree == -0.0) 0.0 else -yawDegree) + } + + else -> { + LogUtils.e(TAG, "unknown type: $currentAxis") + } + } + } + + override fun getGimbalIndex(): ComponentIndexType { + return widgetModel.getGimbalIndex() + } + + override fun updateGimbalIndex(gimbalIndex: ComponentIndexType) { + widgetModel.updateGimbalIndex(gimbalIndex) + } + +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/gimbal/GimbalFineTuneWidgetModel.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/gimbal/GimbalFineTuneWidgetModel.kt new file mode 100644 index 00000000..12006bbe --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/gimbal/GimbalFineTuneWidgetModel.kt @@ -0,0 +1,72 @@ +package dji.v5.ux.gimbal + +import dji.sdk.keyvalue.key.GimbalKey +import dji.sdk.keyvalue.key.KeyTools +import dji.sdk.keyvalue.value.common.ComponentIndexType +import dji.sdk.keyvalue.value.gimbal.FineTunePostureMsg +import dji.sdk.keyvalue.value.gimbal.PostureFineTuneAxis +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.IGimbalIndex +import dji.v5.ux.core.base.WidgetModel +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.util.DataProcessor +import io.reactivex.rxjava3.core.Completable +import io.reactivex.rxjava3.core.Flowable + +open class GimbalFineTuneWidgetModel constructor( + djiSdkModel: DJISDKModel, + uxKeyManager: ObservableInMemoryKeyedStore +) : WidgetModel(djiSdkModel, uxKeyManager), IGimbalIndex { + + private var gimbalIndex = ComponentIndexType.LEFT_OR_MAIN + + private val rollAdjustDegreeProcessor = DataProcessor.create(0.0) + private val yawAdjustDegreeProcessor = DataProcessor.create(0.0) + private val pitchAdjustDegreeProcessor = DataProcessor.create(0.0) + + override fun inSetup() { + bindDataProcessor( + KeyTools.createKey( + GimbalKey.KeyFineTuneRollTotalDegree, gimbalIndex), rollAdjustDegreeProcessor) + bindDataProcessor( + KeyTools.createKey( + GimbalKey.KeyFineTuneYawTotalDegree, gimbalIndex), yawAdjustDegreeProcessor) + bindDataProcessor( + KeyTools.createKey( + GimbalKey.KeyFineTunePitchTotalDegree, gimbalIndex), pitchAdjustDegreeProcessor) + } + + override fun inCleanup() { + //Nothing to cleanup + } + + fun fineTunePosture(axis: PostureFineTuneAxis, value: Double): Completable { + return djiSdkModel.performActionWithOutResult( + KeyTools.createKey(GimbalKey.KeyFineTunePosture, gimbalIndex), + FineTunePostureMsg(axis, value) + ) + } + + fun rollAdjustDegree(): Flowable { + return rollAdjustDegreeProcessor.toFlowable() + } + + fun yawAdjustDegree(): Flowable { + return yawAdjustDegreeProcessor.toFlowable() + } + + fun pitchAdjustDegree(): Flowable { + return pitchAdjustDegreeProcessor.toFlowable() + } + + override fun getGimbalIndex(): ComponentIndexType { + return gimbalIndex + } + + override fun updateGimbalIndex(gimbalIndex: ComponentIndexType) { + if (this.gimbalIndex != gimbalIndex) { + this.gimbalIndex = gimbalIndex + restart() + } + } +} \ No newline at end of file diff --git a/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/gimbal/GimbalSettingWidget.kt b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/gimbal/GimbalSettingWidget.kt new file mode 100644 index 00000000..f92a6c1b --- /dev/null +++ b/android-sdk-v5-uxsdk/src/main/java/dji/v5/ux/gimbal/GimbalSettingWidget.kt @@ -0,0 +1,121 @@ +package dji.v5.ux.gimbal + +import android.content.Context +import android.util.AttributeSet +import android.view.View +import android.widget.Button +import android.widget.Toast +import dji.sdk.keyvalue.value.common.ComponentIndexType +import dji.sdk.keyvalue.value.gimbal.GimbalCalibrationState +import dji.sdk.keyvalue.value.gimbal.GimbalCalibrationStatusInfo +import dji.v5.utils.common.LogUtils +import dji.v5.ux.R +import dji.v5.ux.core.base.DJISDKModel +import dji.v5.ux.core.base.IGimbalIndex +import dji.v5.ux.core.base.SchedulerProvider.ui +import dji.v5.ux.core.base.widget.ConstraintLayoutWidget +import dji.v5.ux.core.communication.ObservableInMemoryKeyedStore +import dji.v5.ux.core.ui.setting.dialog.CommonLoadingDialog +import dji.v5.ux.core.util.ViewUtil + + +open class GimbalSettingWidget @JvmOverloads constructor( + context: Context, + attrs: AttributeSet? = null, + defStyleAttr: Int = 0 +) : ConstraintLayoutWidget(context, attrs, defStyleAttr), View.OnClickListener, IGimbalIndex { + + companion object { + private const val TAG = "GimbalSettingWidget" + } + + private val loadingDialog: CommonLoadingDialog = CommonLoadingDialog(context) + + private var areMotors: Boolean = false + + private val widgetModel = GimbalSettingWidgetModel( + DJISDKModel.getInstance(), + ObservableInMemoryKeyedStore.getInstance() + ) + + override fun initView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) { + inflate(context, R.layout.uxsdk_gimbal_setting, this) + + val btnReset = findViewById