It looks like you're new here. If you want to get involved, click one of these buttons!

I’ve been trying to understand the “test edges and chains“ example in PhysicsLab.

I tried to pick the code apart and explicate the variables, but I’m not sure I did it right:

-- test edges & chains
local points = {}
local overallY = WIDTH * 0.08
local peaksMultiple = WIDTH * 0.00003
local waveHeight = HEIGHT * 0.025
local segmentLength = WIDTH/150
for i = 0, WIDTH, segmentLength do
table.insert(points, vec2(i,(math.sin(i*peaksMultiple) * waveHeight) + overallY))
end
local ground = physics.body(CHAIN, false, table.unpack(points))
self.lab:addBody(ground)

What I would like to do is create a gently sloping curve, just one, with its peak in the middle of the screen, kind of like the curve in the attached picture.

I’ve been able to make that happen on a single device in a single orientation, just by fiddling around with the variables until it looked right, but I can’t figure out how to do it on any device in any orientation.

## Comments

@UberGoober You can start with this.

@dave1707 thanks, that gave me what I needed to figure this out.

The adapted version below shows the solution I needed.

In the screen shots you can see that, in portrait mode, both waves look the same, because they both use the same height and step values—but the difference is that the top one is using hard-coded values and the bottom one is calculating those values relative to screen width.

That’s why (I think) in landscape mode the curves look different. The hard-coded values result in a different width-to-height ratio for some reason.

But the lower curve keeps the same ratio as in portrait because (I think) it uses a ratio to calculate its dimensions to begin with.

if you can draw it from, say, x=0 to x-n, you can scale by desired/n to get it 0-desired. you can translate (x,y) to get it to start at x,y. you can rotate to get it to any desired angle. don't forget to push and pop the matrix.

@UberGoober I guess that would depend on how much of the sine curve you want between the 2 points. In my example above, you can adjust the curve so the right side of the curve would pass through some point on the right side of the screen.

@RonJeffries I am working with Physics bodies, and

`translate`

easily changes where something is drawn (like in your article), but with Physics bodies I need to change where it actually is.The equivalent of using translate, I guess, would be to make the wave horizontally, like normal, move its origin to the midpoint of the desired points, and then change its angle so each end touches the desired points—that’s a lot of math, though, and if there’s a way to just directly calculate the same points using

`math.sin`

that would be better, I think.@dave1707 I’m trying to write a method along the lines of

`makeWaveBetweenPoints(pointA, pointB, numPeaks, heightOfPeaks)`

so I need to control start point, end point, and the wave properties separately.I’ve found this formula on Stack Overflow:

Which looks like this: https://www.wolframalpha.com/input/?i=ParametricPlot[{t/Sqrt[2]+-+Sin[t]/Sqrt[2],+t/Sqrt[2]+++Sin[t]/Sqrt[2]},{t,-10,10}]

…I’m trying to figure out how to apply it….

@UberGoober Try this for starters.

@dave1707 that’s fantastic! I’ve been playing with that formula I found for hours and I’ve been getting only hideous results.

@dave1707 ok I think this does everything I need, though I’m not sure my modifications are done in the best way:

In particular the fact that I’m using the decimal 0.0027 as a multiplier in

`calculateSizeFromLastTouch`

seems completely arbitrary.There must be a way to make that calculation based only on known quantities.

!!!This is functionally exactly the same code as above, except I attempted to actually use it to create CHAIN-type physics bodies.

It seems to work fine… except it

crashes Codeareally quickly.—any idea why??

ok, but why do the math for yourself when codea will do it for you?

@RonJeffries not sure what you mean—there’s math I gotta do either way, right?

I have to calculate the sine wave either way, Codea won’t do that, and then to rotate it into the right position I have to manually calculate the midpoint between the target points, and calculate the angle, and yadda yadda yadda.

But the separation of the creation and placement of the physics body is kind of weird, to me, in that it seems odd to open myself to an opportunity for a whole separate category of errors—errors rooted in creating the thing separately from placing it.

I have to do the sine calculations no matter what (don’t I?) so why add an extra layer of opportunities for failure when I could just do all the calculations in the same formula that calculates the wave?

@John, @Simeon, I think this may be a bug in 2D physics CHAIN handling.

This code boils it down: all it takes to cause a crash is to put your finger down anywhere and then drag it towards the start of the curve—at least, that’s what’s been crashing my iPad twenty times an hour this evening.

The reason I think it’s a bug is that if you make the body a POLYGON instead of a CHAIN the crash does not happen—which makes it seem likely there’s something going wrong with CHAINs.

I think the reason is that CHAIN can’t handle duplicate points in a row. Run this code and drag your finger on the screen. When cnt reaches 80, I create a duplicate occurrence in the table tab. As long as you don’t exceed 80 it doesn’t crash. When you lift your finger, I create a chain.

@dave1707 your example looks solid, what’s wrong with mine, below?

I’m trying to detect duplicate points and discard them, but it still crashes.

Am I doing it wrong?

Here's an article I wrote on using the translate, rotate, and scale capabilities of Codea to draw a sine wave at various sizes and angles. It's not solving the problem here, but the techniques are those I would use to solve this one too.

Note that it only calculates the curve once, in setup.

Questions welcome. Code follows.

Article: The Sines of the Fathers

I see the thread name changed. Confused me

I'm not sure how one would do the same thing with physics, certainly not with the screen functions. Different problem, different tools. Sorry for any confusion, HTH as always.

@UberGoober You only need to check the current set of points with the last set of points. There can be duplicate points, just not 2 in a row. I don’t know if CHAIN subtracts the last 2 sets of points and if it’s 0 then it crashes.

@UberGoober Not sure why yours is crashing. Maybe there’s something else that’s happening that we don’t see.

@dave1707 can you explain easily how you got those equations? thanks!

i changed @UberGoober 's to just check the last (prev) element, still crashes. no idea why yet.

@RonJeffries Read your latest article, The Sines of the Father. You mentioned that nobody wanted to use the translate, rotate, and scale functions. Using those functions would be an easy way to draw a sine curve of any size and angle. I think you missed what was needed. @UberGoober wanted a sine curve of any size and angle to create a physics CHAIN object of the sine curve. To create the CHAIN, a table of points are needed. To create the table, the points of the sine curve had to be calculated based on the size and angle of the sine curve. So each time the angle or size was changed, a new table was needed. Using the translate, rotate, and scale functions only altered what was being drawn and not the actual points.

@RonJeffries Just saw your question. That appeared while I was writing the above post. Anyways, I did a Google search for rotating a point around the origin. I’ll see if I can find the page I found.

.0027 is about 1/360. (370 really) so i think it's compensating for the width scale somehow.

@RonJeffries That didn’t take long, first try. Here’s the link.

yes, i missed the chain thing. still no idea why it crashes. i'll see if i can come up with anything interesting.

@RonJeffries I would calculate the points for the sine curve along the x axis. For each point I would then recalculate the rotated point based on the angle. That would give me a table for the CHAIN function and for drawing the curve.

this is equivalent to @UberGoober 's (and still crashes). Just showing relevant bits in context.

mine also calcs sin on x axis, then rotates, then translates to 300,300.

@RonJeffries Let me play with your code. It might do the exact same thing mine did. If that’s the case then I didn’t need those 2 calculations.

With this iteration I think I have exactly what I need.

@RonJeffries, turns out you’re exactly right—360 is the key number.

This uses POLYGON instead of CHAIN to avoid the crash.

@RonJeffries In your rotate function below, you’re converting ang to radians. The rotate command uses degrees, not radians.

PS. The documentation says rotate uses degrees, but it looks like it really uses radians, so your calculation is correct.

@Simeon Something is wrong with trying to copy code from the forum. Sometimes I can’t even select code, other times I can select some code but when I try to expand to highlighted copy area, as soon as I move the drag icon, the screen just scrolls halfway up the discussion over several posts and I can’t copy anything.

vec2 rotate takes radians. screen rotate takes degrees. codea is weird.

i'm sure it does same as yours. could be wrong, but i'd bet a coke.

@RonJeffries I don’t like it when something similar takes different arguments. I tried some calculations and the rotate was the same as the 2 calculations I was using. I totally forgot about the vec2 rotate and when I did the Google search and found the 2 simple calculations on the first web page, I just used them. It’s amazing how much stuff I forget until someone reminds me about them.

just messing around to understand, i might do this. not entirely happy with the remake flag, but don't see anything nicer.

at my real keyboard i might try computing the wave just once, but i think there's little reason to do it other than just because, even if i can.

no reason to make points up top, it turns out.

@dave1707 yes, i think it's a mistake. don't know if it's unique to codea, or in lua. suspect the former, but i think we're stuck with it.