This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
Lisn87's profile picture

[Solved]Little help with coding and maybe math, i'm building half spheres

Started by Lisn87, 15 April 2016 - 10:42 PM
Lisn87 #1
Posted 16 April 2016 - 12:42 AM
Hi guys,

I'm trying to write a program for building half spheres (eventually spheres) with different dimensions, using the equation x^2 + y^2 + z^2 = r^2 (the center of the sphere is always consider (0,0,0)).

So this is what i got so far: http://pastebin.com/ppH53JN9

It's kinda a mess i know, but i'm not an expert at coding. And i'm not very good at math too, so…
Basically the turtle goes forward and backward, passing every combination of x,y and z coordinates and when the equation is true it places a block. Everything works, kinda.

My first attempt was with the function sphere():

function sphere()
realz = z + 1
equation1 = x^2 + y^2 + z^2
equation2 = radius^2
if equation1 == equation2 then
  return true
else
  return false
end
end

and this was the result: http://imgur.com/hydQfDb
The shape is there, but too much empty space :( i figured the problem was that i was working only with integers so i add decimals left and right and i wrote the function sphere2()


function sphere2()
minx = math.abs(x) - 0.5
maxx = math.abs(x) + 0.5
miny = math.abs(y) - 0.5
maxy = math.abs(y) + 0.5
minz = math.abs(z) - 0.5
maxz = math.abs(z) + 0.5
minr = radius - 0.5
maxr = radius + 0.5
for ix = minx,maxx,0.1  do
  for iy = miny,maxy,0.1 do
	for iz = minz,maxz,0.1 do
	  for ir = minr,maxr,0.1 do
		equation1 = ix^2 + iy^2 + iz^2
		equation2 = ir^2
		if equation1 == equation2 then
		  return true
		end
	  end
	end			  
  end
end
end

trying to make the program check at intervals of 0.1 between x -0.5 and +0.5, y - 0.5 an +0.5 etc… with a mess of for loops because why not. And the result: http://imgur.com/6IiJEBm

Closer, but still full of holes.

and with increments of 0.05: http://imgur.com/OdQ4F2E i kinda got a negative version of the last one.

I tried increments of 0.01 but my turtle just stopped working, probably for the crazy amount of cycles it went through.

So questions: Is it even possible to build a half sphere like this in minecraft using an equation that usually draws points and not 1*1*1 m cubes? Is there something i can change in the code to get better results or should I change my approach? Is there a smarter way to do my function without 4 loops in a row? Is my math completely wrong like I think it is? Thank you guys in advance :P

P.S. I know there are a couple of dome builder program around the interwebz, but i kinda want to write the code by myself
Edited on 17 April 2016 - 07:28 AM
KingofGamesYami #2
Posted 16 April 2016 - 03:41 AM
Instead of checking whether the equations are equal, check if they are close (+-0.5 should do it).

Ex:


if math.abs( equation1 - equation2 ) < 0.5 then
  --#place block

With this, you should also be able to increment by 1, not 0.1.

This is untested
Edited on 16 April 2016 - 01:41 AM
Lisn87 #3
Posted 16 April 2016 - 10:44 AM
Hey thanks for your answer :D
I like your idea about checking if they are close and not only equal.

I don't understand what you mean when you say i can use increments of 1 though.
maybe i'm really really wrong, but i think the issue is that since i'm using turtle movements to increment/decrement coordinates, if i use integers, the program is always gonna check only the exact center of the minecraft block and not the space around it. I don't know if I explained myself correctly (english is hard D:). So i need to use the decimals around the integer (+/- 0.5)… probably.

But… with my new "knowledge" i start to mess with increments for the 4 loops and with how close the 2 equation variable should be.

With increments of 0.1 and math.abs(equation1 - equation2) < 0.5 –> http://imgur.com/LlSUbb5
Really thick, but hey, holes are gone.

With increments of 0.1 and math.abs(equation1 - equation2) < 0.01 –> http://imgur.com/nS4jl2r
Still too thick

With increments of 0.5 and math.abs(equation1 - equation2) < 0.5 –> http://imgur.com/sUoaHWY
Again still too thick but with a better shape

With increments of 0.5 and math.abs(equation1 - equation2) < 0.1 –> http://imgur.com/wU7nsME
This is more art than analytic geometry :D

With increments of 0.2 and math.abs(equation1 - equation2) < 0.1 –> http://imgur.com/uj8nE7P
This is very close, it has still a lot of extra blocks but i'm really close

With increments of 0.2 and math.abs(equation1 - equation2) < 0.01
No blocks were placed

With increments of 0.2 and math.abs(equation1 - equation2) < 0.05 –> http://imgur.com/BU3xnHb
Now it's more thin than before, but the shape it's kinda strange

I want to thank the mod author because this is a lot of fun :P
Anyway I think i'm close, I just hope i'm not just hitting a "you can only use blocks" limitation.
Bomb Bloke #4
Posted 16 April 2016 - 01:39 PM
So questions: Is it even possible to build a half sphere like this in minecraft using an equation that usually draws points and not 1*1*1 m cubes?

Yes: and remember, your very screen is a collection of pixels, much the same as the collection of blocks in a Minecraft world. That fact actually leads to the answer as to how best to do things.

Consider: for a given y, there are a number of x/z points that outline a circle (one set per vertical layer), which you can calculate by figuring angles throughout the range of 360 degrees. So what if you take that equation, and solve it for x? Then you can feed in integral values for z, and plot your circles without gaps.

It may help to first write the code to draw an eighth of your sphere, and then mirror that a few times that to create the rest of it.
Lisn87 #5
Posted 16 April 2016 - 05:40 PM
Consider: for a given y, there are a number of x/z points that outline a circle (one set per vertical layer), which you can calculate by figuring angles throughout the range of 360 degrees. So what if you take that equation, and solve it for x? Then you can feed in integral values for z, and plot your circles without gaps.

Thanks for the answer :D/>
I really don't know how to work with angles in lua and since i'm very very rusty in math i can't figure out how to calculate angles using cos, sen etc
But since i had a perfectly working equation at my disposal, i used y^2 = radius^2 - x^2 - z^2 for any given radius (constant), x coord and z coord (z is the vertical axis because i'm a rebel like that) and all of them except for y is an integer number. So i wrote this:

function sphere4()
 
  if radius^2 - x^2 - z^2 == 0 then
    realY = 0
  else
    realY = math.sqrt(radius^2 - x^2 - z^2)
  end
  print(realY.." "..y)
  turtleY = math.abs(y)
  if math.abs(turtleY - realY) <= 0.5 then
    return true
  end
end

basically calculating the real y of every circle and check if the y coordinate of my turtle is close enough (+/- 0.5).
I had to add the if statement at the beginning because math.sqrt was returning NAN when (radius^2 - x^2 - z^2) was equal to zero.

result: http://imgur.com/XKrDMxA
green is the x axis, blue is the y axis and red is the z axis.

So now is skipping blocks between coord y = +/- 2 and i really don't know why. Probably again my math was wrong somewhere.
Lisn87 #6
Posted 16 April 2016 - 08:15 PM
It's Alive!!

I made it works, I made the program check the 3 coordinates instead of only y coord and it work like a charm.
Spoiler

function sphere4()

  if radius^2 - x^2 - z^2 == 0 then
	realY = 0
  else
	realY = math.sqrt(radius^2 - x^2 - z^2)
  end
  turtleY = math.abs(y)
  if math.abs(turtleY - realY) <= 0.5 then
	return true
  end
  
if radius^2 - y^2 - z^2 == 0 then
	realX = 0
  else
	realX = math.sqrt(radius^2 - y^2 - z^2)
  end
  turtleX = math.abs(x)
  if math.abs(turtleX - realX) <= 0.5 then
	return true
  end

  if radius^2 - x^2 - y^2 == 0 then
	realZ = 0
  else
	realZ = math.sqrt(radius^2 - x^2 - y^2)
  end
  turtleZ = math.abs(z)
  if math.abs(turtleZ - realZ) <= 0.5 then
	return true
  end

end

Probably not the most efficient way of solving the problem, but it does the job. I'm testing it right now on a bigger radius to make sure.

Thank you very much guys for all the help! :P

Just a little last question, then i'm gonna put the solved tag.
In the same program i put another function:

function cube()
  r = radius
   if math.abs(x) == r then
	return true
  elseif math.abs(y) == r then
	return true
  elseif math.abs(z) == r then
	return true
  else
	return false
  end
end
I figured that if a place a block every time anyone of the coordinates is equal to the radius, it's gonna build a cube.
This function doesn't work, it never returns true, unless i put r = math.abs(radius), then it works.
I don't understand why, since radius is the argument i put when i launch the program and it is always positive and it remains constant, since i don't do any operations with it.
Just a bit curios about why it does that, if anyone has the time to explain.
Then i'm gonna stop bothering you, I swear :D

Thank you again guys!
Edited on 16 April 2016 - 06:54 PM
Bomb Bloke #7
Posted 17 April 2016 - 12:36 AM
Up the top of your paste, you're doing this:

radius = arg[1]

The args passed to the script always come in the form of strings. In many cases, Lua will let you treat strings as numbers so long as their content represents a number:

local myVal = "2"
print(type(myVal))  --> "string"
print(type(math.abs(myVal)))  --> "number"

… but comparisons aren't one of those times, so you'd be better off converting to a number from the beginning:

radius = tonumber(arg[1])
Lisn87 #8
Posted 17 April 2016 - 09:27 AM
The args passed to the script always come in the form of strings. In many cases, Lua will let you treat strings as numbers so long as their content represents a number:

Oh i didn't know that lua can use strings as a number. I was very confused because even simple stuff like r = radius - 1 were working. the more you know.
Thanks
Edited on 17 April 2016 - 07:29 AM