cetz icon indicating copy to clipboard operation
cetz copied to clipboard

[feature request] `translate()` in polar coordinates

Open tapyu opened this issue 1 year ago • 7 comments

Currently, draw.translate() function receives as input "a single vector or any combination of the named arguments x, y and z to translate by." (vide manual). However, this is quite restrictive once we cannot pass, for example, polar coordinates.

Consider the following MWE:

#import "@preview/cetz:0.2.2": canvas, plot, draw, coordinate, vector
#set page(width: auto, height: auto, margin: .5cm)

#let draw-me(radius, angle) = {
  draw.group({
    draw.translate(angle: angle, radius: radius)
      draw.line(
        (-0.2,+0.2),
        (rel: (+0.2,-0.2)),
        (rel: (+0.2,+0.2)),
      )
  })
}

#canvas({
  draw.circle((0,0), radius: 0.1)
  draw-me(2, 30deg)
})

This produces

image

translate() doesn't work when polar coordinates is passed.

By changing

draw.translate(angle: angle, radius: radius)

by

draw.translate((radius*calc.cos(angle), radius*calc.sin(angle)))

We can achieve the desired result

image

It would be interesting to overload translate() so that polar coordinates can also be handled by this function.

PS: I am not sure whether relative coordinates can be handled.

tapyu avatar May 21 '24 09:05 tapyu

You can use set-origin(<coordinate>), which allows passing any coordinate, including polar:

set-origin((angle, radius)) or set-origin((angle: angle, radius: radius))

johannes-wolf avatar May 21 '24 10:05 johannes-wolf

But I think adding said functionality to translate is a good idea.

johannes-wolf avatar May 21 '24 10:05 johannes-wolf

You can use set-origin(), which allows passing any coordinate, including polar

Yeah, that might be a workaround.

But I think adding said functionality to translate is a good idea.

Agreed.

tapyu avatar May 21 '24 11:05 tapyu

Didn't we previously allow passing coordinates to translate but changed it in favour of set-origin?

@tapyu what are the cases where being able to translate with polar coordinates are useful? Examples etc.

fenjalien avatar May 21 '24 15:05 fenjalien

@tapyu what are the cases where being able to translate with polar coordinates are useful? Examples etc.

Okay, I can give a very illustrative example:

#import "@preview/cetz:0.2.2": canvas, plot, draw, coordinate, decorations
#set page(width: auto, height: auto, margin: .5cm)

#let draw-satelite(height, angle, name) = {
  // draw.move-to("ground-station.tip")
  draw.group(
      name: name, {
        draw.set-origin("ground-station.tip")
        draw.translate(x: height*calc.cos(90deg-angle), y: height*calc.sin(90deg-angle))
        draw.rotate(-angle)
        draw.anchor("tip", (0,0))
          draw.line(
            (-0.2,+0.2),
            (rel: (+0.2,-0.2)),
            (rel: (+0.2,+0.2)),
          )
          draw.circle((rel: (-0.2, 0.07)), radius: (0.5,0.2), name: "antenna-base")
          draw.rect((rel: (0,0.1)), (rel: (1, 1)), name: "body", anchor: "east")
          draw.rect("body.east", (rel: (0.5, 0.5)), anchor: "north")
          draw.rect("body.west", (rel: (-0.5, 0.5)), anchor: "north")
      }
    )
}

#let draw-ground-station() = {
  draw.group(name: "ground-station", {
      draw.line(name:"base", "earth.80deg", (rel: (0,1), to:"earth.90deg"), "earth.100deg")
      
      draw.move-to("base.50%")
      draw.move-to((rel: (y: 1)))
      draw.move-to((rel: (angle: 320deg, radius: 1)))
      draw.arc((), start: 320deg, stop: 220deg, mode: "CLOSE", name: "antenna-arc")

      draw.anchor("tip", (rel: (0, 0.4), to: "antenna-arc.chord-center"))
      
      draw.line("tip", (rel:(0.2,0), to: "antenna-arc.chord-center"))
      draw.line("tip", (rel:(-0.2,0), to: "antenna-arc.chord-center"))
  })
}

#canvas({
  draw.arc((0,0), start: 45deg, stop: 135deg, radius: 5, name: "earth")

  // the layer
  draw.move-to("earth.chord-center")
  draw.move-to((rel: (angle: 70.1, radius: 8)))
  draw.merge-path(
    fill: gray, {
    draw.arc((), start: 70deg, stop: 110deg, radius: 12, name: "upper-layer")
    draw.line((), (rel: (0, -2)))
    draw.arc((), start: 110deg, stop: 70deg, radius: 12, name: "lower-layer")
    draw.line((), (rel: (0, 2)))
    }
  )  

  draw-ground-station()
  draw-satelite(5, 30deg, "satelite1")
  draw-satelite(5, -30deg, "satelite2")
  
  // scintillation-induced signal
  decorations.wave(draw.line("satelite1.tip", ("satelite1.tip", 20%, "ground-station.tip")),  amplitude: .25, start: 0%, stop: 100%, stroke: red, name: "wave1") 
  for (i, (perc, amp)) in (40%,60%,80%,100%).zip((.125,0.25,0.55,.18)).enumerate() {
    decorations.wave(draw.line("wave"+str(i + 1)+".end", ("satelite1.tip", perc, "ground-station.tip")), amplitude: amp, start: 0%, stop: 100%, stroke: red, name: "wave"+str(i + 2))
  }
  decorations.wave(draw.line("satelite2.tip", "ground-station.tip"), 
  // to scintillation
  amplitude: .25, start: 0%, stop: 100%, stroke: blue)
})

image

In this not-so-minimal working example, a satellite is a set of elements (line(), rect(), circle(), ...) that is grouped and is drawn with the function draw-satelite(height, angle, name), which translates the satellite antenna's tip in polar coordinates and with respect to the ground station antenna's tip.

Here, using polar coordinates to translate/shift it makes total sense as we always think about satellite positioning in terms of radial distance from the ground station and the zenith angle (or, equivalently, the elevation angle):

image

Of course we can came up with workarounds that work (you see that, in my case, I used trigonometry to obtain the same result). But again, translating in polar coordinates is the most intuitive way to go.

tapyu avatar May 22 '24 01:05 tapyu

Didn't we previously allow passing coordinates to translate but changed it in favour of set-origin?

Well, I don't know, but in my POV it is an error. Being able to set the origin in polar coordinates doesn't free us to want to translate an object in polar coordinates with respect to that origin.

This is clear in my previous example, where we set the origin to the ground station antenna's tip, but we want to translate the satellites in polar coordinates with respect to that new origin.

tapyu avatar May 22 '24 01:05 tapyu

So, can we finally agree that it is useful to translate in polar coordinates? :eyes:

tapyu avatar Jun 25 '24 01:06 tapyu