Untitled

 avatar
unknown
plain_text
12 days ago
31 kB
3
Indexable
class MainScreen {

    private lateinit var lifeCycleOwner: LifecycleOwner

    private val blueOutlineSymbol by lazy {
        SimpleLineSymbol(SimpleLineSymbolStyle.Solid, color = com.arcgismaps.Color.fromRgba(0, 0, 255, 255), 2f)
    }

    private val pointSymbol by lazy {
        SimpleMarkerSymbol(SimpleMarkerSymbolStyle.Circle, color = com.arcgismaps.Color.fromRgba(255, 0, 0, 200), 15f).apply {
            // outline = blueOutlineSymbol
        }
    }

    private val lineSymbol by lazy {
        SimpleLineSymbol(SimpleLineSymbolStyle.Solid, color = com.arcgismaps.Color.fromRgba(0, 0, 0, 255), 3f)
    }

    private val polygonSymbol by lazy {
        SimpleFillSymbol(SimpleFillSymbolStyle.Solid, color = com.arcgismaps.Color.fromRgba(100, 0, 255, 100), blueOutlineSymbol)
    }

    private val graphicsOverlay by lazy {
        GraphicsOverlay()
    }
    private val graphicsStack = mutableListOf<List<Graphic>>()
    private val linePoints = mutableListOf<Point>()
    private val polygonPoints = mutableListOf<Point>()
    private val isMeasuring = mutableStateOf(false)
    private val showActionBar = mutableStateOf(false)
    var distance:Double = 0.0
    var area:Double = 0.0

    var originalArea: Double = 0.0
    var originalDistanceUnit: String = "Meter"
    var originalAreaUnit: String = "Acre"
    var distanceText:MutableState<String> = mutableStateOf("0.0")
    var areaText:MutableState<String> = mutableStateOf("0.0")


//    var distanceTextState: MutableLiveData<String> = MutableLiveData() // commented by Ramya

