Ver código fonte

1. 根据修改后的目标形状重新计算长、宽、周长、面积。
2. 替换本地原有信息。

Ulric 1 semana atrás
pai
commit
09f80a6cc1

+ 10 - 0
app/src/main/java/com/ys/imageProcess/utils/GeometryTools.kt

@@ -1,7 +1,17 @@
 package com.ys.imageProcess.utils
 
+import android.graphics.PointF
+import androidx.compose.ui.geometry.Offset
 import androidx.compose.ui.geometry.Size
 
 fun area(size: Size): Float {
     return size.width * size.height
+}
+
+fun Offset.toPointF(): PointF {
+    return PointF(x, y)
+}
+
+fun PointF.toPointF(): Offset {
+    return Offset(x, y)
 }

+ 112 - 28
app/src/main/java/com/ys/imageProcess/viewModel/WorkViewModel.kt

@@ -28,6 +28,7 @@ import com.ys.imageProcess.ui.work.zoomStep
 import com.ys.imageProcess.utils.fileSizeString
 import com.ys.imageProcess.utils.formatDate
 import com.ys.imageProcess.utils.scaleLength
+import com.ys.imageProcess.utils.toPointF
 import com.ys.imageProcess.utils.zoomToFit
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.Dispatchers
@@ -54,9 +55,15 @@ class WorkViewModel : ViewModel() {
 
     val imageState = MutableStateFlow(ImageState())
 
+    // 当前渲染的目标形状,像素点的数组
+    private var displayedContour = mutableListOf<PointF>()
+    private var displayedLength = mutableListOf<PointF>()
+    private var displayedWidth = mutableListOf<PointF>()
+
     private var isEditingVertex = false // 正在编辑目标信息
     private var editingPath = -1 // 正在编辑的路径,0:轮廓,1:长,2:宽
     private var editingPoint = -1 // 正在编辑的顶点坐标的索引
+    private var edited = false // 保存时,若有编辑操作,则调用算法重新计算
 
     private var isAlgRunning: Boolean = false
 
@@ -150,7 +157,7 @@ class WorkViewModel : ViewModel() {
                 }
 
                 val store = ProcessedData(bitmap)
-                store.setMap(mMap)
+                store.updateWithStoredMap(mMap)
                 final = store
             } else {
                 // 解析数据,并将结果存到本地
@@ -221,14 +228,18 @@ class WorkViewModel : ViewModel() {
     }
 
     fun useDefaultPaths() {
-        val sizeValid = canvasSize.width * canvasSize.height > 1
-        val hasData = processedData.value.bitmap != null
-        Log.i(TAG, "size valid:$sizeValid, has data: $hasData")
-        if (sizeValid && hasData) {
+        val canvasValid = canvasSize.width * canvasSize.height > 1
+        val imageValid = processedData.value.bitmap != null
+        Log.i(TAG, "size valid:$canvasValid, has data: $imageValid")
+        if (canvasValid && imageValid) {
             Log.i(TAG, "image:$imageSize, canvas:$canvasSize")
             convertContour()
             convertWidth()
             convertLength()
+
+            displayedContour = processedData.value.contour.toMutableList()
+            displayedLength = processedData.value.lengthLine.toMutableList()
+            displayedWidth = processedData.value.widthLine.toMutableList()
         }
     }
 
@@ -315,16 +326,79 @@ class WorkViewModel : ViewModel() {
             ViewAction.ShowWidth -> imageState.value =
                 imageState.value.copy(showWidth = !imageState.value.showWidth)
 
-            ViewAction.SwitchEdit -> imageState.value =
-                imageState.value.copy(editMode = !imageState.value.editMode)
+            ViewAction.SwitchEdit -> {
+                if (imageState.value.editMode) {
+                    endEditing()
+                } else {
+                    imageState.value = imageState.value.copy(editMode = true)
+                }
+            }
         }
 
         updateVisibleArea()
     }
 
+    /**
+     * 结束编辑
+     */
+    private fun endEditing() {
+        // 退出编辑状态
+        imageState.value = imageState.value.copy(editMode = false)
+        if (edited) {
+            edited = false
+        } else {
+            return
+        }
+
+        // 使用新数据计算结果
+        val contour = mutableListOf<Double>()
+        for (p in displayedContour) {
+            contour.add(p.x.toDouble())
+            contour.add(p.y.toDouble())
+        }
+        val length = mutableListOf<Double>()
+        for (p in displayedLength) {
+            length.add(p.x.toDouble())
+            length.add(p.y.toDouble())
+        }
+        val width = mutableListOf<Double>()
+        for (p in displayedWidth) {
+            width.add(p.x.toDouble())
+            width.add(p.y.toDouble())
+        }
+
+        val result =
+            Process().Update(
+                processedData.value.pixelSize,
+                contour.toDoubleArray(),
+                length.toDoubleArray(),
+                width.toDoubleArray()
+            )
+        Log.i(
+            TAG,
+            "result: ${result.areaUm2},${result.perimeterUm},${result.midLengthUm},${result.midWidthUm}"
+        )
+        if (result.areaUm2 * result.perimeterUm * result.midLengthUm * result.midWidthUm <= 0) {
+            return
+        }
+
+        // 更新界面
+        val data = processedData.value
+        data.updateWithAlgResult(result)
+        processedData.value = data
+        updateInfoMap()
+
+        // 保存计算结果
+        // 先用临时文件名测试
+        val name = imageData.value.name.substringBeforeLast(".")
+        val map = processedData.value.map()
+        ProcessDataStore.saveResult(map, "00001")
+    }
+
     fun exitEditing() {
         imageState.value = imageState.value.copy(editMode = false)
         useDefaultPaths()
+        edited = false
     }
 
     fun onDrag(position: Offset) {
@@ -338,6 +412,7 @@ class WorkViewModel : ViewModel() {
             if (isEditingVertex) {
                 editingPath = pathIndex
                 editingPoint = pointIndex
+                edited = true
             }
 
             Log.i(
@@ -362,18 +437,21 @@ class WorkViewModel : ViewModel() {
 
             when (editingPath) {
                 0 -> {
+                    displayedContour[editingPoint] = newPixel.toPointF()
                     val newPath = contourPath.value.toMutableList()
                     newPath[editingPoint] = newVertex
                     contourPath.value = newPath
                 }
 
                 1 -> {
+                    displayedLength[editingPoint] = newPixel.toPointF()
                     val newPath = lengthPath.value.toMutableList()
                     newPath[editingPoint] = newVertex
                     lengthPath.value = newPath
                 }
 
                 2 -> {
+                    displayedWidth[editingPoint] = newPixel.toPointF()
                     val newPath = widthPath.value.toMutableList()
                     newPath[editingPoint] = newVertex
                     widthPath.value = newPath
@@ -618,7 +696,13 @@ data class ProcessedData(
         private set
 
     init {
-        // 使用 DetectResult 设置数据
+        updateWithAlgResult(result)
+    }
+
+    /**
+     * 使用算法结果更新
+     */
+    fun updateWithAlgResult(result: DetectResult? = null) {
         result?.let {
             area = it.areaUm2
             perimeter = it.perimeterUm
@@ -631,6 +715,26 @@ data class ProcessedData(
         }
     }
 
+    /**
+     * 使用本地数据更新
+     */
+    fun updateWithStoredMap(map: Map<String, Any>?) {
+        if (map == null) return
+
+        area = map[processDataKeyArea] as Double
+        perimeter = map[processDataKeyPerimeter] as Double
+        length = map[processDataKeyLength] as Double
+        width = map[processDataKeyWidth] as Double
+        pixelSize = map[processDataKeyScale] as Double
+        scaleLength = map[processDataKeyScaleLength] as Int
+
+        contour = mapArrayToPoints(map[processDataKeyContour] as ArrayList<*>)
+        lengthLine =
+            mapArrayToPoints(map[processDataKeyLengthLine] as ArrayList<*>)
+        widthLine =
+            mapArrayToPoints(map[processDataKeyWidthLine] as ArrayList<*>)
+    }
+
     /**
      * 将数据转为 Map
      */
@@ -650,26 +754,6 @@ data class ProcessedData(
         return map
     }
 
-    /**
-     * 使用 Map 设置数据
-     */
-    fun setMap(map: Map<String, Any>?) {
-        if (map == null) return
-
-        area = map[processDataKeyArea] as Double
-        perimeter = map[processDataKeyPerimeter] as Double
-        length = map[processDataKeyLength] as Double
-        width = map[processDataKeyWidth] as Double
-        pixelSize = map[processDataKeyScale] as Double
-        scaleLength = map[processDataKeyScaleLength] as Int
-
-        contour = mapArrayToPoints(map[processDataKeyContour] as ArrayList<*>)
-        lengthLine =
-            mapArrayToPoints(map[processDataKeyLengthLine] as ArrayList<*>)
-        widthLine =
-            mapArrayToPoints(map[processDataKeyWidthLine] as ArrayList<*>)
-    }
-
     private fun digitsToPoints(array: DoubleArray): List<PointF> {
         val list = mutableListOf<PointF>()
         for (i in array.indices step 2) {