Hi again guys, this is partly a Compose question w...
# compose
n
Hi again guys, this is partly a Compose question which is why I am posting here, hoping for the best. Please see details in đŸ§”
Currently I am achieving the embryo of a word cloud (screenshot below) , but the problem is that words overlap each other because they are positioned randomly. To avoid overlapping, I am trying to add padding to each word: This is the code that I use to put some padding around the words, but there is no effect:
Copy code
Canvas(modifier = Modifier
            .size(350.dp)
            .background(Color.Blue)
            .padding(30.dp)
            .clipToBounds(),

            onDraw = {
                val canvasWidth = size.width
                val canvasHeight = size.height
                val paint = Paint()
                wordsAndColors.forEach { (word, color) ->
                    val padding = PaddingValues(10.dp)
                    val wordWidth = paint.measureText(word) + padding
                        .calculateLeftPadding(LayoutDirection.Ltr).roundToPx() + padding
                        .calculateRightPadding(LayoutDirection.Ltr).roundToPx()
                    val wordHeight = paint.ascent() + paint.descent()+ padding
                        .calculateTopPadding().roundToPx() + padding.calculateBottomPadding().roundToPx()
                    println(wordHeight)
                    val xCoordinate = Random.nextInt(canvasWidth.toInt() - wordWidth.toInt())
                    val yCoordinate = Random.nextInt(canvasHeight.toInt() - wordHeight.toInt())


                    paint.textSize = 64f
                    paint.isFakeBoldText = true
                    paint.color = color.toArgb()
                    paint.isAntiAlias = true
                    paint.textAlign = Paint.Align.CENTER

                    drawContext.canvas.nativeCanvas.drawText(
                        word.decapitalize(Locale.ROOT),
                        xCoordinate.toFloat(), yCoordinate.toFloat(),
                        paint
                    )
Any ideas how to do this properly?
t
I wonder if the padding is doing anything. It’s seems to mostly ensure that the words randomly render at “text + padding” distance away from the right edge.
👍 1
Conceptually, you might have to use some type of Rect to detect overlaps and move things over. Might need to save some state of all the coordinates you’ve calculated so far, and check against those before figuring out the next coordinate.
🙏 1
d
Answer by Jonathan Feinberg https://stackoverflow.com/a/1478314:
Each word "wants" to be somewhere, such as "at some random x position in the vertical center". In decreasing order of frequency, do this for each word:
place the word where it wants to be
while it intersects any of the previously placed words
    move it one step along an ever-increasing spiral
That's it. The hard part is in doing the intersection-testing efficiently, for which I use last-hit caching, hierarchical bounding boxes, and a quadtree spatial index (all of which are things you can learn more about with some diligent googling).
http://static.mrfeinberg.com/bv_ch03.pdf
🙏 1
n
Thanks guys, this is all extremely helpful! 😊
t
Found this android view implementation, might be insightful https://github.com/sirmordred/WordCloud
👌 1