Posts tagged with 'spherical'

Spherical Functions as Voxels

  • Posted on November 29, 2014 at 6:07 pm
Voxel posts

  1. Intro
  2. Cartesian Functions
  3. Spherical Functions (this post)
  4. Curve functions

To convert spherical functions into a voxel volume is a bit, but not much, more coplicated than for Cartesian functions.

In the case of Cartesian functions the key criterion was the height above the x-y plane. In the case of a spherical function, it’s the distance from the centre point of the function that we’ll need to perform the comparison on.

We define our spherical functions using angles θ and φ circumlocating this point. The angle θ represents the angle around the z-axis through the centre point of the object. The angle φ represents the elevation above the x-y plane also through the centre.
Converting to a triangulation involves stepping through θ and φ with a given step distance and calculating the radius r = f(θ, φ) for the function. This radius acts like a spine emerging from the centre at the given angle and with length r as defined by the function. These spines are used to define the vertices of the triangles that form the surface of the object.

When voxelating the volume, the question becomes one of whether a given voxel, defined by its (x, y, z) position, is inside or outside the object. We do this by considering the spine that runs between the voxel co-ordinates and the centre of the object, and calculating the θ and φ values that would apply in this case.

The contrasting nature of the two approaches shows itself here. To create triangles you have to calculate the (x, y, z) position of a triangle vertex from the θ and φ values. In both cases the θ and φ are needed to calculate the radius.

Calculating θ (rotation) and φ (elevation) values isn’t hard with a bit of trigonometry.

θ = tan-1 (y / x)

and

φ = tan-1 (z / (x2 + y2)1/2)

Here’s the code we use to do this.

fZFunc = psFuncData->fZMin + (nSlice * fZStep);
for (nX = 0; nX < nResolution; nX++) {
	fXFunc = psFuncData->fXMin + (nX * fXStep);
	for (nY = 0; nY < nResolution; nY++) {
		fYFunc = psFuncData->fYMin + (nY * fYStep);

		// Calculate the angles
		fOpposite = (fXFunc - psSphericalData->fXCentre);
		fAdjacent = (fYFunc - psSphericalData->fYCentre);
		fElevation = (fZFunc - psSphericalData->fZCentre);
		fAFunc = atan2 (fOpposite, fAdjacent);
		fDiag = sqrt ((fAdjacent * fAdjacent) + (fOpposite * fOpposite));
		fPFunc = atan2 (fElevation, fDiag);

		if (psSphericalData->psVariableA) {
			SetVariable (psSphericalData->psVariableA, fAFunc);
		}

		if (psSphericalData->psVariableP) {
			SetVariable (psSphericalData->psVariableP, fPFunc);
		}

		fRFunc = ApproximateOperation (psFuncData->psFunction);
		fDistance = sqrt ((fAdjacent * fAdjacent) + (fOpposite * fOpposite) + (fElevation * fElevation));

		if ((fDistance < fRFunc) && ((psFuncData->boMaterialFill == TRUE) || (fDistance > (fRFunc - psFuncData->fMaterialThickness)))) {
			ucFill = 255u;
		}
		else {
			ucFill = 0u;
		}
	}
}

Once we have them, we can plug them into the function that defines our spherical object to calculate the radius at that point r‘ = f(θ, φ). We compare this with r, the length of the spine from the centre of the object to the position of our voxel.

r = (x2 + y2 + z2)1/2.

Notice we’re pretending here the co-ordinates of our object are at the origin. If they aren’t, we need to subtract the centre co-ordinates component-wise from our voxel co-ordinates first.

The comparison is then simply rr‘ if we’re inside the object and r > r‘ if we’re outside.

