Ep. 046: Math | Flutter Processing

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
what is up flutter devs let's start today with a quick recap or check in with the status of our port of processing over to flutter we've successfully ported a whole lot of the api surface i'd say a majority of the behaviors that someone wants in processing we have ported over from processing to flutter we've implemented it in the flutter processing package so let's take an inventory of where we are and where we're going from here there are a few things left to accomplish in my mind what we're going to focus on in the near term is there there are two or three categories of properties and behaviors in the processing specification that should be very easy for us to port over these are like we have mathematical constants mathematical functions uh kind of some other some other behaviors that are almost direct representations of things that are already in dart to begin with now i wasn't sure at the beginning of this project if i even wanted to create those methods those behaviors in the processing sketch given that things like pi and cosine are already available but at the same time there's probably a fair bit of processing code out there that has invocations of sine cosine tangent pi ceiling absolute value distance and wouldn't it be nice if people who already have some of that code don't have to necessarily rewrite that part obviously there are parts that they will need to rewrite or they might need to adjust parameters but if they copy some code over and the cosine function seems like it doesn't even exist well that's a little bit confusing so i thought okay let's go ahead and give processing developers access to the properties and methods that they're used to unless it would be like totally egregious to do so uh obviously for example we are not going to overload mathematical operations that are described in the specification i mean like like look like plus minus modulus division those are literally baked in to how you work with integers and doubles so we're not going to reinvent that wheel but i think a number of these methods it makes sense for us to go ahead and pipe them through so that you can invoke them like you normally would in a processing sketch so for the next few videos we're just going to take entire categories of properties and pretty much direct replications of behaviors and we're going to make them available in the sketch api now some of those behaviors still will require a little bit of work for example i think there's a distance function over here which is not directly implemented on integers or doubles or anything so we'll need to create that but there shouldn't be a lot of that work to be done but after that or we'll actually starting with that process starting with these last two or three categories of easy porting behaviors we're going to begin breaking down the definition of the sketch api into a bunch of different pieces we're going to start doing that by defining for example the mathematical operations the mathematical functions in its own file as a mix-in and we're going to take that mix in and we're going to mix it into our sketch definition so that anybody who uses a sketch will have access to it but we can partition it into its own file once we do that with the next few videos we're going to come back in a dedicated video and really start breaking down the big mess of sketch methods that we've defined up to this point we're going to try to categorize it the same way we're going to categorize it in directories and files the way that processing categorizes them that way we can get to the third area of interest which is how do we turn this into more of a community project moving forward obviously we don't want me to be responsible for everything forever on this project we'd like to get more people involved well if we can get the structure of the core sketch definition broken down into pieces then other developers will have specific areas where they can work without risking the broader project and it will also be easier hopefully to understand how things work when you have responsibilities broken down by directories and files and the test structure reflects that directory structure and all of those things these are my focal points for the next however many videos and then after that i'm going to return to doing you know to replicating some of the code challenges from the coding train and try to put some more creative um processing works out there so that people can see more of what's possible with processing and flutter processing in particular and then we can kind of go on a bit of a marketing campaign together to let the world know that as long as you're not doing 3d graphics and as long as you're not doing audio you pretty much have what you need here in flutter processing so with that big update out of the way let's go look at what we're doing today you'll see here we're back at the processing specification and what you see over here on the right side of the screen let me see if i can zoom in on this you'll see that we have a whole bunch of calculations here absolute value ceiling constrain distance exponent floor and down below we have trigonometry so these are a couple of the categories that i'm talking about where even though most of these behaviors already exist in some fashion in the world of dart we are going to expose these methods on the sketch object itself and that way it should be easier for processing developers to port their code so let's make that happen we'll start with trigonometry because there are fewer methods here than there are up in the calculation category and also probably you know just about all of these will be direct call throughs to methods that already exist so let's go see how we're going to do this now again i said we're folk we're also focused at this point on simplifying or breaking down the structure of our core implementation so notice obviously this is the trigonometry subcategory but it sits within the math primary category let's come over here to our project and under source source in a package a dart package is where your private definitions go and then you export them from typically a file a file exports all the stuff that you want users of your package to have access to but everything under source that structure is private to us as the people working on the package let's create a new directory we'll call it math and within math we will create trigonometry did i spell that correctly trigonometry trigonometry sure did okay and actually i spoke too soon that doesn't really need to be its own direct math we need as a directory but trigonometry we just want as a file so let me redo this we'll have math and then within math we will have trigonometry now i said that what we were going to do here is utilize mix-ins the idea is that in core let's go all the way up near the top of core here it's a little too far i think i'm looking for the definition of a sketch i guess we are in the definition of a sketch yeah here we go sketch right here any mix-in that we say with something whatever is defined in something will be directly accessible to any sub-class of sketch therefore when we define sine cosine tangent in our mixin we can mix it in with sketch so let's get the relationship set up right off the bat we will say it's been a while since i've defined a mix and i can't remember if it's a keyword or if it's a class i think it's just a class but we'll see if i'm wrong about that we will call this sketch trigonometry and let's just stub out a function we will say double sine double angle in radians for now we'll return zero now let's go back to our definition of a sketch and let's say with sketch trigonometry okay now wherever we subclass a sketch or invoke something on a sketch we should be able to invoke this sign method so let's see if i can just show you this compiling let me open up our main example we won't bother running it for right now i just want to show you what i mean about invoking it so i'm just going to go to a random place here where we are this is the definition of a sketch where we use callbacks and in here anywhere i want i can say s for sketch dot sign and so even though we didn't define the sine method on the sketch itself because we mixed it in we can invoke it as if we defined it within the sketch this is going to be our primary tool for breaking down our big massive core definition for a sketch but again for now we're not we're not breaking it down yet for now we are just implementing some new categories as mix-ins uh now let's see what we want to actually implement here coming back to trigonometry we have sine cosine tangent then a sine a cosine a tangent a tan two let me just declare these actually we can probably just implement them directly so uh let's import math import is it dart math and we're say as math because we're going to have some name conflicts here so math dot sign angle in radians now let me see if uh okay so degrees and radians these are two different modes so here's the problem we're going to run into let's see where whoops oh i think i just removed there it is okay so where is sine here's sine here's what we need to contend with let's see calculate the sine of an angle this function expects the value of angle parameter to be provided in radians okay that's interesting so i need to see maybe i misunderstood what a couple of these methods were doing what is this okay this is a conversion method so in some areas of processing there are methods that set the future interpretation of values i thought that calling degrees would cause all of processing to interpret all future angles as degrees instead of radians that's not the case it looks like degrees really means what this really means is radians 2 degrees but it's just called degrees as a shorthand so that's fine this implementation right here is actually all that we need we can do the same we can come and say cosine angle in radians return math cosine angle and radians and then tangent angle in radians and then we want arc sine which is a sine let's see what should we call i mean that's just a uh fraction but let me see i don't know what i don't know what that parameter is typically referred to they're just calling it a value okay fine double value return math dot arc sign value uh and let you know let me do something that's going to make this easier on us we're going to take in a num you know all those places that i keep having to write two double everywhere well num is a type that includes both integers and doubles so then you can pass in an integer here and it's not going to complain about the type all right we also want arc cosine and we want arctangent and then there is a second version of arc tangent which i believe it it's d y d x d y or d y d x let me see what the order they that processing takes these in y and x okay so we will say num y num x return math return math a tan to y x and i believe it's the same order for dart but let me make sure turn it between the positive x and the vector ba the vector ba and what's the order of vectors vectors are x comma y therefore a is y b is x so we are good a tan y x all right what else do we have here degrees and radians okay i'm going to define that up here at the top because i think these will be more commonly used double degrees we will take in angle in radians how do we return let's see what is this complaining about no i just haven't returned anything yet okay so how do we convert degrees to radians we take or actually how do we convert radians to degrees we will take angle in radians divided by 2 times pi times 360 degrees this first part is the fraction of a circle based on radians and then we multiply it by the number of degrees in a circle double radians which we will take in degrees we will return degrees divided by 360 times two times pi now there's something else that we can do here that technically will remove i mean it's it really is not relevant for performance but we could technically i think reduce the computation here because what we're dealing with is ratios we could say for example uh angle and radians divided by pi times 180 degrees those are the same ratios but we remove the multiplication by two and similarly down here we can say degrees times or degrees excuse me divided by 180 times math dot pi pi radians is one half of a circle 180 degrees is one half of a circle in terms of sweeping angle obviously okay so i think that is everything there right we've now technically just like that implemented the entire trigonometry subcategory now interestingly some of these things have tests or well for us they can be tests but they have visual examples and you know that whenever possible i like to replicate these visual examples so let's see if we can do that here let's open up our project structure let's go down to our tests in the package and let's create a directory for math and then let's say dart file trigonometry test and let's just copy one of these other groups of tests this is going to be math and then trigonometry and then i think what are we testing over here we're testing tangent now i'm going to get rid of all the other tests in here we'll just start with one and then replicate it for the few others that have tests i think that matches up and this is going to be math trigonometry tangent like that and then let's see what this code says we'll grab this code we'll come into the draw method here we are not going to draw a circle because that's from the old test we don't we want to keep no loop because we don't want to animate that'll keep our test from completing now let's port this code we will say final a actually not it's not final with double a double inc which stands for increment okay now here's something we didn't put in there yet but we should so c 2 pi in this case that should actually be s dot 2 pi but that's a constant that's defined by processing let me go c forget where those are those are under constants okay so let's also add those as well now as constants are its own category so we'll follow up we could put that in its own file but to follow to avoid any confusion let me create a directory called constance and i will also create a file called constants and by the way these files i should i believe they should begin with underscores i think to indicate that they are not public but what we now say we want to export it from flutterprocessing.dart but actually i don't think we need to because we're already mixing the apis into the sketch under constants what constants do we want here well first let's let's say sketch constants okay that's where we're going to put the constants now let's go to core and now not only do we have sketch trigonometry but we're going to mix in sketch constants now we have two mixins you can see how we keep adding more and more mixins under constants we want pie half pie quarter pie half pi is pi divided by two quarter pi is pi divided by four and then we want tau and two pi well let's start with two pi and then we have to figure out what tau is let's go see what tau is did i click the wrong thing i think i did okay tau is a mathematical constant with the value of this thing it is the circle uh it is the circle constant relating the circumference of a circle to its linear dimension the ratio of the circumference of a circle to its radius it is useful in combination with trigonometric functions such as sine and cosine well if they say so okay now this is going to complain because we're using processing capitalization i'm going to suppress this i'm going to suppress it for the file except i can't remember what the syntax is for that let's go do a search this is dart analysis options ignore for file enabling and disabling individual rules here we go ignore for file there okay now no more analyzer complaints let's save that come back to this test now two pi is resolved line needs to become s dot line and then we need to actually pass in offsets for this instead of just a bunch of properties or a bunch of arguments i should say and then can i make that a double okay now everything compiles and the question is will this golden file look more or less like the tangent example here let's find out flutter test update golden's plane name equals tangent and this is going to be test math trigonometry test well it says it was successful but where are the goldens there they are okay well once again we have issues with specifics around how lines are rendered essentially um clearly it's not as precise with what we're getting out of flutter versus what we get here from processing that's not a problem related i don't think to what we're doing here this is a recurring issue maybe at some point i'll figure out there's a flag that we can pass that gets us slightly more accurate rendering or changes the anti-aliasing logic or whatever it is that's causing this this problem for us nonetheless what you can see definitely is the same waveform so as far as i'm concerned that's a successful test let's see what else we have here here is sign so let's test sine call the file sign call the test sign copy the code over a is double increment is double gonna rename you to increment also a is for angle and its angle in radians there are no extra points here for avoiding variable names that make sense angle whoops angle in radians and then i we're going to make into a double so that we can say offset the starting offset of the line the ending offset of the line save that and now we're going to run the test again except this time we're going to run sign and there's sign and now this time the spacing worked out for whatever reason i guess that i guess more space fewer lines are being drawn so there's more space between them but there we go that's sine what else do we have here here's cosine let's implement that one change the name of the test to cosine change the name well name of the file and then the name of the test both to cosine now let's copy this code angle you're a double you're a double increment s dot two pi blank line to match the others change i to a double s dot line offset and offset save run the test and there's cosine which matches pretty much what we're seeing there close enough okay do we have any other visuals no okay well let's wipe these out let's get rid of all these tabs to make some space we've implemented these and the ones that have visual tests we have tested visually now interestingly tau itself seems to have a test so let's test that but let's also see if any of the other constants have visual tests for some reason and they do actually these are all the same tests these are all drawing the same thing they're using all of the constants let's test these in our test directory let's create a new package called constants and then we will create constants test let's copy our test from math we will call this constance test which is well overwrite the one we already created and now this is the group is constants there is no subgroup so i'm going to get rid of the subgroup here i'm also going to get rid of two of the three tests because we only have one golden file to draw here and this is going to be just constants is the name of the file constants is the test name although yeah i guess that's i mean as constants constants doesn't tell us much maybe it's nice to put the constant names in there but there are a number of constants let's just let's leave it like that that's fine all right let's take this code here let's copy it over you're going to be s dot width divided by 2 s dot height divided by 2 [Music] s dot width and these are all these look like these are all final i don't think they're changing here so we'll make them final and then we want oh we don't have arc that's that's going to be a problem so we actually can't write this test yet so what i'm going to do is say to do bring back when we have arc support and then we're going to comment it out so when we implement arcs whenever that happens we'll come back and make this test possible at least i think we didn't have arc right we do have arc oh okay what i was thinking of was bezier curves that's what we don't have yet we're missing bezier curves okay so false alarm we just need the parameters to be correct here so arc requires an ellipse a start angle and an end angle so what is our ellipse here so s dot arc ellipse and what are they passing in i think we want ellipse from center with radius the center is x comma y the radius radius 1 in this case is d and d again so the first one's a circle actually they're all circles they're just smaller and smaller circles so hold on we might be able to make this with less detail then ellipse from center width and height center with radius uh it's going to be the same amount of information either way start angle is going to be 0 and then quarter pi s dot quarter pi quarter pi is one of the constants that we're testing here okay so that's the first arc then the second arc has i'm passing these in as radius that's going to be a problem because these aren't the radius are they these are that's the weird thing is like well let's go see what the definition of arc is it's kind of weird that arc is taking in the diameter but maybe it is okay width and height and the width and height will be diameter so let me change this from over to center with the width and the height width height okay so that's the first ellipse the second ellipse is similar uh the diameter we have a minus 20 on the diameter and then the end angle here is half pi then we want minus 40 on the diameter and we want full pi which is half a circle and then lastly we want this tau thing we're going to go minus 60 on the diameter and then we want s dot tau okay let's save that now we're going to say the test is called constance and the file is going to be test constants test let's see what we get okay well not quite what we were expecting let's see so the question is why are we getting this the sector that's drawing way out here to the edge because i still have one incorrectly specified ellipse in fact i think i have an extra ellipse don't i i don't even think this one should be here let's try this one more time all right now we have what we're looking for so i guess tau i'm not really sure how that works then because these these first three are clearly operating on angle values but i thought tau was some kind of ratio this constant relating to the circumference of a circle to its linear dimension well whatever [Music] i guess the question is what's the difference between tau and two pi i don't know here's the value for two pi eight three one eight five five go back to tau six point two eight three one eight five five they're literally the same value so i guess they're just domain i guess tau has a domain specific meaning in mathematics and it happens to be equivalent to two pi which is the a full rotation around a circle okay let's close all that down where are we now i said today we're going to try to get all of math so you've seen how we're approaching this now let's see if we can power through the last subcategory so we're not going to do bitwise operations those are literally baked in to the dart number manipulation system we're not going to do operators for the same reason i think p vector maybe i'll come back in another video and do p vector probably a little bit too much for us today but i think calculation we can do so i'm going to try to select all of these if i can copy those let's come back in here let's come back up to our math directory and let's create calculations class sketch calculations i'm going to paste these in here absolute value is going to return a double from a num i think ceiling is a double from a num again a number could be either a double a floating point or an integer constrain i don't know what the api is on that let's see constrain the value minimum maximum so it maps to clamp let's go ahead and just implement these as we go return value dot absolute value is that only defined on doubles let's return a num return value dot ceiling you will return an integer because if you are calling ceiling in concept what you are doing is saying give me the integer which is higher but closest to my current value so it is inherently an integer though you can cast it back to a double if you want here for constrain we will say we will return a num and we will take in a num value a num min and a num max and we will return value.clamp min max dist let's go see what's up with dist calculates the distance between two points okay well in this area i'm going to keep things i think actually well i was going to say keep it the same way processing has it but we can't represent both of these at the same time so i think we're going to have to go [Music] with offsets for now let's just support let's see what we want to do we'll return a num and we will take in 0.1 and 0.2 we will return let's see we want to import dart ui sure p2 minus p1 dot distance let me see distance between two points this order shouldn't matter i guess because distance is going to uh to take a positive it's going to always be positive all right x let's see what we're doing with exponents here returns euler's number raised to the power of n so it's e to the n is what this means i guess technically we can return a double here because there's no way this evaluates to something other than a double and we will take an int n and we will return i don't know if e is defined i guess it is um and there is there a pow see power e to the n i think is probably what we want let's see what this says oh no that's that's our power okay we to avoid name conflicts we need to call this math this will be math.e and math.power i guess that returns a num so we should too returns x to the power of exponent so this should be e and this should be our exponent now what to complaining about i guess we can call that a num okay then we're good all right so that's exponent e to the whatever floor we can return an integer floor is essentially the opposite of ceiling lerp stands for linear interpolation but let's see what the specific arguments or parameters should be for this start stop amount so between these two values we're going to apply that percent i think we can return a num from start and num percent and we will return uh okay actually we don't want to return a num here because what we want is double dot or sorry lerp double start end percent which means we need to return a double and for some reason this returns an unknowable type why are you nullable i'm just going to assume that it's non-null because there are weird cases where that's a complaint okay and apparently percent needs to be a double logarithm calculates the natural log of the given value so we will return a num we will take in a num which is n we will return math dot this is this is natural log right natural logarithm of two i think that's what we want oh that's that's a sorry that's a value what do we have in terms of methods okay here so i guess same name then magnitude calculates the magnitude of a vector so we will return a num i think we'll see if that works out we will take int x into y and then optional int z now if it's just x and y then all we need is uh we can just use an offset and ask for the distance which is similar to what we have up above with z i don't remember what we want to do to the math to get the distance on three dimensions [Music] just add one more piece to the equation so we can return math dot square root of uh now this is so this formula is between two points x2 x1 y2 y1 z2 z1 distance if we're asking what is the distance of a of a vector the second point is just 0 0 or zero zero zero so it's x minus zero y minus zero z minus zero and so what we can say is math.power x 2 so this is x squared x minus 0 squared is x squared plus math.power y minus 0 squared is the same thing as y squared and then we will say math.power what we will do here actually is we will say equal to zero by default so we will say z to and then that should be should be the distance of a two or three dimensional vector or point from the origin all right what are we mapping in map remaps a number from from one range to another which is essentially what linear interpolation does by the way in the first example above the number 25 is converted from a value in the range 0 to 100. all right here's what we're going to do there may be a there may be a a more efficient way to do this than what i'm about to do but i think what i have in mind will work fine so we're going to say value start one oh we'll say uh domain start and these don't need to be ins double value double domain start or perhaps domain min double domain max double [Music] range min double range max and then what we can say is percent uh sorry let me think here percent is domain max minus domain min it's going to be value divided by that that's the percentage between the min and the max and then we can return the linear interpolation of range min range max with the percent that we just calculated i think that should work probably should write some tests for some of these but i'm not going to today maybe some other time max let's confirm what this means first number second number third number or a list okay well the question here challenge here is how do we do the best we can to replicate this knowing that we can't overload methods for handling two or three parameters that's straightforward we can just make c optional but then there's no way to handle the list i think i'll just create a second method called max list or max in list so first we'll have max and it will take in a b and then these should be nums again [Music] optional c and then let's see i don't know what the most concise way is to get the max and we there is already a max a math dot max between a and b actually we say return c is not equal to null we'll return the max we just calculated otherwise we will say math max and c oops i have that backwards okay and then we can say max in list and we can take a list of num [Music] and here what we are going to do is fold we're going to say list i think it's fold initial value we can say list dot first what fold does is it runs a function for every single item in a list and it tells you some previous value that you're holding on to and reports the new value and for us we just want to go down the list and remember the largest value so we're going to return max between let's call this one previous max so we want the max between the previous max and the new value and what we get out the other side will be the max and here i'm going to put assert list is not empty because it makes no sense for you to ask for the max in a list where there are no values because then there is no max min let's kind of do the same thing for men here min rename this to min math dot min math dot min min in list we want this to be previous min and then we want math.min okay norm is going to be some kind of normalize or normal let's go c normalizes a number from another range into a valid value between zero and one identical to calling map value low high zero one well then that's exactly how we're going to implement it returns a num takes in what is it three parameters value start stop num value num start num stop and we're going to return map value start stop zero one let's see did these did i say those had to be doubles that one doesn't have to be a double that one doesn't have to be a double i don't think any of these had to be doubles all right now norm is implemented now let's look at pow for power base of the exponential expression power by which to raise the base so we're going to say so it's going to return a num and we're going to say num base num exponent i'm not calling it e because i don't want to confuse the actual number e in mathematics in fact let's go all the way to exponent all right round will return an integer because rounding inherently takes one value and round rounds it to the nearest integer we return value dot round and then what's the difference between sk and square root so this a square is a number okay [Music] all right and then square root um i guess there are some is if you're if you are already a square of something then you might be an integer when you're returned so we can return a num and we will return math dot square root of value all right save and that is all of the calculations now did we mix that in yet sketch calculations now we have three mix-ins we have the mathematical constants the mathematical calculations and the trigonometry now you can see how we are composing not in the widget tree sense not in the run time composition sense but at compile time we are composing our definition for a sketch and eventually we're going to break down a bunch of this nonsense into pieces that we bring as mix-ins as well it's going to get a little more complicated with some of those but we've now gotten rid of all of these math apis let me see if i can close all of these close that whole group i think p vector will come back and do in a dedicated video because there's a bit more to it but beyond that what else am i what else am i thinking about here in terms of categories and then i can't remember which category i have scheduled for the next video but uh gee i can't remember now i don't know there's one or two other major categories here that we can essentially do the same thing and we will because we can knock those out quickly like we did today and they're done don't have to worry about them anymore so i think we have one to two more videos where we do this same kind of thing then after that we're going to refactor we're going to break down our core definition into many pieces we're going to figure out we're going to talk about defining a kind of a kind of base painting context that will allow us to define some of those painting related behaviors on top of it so that we can break it apart and then what we'll do is probably put together a contributing guide for the repository we might expand the readme file a little bit we'll clean up some of the testing tools so that it's easier to write some of these tests and then the project is kind of ready for other people to get involved and at that point the videos coming out after that will be mostly around hopefully creative coding actually using this thing for coding train coding challenges as well as various projects of my own um so that's what's coming in the future i hope you learned something today i hope you see the direction that we're moving i hope you're getting excited for us kind of almost being at the mvp milestone for this project i'll see you in the next video [Music] you
Info
Channel: SuperDeclarative!
Views: 411
Rating: undefined out of 5
Keywords: flutter, widgets, mobile-apps, web-apps
Id: FVAH77JOT6Y
Channel Id: undefined
Length: 60min 5sec (3605 seconds)
Published: Thu Jul 29 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.