Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plot: Improve contour plots #270

Closed
9 of 13 tasks
Andrew15-5 opened this issue Oct 21, 2023 · 26 comments · Fixed by #271
Closed
9 of 13 tasks

plot: Improve contour plots #270

Andrew15-5 opened this issue Oct 21, 2023 · 26 comments · Fixed by #271
Assignees
Labels
bug 🐛 Something isn't working lib:plot

Comments

@Andrew15-5
Copy link
Contributor

Andrew15-5 commented Oct 21, 2023

I'm really happy that we went from 0 to 60 (percent) real quick (#215). But it still has a lot of rough edges. So I figured, that I will list them here and then probably convert it to a tracking issue (of dependency sub-issues).

Notes:

  • all "formulas" are assumed to be prefixed with (x, y) => ;
  • some of them are simplified (not the same as in the plot example) to simply convey the main idea.
  • struck out items mean that "it is not the intended usage" (see a note below such an item).

Issues that must be fixed (high priority):

  • Straight lines are offsetted.
    • No issues with conditionals (x >= 0, y >= 0, x == y).
      Note: boolean usage is discouraged (see this and this).
    • x is now showing as x = 1 (offsets by +1 to the right) and y is now showing as y = 1 (offsets by +1 to the top).
      Note: if z: 0 then it works correctly (default is z: 1, at least at the time of testing).
  • Circle is filling outside the contour.
    • Correctly fills if 9 - x² + y² (which is 9 = x² + y² or a positive float).
      Note: use x² + y² and z: 9 (for the right-hand side) instead.
    • Correctly fills if x² + y² <= 9.
      Note: boolean usage is discouraged (see this and this).
    • Doesn't work if x² + y² - 9 (which is x² + y² = 9 or a negative float).
      Note: use x² + y² and z: 9 (for the right-hand side) instead.
  • Circle contour is wrong if bool is returned bool (x² + y² <= 9).
    Note: boolean usage is discouraged (see this and this).
  • Hyperbola contour is wrong if bool is returned bool (x ⋅ y >= 1).
    Note: boolean usage is discouraged (see this and this).
  • Hyperbola contour is inverted if 1 - x ⋅ y (negative float), but it's correct if x ⋅ y - 1 (positive float).
    Note: use x ⋅ y and z: 1 (for the right-hand side) instead.

Issues that should be fixed (medium priority):

  • x can only fill to the right and y can only fill to the top (same with x - y).
    This probably can only be fixed (ideally) with x <= 0/y <= 0, i.e., changing return value from float to bool.
    Note: logical/boolean operators (conditionals) are already supported and with the right value for x-domain/y-domain the fill direction is correct. Use a new op: "<=" (or ">=") option and leave x/y as is.
  • Contour for x and y is drawn as a C and U (sometime even O) shapes instead of straight lines (with limited length).

Features that are nice to have (low priority):

  • Can't get intersection points (and their coordinates).
  • Multiple layers of fill don't blend/mix.
    Note: use style: (line: (stroke: rgb("#378A467F"), fill: rgb("#378A467F").lighten(25%))) inside the add-contour (see rgb()).

This issue was created after testing against the master#0a92100. The base code through which all of the above problems/missing features were discovered:

base.typ
#import "@local/cetz:0.1.2"

#set page(fill: black)
#set text(fill: white)

