# Test if a point is inside a Shape

**URL:** <https://openrndr.discourse.group/t/test-if-a-point-is-inside-a-shape/339>\
**Category:** Tutorials\
**Created:** [February 13, 2022, 11:35am UTC](https://openrndr.discourse.group/t/test-if-a-point-is-inside-a-shape/339 "2022-02-13T11:35:15Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [February 13, 2022, 11:35am UTC](https://openrndr.discourse.group/t/test-if-a-point-is-inside-a-shape/339/1 "2022-02-13T11:35:15Z")

</div>

This post is about testing if 2D points are located inside a 2D shape or not. It is actually very simple to test :

```auto
if(myShape.contains(myPoint) { ... }
// or
if(myPoint in myShape) { ... }

```

But what if the shape has a hole? Like in the letter “O”? In that case we need to make sure that the hole has the right winding when creating the shape.

### Hole with correct winding

 ![TestShapeContainsVector2-2022-02-13-11.35.49](https://global.discourse-cdn.com/free1/uploads/openrndr/original/1X/c525e6d8ca7dbb2585104d6719a047e26fd84dc9.png)

> **imports**
>
> ```kotlin
> import aBeLibs.geometry.circleish
> import org.openrndr.application
> import org.openrndr.color.ColorRGBa
> import org.openrndr.draw.isolated
> import org.openrndr.extensions.Screenshots
> import org.openrndr.math.Vector2
> import org.openrndr.shape.LineSegment
> import org.openrndr.shape.Shape
> import org.openrndr.shape.contains
> 
> /**
> * Shows that Shape.contains(Vector2) does take into account holes
> * if they have the correct winding (use .reversed!)
> */
> 
> ```

```kotlin
fun main() = application {
    program {
        val shp = Shape(
            listOf(
                circleish(drawer.bounds.center, 200.0).contour,
                circleish(drawer.bounds.center, 100.0).contour.reversed
            )
        )
        val allPoints = LineSegment(Vector2.ZERO, drawer.bounds.dimensions)
            .sub(0.1, 0.9).contour.equidistantPositions(20)
        val insidePoints = allPoints.filter { it in shp }

        extend {
            drawer.isolated {
                clear(ColorRGBa.WHITE)
                stroke = null
                fill = ColorRGBa.GRAY
                shape(shp)
                fill = ColorRGBa.GREEN
                circles(insidePoints, 10.0)
                fill = ColorRGBa.PINK
                circles(allPoints, 6.0)
            }
        }
    }
}

```

### Hole with incorrect winding

 ![TestShapeContainsVector2-2022-02-13-11.36.14](https://global.discourse-cdn.com/free1/uploads/openrndr/original/1X/cba63b4656c65cfebc862d7cef3e9ae0b034ee5d.png)

The only difference between both images is that in the second one I forgot to use `.reversed` when constructing the second contour (the hole).

Note: In this program I used a function I called `circleish()` but you can replace it by `Circle()` to have regular circles instead.

I’ll explain two lines of this program. The first one is

```auto
val allPoints = LineSegment(Vector2.ZERO, drawer.bounds.dimensions)
     .sub(0.1, 0.9).contour.equidistantPositions(20)

```

It creates a straight line segment that goes from top-left to bottom right of the canvas. Another way to write the same would be `LineSegment(0.0, 0.0, width.toDouble(), height.toDouble())` but I prefer to use `Vector2`s because there’s so many things you can do with them in OPENRNDR (pass them to methods, query information about them, do arithmetic operations, etc).

From that `Segment` I obtain a shorter sub-segment that goes from 10% to 90% of the original length because I want to leave some margin and avoid the line starting and ending on the edges of the window.

Next I convert it to a `ShapeContour` because `ShapeContour` provides a bunch of interesting methods, for example `equidistantPositions()` which returns a list of Vector2.

Now I can use this list of positions in the `.circles()` method to draw many circles.

The second line I wanted to describe is

```auto
val insidePoints = allPoints.filter { it in shp }

```

which creates a subset of `allPoints`, specifically, the ones that are inside `shp`. Very short, right? 🙂

### Why write code inside `program {}` but before `extends {}` ?

Code outside the `extends {}` block runs just once instead of once per animation frame.

Inside `program` I already have access to `drawer.bounds`, `width`, `height`, `drawer`, etc. which I may need to lay out things relative to the canvas. I could as well do all calculations inside `extend { ... }`, but then the program would be recalculating everything on every animation frame.

With simple programs like this it does not make much of a difference but I often create designs that take up to a minute to generate and I wouldn’t want to recreate such designs again and again keeping my CPU usage at 100%. I think it’s probably a good idea to set up the data that won’t change per frame using this approach.

---

<div class="post-metadata">

**Author:** ![Neurotypique](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/neurotypique/32/585_2.png) [@Neurotypique](https://openrndr.discourse.group/u/Neurotypique)\
**Post date:** [June 17, 2023, 3:03pm UTC](https://openrndr.discourse.group/t/test-if-a-point-is-inside-a-shape/339/2 "2023-06-17T15:03:11Z")

</div>

This is amazing thanks a lot! I’m trying to do this with text but cannot figure out how to transform text into shape for it to work. Do I need to draw text into an invisible texture and sample the texture? I’m trying to replicate what I see in Open RNDR showreel with shapes inside letter shapes

---

<div class="post-metadata">

**Author:** ![abe](https://yyz2.discourse-cdn.com/free1/user_avatar/openrndr.discourse.group/abe/32/700_2.png) [@abe](https://openrndr.discourse.group/u/abe)\
**Post date:** [June 18, 2023, 5:11pm UTC](https://openrndr.discourse.group/t/test-if-a-point-is-inside-a-shape/339/3 "2023-06-18T17:11:00Z")

</div>

You are very welcome 🙂

I just posted this (after asking @edwin if it was possible):

> [@Converting font characters to contours](https://openrndr.discourse.group/t/converting-font-characters-to-contours/576):
>
> [FontShape-2023-06-18-19.02.21] It is possible to convert font characters to shapes and contours. I believe it’s not yet documented, but here a quick example: 
> 
> > **imports**
> >
> > import org.openrndr.application import org.openrndr.color.ColorRGBa import org.openrndr.draw.font.loadFace import org.openrndr.extensions.Screenshots import org.openrndr.shape.LineSegment
> 
> fun main() = application { program { val face = loadFace("data/fonts/default.otf") val shape = face.glyphForCharacter('a').s…

I think drawing to a RenderTarget and sampling that is definitely an option. It can be faster too, but depends on the use case. To animate zooming letters or to draw with pen plotters having access to the contour is very nice 🙂
