ANALYSIS OF THE SLIDING OF A BODY DOWN AN INCLINED PLANE - AN EXAMPLE IN PROCESSING
An example should look like the animation below:
Moving body trough inclined plaine
Animacija ne radi? Učitajte stranicu ponovo(refresh)
← scroll horizontal →
To the previously described basic animation of a body sliding down an inclined plane, where the user can only observe and not influence the animation, the possibility has now been added that by moving the square at the top of the inclined plane, the height of the inclined plane can be increased or decreased, thereby also changing the angle of inclination . The following functionalities have also been added: the possibility of resetting for the desktop and mobile variant, as well as the display of basic sizes by drawing text on the screen. In order to incorporate the animation into the web page, a javascript code was added that improves the functionality. The code that is described in the basic version of the animation has been rearranged for translation into javascript using the javascript file: processing.js .
Description for using the displayed animation:
1) Selecting and deselecting squares. By clicking the mouse (mouseClick event) or pressing the finger (touchStart event) on the square in the corner of the steep plane, it becomes selected and is then colored red. Clicking anywhere on the animation, outside of the square, will deselect it.
2) Moving the squares (changing the height of the inclined plane). After selection, the box can be moved in several ways depending on the device: On a desktop computer or tablet, if a mouse is used, it can be dragged (mouseDragged) along the Y axis and change the position and thus the height of the inclined plane, or once click above or below the previous square position. If keyboard operation is supported, clicking the UP or DOWN arrows can also change the height of H, the inclined plane.
On mobile devices and tablets, the square can be moved after selection with the finger (touchMove event).
As the position of the square changes, the height H of the inclined plane changes, as does the slope. In the default position, for defined sizes:
2) Moving the squares (changing the height of the inclined plane). After selection, the box can be moved in several ways depending on the device: On a desktop computer or tablet, if a mouse is used, it can be dragged (mouseDragged) along the Y axis and change the position and thus the height of the inclined plane, or once click above or below the previous square position. If keyboard operation is supported, clicking the UP or DOWN arrows can also change the height of H, the inclined plane.
On mobile devices and tablets, the square can be moved after selection with the finger (touchMove event).
As the position of the square changes, the height H of the inclined plane changes, as does the slope. In the default position, for defined sizes:
Ftr = μ * N;
gde je
coefficient of friction μ = 0,2 i
mass m = 1kg
friction force Ftr = μ * N;
does not allow the body to move, because for the initial angle of α = 4,o
obtained by the formula
α = atan(H/L);
the force of gravity along the inclined plane is not large enough to overcome the force of friction
By increasing the height of the inclined plane, the intensity of this component of the force of gravity (weight of the body) also changes, so that at some point it will become greater than the force of friction and then the body will begin to slide down the inclined plane. So, the condition under which sliding occurs is:
Fa >= Ftr,
gde je Fa component of the force of gravity along an inclined plane
gde je Fa component of the force of gravity along an inclined plane
3) Reset. The animation can be reset either by clicking the 'r' button on the keyboard (desktop and tablet), or by double-clicking the animation with your finger (mobile devices and tablets). On reset, the sizes will return to their initial values and the plotting loop will restart, but the height of the plane will remain as it was last changed. To recall, when the body descends to the limit position at the bottom of the inclined plane, the loop stops.
4) Printing the text. In order to draw text, it is first necessary to create a font f(PFont). Then the textFont(f) method (from the basic processing library) should be used to set the previously created font, passing it as a parameter to the textFont() method. In the end, printing is also done using the processing method text(textForPrinting, x,y) , where the text to be printed and the position of that text on the screen, given by the sent coordinates x and y, are passed as parameters.
4) Printing the text. In order to draw text, it is first necessary to create a font f(PFont). Then the textFont(f) method (from the basic processing library) should be used to set the previously created font, passing it as a parameter to the textFont() method. In the end, printing is also done using the processing method text(textForPrinting, x,y) , where the text to be printed and the position of that text on the screen, given by the sent coordinates x and y, are passed as parameters.
Code analysis
Since the PShape object and everything related to drawing shapes in this way is not supported in javascript, this had to be done in another way, which will be shown in the following images. The old code is only commented out so that it can be distinguished with the new code. In the case of using the application on desktop computers, PShape can be used. Let's first look at the changes in the SlidingBody class, which are shown in the image below:
We see that the body object declared as PShape is commented out, because as already mentioned, this code will be uploaded to the website and compiled there as javascript, and PShape is not supported in that case, Instead the body will be created using beginShape() - vertex - endShape(). How to create your own (custom) shape object, read on the page:
processing.org/reference/beginShape_.html
processing.org/reference/beginShape_.html
In the main part of scatch the variables are declared: angle of inclination of the inclined plane fi, vectors of position, velocity v, acceleration a, component of the force of the weight of the body along the inclined plane Tx, Normal force with which the body acts on the base N, resultant force Fr, mass m and coefficient friction. In the constructor, vectors are created to the end and initial values are set with components whose intensities are equal to zero.
.
.
Inside the forces() method, the force vectors that affect the body's motion are created. The following are defined: Tx - force component in the x direction, i.e. in the direction parallel to the inclined plane, the reaction of the substrate N, the friction force tr and at the end of the resultant Fr. The friction force has the direction of the velocity vector, therefore it is first created based on that vector. The function normalize() reduces that vector to unit. Then the scalar vector is multiplied by the -1 function mult, because it has the direction opposite to the direction of the velocity vector. Finally, it is multiplied by the intensity, which is calculated as the product of the coefficient of friction and the intensity of the normal force on the surface. You can read more about vectors and functions of the PVector class on the page: Vectors in Processing
The resultant force Fr is calculated, when the condition that the body starts to move is met, and this will happen when the component of the friction force in the x direction becomes greater than the friction force Tx.mag()>frictionInt
In the continuation of the SlidingBody class, 3 more methods can be seen in Figure 3: move(), render() and reset().
The move() method defines changes in acceleration, velocity and position of the body between two calls to the draw() method, i.e. every 1/NUMBER_OF_FRAMES seconds.
The change in acceleration is caused by the change in the resultant force, which causes this acceleration: a=PVector.div(Fr/m) i.e. (a=Fr/m - 2nd Newton's law).
Since the measurements are in px and not in meters, scale is used to make the animation more realistic.
A change in acceleration further causes a change in velocity, and a change in velocity causes a further change in position, the calculation of which can be seen in the continuation of the move() method.
the boundaryConditions() method has not been changed in relation to the basic variant of the task.
The reset() method returns the physical sizes to their initial values, as they were defined in the constructor.
The main part of scatch can be seen in Figures 4-11.
The move() method defines changes in acceleration, velocity and position of the body between two calls to the draw() method, i.e. every 1/NUMBER_OF_FRAMES seconds.
The change in acceleration is caused by the change in the resultant force, which causes this acceleration: a=PVector.div(Fr/m) i.e. (a=Fr/m - 2nd Newton's law).
Since the measurements are in px and not in meters, scale is used to make the animation more realistic.
A change in acceleration further causes a change in velocity, and a change in velocity causes a further change in position, the calculation of which can be seen in the continuation of the move() method.
the boundaryConditions() method has not been changed in relation to the basic variant of the task.
The reset() method returns the physical sizes to their initial values, as they were defined in the constructor.
The main part of scatch can be seen in Figures 4-11.
And here the objects that in the basic version were created as PShape objects (commented out), are now created with beginShape() and endShape(). They are objects that represent the ground and the square (M) with which the height of the steep plane is changed. Other variables that are declared as global are respectively: the height of the slope of the plane H, the length of the inclined plane L (H and L are the legs of the right triangle that represents the inclined plane colored in green in the animation, while the plane itself is the hypotenuse of the triangle).
They are further defined: angle of inclination-angle (error, this line should be deleted), sliding body-slidingBody, w and h are the width and height of the body, fi-angle of inclination of the inclined plane in radians.
The logical variables stop and pressed tell about whether the body has reached the bottom of the inclined plane and the animation is stopped, while the variable pressed refers to the selection of the control point (square M), whether it is selected or not. Once selected, it can be moved by dragging the mouse, up or down, thereby increasing or decreasing the height of the inclined plane.
The constants G, SCALE and NUMBER_OF_FRAMES define the gravity constant, scale(px/m) and the number of frames per second, respectively.
The variables f, event and pY are also defined. The variable f is used to define the font to print the text on the screen. The string variable event displays the type of event (eg mouseClick), which is displayed as text on the animation (see below in Figure 6).
The variable pY stores the previous value for the Y coordinate of the position of the control point M.
Figure 4 shows part of the setup() method. This part is explained in the basic version of the animation.
They are further defined: angle of inclination-angle (error, this line should be deleted), sliding body-slidingBody, w and h are the width and height of the body, fi-angle of inclination of the inclined plane in radians.
The logical variables stop and pressed tell about whether the body has reached the bottom of the inclined plane and the animation is stopped, while the variable pressed refers to the selection of the control point (square M), whether it is selected or not. Once selected, it can be moved by dragging the mouse, up or down, thereby increasing or decreasing the height of the inclined plane.
The constants G, SCALE and NUMBER_OF_FRAMES define the gravity constant, scale(px/m) and the number of frames per second, respectively.
The variables f, event and pY are also defined. The variable f is used to define the font to print the text on the screen. The string variable event displays the type of event (eg mouseClick), which is displayed as text on the animation (see below in Figure 6).
The variable pY stores the previous value for the Y coordinate of the position of the control point M.
Figure 4 shows part of the setup() method. This part is explained in the basic version of the animation.
Below, Figure 5 shows the complete setup() and part of the draw() method. Here we also see the commented out code that previously related to the ground and control square M objects. In the setup() method, after creating the body as an object of the Point class, the tiltAngle() method is called which calculates the tilt angle based on the height and length of the ground H and L.
Then the font f is created, the text for the event display is defined, and the initial value of the y coordinate where the body is located is calculated.
Inside the draw() method, after setting the background color and the fill color, the beginning of beginShape(TRIANGLE_STRIP) can be seen. This will create and plot the ground. This is further shown below (Figure 6).
Then the font f is created, the text for the event display is defined, and the initial value of the y coordinate where the body is located is calculated.
Inside the draw() method, after setting the background color and the fill color, the beginning of beginShape(TRIANGLE_STRIP) can be seen. This will create and plot the ground. This is further shown below (Figure 6).
Figure 6 shows the part of the draw() method that creates and draws the ground, as well as the control square M. For the ground, between beginShape(TRIANGLE_STRIP) and endShape(CLOSE), the fill color is defined first with the fill() method, and in this case it is it green color and then using the vertex() method lines are drawn between the points of the triangle. The coordinates of the points are defined as parameters in the call to the vertex method. The CLOSE parameter inside endShape() says that it is a closed polygon that is being drawn and in this case it is a triangle because there are only 3 points. Unlike ground for drawing squares, vertex is called 4 times between beginShape(QUAD) and endShape(CLOSE).
The indicators TRIANGLE_STRIP and QUAD indicate that the area of the triangle (ground) and square (M) is obtained by joining consecutive right triangles and squares, respectively.
Before drawing the square M, the coordinate system was translated from the upper left corner of the screen to the top of the ground, i.e. for the value height-H-h/2.
This means that the coordinates for drawing the check box points are now measured in the new coordinate system. These changes will be used to draw the square, but the state will return to the old state after that, because this code is written between pushMatrix() and popMatrix().
Read more about it in the article: processing.org/reference/pushMatrix_.html
The indicators TRIANGLE_STRIP and QUAD indicate that the area of the triangle (ground) and square (M) is obtained by joining consecutive right triangles and squares, respectively.
Before drawing the square M, the coordinate system was translated from the upper left corner of the screen to the top of the ground, i.e. for the value height-H-h/2.
This means that the coordinates for drawing the check box points are now measured in the new coordinate system. These changes will be used to draw the square, but the state will return to the old state after that, because this code is written between pushMatrix() and popMatrix().
Read more about it in the article: processing.org/reference/pushMatrix_.html
Figure 7 shows the draw() method to the end. Next, between pushMatrix() and popMatrix(), the body is prepared and drawn, as well as the axes of the current moving coordinate system that moves with the body and has a coordinate origin in the center of the body.
The preparation refers to the rotation of the coordinate system by the angle fi, and then the methods defined in the body class are called in order: forces(), move(), boundaryConditions(). These methods have been explained earlier.
Before drawing the body, by calling the render() method, the coordinate system, in addition to the previous rotation, is now additionally translated to the position above the top of the ground, at the beginning of the oblique plane, from where the body will actually start moving, i.e. to slide along that plane.
After drawing the body, the coordinate system is returned to the old one, and then the text is printed on the screen, by calls to the text() method. Using the text method and setting the font is described in the article processing.org/reference/text_.html
The preparation refers to the rotation of the coordinate system by the angle fi, and then the methods defined in the body class are called in order: forces(), move(), boundaryConditions(). These methods have been explained earlier.
Before drawing the body, by calling the render() method, the coordinate system, in addition to the previous rotation, is now additionally translated to the position above the top of the ground, at the beginning of the oblique plane, from where the body will actually start moving, i.e. to slide along that plane.
After drawing the body, the coordinate system is returned to the old one, and then the text is printed on the screen, by calls to the text() method. Using the text method and setting the font is described in the article processing.org/reference/text_.html
Finally, the value of the logical variable stop is checked. If it was previously set to true within the boundaryConditions() method, it is a sign that the body has reached the base of the steep plane and then the animation loop is stopped and the values of the physical quantities are set to their initial values, within the reset() method, which is called from here.
In the continuation of the main scatch, the keyPressed() method is defined, in which the presses on the 'r' keys are defined - to reset, UP - to increase the height of the steep plane and DOWN - to decrease the height of the inclined plane. With the change in the height of the plane H, the angle of inclination also changes, and that is why the method of the same name was called.
The mouseClicked() method is called when the mouse button is clicked on a desktop or tablet computer, or when a finger is pressed on the screen on mobile devices and tablets, unless it's set to turn off the default screen touch behavior, which is to also call mouseClicked() by default. . This can be achieved by calling evt.preventDefault(); in the javascript-part of the application, where evt is an object of the TouchEvent class.
Read more about it in the article:developer.mozilla.org/en-US/docs/Web/API/Touch_events
Read more about it in the article:developer.mozilla.org/en-US/docs/Web/API/Touch_events
Part of the javascript code will be shown at the end of this article.
The handleMove(float dH) method is called from the mentioned javascript. It changes the height of the steep plane by the dH value that is passed as a parameter to this method, and is also determined within javascript.
The handleMove(float dH) method is called from the mentioned javascript. It changes the height of the steep plane by the dH value that is passed as a parameter to this method, and is also determined within javascript.
Figure 10 shows the changeH(), setPressed() and reset() methods, which are self-explanatory. The touchStart() method is called from javascript code when the user presses their finger on the screen. The values of the parameter mx and my are the coordinates of the point on the screen that the user touched. Inside the method it is determined whether this point is inside the check box or not and accordingly sets the pressed variable to true or false.
The handleDbClick() method is a handler method that is called from javascript when the user quickly clicks 2 times in a row. and does the same as the reset() method which is called when the user presses the 'r' key on the keyboard.
The handleDbClick() method is a handler method that is called from javascript when the user quickly clicks 2 times in a row. and does the same as the reset() method which is called when the user presses the 'r' key on the keyboard.
Javascript code in the application that describes the animation of a body sliding down an inclined plane: "InclinedPlaneObject"
The Javascript code is located in the main.js file and is shown in parts in Figures 11-14.
Inside the startup() method, which is called when a part of the page is loaded and fires an event event shown in line 19 in Figure 11, the events: touchStart, touchEnd, touchCancel and touchMove are registered, which are fired when the user presses (touchStart), finish pressing a point on the screen (touchCancel), when moving the finger on the screen (touchMove) and when it ends (touchEnd).
Read more about it in the article: developer.mozilla.org/en-US/docs/Web/API/Event/defaultPrevented
The tapEvent method is called either when the user has tapped the screen once or twice quickly (double-click). If the clickTimer object is not null, it is checked whether the time between two clicks is less than 500ms (double click). If the screen is touched for the first time, this time must be greater than 500 and then a nested function will be executed in which the clickTimer object is set to null and handleStart is called which is responsible for the reaction if the screen is only touched once. In the case of a repeated touch, given that now the clickTimer is a null object, which means that it is a double-click and part of the code under else will be executed. Next, the code redirects to the handleDbClick function explained earlier.
The handleStart method receives a TouchEvent object as a parameter and checks whether the logical variable defaultPrevented is equal to true. If not, the evt.defaultPrevented() method is called, which will prevent the default behavior when touching the screen, which means that mouseClick will also be called, and when the finger is dragged, the page will scroll and the control point will not move and the mouseMove event will not be fired. Read more about it in the article: blog.mobiscroll.com/working-with-touch-events/
The handleStart method receives a TouchEvent object as a parameter and checks whether the logical variable defaultPrevented is equal to true. If not, the evt.defaultPrevented() method is called, which will prevent the default behavior when touching the screen, which means that mouseClick will also be called, and when the finger is dragged, the page will scroll and the control point will not move and the mouseMove event will not be fired. Read more about it in the article: blog.mobiscroll.com/working-with-touch-events/
Podrazumevano pozivanje događaja se može regulisati i na druge načine, pomoću osobine cancelable, što se opisuje u članku: developer.mozilla.org/en-US/docs/Web/API/Event/cancelable
Canvas element u kome se izvršava animacija tj. processing kod se dobija u redu 45 na slici 12, metodom getElementById. Zatim se u sledećem redu dobije sam id i na osnovu njega processing instanca u redu 47, pomoću koje se mogu pozivati metode definisane u scatch-u processing-a.
Pomoću objekta evt se dobije niz prethodno dodirnutih tačaka: evt.changedTouches
Koordinate tačke dodira se određuju u linijama 49 i 50.
S obzirom da je promenljiva touches niz, član niza(jedini) je touches[0], a pageX daje koordinatu x na html stranici, dok PageY daje y koordinatu u odnosu na stranicu. Canvas element može biti pomeren po x osi u odnosu na stranicu za veličinu OffsetLeft po x ili OffsetTop po y osi.
Posle izračunavanja koordinata dodira prsta u odnosu na Canvas, pomoću processing instance se poziva metoda touchStart, koja je ranije objašnjena.
Pomoću objekta evt se dobije niz prethodno dodirnutih tačaka: evt.changedTouches
Koordinate tačke dodira se određuju u linijama 49 i 50.
S obzirom da je promenljiva touches niz, član niza(jedini) je touches[0], a pageX daje koordinatu x na html stranici, dok PageY daje y koordinatu u odnosu na stranicu. Canvas element može biti pomeren po x osi u odnosu na stranicu za veličinu OffsetLeft po x ili OffsetTop po y osi.
Posle izračunavanja koordinata dodira prsta u odnosu na Canvas, pomoću processing instance se poziva metoda touchStart, koja je ranije objašnjena.
Inside the handleMove method, which will be called when the user "drags" his finger on the screen, in case the device is a tablet or mobile device, the processing instance is first "picked up" in the way already described. Then it is checked whether the pressed variable is set to true. In this case, the getter isPressed() is used for access.
If it is, the previously touched points on the canvas are taken from the event object and placed in the touches constant (line 81).
If y==0 which is the case at the beginning, the first value of the y coordinate of the check box is calculated, which is used to remember the previous position and only the y coordinate.
Below, the change in the y coordinate between the current and previous position of the check box M(dH1) is calculated.
Then that value is used as a parameter and passed to the called handleMove function defined in the application's scatch(.pde).
Processing's instance is also downloaded within the handleDbClick() method, and the function of the same name defined in the application scatch (.pde) is called via that instance.
The other shown functions colorForTouch() and copyTouch() are not used in this application and can be deleted.
If it is, the previously touched points on the canvas are taken from the event object and placed in the touches constant (line 81).
If y==0 which is the case at the beginning, the first value of the y coordinate of the check box is calculated, which is used to remember the previous position and only the y coordinate.
Below, the change in the y coordinate between the current and previous position of the check box M(dH1) is calculated.
Then that value is used as a parameter and passed to the called handleMove function defined in the application's scatch(.pde).
Processing's instance is also downloaded within the handleDbClick() method, and the function of the same name defined in the application scatch (.pde) is called via that instance.
The other shown functions colorForTouch() and copyTouch() are not used in this application and can be deleted.