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

Morphs and Partially draw Objects #482

Merged
merged 145 commits into from
Aug 9, 2022

Conversation

ArbitRandomUser
Copy link
Contributor

@ArbitRandomUser ArbitRandomUser commented May 13, 2022

  • Did I update CHANGELOG.md with whatever changes/features I added with this PR?
  • Did I make sure to only change the part of the file where I introduced a new change/feature?
  • Did I cover all corner cases to be close to 100% test coverage (if applicable)?
  • Did I properly add Javis dependencies to the Project.toml + set an upper bound of the dependency (if applicable)?
  • Did I properly add test dependencies to the test directory (if applicable)?
  • Did I check relevant tutorials that may be affected by changes in this PR?
  • Did I clearly articulate why this PR was made the way it was and how it was made?

How did you address these issues with this PR? What methods did you use?

Install master branch Luxor.jl branch till Luxor 3.5 is released if you want to try out this PR

PR allows Arbitrary morphs from any Object to Object , Object to Function .
and also keyframed morphs with Animations.jl .
PR also brings in ability to draw Objects partially , and "show-creation" (and destruction) of objects.

This is made possible with the help of JPath a structure holding data of polygons and how to fill and stroke them.
Every Javis Object now has a a jpaths field an array for JPath that is got from evaluating the object.func fo the Object

Extracting the polygons is made possible by over-riding luxors strokepath/stroke/fillpath/fillpreserve methods . These four methods are only ways to lay the current path onto the canvas and all of luxors "drawing function" eventually call one or more of these four. (except for text ).

Morphs between polygons are using a modified version of luxors polymorph. (modified so that
polys dont have to be resampled everytime its called)

Limitations:
afaik...

  1. Cannot be used in conjunction with sethue in Actions. Morphs will work , but the sethue will not
    if you want to change hue while morphing you will have to change the hue of the target you are morphing to.
  2. Objects and Functions which have clipping regions in their drawings will not be morphed properly.
  3. Gets the morphs done .. but might not be the most "natural" or simplest morph possible. morphs are somewhat "natural" now by offseting the index for best match between two polygons. But individual polygons are not matched for the shortest transformation
  4. dashed lines not yet implemented . Objects should use only solid lines
  5. strokescale doesnt change during morph (not yet implemented) . Objects should have the default strokethickness

Examples for Morphs:

Object to Object morphs ...

using Javis

video = Video(500,500)
nframes = 160 

function circdraw(colo)
    sethue(colo)
    setopacity(0.5)
    circle(O,100,:fillpreserve)
    setopacity(1.0)
    sethue("white")
    strokepath()
end

function boxdraw(colo)
    sethue(colo)
    box(O,100,100,:fillpreserve)
    setopacity(1.0)
    sethue("white")
    strokepath()
end

Background(1:nframes,(args...)->background("black"))
boxobj  = Object((v,o,f) -> boxdraw("green"))
circobj = Object((v,o,f) -> circdraw("red"))

transform_to_box = Action(20:nframes-20, morph_to(boxobj))
act!(circobj, transform_to_box)
render(video,pathname="circ_to_box.gif")

circ_to_box_pr

Object to Function morphs ...

Background(1:nframes,(args...)->background("black"))
circobj = Object(1:nframes,(args...) -> circdraw("red"))

transform_to_box = Action(20:nframes-20, morph_to(boxdraw,["blue"]))
act!(circobj, transform_to_box)

render(video,pathname="circ_to_box_fn.gif")

circ_to_box_fn

Keyframed morphs using Animations.jl

using Javis
using Animations
video = Video(500,500)
nframes = 160 

function circdraw(colo)
    sethue(colo)
    setopacity(0.5)
    circle(O,50,:fillpreserve)
    setopacity(1.0)
    sethue("white")
    strokepath()
end

function boxdraw(colo)
    sethue(colo)
    box(O,100,100,:fillpreserve)
    setopacity(1.0)
    sethue("white")
    strokepath()
end

function stardraw()
    sethue("white")
    star(O,100,5,0.5,0.0,:stroke)
end

Background(1:nframes+10,(args...)->background("black"))
boxobj = Object(1:nframes+10 , (args...) -> boxdraw("green") )
anim = Animation([0, 0.7, 1],  MorphFunction[(boxdraw, ["green"]),
                                             (stardraw, []),
                                             (circdraw, ["red"])
                                             ])


action = Action(1:nframes,anim,morph())
act!(boxobj,action)
render(video,pathname="box_to_star_to_circ.gif")

box_to_star_to_circ

Examples for Partial Draw .

using Javis
video = Video(500,500)
nframes = 360 

function ground()
    background("black")
    sethue("white")
end

function boxdraw(colo)
    circle(O+100,50,:stroke)
    sethue(colo)
    box(O,100,100,:fillpreserve)
    setopacity(1.0)
    sethue("white")
    strokepath()
end

Background(1:nframes+60,(args...)->ground())
boxobj = Object(1:nframes+60 , (args...) -> boxdraw("green") )

action_create = Action(1:nframes÷2,sineio(),Javis.showcreation())
action_remove = Action(nframes÷2+30:nframes,sineio(),Javis.showdestruction())
act!(boxobj,action_create)
act!(boxobj,action_remove)
render(video,tempdirectory="images",pathname="show_box_creation.gif")
run(`mpv show_box_creation.gif`)