Calculating the inside and outside of the spherical volume (so, okay, it's an area here)

Calculating the inside and outside of the spherical volume (so, okay, it's an area here)

We perform these calculations and comparison for each voxel in our voxel space. As before, if we’re inside we set the voxel to be filled, otherwise we leave it empty.

That deals with Cartesian and spherical functions, which are the easy ones, because the mapping between voxels and the co-ordinate system is one-to-one. Sadly this isn’t the case for curve functions, which I’ll tackle in the next post.

Projections

  • Posted on July 30, 2013 at 6:10 pm

The sun was out in Liverpool today, creating crisp and long evening shadows. So it seemed like a great opportunity to take photos of recent 3D printed Functy objects. The full images are rather large, but show the grain of the printing, which I think is rather interesting in itself. Click on the images for the full views.

The original Lissajous is up on deviantArt and Shapeways; the alien egg is also on deviantArt and Shapeways.

Comparing renders with reality

  • Posted on July 27, 2013 at 11:33 pm

Shapeways delivered a new batch of 3D prints recently. I was particularly pleased with the Alien Egg print of a spherical function with the formula:

radius = (3*(0.5+(sin(cos(a)+(p*((3+cos((pi*0.3)-1.5))/4))*10)**2)+((6/6.6)*((2+sin(8*a))/3)**4)))*sin(p)+(4.3*(1-(sin(p)**2))),

colour (R, G, B) = (r/8, (3+sin((a)*8))/5, (3+cos(a*8))/5).

The print is actually rather small (just 6 cm diameter) and the ridges of the shape are really quite delicate. In spite of this, the 3D print has come out really very similar to the original design. I guess you might expect it to be pretty similar, given the way it was produced directly from the model! However, if you look really closely at the original you can see the strata through the object created by the printing process. What I’m really impressed with, though, is the colour produced. I’d expected this to be a bit washed out, but in practice it’s a pretty impressive match.

Below is a comparison of (from top to bottom) the Functy render, the 3D print and a render done using Blender Cycles. In case you’re interested and your browser supports APNGs, there’s also a peculiar animated version!

Alien Egg Comparison (Functy, 3D print, Blender; click to enlarge)

Alien Egg Comparison: Functy, 3D print, Blender (click to enlarge)

Functions in the real world

  • Posted on July 6, 2012 at 1:59 am

This afternoon a very exciting (at least for me!) parcel arrived all the way from Eindhoven in the Netherlands. The first ever ‘real’ 3D function generated using Functy and printed by Shapeways using a 3D printer.
I’m really pleased with the results. Shapeways were not only able to print out the rather convoluted function in 3D, but they also printed it in full colour too.

Here’s a screenshot and some photos of the final result.

The colouring is really great - much more vivid than I’d expected - and it’s not as delicate as I’d feared (it survived the journey through the post, at any rate!). This is a spherical function, which is the easiest to print (they generate meshes without holes automatically, which are needed for 3D printing). Hopefully the next step will be to attempt a parametric curve print.

If you want to play around with the model yourself, you can download the Functy definition file, or if you’re feeling flush, order your own 3D printed version from Shapeways. Such is the beauty of 3D printing!

Spherical co-ordinates

  • Posted on June 8, 2009 at 9:00 pm
Function using spherical co-ordinates

Function using spherical co-ordinates

So far Functy has worked only using Cartesian co-ordinates, but I’m currently working on code for the next release to allow functions to be defined using spherical co-ordinates too.

Spherical function plotting is already working as you can see in the screenshot. It seems to produce some nice effects that are quite different from those you generally get using Cartesian functions.

The tricky part seems to be getting the code for both co-ordinate types integrated nicely together, and also sorting out a suitable user interface to allow them both to be added seamlessly.

The reason the code is turning out to be tricky is that I’m trying to develop using object oriented techniques, but using C rather than C++. I know it’s perfectly possible to do this (and do it well; although not necessarily by me!), and so far there hasn’t been much problem. However, I’m now in a situation where inheritance would seem to be the perfect technique to use. Most of the methods needed for the two co-ordinate systems are the same, so in C++ it would make sense to use some virtual interfaces to define them and inherit these from a generic function type. Unfortunately I’m not sure if this is going to work well in C.

It seems like a silly thing to get stuck on and it would be nice to get the spherical functionality into the next build. I’m hoping the best method will become clearer as things progress.

Top