#cetz.canvas({
  import cetz.draw: *
  import cetz.plot
  let get-style(color) = (line: (stroke: color, fill: color.lighten(75%)))
  plot.plot(size: (15, 15), {
    // x >= 0
    plot.add-contour(
      (x, y) => x + 1,
      x-domain: (0, 10),
      y-domain: (-10, 10),
      fill: true,
      style: get-style(green),
    )

    // y >= 0
    plot.add-contour(
      (x, y) => y + 1,
      x-domain: (-10, 10),
      y-domain: (0, 10),
      fill: true,
      style: get-style(purple),
    )

    // hyperbola
    plot.add-contour(
      (x, y) => (x - 1) * (y - 1) - 1,
      x-domain: (-10, 10),
      y-domain: (-10, 10),
      fill: true,
      style: get-style(red),
    )

    // circle
    plot.add-contour(
      (x, y) => calc.pow((x - 1), 2) + calc.pow((y - 1), 2) - 9,
      x-domain: (-10, 10),
      y-domain: (-10, 10),
      // fill: true, // Paint outside of the circle
      style: get-style(blue),
    )

    // line
    plot.add-contour(
      (x, y) => x + 1 - y,
      x-domain: (-10, 10),
      y-domain: (-10, 10),
      style: get-style(black),
    )
  })
})
Plot screenshot

image

Reference screenshots from Desmos

image

image

image


New issues after testing against redesign-internals#742d560.

  • When using op: "==" to plot straight lines (x - y + z: 0) nothing is plotted (the line isn't present).

  • When using x² + y² + op: ">=" + z: 9 + fill: true it fills outside the circle and inside of it (although it works as expected with hyperbola). Fill only outside of a circle contour cetz-plot#6

  • With style: (line: (stroke: color + 1em, fill: color)) (for add-contour()) instead of adding thickness to the contour line (border) it also increases area of the fill, including outside the borders:

    screenshot

    image

    code
    #import "@local/cetz:0.1.2"
    
    #cetz.canvas({
      import cetz.draw: *
      import cetz.plot
      // let get-style(color) = (line: (stroke: color, fill: color.lighten(25%)))
      let get-style(color) = (line: (stroke: color + 1em, fill: color.lighten(25%)))
      plot.plot( size: (15, 15), axis-style: "school-book", {
        // x >= 0
        plot.add-contour(
          (x, y) => x,
          z: 0,
          x-domain: (0, 15),
          y-domain: (-1, 1),
          fill: true,
          style: get-style(rgb("#378A467F")),
        )
    
        // hyperbola
        plot.add-contour(
          (x, y) => (x - 1) * (y - 1),
          z: 20,
          x-domain: (-15, 15),
          y-domain: (-15, 15),
        )
      })
    })
    Note: I forgot to remove transparency of the contour line. Use this:
    #let get-style(color) = {
      let (r, g, b, ..) = color.to-rgba()
      (line: (stroke: rgb(r, g, b) + 1em, fill: color.lighten(25%)))
    }
  • In the above scenario, the thickened contour stroke is added to the right of the RHS, instead of the center.
    Note: this is a blending effect, not a bug, see note of the task above.

@Andrew15-5
Copy link
Contributor Author

@johannes-wolf, tell me if I should create a separate issue for every task (now or later) and do I need to add anything else (implementation optimizations or something like that).

@johannes-wolf
Copy link
Member

johannes-wolf commented Oct 21, 2023

You can get a correct looking result with:

#import "src/lib.typ"
#let cetz = lib

#cetz.canvas({
  import cetz.draw: *
  import cetz.plot
  let get-style(color) = (line: (stroke: color, fill: color.lighten(75%)))
  plot.plot(size: (15, 15), {
    // x >= 0
    plot.add-contour(
      (x, y) => x >= 0,
      x-domain: (0, 10),
      y-domain: (-10, 10),
      fill: true,
      style: get-style(green),
    )

    // y >= 0
    plot.add-contour(
      (x, y) => y >= 0,
      x-domain: (-10, 10),
      y-domain: (0, 10),
      fill: true,
      style: get-style(purple),
    )

    // hyperbola
    plot.add-contour(
      (x, y) => (x - 1) * (y - 1),
      x-domain: (-10, 10),
      y-domain: (-10, 10),
      fill: true,
      z: 1,
      style: get-style(red),
    )

    // circle
    plot.add-contour(
      (x, y) => 9 - (calc.pow((x - 1), 2) + calc.pow((y - 1), 2)),
      x-domain: (-10, 10),
      y-domain: (-10, 10),
      z: 0,
      fill: true,
      style: get-style(blue),
    )

    // line
    plot.add-contour(
      (x, y) => x + 1 - y,
      x-domain: (-10, 10),
      y-domain: (-10, 10),
      style: get-style(black),
    )
  })
})

grafik

The offset of x and y for non-boolean is incorrect. I will take a look into that. It is a bog with the domain! If you set the lower domain limit != 0 it works. Circle filling works.

@johannes-wolf
Copy link
Member

Please test against branch redesign-internals as this one is becoming 0.2.0.

@johannes-wolf
Copy link
Member

johannes-wolf commented Oct 21, 2023

Issues that should be fixed (medium priority):

  • x can only fill to the right and y can only fill to the top (same with x - y).
    This probably can only be fixed (ideally) with x <= 0/y <= 0, i.e., changing return value > from float to bool.
  • Contour for x and y is drawn as a C and U shapes instead of straight lines with limited length.

Can you give examples for those?

@johannes-wolf johannes-wolf added bug 🐛 Something isn't working lib:plot labels Oct 21, 2023
@johannes-wolf johannes-wolf self-assigned this Oct 21, 2023
@johannes-wolf johannes-wolf changed the title Improve contour plots plot: Improve contour plots Oct 21, 2023
@johannes-wolf
Copy link
Member

You can use a color with transparency to get blending.

@johannes-wolf
Copy link
Member

johannes-wolf commented Oct 21, 2023

Or did you mean, that plots with holes do not work? This is true, the hole gets stroked, but everything gets filled.
With #271 I pushed some changes + fixes. You can now specify a comparison operator (optional).

@Andrew15-5
Copy link
Contributor Author

I will go through all your comments later. In the meanwhile, please check the updated OP. I expanded it and included what you showed here: #270 (comment). But overall the issues are still present, except this one:

x can only fill to the right and y can only fill to the top (same with x - y).
This probably can only be fixed (ideally) with x <= 0/y <= 0, i.e., changing return value from float to bool.
Note: logical/boolean operators (conditionals) are already supported and with the right value for x-domain/y-domain the fill direction is correct.

@johannes-wolf
Copy link
Member

johannes-wolf commented Oct 21, 2023

x is now showing as x = 1 (offsets by +1 to the right) and y is now showing as y = 1 (offsets by +1 to the top).

Are you setting z: 0? Because it defaults to 1 which explains the behavior.

Circle contour is wrong if bool is returned bool (x² + y² <= 9).
Hyperbola contour is wrong if bool is returned bool (x ⋅ y >= 1).

Unfixable, do not use booleans. Use the new operator support + z: z: 9, op: "<=" and z: 1, op: ">=". See/use my PR for testing, as this is a new feature.

I think, in some cases you are not using the correct z value(s).

@Andrew15-5
Copy link
Contributor Author

Are you setting z: 0? Because it defaults to 1 which explains the behavior.

With z: 0 the line is closer to zero, but now it's in the negative half.

source
    // x >= 0
    plot.add-contour(
      (x, y) => x,
      z: 0,
      x-domain: (0, 10),
      y-domain: (-10, 10),
      fill: true,
      style: get-style(green),
    )

    // y >= 0
    plot.add-contour(
      (x, y) => y,
      z: 0,
      x-domain: (-10, 10),
      y-domain: (0, 10),
      fill: true,
      style: get-style(purple),
    )

image

Unfixable, do not use booleans. Use the new operator support + z: z: 9, op: "<=" and z: 1, op: ">=". See/use my PR for testing, as this is a new feature.

I think, in some cases you are not using the correct z value(s).

Whaa? I thought z is background/foreground index (z-index in CSS). Yeah, op wasn't there, so I need to check it out (later). So you are saying that you never ever should use boolean expression when plotting contours? Only function with a returned number + z and op? I mean that is this applied to any contour or only circle/hyperbola?

@johannes-wolf
Copy link
Member

Have you tested with the branch from the PR?
Yes, no booleans. It can not work, because the sampled matrix is a matrix of booleans, this means interpolation does not work at all. I mean you can use bools, but you have to use a high sample number to get pleasing results.

@Andrew15-5
Copy link
Contributor Author

Issues that should be fixed (medium priority):

  • x can only fill to the right and y can only fill to the top (same with x - y).
    This probably can only be fixed (ideally) with x <= 0/y <= 0, i.e., changing return value > from float to bool.
  • Contour for x and y is drawn as a C and U shapes instead of straight lines with limited length.

Can you give examples for those?

The first one is already resolved.

for the second one just use smaller domain than the canvas:

code
plot.add-contour(
  (x, y) => x,
  z: 0,
  x-domain: (0, 10),
  y-domain: (-1, 1),
  fill: true,
)

image

I would increase border/contour thickness, but it has a weird bug (which isn't noted), or I do something wrong:

code
#cetz.canvas({
  import cetz.draw: *
  import cetz.plot
  let get-style(color) = (line: (stroke: color + 1em, fill: color))
  // let get-style(color) = (line: (stroke: color, fill: color.lighten(25%)))
  plot.plot(size: (15, 15), axis-style: "school-book",
  {
    // x >= 0
    plot.add-contour(
      (x, y) => x,
      z: 0,
      x-domain: (0, 10),
      y-domain: (-1, 1),
      fill: true,
      style: get-style(rgb("#378A467F")),
    )

    // hyperbola
    plot.add-contour(
      (x, y) => (x - 1) * (y - 1),
      z: 19,
      x-domain: (-10, 10),
      y-domain: (-10, 10),
      x-samples: 50,
      y-samples: 50,
      fill: true,
      style: get-style(rgb("#C8423F7F")),
    )
  })
})

image

Oh, right, it's not C/U, it's actually O (closed path), at least with big thickness. It supposed to be one line along x == 0 and just the fill color to the right (not both).

@Andrew15-5
Copy link
Contributor Author

This is as close as I could get to the first Desmos screenshot:

code
#import "@local/cetz:0.1.2"

#set page(width: 16.13cm, height: 14.03cm, margin: 0pt)
#set box(inset: -1em)

#cetz.canvas({
  import cetz.draw: *
  import cetz.plot
  // Bug with thickness.
  // let get-style(color) = (line: (stroke: color + 1em, fill: color.lighten(25%)))
  let get-style(color) = (line: (stroke: color, fill: color.lighten(25%)))
  set-style(axes: (
    tick: (stroke: none),
    stroke: none,
    // grid: (stroke: yellow), // Doesn't work.
  ))
  let x-min = -8
  let x-max = 15
  let y-min = -10
  let y-max = 10
  let width = x-max - x-min
  let height = y-max - y-min
  let factor = 0.7
  width = width * factor
  height = height * factor
  plot.plot(
    size: (width, height),
    axis-style: "school-book",
    x-label: none,
    y-label: none,
    x-tick-step: none,
    y-tick-step: none,
    x-ticks: range(-1, 3).map(it => it * 5),
    y-ticks: range(-1, 2).map(it => it * 5),
  {
    // hyperbola
    plot.add-contour(
      (x, y) => (x - 1) * (y - 1),
      z: 1,
      x-domain: (x-min, x-max),
      y-domain: (y-min, y-max),
      x-samples: 50,
      y-samples: 50,
      fill: true,
      style: get-style(rgb("#C8423F7F")), // red
    )

    // circle
    plot.add-contour(
      (x, y) => (calc.pow((x - 1), 2) + calc.pow((y - 1), 2)),
      op: "<=",
      z: 9,
      x-domain: (x-min, x-max),
      y-domain: (y-min, y-max),
      x-samples: 50,
      y-samples: 50,
      fill: true,
      style: get-style(rgb("#2D6FB47F")), // blue
    )

    // x >= 0
    plot.add-contour(
      (x, y) => x,
      z: 0,
      x-domain: (0, x-max),
      y-domain: (y-min, y-max),
      fill: true,
      style: get-style(rgb("#378A467F")), // green
    )

    // y >= 0
    plot.add-contour(
      (x, y) => y,
      z: 0,
      x-domain: (x-min, x-max),
      y-domain: (0, y-max),
      fill: true,
      style: get-style(rgb("#6042A57F")), // purple
    )

    // x (y = x)
    plot.add(domain: (x-min, y-max), x => x, style: (stroke: black))

    // `op: "=="` doesn't work.
    // x (y = x)
    // plot.add-contour(
    //   // (x, y) => x == y,
    //   (x, y) => x - y,
    //   // op: "==",
    //   z: 0,
    //   x-domain: (x-min, x-max),
    //   y-domain: (y-min, y-max),
    //   // style: get-style(black),
    //   style: get-style(rgb("#0000007F")),
    // )
  })
})
screenshot

