Sudha247 / ocaml-joy

MIT License
22 stars 14 forks source link

Scale transformation for lines #49

Closed nikochiko closed 6 months ago

nikochiko commented 10 months ago

Scale transformation is being added with https://github.com/Sudha247/ocaml-joy/pull/34

But, it is not clear how to scale up/down lines -- given their current representation as start/end points.

e.g. if there are 4 lines forming a square and all four of them are scaled by 0.5, should the resulting diagram still be a square? Maybe yes because the diagram should still be consistent, but that might involve making the lines themselves thinner/thicker too. This is also something that happens when SVGs are scaled.

Mankavelda commented 10 months ago

Hello @nikochiko , can you please assign me to this issue?

Sudha247 commented 10 months ago

@Mankavelda I'm happy for you to work on this issue. But first, we should decide how we're approaching this.

if there are 4 lines forming a square and all four of them are scaled by 0.5, should the resulting diagram still be a square? Maybe yes because the diagram should still be consistent

I agree with this.

but that might involve making the lines themselves thinner/thicker too.

I'm not so sure about this.. lines are one-dimensional, could we just scale it linearly by the scaling factor?

nikochiko commented 10 months ago

could we just scale it linearly by the scaling factor?

I agree, but it's also not straightforward. If in the above 4-line square example, we keep the midpoints same and shrink the lines, we'll get 4 disjoint lines.

nikochiko commented 10 months ago
image

We want the second one.

I think the intuition should be "scale the canvas size up/down while keeping the dimensions and distances in proportion", then center that scaled canvas at the origin. So there would be bias for scaled down diagrams to come towards the center, and for scaled up diagrams to go outwards. Maybe our current transformation also needs to be changed with this logic.

Mankavelda commented 10 months ago

Interesting @nikochiko but I am not sure I quite understand what you mean. Please a deeper explanation will help. We could also consider uniform scaling, scaling with midpoints and linear scaling

nangahamandine commented 10 months ago

Interesting @nikochiko but I am not sure I quite understand what you mean. Please a deeper explanation will help. We could also consider uniform scaling, scaling with midpoints and linear scaling

From my understanding of what the mentors suggested, what you should do is to first;

You can update the scale function to look something like this:

let scale factor s =
  let scale_length len fact = int_of_float ((float_of_int len) *. fact) in
  match s with
  | Circle circle' -> circle ~x:circle'.c.x ~y:circle'.c.y (scale_length circle'.radius factor)
  | Rectangle rectangle' -> rectangle ~x:rectangle'.c.x ~y:rectangle'.c.y
                                    (scale_length rectangle'.length factor)
                                    (scale_length rectangle'.width factor)
  | Ellipse ellipse' -> ellipse ~x:ellipse'.c.x ~y:ellipse'.c.y
                                (scale_length ellipse'.rx factor)
                                (scale_length ellipse'.ry factor)
  | Line line' -> line ~x1:line'.a.x ~y1:line'.a.y
                       (line'.b.x + int_of_float((float_of_int line'.b.x -. float_of_int line'.a.x) *. factor))
                       (line'.b.y + int_of_float((float_of_int line'.b.y -. float_of_int line'.a.y) *. factor))

Hopefully this works for you. These are my thoughts based on my understanding so I don't know if the mentors would agree.

Mankavelda commented 10 months ago

Interesting @nikochiko but I am not sure I quite understand what you mean. Please a deeper explanation will help. We could also consider uniform scaling, scaling with midpoints and linear scaling

From my understanding of what the mentors suggested, what you should do is to first;

  • Implement Scaling Transformation, that is in the scale function, you first calculate the scaled dimensions of the shape. To maintain proportionality, you can calculate the scaled length and width of the shape based on the given factor. Possibly handle all the shape types: Circle, Rectangle, Ellipse, and Line. For circles, you can use a simple scaling formula, while for rectangles and ellipses, you need to scale both length and width (rx and ry for ellipses). Lines can be scaled by modifying their endpoints.

You can update the scale function to look something like this:

let scale factor s =
  let scale_length len fact = int_of_float ((float_of_int len) *. fact) in
  match s with
  | Circle circle' -> circle ~x:circle'.c.x ~y:circle'.c.y (scale_length circle'.radius factor)
  | Rectangle rectangle' -> rectangle ~x:rectangle'.c.x ~y:rectangle'.c.y
                                    (scale_length rectangle'.length factor)
                                    (scale_length rectangle'.width factor)
  | Ellipse ellipse' -> ellipse ~x:ellipse'.c.x ~y:ellipse'.c.y
                                (scale_length ellipse'.rx factor)
                                (scale_length ellipse'.ry factor)
  | Line line' -> line ~x1:line'.a.x ~y1:line'.a.y
                       (line'.b.x + int_of_float((float_of_int line'.b.x -. float_of_int line'.a.x) *. factor))
                       (line'.b.y + int_of_float((float_of_int line'.b.y -. float_of_int line'.a.y) *. factor))

Hopefully this works for you. These are my thoughts based on my understanding so I don't know if the mentors would agree.

Thanks very much @nangahamandine

nangahamandine commented 10 months ago

You're welcome @Mankavelda