    @SuppressLint("SuspiciousIndentation")
    @Composable
    fun MainScreenComposable() {
        val context = LocalContext.current
        val coroutineScope = rememberCoroutineScope()
        ArcGISEnvironment.applicationContext = context.applicationContext
        val mapType: MutableState<BasemapStyle> = remember { mutableStateOf(BasemapStyle.ArcGISTopographic) }
        lifeCycleOwner = LocalLifecycleOwner.current
        // Observe changes to the switchState LiveData
//        distanceTextState.observe(
//            lifeCycleOwner
//        ) { value ->
//            distanceTextState.value = value
//        }
        val locationDisplay = rememberLocationDisplay().apply {
            setAutoPanMode(LocationDisplayAutoPanMode.Recenter)
        }

        val map = remember(mapType.value) {
            ArcGISMap(mapType.value).apply {
                initialViewpoint = Viewpoint(
                    latitude = 13.0236, longitude = 80.1780, scale = 72000.0
                )
            }
        }

        var cumulativeDistance by remember { mutableStateOf(0.0) }
//        var distanceText by remember { mutableStateOf(" ") }
//        var distance:Double =0.0
//        var distance by remember { mutableStateOf(0.0) }
//        var area by remember { mutableStateOf(0.0) }
//        var distanceText by remember { mutableStateOf(" 0.0 Metre") }
//        var areaText by remember { mutableStateOf(" 0.0 Acre") } // Added state for area text
        var requestPermissions by remember { mutableStateOf(false) }
        var selectedGeometryType by remember { mutableStateOf("Distance") }
        var selectedUnit by remember { mutableStateOf("Meter") }
        var pointsDrawn by remember { mutableStateOf(false) }
        var isCalloutVisible by remember { mutableStateOf(true) }
        val distanceUnits = mutableListOf("Meter", "Kilometre", "Foot", "Yard")
        val areaUnits = listOf("Acre", "Hectare", "Square Meter", "Square Kilometer", "Square Foot")

        if (selectedGeometryType == "Area" && selectedUnit !in areaUnits) {
            selectedUnit = "Acre"
        }

        if (requestPermissions) {
            RequestPermissions(
                onPermissionGranted = {
                    coroutineScope.launch {
                        locationDisplay.setAutoPanMode(LocationDisplayAutoPanMode.Navigation)
                        locationDisplay.dataSource.start()
                    }
                }
            )
        }

        Box(modifier = Modifier.fillMaxSize()) {
            val mapViewProxy = MapViewProxy()

            var calloutLocation by remember { mutableStateOf<Point?>(null) }

            MapView(
                modifier = Modifier.fillMaxSize(),
                mapViewProxy = mapViewProxy,
                arcGISMap = map,
                graphicsOverlays = listOf(graphicsOverlay),
                locationDisplay = locationDisplay,
                onSingleTapConfirmed = { screenCoordinate ->
                    if (isMeasuring.value) {
                        val mapPoint: Point? = mapViewProxy.screenToLocationOrNull(screenCoordinate.screenCoordinate)

                        if (mapPoint != null) {
                            pointsDrawn = true
                            val mapPointNotNull: Point = mapPoint
                            val mapPointProjected: Point? = GeometryEngine.projectOrNull(
                                mapPointNotNull,
                                SpatialReference.wgs84()
                            )
                            val latitude = mapPointProjected?.y
                            val longitude = mapPointProjected?.x

                            calloutLocation = mapPointProjected

                            Toast.makeText(
                                context,
                                "Map tapped at: Latitude: $latitude, Longitude: $longitude",
                                Toast.LENGTH_SHORT
                            ).show()

                            val relatedGraphics = mutableListOf<Graphic>()

                            when (selectedGeometryType) {
                                "Area" -> {
                                    val pointGraphic = Graphic(mapPoint, pointSymbol)
                                    graphicsOverlay.graphics.add(pointGraphic)
                                    relatedGraphics.add(pointGraphic)

                                    polygonPoints.add(mapPointNotNull)
                                    if (polygonPoints.size > 1) {
                                        val polyline = Polyline(polygonPoints)
                                        val lineGraphic = Graphic(polyline, lineSymbol)
                                        graphicsOverlay.graphics.add(lineGraphic)
                                        relatedGraphics.add(lineGraphic)

                                        // Remove previous text symbols
                                        graphicsOverlay.graphics.removeAll { it.symbol is TextSymbol }

                                        if (polygonPoints.size > 2) {
                                            val polygon = Polygon(polygonPoints)
                                            val polygonGraphic = Graphic(polygon, polygonSymbol)
                                            graphicsOverlay.graphics.add(polygonGraphic)
                                            relatedGraphics.add(polygonGraphic)

                                            val areaValue = GeometryEngine.areaGeodetic(
                                                polygon,
                                                getAreaUnit(selectedUnit),
                                                GeodeticCurveType.Geodesic
                                            )
                                            area = areaValue
                                            areaText.value = formatMeasurementValue(areaValue, selectedUnit) // Update area text

                                        } else {
                                            val distanceValue = GeometryEngine.lengthGeodetic(
                                                polyline,
                                                getLinearUnit(selectedUnit),
                                                GeodeticCurveType.Geodesic
                                            )
                                            distance = distanceValue
                                            distanceText.value = formatMeasurementValue(distanceValue, selectedUnit) // Update area text
//                                            distanceTextState.postValue(distanceValue.toString())
                                        }
                                    }
                                }

                                "Distance" -> {
                                    val pointGraphic = Graphic(mapPointNotNull, pointSymbol)
                                    graphicsOverlay.graphics.add(pointGraphic)
                                    relatedGraphics.add(pointGraphic)

                                    linePoints.add(mapPointNotNull)

                                    if (linePoints.size > 1) {
                                        val polyline = Polyline(linePoints)
                                        val lineGraphic = Graphic(polyline, lineSymbol)
                                        graphicsOverlay.graphics.add(lineGraphic)
                                        relatedGraphics.add(lineGraphic)

                                        val distanceValue = GeometryEngine.lengthGeodetic(
                                            polyline,
                                            getLinearUnit(selectedUnit),
                                            GeodeticCurveType.Geodesic
                                        )
                                        cumulativeDistance += distanceValue
                                    }

                                    // Remove previous text symbols
                                    graphicsOverlay.graphics.removeAll { it.symbol is TextSymbol }

                                    // Only add the text symbol at the last point
                                    if (linePoints.size > 1) {
                                        linePoints.last()
                                        distance = cumulativeDistance
                                        distanceText.value = formatMeasurementValue(cumulativeDistance, selectedUnit)
//                                        distanceTextState.value = distanceText.value
                                        TextSymbol().apply {
                                            text = distanceText.value
                                            color = com.arcgismaps.Color.fromRgba(0, 0, 0, 255) // Black color
                                            size = 15f
                                        }
                                    }
                                }
                            }
                            graphicsStack.add(relatedGraphics)
                        }
                    }
                }
            )

            {
                calloutLocation?.let { location ->

                    Callout(location = location, offset = Offset(0f, -50f)) {
                        Text(
                            text = if (selectedGeometryType == "Area") {

                                "${areaText.value} ${originalAreaUnit}"

                            } else {
                                "${distanceText.value} ${originalDistanceUnit}"
//                                distanceText.value
                            }
                        )
                    }
                }
            }


            ImageButtonWithSpinner(mapType, context)

            IconButton(
                onClick = {
                    if (checkPermissions(context)) {
                        coroutineScope.launch {
                            locationDisplay.setAutoPanMode(LocationDisplayAutoPanMode.Navigation)
                            locationDisplay.dataSource.start()
                        }
                    } else {
                        requestPermissions = true
                    }
                },
                modifier = Modifier
                    .align(Alignment.CenterEnd)
                    .padding(end = 16.dp, top = 200.dp)
            ) {
                Image(
                    painter = painterResource(R.mipmap.ic_location),
                    contentDescription = "My Location"
                )
            }

            IconButton(
                onClick = {
                    showActionBar.value = true
                    isMeasuring.value = true
                },
                modifier = Modifier
                    .align(Alignment.CenterEnd)
                    .padding(end = 16.dp, top = 40.dp)
            ) {
                Image(
                    painter = painterResource(R.mipmap.ic_measure),
                    contentDescription = "Measure"
                )
            }

            if (showActionBar.value) {
                CustomTopBar(
                    selectedGeometryType = selectedGeometryType,
                    onGeometryTypeChange = { selectedGeometryType = it },
                    selectedUnit = selectedUnit,
//                    onUnitChange = { selectedUnit = it },
                    onUnitChange = { unit ->
                        selectedUnit = unit
//                        if (selectedGeometryType == "Distance") {
//                            updateDistanceUnits(unit)
//                        } else if (selectedGeometryType == "Area") {
//                            updateAreaUnits(originalArea, unit)
//                        }
                    },
                    distanceUnits = distanceUnits,
                    areaUnits = areaUnits,
                    onShowActionBarChange = { showActionBar.value = it },
                    onClearGraphics = {
                        clearGraphics()
                        linePoints.clear()
                        polygonPoints.clear()
                        calloutLocation = null // Reset callout location
                        distanceText.value = " " // Reset distance text
//                        distanceTextState.value = " "
                        areaText.value = " " // Reset area text
                        cumulativeDistance = 0.0 // Reset cumulative distance
                    },
                    pointsDrawn = pointsDrawn

                )
            }


            // Call setupMapClickListener here
            setupMapClickListener()
        }

    }



    private fun getAreaUnit(unit: String): AreaUnit? {
        return when (unit) {
            "Square Meter" -> AreaUnit.squareMeters
            "Square Kilometer" -> AreaUnit.squareKilometers
            "Acre" -> AreaUnit(AreaUnitId.Acres)
            "Hectare" -> AreaUnit(AreaUnitId.Hectares)
            "Square Foot" -> AreaUnit.squareFeet
            else -> null
        }
    }

    private fun getLinearUnit(unit: String): LinearUnit? {
        return when (unit) {
            "Meter" -> LinearUnit.meters
            "Kilometre" -> LinearUnit.kilometers
            "Foot" -> LinearUnit.feet
            "Yard" -> LinearUnit(LinearUnitId.Yards)
            else -> null
        }
    }

    private fun formatMeasurementValue(value: Double, unit: String): String {
        var measureVal:String =  String.format("%.2f", value)
        var mutablemeasureVal = mutableStateOf(measureVal)
        return mutablemeasureVal.value
//        return "$value $unit"
    }

    private fun clearGraphics() {
        graphicsOverlay.graphics.clear()
        graphicsStack.clear()
//        linePoints.clear()
//        polygonPoints.clear()
    }
    private fun undoLastGraphic() {


        if (graphicsStack.isNotEmpty()) {
            val lastGraphics = graphicsStack.removeAt(graphicsStack.size - 1)
            lastGraphics.forEach { graphic ->
                graphicsOverlay.graphics.remove(graphic)
            }


        }
    }


    @Composable
    fun CustomTopBar(
        selectedGeometryType: String,
        onGeometryTypeChange: (String) -> Unit,
        selectedUnit: String,
        onUnitChange: (String) -> Unit,
        distanceUnits: List<String>,
        areaUnits: List<String>,
        onShowActionBarChange: (Boolean) -> Unit,
        onClearGraphics: () -> Unit,
        pointsDrawn: Boolean


    ) {
        var expanded by remember { mutableStateOf(false) }
        val units = if (selectedGeometryType == "Distance") distanceUnits else areaUnits

        Box(
            modifier = Modifier
                .fillMaxWidth()
                .padding(8.dp)
                .background(color = Color.DarkGray)
        ) {
            Row(
                modifier = Modifier.align(Alignment.CenterStart),
                verticalAlignment = Alignment.CenterVertically
            ) {

                IconButton(onClick = { onShowActionBarChange(false)
                    onClearGraphics()
                    isMeasuring.value = false
                }) {
                    Image(
                        painter = painterResource(R.mipmap.ic_backbutton),
                        contentDescription = "Back"
                    )
                }
            }
            Row(
                modifier = Modifier.align(Alignment.CenterEnd),
                verticalAlignment = Alignment.CenterVertically
            ) {

                if (pointsDrawn) {
                    IconButton(onClick = { undoLastGraphic() }) {
                        Image(
                            painter = painterResource(R.mipmap.ic_undo),
                            contentDescription = "Undo"
                        )
                    }
                    IconButton(onClick = {
                        onClearGraphics()
                        linePoints.clear()
                        polygonPoints.clear()



                    }) {
                        Image(
                            painter = painterResource(R.mipmap.ic_delete),
                            contentDescription = "Delete"
                        )
                    }
                }
                IconButton(onClick = { expanded = true }) {
                    Image(
                        painter = painterResource(R.mipmap.ic_selection),
                        contentDescription = "Settings"
                    )
                }
                DropdownMenu(
                    expanded = expanded,
                    onDismissRequest = { expanded = false },
                    modifier = Modifier.width(150.dp),
                ) {
                    Column(modifier = Modifier.padding(1.dp)) {
                        Text(text = "Select Geometry Type", color = Color.Blue)
                        Row(verticalAlignment = Alignment.CenterVertically) {
                            Checkbox(
                                checked = selectedGeometryType == "Distance",
                                onCheckedChange = {
                                    if (it) onGeometryTypeChange("Distance")
                                }
                            )
                            Text(text = "Distance")
                        }
                        Row(verticalAlignment = Alignment.CenterVertically) {
                            Checkbox(
                                checked = selectedGeometryType == "Area",
                                onCheckedChange = {
                                    if (it) onGeometryTypeChange("Area")
                                }
                            )
                            Text(text = "Area")
                        }

                        Text(text = "Select Unit", color = Color.Blue)
                        units.forEach { unit ->
                            Row(verticalAlignment = Alignment.CenterVertically) {
                                Checkbox(
                                    checked = selectedUnit == unit,
                                    onCheckedChange = {
                                        if (it) {
                                            onUnitChange(unit)
                                            if (selectedGeometryType == "Distance") {
                                                updateDistanceUnits(unit)
                                            } else if (selectedGeometryType == "Area") {
                                                updateAreaUnits(unit)
                                            }
                                        }
                                    }
                                )
                                Text(text = unit, modifier = Modifier.padding(4.dp))
                            }
                        }
                    }
                }
            }
        }
    }