show_box_creation

@codecov-commenter
Copy link

codecov-commenter commented May 13, 2022

Codecov Report

Merging #482 (974344c) into main (6add2f2) will decrease coverage by 18.75%.
The diff coverage is 88.34%.

@@             Coverage Diff             @@
##             main     #482       +/-   ##
===========================================
- Coverage   96.50%   77.74%   -18.76%     
===========================================
  Files          35       38        +3     
  Lines        1630     1991      +361     
===========================================
- Hits         1573     1548       -25     
- Misses         57      443      +386     
Impacted Files Coverage Δ
src/luxor_overrides.jl 86.54% <76.13%> (-11.05%) ⬇️
src/action_animations.jl 95.80% <81.08%> (-4.20%) ⬇️
src/partial_draw.jl 84.90% <84.90%> (ø)
src/structs/Object.jl 95.34% <86.66%> (-4.66%) ⬇️
src/morphs.jl 38.63% <95.49%> (-57.35%) ⬇️
src/Javis.jl 96.92% <100.00%> (-0.04%) ⬇️
src/luxor_utils.jl 100.00% <100.00%> (ø)
src/structs/JPath.jl 100.00% <100.00%> (ø)
src/Shape.jl 0.00% <0.00%> (-97.06%) ⬇️
... and 2 more

Help us with your feedback. Take ten seconds to tell us how you rate us.

@Wikunia
Copy link
Member

Wikunia commented Jul 27, 2022

Thanks for the fast response. Perfect looking forward to thread safety as well then ☺️

empty!(CURRENT_JPATHS)
global CURRENT_FETCHPATH_STATE = true
global DISABLE_LUXOR_DRAW = true
v, o, f = nothing, nothing, nothing
Copy link
Member

@gpucce gpucce Jul 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @ArbitRandomUser, can't you pass v, o, f explicitly as arguments to getjpaths instead of defining them as nothing, nothing, nothing? It looks they are always available where getjpaths! is called

@Wikunia
Copy link
Member

Wikunia commented Jul 28, 2022

I think we can now set Luxor to 3.5 and run the tests 😄

@ArbitRandomUser
Copy link
Contributor Author

ArbitRandomUser commented Jul 29, 2022

I think we can now set Luxor to 3.5 and run the tests smile

tests failed , it seems theres some clash in the deps.
─restricted by julia compatibility requirements to versions: [0.11.0-0.11.2, 0.12.0, 1.0.0, 1.1.0-1.1.5, 1.2.0, 1.3.0, 1.4.0, 1.5.0, 1.6.0, 1.7.0, 1.8.0, 1.9.0, 1.10.0, 1.11.0, 1.12.0, 2.0.0, 2.1.0, 2.2.0-2.2.1, 2.3.0, 2.4.0, 2.5.0-2.5.1, 2.6.0, 2.7.0, 2.8.0, 2.9.0, 2.10.0, 2.11.0, 2.12.0, 2.13.0, 2.14.0, 2.15.0, 2.16.0, 2.17.0, 2.18.0, 2.19.0, 3.0.0, 3.1.0-3.1.1, 3.2.0] or uninstalled — no versions left.

will this be fixed by bumping the julia version up ?

@Wikunia
Copy link
Member

Wikunia commented Jul 29, 2022

Yeah Luxor.jl needs Julia 1.6 now which is fine as it's the LTS

@ArbitRandomUser
Copy link
Contributor Author

@Wikunia that didnt work .

@Wikunia
Copy link
Member

Wikunia commented Jul 29, 2022

@Wikunia Wikunia self-requested a review July 30, 2022 10:27
Copy link
Member

@Wikunia Wikunia left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some minor things but afterwards I would like to merge.
Thanks a lot for your awesome work. Looking forward to use this functionality.

CHANGELOG.md Outdated
@@ -2,7 +2,14 @@

# PR changes
- changed render method for mp4 to use ffmpeg directly inplace of VideoIO

- Added jpaths a field in Object that is usefull for morphs and partial drawing
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*useful

"""
_betweenpoly_noresample(loop1,loop2,k; easingfunction = easingflat)

Just like _betweenpoly from Luxor , but expects polygons `loop1` and `oop2` to be of same size , and
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*loop2


returns the sum of all the lengths of the polys that this `jpath` contains
"""
len_jpath(jpath::JPath) = sum([
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no need to create an array here

JPath(polys, closed, fill, stroke, lastaction, linewidth) =
JPath(polys, closed, fill, stroke, lastaction, linewidth, nothing)

CURRENT_JPATHS = JPath[] #TODO change to const later
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this be changed to const ?

@@ -1,3 +1,4 @@
include("JPath.jl")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's keep all includes in one place, similar to the structs

@@ -0,0 +1,217 @@
astar(args...; do_action = :stroke) = star(Point(-100, -100), 30, 5, 0.5, 0, do_action)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can this file be removed seems like it's not used, right?

@TheCedarPrince
Copy link
Member

Hey! Just did a first pass review of the PR - WOW.
@ArbitRandomUser and @Wikunia , this is absolutely incredible!
If it is alright, may I have one more day to do a few edits to the tutorial and try to follow along it?
Was also going to finish a run through of documentation.
Otherwise, incredible work!

@Wikunia Wikunia merged commit 1e74392 into JuliaAnimators:main Aug 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants