Geotools interpolation - kotlin

I have some spatial data with a value. lat, lon and z value. And a polygon where this data is from. Now i'm trying to create a geotiff so i can serve this through geoserver. I want a smooth graph, so i need to do some interpolation dit missing values in my polygon. Values outside my polygon should nu cropped or marked as no data.
I'm trying to do this through geotools, but i'm having trouble with thé interpolation. My geotiff before and after are exactly the same. Ant idea that is wrong? This is my code:
class GeoToolsExperiment {
fun execute(pointWithDatas: List<PointWithData>, polygon: Polygon) {
val crs: CoordinateReferenceSystem = CRS.decode("EPSG:3857")
val bounds = ReferencedEnvelope(polygon.envelopeInternal, crs)
val factory: GridCoverageFactory = CoverageFactoryFinder.getGridCoverageFactory(null)
val width = (bounds.width * 100000).toInt()
val height = (bounds.height * 100000).toInt()
val writableRaster: WritableRaster = createRaster(width, height)
val gc: GridCoverage2D = createGridCoverage(factory, writableRaster, bounds)
fillRaster(pointWithDatas, gc, writableRaster)
val ci = interpolate(gc)
writeToTif(ci)
}
private fun writeToTif(ci: GridCoverage?) {
val outFile = "test.tif"
val out = File(outFile)
val format: AbstractGridFormat = GeoTiffFormat()
val writer = format.getWriter(out)
try {
writer.write(ci)
writer.dispose()
} catch (e: IllegalArgumentException) {
// TODO Auto-generated catch block
e.printStackTrace()
} catch (e: IOException) {
e.printStackTrace()
}
}
private fun interpolate(gc: GridCoverage2D): GridCoverage {
val interp = Interpolation.getInstance(Interpolation.INTERP_BILINEAR)
val interpolate = Operations.DEFAULT.interpolate(gc, interp)
return interpolate as GridCoverage2D
}
private fun createGridCoverage(
factory: GridCoverageFactory,
writableRaster: WritableRaster,
bounds: ReferencedEnvelope
): GridCoverage2D {
val gc: GridCoverage2D = factory.create("band1", writableRaster, bounds)
return gc
}
private fun createRaster(width: Int, height: Int): WritableRaster {
val writableRaster: WritableRaster = RasterFactory.createBandedRaster(
DataBuffer.TYPE_DOUBLE, width,
height, 1, null
)
return writableRaster
}
private fun fillRaster(
pointWithDatas: List<PointWithData>,
gc: GridCoverage2D,
writableRaster: WritableRaster
) {
pointWithDatas.forEach { pwd ->
val directPosition = DirectPosition2D(pwd.point.x, pwd.point.y)
val transformPointToGridCoverage = gc.gridGeometry.worldToGrid(directPosition)
val data = DoubleArray(1)
data[0] = pwd.data
writableRaster.setDataElements(transformPointToGridCoverage.x, transformPointToGridCoverage.y, data)
}
}
}
Polygon
Vector Data
Result from the code
Result i'm looking for (created manual with qgis)

Related

FileNotFoundException when using ExifInterface onActivityResult

what I want to do is to take a photo with the cellphone en then displays that image in a imageview, but when I did that the image appeared roated 90 degrees. So I searched for solutions to that issue and found that I had to do it this way.
private fun capturePhoto() {
val cameraIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE)
val filePhoto = File(Environment.getExternalStorageDirectory(), "Pic.jpg")
imageUri = FileProvider.getUriForFile(
this#ShowLocationFragment.requireActivity(),
"com.example.countriesapp.provider",
filePhoto
)
path = imageUri.path
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri)
startActivityForResult(cameraIntent, REQUEST_CODE)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE) {
if (path != null) {
val inputStream =
this#ShowLocationFragment.requireActivity().contentResolver.openInputStream(
imageUri
)
val ei = inputStream?.let { ExifInterface(it) }
val orientation = ei?.getAttributeInt(
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_UNDEFINED
)
val bitmap = getBitmapFromUri()
var rotatedBitmap: Bitmap? = null
rotatedBitmap = when (orientation) {
ExifInterface.ORIENTATION_ROTATE_90 -> rotateImage(bitmap, 90)
ExifInterface.ORIENTATION_ROTATE_180 -> rotateImage(bitmap, 180)
ExifInterface.ORIENTATION_ROTATE_270 -> rotateImage(bitmap, 270)
else -> bitmap
}
binding.ivPlaceMemory.setImageBitmap(rotatedBitmap)
}
}
}
These are rotateImage and getBitmapFromUri functions
private fun rotateImage(source: Bitmap?, angle: Int): Bitmap? {
if (source == null) return null
val matrix = Matrix()
matrix.postRotate(angle.toFloat())
return Bitmap.createBitmap(
source, 0, 0, source.width, source.height,
matrix, true
)
}
private fun getBitmapFromUri(): Bitmap? {
this#ShowLocationFragment.requireActivity().contentResolver.notifyChange(imageUri, null)
val cr: ContentResolver = this#ShowLocationFragment.requireActivity().contentResolver
val bitmap: Bitmap
return try {
bitmap = MediaStore.Images.Media.getBitmap(cr, imageUri)
bitmap
} catch (e: Exception) {
e.printStackTrace()
null
}
}
However, I'm having this exception
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1331636152, result=-1, data=null} to activity {com.example.countriesapp/com.example.countriesapp.presentation.MainActivity}: java.io.FileNotFoundException: open failed: ENOENT (No such file or directory)
Can anybody help to figure out what is going on?
Ive tried to search for solutions but havent found anything that works out.

My response data return " kotlinx.coroutines.flow.SafeFlow#1493a74"

I am trying to do dictionary app using kotlin language. I built the project with mvvm and clean architecture. I have been trying to pull vocabulary information from the internet using jsoap. I am using flow for data. I couldnt find where the issiue is. Normally, the words should appear on the screen or I should be able to see the data when I println on the console.But I can't see it on the screen or on the console, probably because the data coming from the internet is as follows.
kotlinx.coroutines.flow.SafeFlow#1493a74
I am sharing my codes below
ExtractedData
data class ExtractedData(
var id :Int = 0,
var word:String = "",
var meaning :String = ""
)
I created ExtractedData class to represent vocabulary or word data from internet
WordInfoRepositoryImpl
class WordInfoRepositoryImpl #Inject constructor(
private val api:DictionaryApi
) : WordInfoRepository {
//get words with meanings on the internet using jsoap
override fun getEventsList(): Flow<Resource<MutableList<ExtractedData>>> = flow {
emit(Resource.Loading())
val listData = mutableListOf<ExtractedData>()
try {
val url = "https://ielts.com.au/australia/prepare/article-100-new-english-words-and-phrases-updated-2020"
val doc = withContext(Dispatchers.IO){
Jsoup.connect(url).get()//-->Here it gives the following warning even though I have it in withContext `Inappropriate blocking method call`
}
val table = doc.select("table")
val rows = table.select("tr")
val eventsSize = rows.size
for (i in 1 until eventsSize) {
val row = rows[i]
val cols = row.select("td")
val word = cols[0].text()
val meaning = cols[1].text()
listData.add(ExtractedData(i,word,meaning))
}
}
catch (e: IOException) {
emit(Resource.Error("IO Exception"))
}
catch (e : HttpException) {
emit(Resource.Error("HTTP EXCEPTION"))
}
emit(Resource.Success(listData))
}
}
getEventsList is in my WordInfoRepositoryImpl class in my data layer here I am pulling data from internet using jsoap
WordInfoRepository
interface WordInfoRepository {
fun getEventsList(): Flow<Resource<MutableList<ExtractedData>>>
}
this is the interface that I reference wordInforepositoryImpl in the data layer in my interface domain layer
GetWordsAndMeaningsOnTheInternetUseCase
class GetWordsAndMeaningsOnTheInternetUseCase#Inject constructor(
private val repository: WordInfoRepository
){
operator fun invoke() : Flow<Resource<MutableList<ExtractedData>>> {
return repository.getEventsList()
}
}
GetWordsAndMeaningsOnTheInternetUseCase is my usecase in my domain layer
ViewModel
#HiltViewModel
class MostUsedWordScreenViewModel #Inject constructor(
private val getWordsAndMeaningsOnTheInternetUseCase: GetWordsAndMeaningsOnTheInternetUseCase
) : ViewModel() {
private var searchJob: Job? = null
private val _state = mutableStateOf(MostUsedWordState())
val state: State<MostUsedWordState> = _state
init {
fetchData()
}
private fun fetchData() {
searchJob?.cancel()
searchJob = viewModelScope.launch(IO) {
getWordsAndMeaningsOnTheInternetUseCase().onEach { result ->
when (result) {
is Resource.Success -> {
_state.value = state.value.copy(
mostWordUsedItems = result.data ?: mutableListOf(),
isLoading = false
)
}
is Resource.Error -> {
_state.value = state.value.copy(
mostWordUsedItems = result.data ?: mutableListOf(),
isLoading = false
)
}
is Resource.Loading -> {
_state.value = state.value.copy(
mostWordUsedItems = result.data ?: mutableListOf(),
isLoading = true
)
}
}
}
}
}
}
MostUsedWordScreen
#Composable
fun MostUsedWordScreen(viewModel: MostUsedWordScreenViewModel = hiltViewModel()) {
val state = viewModel.state.value
println("state --- >>> "+state.mostWordUsedItems)
LazyColumn(
modifier = Modifier.fillMaxSize()
) {
items(state.mostWordUsedItems.size) { i ->
val wordInfo = state.mostWordUsedItems[i]
if(i > 0) {
Spacer(modifier = Modifier.height(8.dp))
}
MostUsedWordItem(word = wordInfo)
if(i < state.mostWordUsedItems.size - 1) {
Divider()
}
}
}
}
#Composable
fun MostUsedWordItem(word : ExtractedData ) {
// println("this is MostUsedWordItem")
Column(modifier = Modifier
.padding(5.dp)
.fillMaxWidth()) {
Text(text = word.word,
modifier = Modifier.padding(3.dp),
textAlign = TextAlign.Center,
fontSize = 18.sp,
)
}
}
It is included in the MostUsedWordScreenViewModel and MostUsedWordScreen presententation layer
Where I println("state --- >>> "+state.mostWordUsedItems) in MostUsedWordScreen, the state console shows as empty like this System.out: state --- >>> []
I tried to explain as detailed as I can, I hope you can understand.
A Flow doesn't do anything until you call a terminal operator on it. You called onEach, which is not a terminal operator. You should use collect. Or you can avoid the nesting inside a launch block by using onEach and launchIn, which does the same thing as launching a coroutine and calling collect() on the flow. You don't need to specify Dispatchers.IO here because nothing in your Flow is blocking. You correctly wrapped the blocking call in withContext(Dispatchers.IO), and the warning is a false positive. That's a well-known bug in their compiler inspection.
searchJob = getWordsAndMeaningsOnTheInternetUseCase().onEach { result ->
when (result) {
is Resource.Success -> {
_state.value = state.value.copy(
mostWordUsedItems = result.data ?: mutableListOf(),
isLoading = false
)
}
is Resource.Error -> {
_state.value = state.value.copy(
mostWordUsedItems = result.data ?: mutableListOf(),
isLoading = false
)
}
is Resource.Loading -> {
_state.value = state.value.copy(
mostWordUsedItems = result.data ?: mutableListOf(),
isLoading = true
)
}
}
}.launchIn(viewModelScope)
By the way, you need to move your emit(Success...) inside your try block. The way it is now, when there is an error, the error will immediately get replaced by a Success with empty list.
Side note, I recommend avoiding passing MutableLists around between classes. You have no need for them and it's a code smell. Sharing mutable state between classes is error-prone. I don't think there is any justification for using a Flow<MutableList> instead of a Flow<List>.
You rarely even need a MutableList locally in a function. For example, you could have done in your try block:
val listData = List(eventsSize - 1) {
val row = rows[it + 1]
val cols = row.select("td")
val word = cols[0].text()
val meaning = cols[1].text()
ExtractedData(i,word,meaning)
}
emit(Resource.Success(listData))

Unable to get TFlite model working because of wrong inputs

I have a model called RepNet I want to run on TFlite for Kotlin, the interpreter provides the shape and DataType of the data, but I simply could not get the data to work with the interpreter, I have problems getting it to the correct shape.
The data shape is this :
But I simply can't get my list of Images to match the correct shape, I'll include my code down below if someone could help me make the right transformations to get it working and thank you.
class TestActivity2 : AppCompatActivity() {
#RequiresApi(Build.VERSION_CODES.P)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_test2)
//val file = File("/assets/repnet.tflite")
//Log.d("Path", file.path)
var file = loadModelFile(assets,"repnet2.5.tflite")
var interpreter = Interpreter(file!!)
var counts = getCount(interpreter)
interpreter.close()
Log.d("Counts", counts.toString())
}
#RequiresApi(Build.VERSION_CODES.P)
private fun getImages(): MutableList<TensorImage> {
val mmd = MediaMetadataRetriever()
val path = "/sdcard/bicycle.mp4"
mmd.setDataSource(path)
var duration = mmd.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_FRAME_COUNT)
var inputImages = mutableListOf<TensorImage>()
Log.d("Duration",duration.toString())
if (duration != null) {
for (i in 0 until 50) {
var bitmap: Bitmap?
Log.d("Frame", i.toString())
try {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
bitmap = mmd.getFrameAtIndex(i)
if (bitmap != null) {
bitmap = bitmap.copy(Bitmap.Config.ARGB_8888, true)
inputImages.add(TensorImage.fromBitmap(bitmap))
}
}
} catch (e: Exception) {
println("Could not convert image to BitMap")
e.printStackTrace()
}
}
}
return inputImages
}
fun preprocessImages(images: List<TensorImage>): List<TensorImage> {
val imageMean = 127.5F
val imageStd = 127.5F
val imageSize = 224
val imageProcessor = ImageProcessor.Builder()
.add(CastOp(DataType.FLOAT32))
.add(NormalizeOp(imageMean,imageStd))
.add(ResizeOp(imageSize,imageSize,ResizeOp.ResizeMethod.BILINEAR))
.build()
val preprocessedImages = mutableListOf<TensorImage>()
for (image in images) {
val processedImage = imageProcessor.process(image)
preprocessedImages.add(processedImage)
}
return preprocessedImages
}
#RequiresApi(Build.VERSION_CODES.P)
fun getCount(interpreter: Interpreter): Int {
var images = getImages()
images = preprocessImages(images as List<TensorImage>).toMutableList()
val batchImages = mutableListOf<TensorBuffer>()
for(img in images) {
batchImages.add(img.tensorBuffer)
}
var inputBuffer = TensorBuffer.createDynamic(DataType.FLOAT32)
var outputBuffer = TensorBuffer.createFixedSize(interpreter.getOutputTensor(0).shape(),interpreter.getOutputTensor(0).dataType())
interpreter.run(images[0].tensorBuffer,outputBuffer.buffer)
Log.d("Result", outputBuffer.floatArray[0].toString())
Log.d("Output", outputBuffer.toString())
return 0
}
#Throws(IOException::class)
private fun loadModelFile(assets: AssetManager, modelFilename: String): MappedByteBuffer? {
val fileDescriptor = assets.openFd(modelFilename)
val inputStream = FileInputStream(fileDescriptor.fileDescriptor)
val fileChannel: FileChannel = inputStream.getChannel()
val startOffset = fileDescriptor.startOffset
val declaredLength = fileDescriptor.declaredLength
return fileChannel.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength)
}
}

How to parse two data list from one PagingData Source in Android Kotlin?

This is My ViewModle Class
#HiltViewModel
class MainViewModel #Inject constructor(
private val movieRepository: MovieRepository,
private val favMovieRepository: FavMovieRepository
) : ViewModel() {
...
private var _movieState = mutableStateOf(false)
val movieState = _movieState
val nowPlayingMovies: Flow<PagingData<Movie>> = Pager(PagingConfig(pageSize = 10)) {
MoviePagingSource(movieRepository)
}.flow
val popularMovies: Flow<PagingData<Movie>> = Pager(PagingConfig(pageSize = 10)) {
MoviePagingSource(movieRepository)
}.flow
...
fun setListToPopular(){
_movieState.value = true
}
}
PagingSource file is here
class MoviePagingSource(
private val movieRepository: MovieRepository
) : PagingSource<Int , Movie>() {
override suspend fun load(params: LoadParams<Int>): LoadResult<Int, Movie> {
return try {
val nextPage = params.key ?: 1
val nowPlayingMovieResponse = movieRepository.getNowPlayingMovies(nextPage)
val popularMovieResponse = movieRepository.getPopularMovies(nextPage)
LoadResult.Page(
data = nowPlayingMovieResponse.results,
prevKey = if (nextPage == 1) null else nextPage - 1,
nextKey = nowPlayingMovieResponse.page.plus(1)
)
LoadResult.Page(
data = popularMovieResponse.results,
prevKey = if (nextPage == 1) null else nextPage - 1,
nextKey = popularMovieResponse.page.plus(1)
)
} catch (e: Exception) {
LoadResult.Error(e)
}
}
...
}
Here I define two LoadResult one for NowPlaying other for popluar movies.
I want to get the follwing result as expected Below.
Here whenever i choose one result should be in my favour for that i have my Home screen.
#Composable
fun MovieListView(viewModel: MainViewModel) {
val lazyMovieItems = viewModel.nowPlayingMovies.collectAsLazyPagingItems()
val lazyPopularMovieItems = viewModel.popularMovies.collectAsLazyPagingItems()
val movieItems = if (!viewModel.movieState.value) lazyMovieItems else lazyPopularMovieItems
LazyColumn {
item {
Row(... ) {
PopularityDropDown(){
viewModel.setListToPopular()
}
} }
items(movieItems) { item ->
MovieCard(movie = item!!) {
...
)
}else Log.d(TAG, "MovieListView: ${item.original_title} with id ${item.id} It is Not favorite ")
}
}
movieItems.apply {
...
}
}
What should be the way for fetching data from PagingSource ? and please suggest better way for handling NowPlaying and popular movie.

Incompatible types: Int and Article

I am developing news app I have implemented multipleview types in recyclerview adapter class but I am getting following error
Incompatible types: Int and Article
below BBCSportAdapter class where I have implemented multipleview types
#Suppress("UNREACHABLE_CODE")
class BBCSportAdapter(private val listViewType: List<Int>) : RecyclerView.Adapter<BBCSportAdapter.MyViewHolder>() {
companion object {
val ITEM_A = 1
var ITEM_B = 2
}
var articleList: List<Article> = listOf()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MyViewHolder {
val inflater =
LayoutInflater.from(parent.context)
return when (viewType) {
ITEM_A -> ViewHolderItemA(inflater.inflate(R.layout.bbc_sport_list, null))
else -> {
ViewHolderItemB(inflater.inflate(R.layout.bbc_sport_item, null))
}
}
}
#SuppressLint("NewApi")
override fun onBindViewHolder(holder: MyViewHolder, position: Int) {
val viewType = articleList[position]
when (viewType) {
ITEM_A -> {
val viewHolderA = holder as ViewHolderItemA
Picasso.get().load(articleList[position].urlToImage)
.into(viewHolderA.topFlameImageView)
}else -> {
val viewHolderB = holder as ViewHolderItemB
}
}
}
override fun getItemCount(): Int {
return articleList.size
}
// holder.articleTitle.text = articleList[position].title
// holder . articleSourceName . text = articleList [position].source.name
// Picasso . get ().load(articleList.get(position).urlToImage).into(holder.image)
//
// val input = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX")
// val output = SimpleDateFormat("dd/MM/yyyy")
// var d = Date()
// try {
// d = input.parse(articleList[5].publishedAt)
// } catch (e: ParseException) {
// try {
// val fallback = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
// fallback.timeZone = TimeZone.getTimeZone("UTC")
// d = fallback.parse(articleList[5].publishedAt)
// } catch (e2: ParseException) {
// // TODO handle error
// val formatted = output.format(d)
// val timelinePoint = LocalDateTime.parse(formatted)
// val now = LocalDateTime.now()
//
// var elapsedTime = Duration.between(timelinePoint, now)
//
// println(timelinePoint)
// println(now)
// elapsedTime.toMinutes()
//
// holder.articleTime.text = "${elapsedTime.toMinutes()}"
// }
// }
// }
fun setMovieListItems(articleList: List<Article>) {
this.articleList = articleList
notifyDataSetChanged()
}
open inner class MyViewHolder(itemView: View?) : RecyclerView.ViewHolder(itemView!!){}
inner class ViewHolderItemA(itemView: View) : MyViewHolder(itemView) {
val topFlameImageView: ImageView = itemView.findViewById(R.id.topFlameImageView)
}
inner class ViewHolderItemB(itemView: View?) : MyViewHolder(itemView) {
val image: ImageView = itemView!!.findViewById(R.id.imageView)
val articleTitle: TextView = itemView!!.findViewById(R.id.articleTitle)
val articleSourceName: TextView = itemView!!.findViewById(R.id.articleSourceName)
val imageCategory: ImageView = itemView!!.findViewById(R.id.imageCategory)
val articleTime: TextView = itemView!!.findViewById(R.id.articleTime)
}
}
I have followed this link https://github.com/CoderJava/Multiple-View-Type-RecyclerView-Kotlin-Android/blob/master/app/src/main/java/com/ysn/multipleviewtypeexample/AdapterRecyclerView.kt
In your onBindViewHolder articleList is list of artical but in your when statement you are comparing Article with an Int i.e. ITEM_A, which is wrong. Instead you should have some type in your article object and comparison is based on that type. Moreover you have not implemented getItemViewType() where you can make decision which view will be inflated. In your case viewType in parameter of oncreateViewHolder will always return 0 and else condition will be executed always and you will always have single type of view.