    private fun updateDistanceUnits(unit: String) {

        distance = when (unit) {

            "Meter" -> {
                if (originalDistanceUnit.equals("Kilometre")){
                    convertFromKiloMeterToMeter(distance)
                }
                else if (originalDistanceUnit.equals("Foot")){
                    convertFromFootToMeter(distance)
                }
                else {
                    convertFromYardToMeter(distance)
                }

            }
            "Kilometre" -> {
                if (originalDistanceUnit.equals("Meter")){
                    convertFromMeterToKiloMeter(distance)
                }
                else if (originalDistanceUnit.equals("Foot")){
                    convertFromFootToKiloMeter(distance)
                }
                else {
                    convertFromYardToKiloMeter(distance)
                }

            }
            "Foot" -> {
                if (originalDistanceUnit.equals("Meter")){
                    convertFromMeterToFeet(distance)
                }
                else if (originalDistanceUnit.equals("Kilometre")){
                    convertFromKilometerMeterToFeet(distance)
                }
                else {
                    convertFromYardToFeet(distance)
                }

            }
            "Yard" -> {
                if (originalDistanceUnit.equals("Meter")){
                    convertFromMeterToYards(distance)
                }
                else if (originalDistanceUnit.equals("Kilometre")){
                    convertFromKilometerMeterToYards(distance)
                }
                else {
                    convertFromFootToYard(distance)
                }

            }
            else -> distance
        }
        originalDistanceUnit = unit
//        distanceTextState.value = "%.2f" .format(distance)
        distanceText.value = "%.2f" .format(distance)


    }

    private fun convertFromMeterToKiloMeter(distance: Double):Double{
        return distance / 1000
    }

    private fun convertFromMeterToFeet(distance: Double): Double {
        return distance * 3.28084
    }

    private fun convertFromMeterToYards(distance: Double): Double {
        return distance * 1.09361
    }

    private fun convertFromKiloMeterToMeter(distance: Double):Double{
        return distance * 1000
    }

    private fun convertFromKilometerMeterToYards(distance: Double): Double {
        return convertFromKiloMeterToMeter(distance) * 1.09361
    }

    private fun convertFromKilometerMeterToFeet(distance: Double): Double {
        return convertFromKiloMeterToMeter(distance) * 3.28084
    }

    private fun convertFromFootToMeter(distance: Double): Double {
        return distance / 3.28084
    }

    private fun convertFromFootToKiloMeter(distance: Double): Double {
        return convertFromFootToMeter(distance) / 1000
    }

    private fun convertFromFootToYard(distance: Double): Double {
        return convertFromFootToMeter(distance) * 1.09361
    }

    private fun convertFromYardToMeter(distance: Double): Double {
        return distance / 1.09361
    }

    private fun convertFromYardToKiloMeter(distance: Double): Double {
        return convertFromYardToMeter(distance) / 1000
    }

    private fun convertFromYardToFeet(distance: Double): Double {
        return convertFromYardToMeter(distance) * 3.28084
    }


    private fun updateAreaUnits(unit: String) {

        area = when (unit) {

            "Acre" -> {
                if (originalAreaUnit.equals("Hectare")){
                    convertHectareToAcre(area)
                }
                else if (originalAreaUnit.equals("Square Meter")){
                    convertSquareMeterToAcre(area)
                }
                else if (originalAreaUnit.equals("Square Kilometer")){
                    convertSquareKilometerToAcre(area)
                }
                else{
                    convertSquareFootToAcre(area)
                }
            }

            "Hectare" -> {
                if (originalAreaUnit.equals("Acre")){
                    convertAcreToHectare(area)
                }
                else if (originalAreaUnit.equals("Square Meter")){
                    convertSquareMeterToHectare(area)
                }
                else if (originalAreaUnit.equals("Square Kilometer")){
                    convertSquareKilometerToHectare(area)
                }
                else{
                    convertSquareFootToHectare(area)
                }
            }

            "Square Meter" -> {
                if (originalAreaUnit.equals("Acre")){
                    convertAcreToSquareMeter(area)
                }
                else if (originalAreaUnit.equals("Square Meter")){
                    convertHectareToSquareMeter(area)
                }
                else if (originalAreaUnit.equals("Square Kilometer")){
                    convertSquareKilometerToSquareMeter(area)
                }
                else{
                    convertSquareFootToSquareMeter(area)
                }
            }

            "Square Kilometer" -> {
                if (originalAreaUnit.equals("Acre")){
                    convertAcreToSquareKilometer(area)
                }
                else if (originalAreaUnit.equals("Square Meter")){
                    convertHectareToSquareKilometer(area)
                }
                else if (originalAreaUnit.equals("Square Kilometer")){
                    convertSquareMeterToSquareKilometer(area)
                }
                else{
                    convertSquareFootToSquareKilometer(area)
                }
            }
            "Square Foot" -> {
                if (originalAreaUnit.equals("Acre")){
                    convertAcreToSquareFoot(area)
                }
                else if (originalAreaUnit.equals("Square Meter")){
                    convertHectareToSquareFoot(area)
                }
                else if (originalAreaUnit.equals("Square Kilometer")){
                    convertSquareMeterToSquareFoot(area)
                }
                else{
                    convertSquareKilometerToSquareFoot(area)
                }
            }

            else -> {
                area
            }
        }



        originalAreaUnit = unit
//        updateAreaText("$area $unit")
        areaText.value = "%.2f" .format(area)
    }

    private fun convertAcreToHectare(area: Double):Double{
        return area * 0.404686
    }

    private fun convertAcreToSquareMeter(area: Double):Double{
        return area * 4046.86
//        return convertAcreToSquareMeter(area) * 0.0001
    }

    private fun convertAcreToSquareKilometer(area: Double):Double{
//        return area * 0.004046
        return convertAcreToSquareMeter(area) / 1_000_000
    }

    private fun convertAcreToSquareFoot(area: Double):Double{
        return area * 43560.038507
//        return convertAcreToSquareMeter(area) * 10.7639
    }

    private fun convertHectareToAcre(area: Double):Double{
        return area * 2.471055
//        return convertHectareToSquareMeter(area) * 0.000247105
    }

    private fun convertHectareToSquareMeter(area: Double):Double{
        return area * 10000.008840
//        return area * 10_000

    }

    private fun convertHectareToSquareKilometer(area: Double):Double{
//        return area * 0.01
        return convertHectareToSquareMeter(area) / 1_000_000
    }

    private fun convertHectareToSquareFoot(area: Double):Double{
//        return area * 107639.199320
        return convertHectareToSquareMeter(area) * 10.7639
    }

    private fun convertSquareMeterToAcre(area: Double): Double {
        return area * 0.000247105
    }

    private fun convertSquareMeterToHectare(area: Double): Double {
        return area * 0.0001
    }

    private fun convertSquareMeterToSquareKilometer(area: Double): Double {
        return area * 1e-6
    }

    private fun convertSquareMeterToSquareFoot(area: Double): Double {
        return area * 10.7639
    }

    private fun convertSquareKilometerToAcre(area: Double): Double {
//        return area * 247.105
        return convertSquareKilometerToSquareMeter(area) * 0.000247105
    }

    private fun convertSquareKilometerToHectare(area: Double): Double {
//        return area * 100.00008840000052146
        return convertSquareKilometerToSquareMeter(area) * 0.0001

    }

    private fun convertSquareKilometerToSquareMeter(area: Double): Double {
        return area * 1000000.8840000052005
    }

    private fun convertSquareKilometerToSquareFoot(area: Double): Double {
//        return area * 10763919.932006586343
        return convertSquareKilometerToSquareMeter(area) * 10.7639
    }

    private fun convertSquareFootToAcre(area: Double): Double {
//        return area * 2.2957e-5
        return convertSquareFootToSquareMeter(area) * 0.000247105
    }

    private fun convertSquareFootToHectare(area: Double): Double {
//        return area * 9.2903e-6
        return convertSquareFootToSquareMeter(area) * 0.0001

    }

    private fun convertSquareFootToSquareMeter(area: Double): Double {
        return area * 0.092903
    }

    private fun convertSquareFootToSquareKilometer(area: Double): Double {
//        return area * 9.2903e-8
        return convertSquareFootToSquareMeter(area) / 1_000_000
    }

Editor is loading...
Leave a Comment