image

The main visual problem is that I couldn't (for some reason) add a grid. Could you please help me with that?

@johannes-wolf
Copy link
Member

Issues that should be fixed (medium priority):

  • x can only fill to the right and y can only fill to the top (same with x - y).
    This probably can only be fixed (ideally) with x <= 0/y <= 0, i.e., changing return value > from float to bool.
  • Contour for x and y is drawn as a C and U shapes instead of straight lines with limited length.

Can you give examples for those?

The first one is already resolved.

for the second one just use smaller domain than the canvas:
code

plot.add-contour(
  (x, y) => x,
  z: 0,
  x-domain: (0, 10),
  y-domain: (-1, 1),
  fill: true,
)

image

I would increase border/contour thickness, but it has a weird bug (which isn't noted), or I do something wrong:
code

image

Oh, right, it's not C/U, it's actually O (closed path), at least with big thickness. It supposed to be one line along x == 0 and just the fill color to the right (not both).

The problem here is, that the sampled domain is the visible domain. Since the function gets sampled between [0, 10] it can not know that there are no vertical "borders" because no values outsides that range are known. A solution would be having a bigger sample-domain and not showing the fully sampled domain. We could add a flag "oversample" that samples left and right of the sampling domain, bot not modifying the visible domain?

@Andrew15-5
Copy link
Contributor Author

Andrew15-5 commented Oct 23, 2023

Let's test this. But the problem here is that not only it shows right vertical line, it also shows top and bottom one. So the flag should "oversample" left, right, top and bottom.

I still don't get why the area of the fill color is also expanded as the contour stroke is thickened? I think this is a clear bug.
image

And you can also see that the thick contour stroke is fully drawn at x => 0 instead of dead center of the x == 0, you know? Usually, when you draw a thick line, the center of that thick line should go right where the center of the thin line is. In the screenshot, the center of the thick (x, y) => x (+ op: ">=" + z: 0) line is not aligned with the center of the Y axis thin line.

Check out new tasks at the bottom of the OP.

@johannes-wolf
Copy link
Member

johannes-wolf commented Oct 23, 2023

This is strange as I can not reproduce it.

style: (stroke: 0pt)
grafik

style: (stroke: 5pt)
grafik

Code
#cetz.canvas({
  import cetz.draw: *
  import cetz.plot
  plot.plot(size: (10, 4), y-max: 4, {
    plot.add-contour(
      (x, y) => x,
      z: 0,
      x-domain: (0, 10),
      y-domain: (-1, 1),
      fill: true,
      style: (stroke: 5pt + blue),
    )
  })
})

@johannes-wolf
Copy link
Member

johannes-wolf commented Oct 23, 2023

When using op: "==" to plot straight lines (x - y + z: 0) nothing is plotted (the line isn't present).

This is expected and has to do with sampling. The sampling is not "hitting" the values where the function is zero. Try using different <x/y>-samples: values.

We could either allow op: to be of type function so the user can code his/her own comparison including an epsilon or have an epsilon attribute.

EDIT: I now added the option to pass a function (z0, z1) => boolean to op: to support custom comparison.

@johannes-wolf
Copy link
Member

johannes-wolf commented Oct 23, 2023

When using x² + y² + op: ">=" + z: 9 + fill: true it fills outside the circle and inside of it (although it works as expected with hyperbola).

This is very complicated to solve as of now. Please create a separate ticket for this. Detecting holes is a contour is currently not supported. We could test if a polygon lies insides another polygon. BUT Typst is currently unable to draw paths with holes in them.

@Andrew15-5
Copy link
Contributor Author

This is strange as I can not reproduce it.

Shoot, I really should've thought this through. I didn't remove alpha from contour stroke, so the contour thick line mixed with the inner fill, created in 2 layers of the same transparent color making an illusion that the fill has exceeded its area and the stroke is offsetted inside. My bad. Here is the fixed get-style():

#{
  let get-style(color) = {
    let (r, g, b, ..) = color.to-rgba()
    (line: (stroke: rgb(r, g, b) + 1em, fill: color.lighten(25%)))
  }
}

added the option to pass a function (z0, z1) => boolean to op: to support custom comparison.

Hmm, it does work, but what do the arguments mean? What exactly do we compare? This works ok: op: (l, r) => calc.abs(r - l) < 1, but you can see the unwanted extra lines alongside the canvas border:
image image

It's kinda confusing since the op is supposed to be an operator, logical operator: "<=", ">=", "==". When you give it the function with arguments, it obscures the meaning, IMO.

@johannes-wolf
Copy link
Member

johannes-wolf commented Oct 23, 2023

The first argument is the z-value you passed to add-contour, the second is the z value of your data. This is because you can pass an array of values to z: to plot multiple contours per data.

@Andrew15-5
Copy link
Contributor Author

the second is the z value of your data

Hold on, which data? I only pass a function and about 6 named arguments. Do I miss something obvious?

you can pass an array of values to z: to plot multiple contours per data.

Wow, I can actually plot 2 circles for the price of one with z: (9, 16). This is pretty cool stuff.

@johannes-wolf
Copy link
Member

johannes-wolf commented Oct 23, 2023

the second is the z value of your data

Hold on, which data? I only pass a function and about 6 named arguments. Do I miss something obvious?

The matrix of the sampled values. But you can also pass a matrix as an array of arrays of numbers if you want to.

you can pass an array of values to z: to plot multiple contours per data.

Wow, I can actually plot 2 circles for the price of one with z: (9, 16). This is pretty cool stuff.

Yes, take a look at the test images here: https://github.com/johannes-wolf/cetz/pull/271/files#diff-c42484ff5212737b6f585e90895e76fde4994035aa35f36f1ebb8e898c2d8ec1
(you have to pay for the contour finding per z-value, but not the sampling)

I want to add the option to set a gradient for z-values in the future, so it can interpolate between colors for the different z-levels.

@Andrew15-5
Copy link
Contributor Author

you have to pay for the contour finding per z-value, but not the sampling

I was referring to the count of add-contour() compared to the count of drawn circles. But it's nice that sampling is only "paid" once as well. The only price to pay is that style is shared between all the circles.

@Andrew15-5
Copy link
Contributor Author

So far it looks very close, but the redundant contour lines (that shouldn't exist) are still there:

screenshot

image

code
#import "@local/cetz:0.1.2"

#set page(width: 16.13cm, height: 14.03cm, margin: 0pt)
#set box(inset: -3.9mm)
#set text(font: "Fira Sans", size: 16pt, fill: rgb(0, 0, 0, 70%))

#cetz.canvas({
  import cetz.draw: *
  import cetz.plot
  let get-style(color) = {
    let (r, g, b, ..) = color.to-rgba();
    let stroke-color = rgb(r, g, b, 80%)
    let fill-color = rgb(r, g, b, 50%)
    (line: (stroke: stroke-color + 2.5pt, fill: fill-color.lighten(25%)))
  }
  set-style(axes: (
    tick: (stroke: none),
    stroke: none,
    grid: (stroke: rgb("#88888888") + 0.6pt),
  ))
  let x-min = -8
  let x-max = 15
  let y-min = -10
  let y-max = 10
  let width = x-max - x-min
  let height = y-max - y-min
  let factor = 0.7
  width = width * factor
  height = height * factor
  plot.plot(
    size: (width, height),
    axis-style: "school-book",
    x-label: none,
    y-label: none,
    x-tick-step: none,
    y-tick-step: none,
    x-ticks: range(-1, 3).map(it => it * 5),
    y-ticks: range(-1, 2).map(it => it * 5),
    x-minor-tick-step: 1,
    y-minor-tick-step: 1,
    x-grid: "both",
    y-grid: "both",
    x-format: value => [#value],
    y-format: value => [#value],
    {
      // hyperbola
      plot.add-contour(
        (x, y) => (x - 1) * (y - 1),
        z: 1,
        x-domain: (x-min, x-max),
        y-domain: (y-min, y-max),
        x-samples: 50,
        y-samples: 50,
        fill: true,
        style: get-style(rgb("#C8423F")), // red
      )

      // circle
      plot.add-contour(
        (x, y) => (calc.pow((x - 1), 2) + calc.pow((y - 1), 2)),
        op: "<=",
        // z: 9,
        z: 9,
        x-domain: (x-min, x-max),
        y-domain: (y-min, y-max),
        x-samples: 50,
        y-samples: 50,
        fill: true,
        style: get-style(rgb("#2D6FB4")), // blue
      )

      // x >= 0
      plot.add-contour(
        (x, y) => x,
        z: 0,
        x-domain: (0, x-max),
        y-domain: (y-min, y-max),
        fill: true,
        style: get-style(rgb("#378A46")), // green
      )

      // y >= 0
      plot.add-contour(
        (x, y) => y,
        z: 0,
        x-domain: (x-min, x-max),
        y-domain: (0, y-max),
        fill: true,
        style: get-style(rgb("#6042A5")), // purple
      )

      // x (y = x)
      plot.add-contour(
        (x, y) => x - y,
        op: (z, r) => calc.abs(r - z) < 1,
        z: 0,
        x-domain: (x-min, x-max),
        y-domain: (y-min, y-max),
        fill: true,
        style: get-style(rgb("#000000")), // black
      )
    },
  )
})

@johannes-wolf
Copy link
Member

The way to get rid of them is fixing your x-min/x-max y-min/y-max to a value so that the domain is outsides that window.

@Andrew15-5
Copy link
Contributor Author

This is also known as hacking. The problem is that the API is supposed to be created for the user to use, so it should be straightforward. But a lot of time the API is either not flexible enough yet or for eternity. I've encountered this kind of plotting hacking where the output isn't really what it should have been, so you are trying hard to get it work just like you wanted by making a lot of hacky stuff, like instead of defining range for an axis from -15 to +15, you define it as [-14.6; +14.6], so that the 15 on the plot wouldn't show up (at all) in the unreadable manner (like when the number is smashed on top of the tick which makes it unreadable or ugly).

This problem has the same idea. I will try changing the domain values, but you already said about "oversampling", if I'm understanding correctly, it will do the same thing as what you have just said (about domain). So try implementing such a thing, and we will then test it and see if it's good or not.

@fenjalien fenjalien linked a pull request Oct 23, 2023 that will close this issue
@johannes-wolf
Copy link
Member

I checked against matplotlib output and I will try to replicate the edge behavior (soonish).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug 🐛 Something isn't working lib:plot
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants