# Getting things flat in Rhino

I am having issues getting things to be perfectly flat with respect to the world top view in Rhino, I don’t know if I just have a precision setting wrong or what’s going on. Here is a simple example that demonstrates what is happening. I have a plane that I originally drew at some funny compound angle… but it is a FLAT plane. Then I try to make a copy of this plane that is flat to the “World Top” CPlane using Orient3Pt. I select what I want to become the lower left corner first by its endpoint, then the lower right, then the upper left as shown:

then to get it perfectly flat, I don’t select anything, instead I type in coordinates… for point 1, I enter 0,0,0 for point 2 I enter 100,0,0 and for point 3 I enter 0,100,0
So I have specified Z=0 for all 3 points.

This puts the plane somewhat where I expected, but it is NOT perfectly flat, and NOT at Z=0
I fully expected it to be precisely at Z=0.0000000 as if I drew it there.

If I put a bounding box around it, the bounding box has the following:
min = -0.0000003,0.0000000,0.0000000
max = 70.4130707,37.9674815,0.0000006
dimensions = 70.4130710, 37.9674815, 0.0000006 inches

where did the 0.0000006 thickness come from? how can I get this FLAT?

if I draw a plane specifying its coordinates to be flat, then it really is flat as in this example of another plane I drew by coordinates.
min = -72.0000000,0.0000000,0.0000000
max = 0.0000000,48.0000000,0.0000000
dimensions = 72.0000000, 48.0000000, 0.0000000 inches

the plane re-oriented with Orient3Pt is also proven to be out of flat by getting the distance from 0 to the lower right corner:

Command: Distance
First point for distance ( Units=Model_Units ): 0
Second point for distance ( Units=Model_Units Undo )
CPlane angles and deltas: xy = 0.0000000 elevation = 0.0000005 dx = 70.4130707 dy = 0.0000000 dz = 0.0000006
World angles and deltas: xy = 0.0000000 elevation = 0.0000005 dx = 70.4130707 dy = 0.0000000 dz = 0.0000006
Distance = 70.4130707 inches

I can’t see any reason why any of the plane should be above 0 because I specified Z=0 for every coordinate of the Orient3Pt.

I know I can force things flat with Project to CPlane, but that will not work because the things I am trying to get to be flat are complicated blocks… I’m just using the plane as an example that demonstrates the issue and hopefully whatever solution I find for the plane would work for the block as well.

Another thing I have tried was to set a CPlane to the diagonal plane, then copy it to the clipboard then set it back to World Top and paste it… but it just pastes it back where it was diagonally… apparently copy and paste do not take the CPlane into account… but I do notice that when I set the CPlane this way and then check the 4 corners of my plane with Distance that all 4 corners report Z=0.0000000 so if I could somehow copy it with respect to this CPlane then paste it to the “World Top” CPlane it should be right. but I don’t see how to copy with respect to CPlane.

Here is the sample drawing in case anyone sees where I have a setting wrong or something
Flat Planes.3dm (186.1 KB)

Dear James

you can set a custom c-plane to the original, green surface.
use the same 3 points as you used for orient3Pts.

0.0000006

CPlane coordinates:
min = -0.0000003,0.0000000,-0.0000000
max = 70.4130670,37.9674815,0.0000006
dimensions = 70.4130673, 37.9674815, 0.0000006 inches

some thinks you might want to consider - or check the corresponding commands if you don t know them:

• use Modelling-Aid planar
• use project
• use custom c-planes
• don t use near snap, use single one-shot-snaps instead
• commands like _cplane, _projectToCplane, _remapCplane, _setPt, _selPlanarSrf, _selPlanarCrv
• do not change unit-Tolerance will modelling (at least don t make it more accurate)

use typical tolerances in the file - not sure if rhino feels comfortable with the 0.00000001 unit Tolerance in your file…
check this post

you may also want to read
https://wiki.mcneel.com/rhino/faqtolerances
and

EDIT:
Some stuff you might find below - kind of summary as this topic got unexpected long:

## Summary

• a very tight Unit-Tolerance is not recommended, typically use 0.001
• `_boundingbox` might interact with display-meshes, if you really need a 0.00000…
• use `_ClearAllMeshes` or
• `_reFreshShade`
before running _boundingbox, you can wright a macro for this and assign it to a button or to an Alias.
• to fix 0.00000… use
• `_setPt`
• `_ProjectToCPlane`
1 Like

Hi James - your file shows an absolute tolerance of 0… that should not be allowed, and in V8 this would be reset to .001 - that’s what I’d use.

How did you make the plane to begin with? What command and input?

Once oriented, you can `ProjectToCPlane` to true it up, as Tom suggests.

All that said, without any projecting, the corner points all show 0 as the Z coordinate, so BoundingBox may need a look. It looks like it is using meshes, possibly as a starting point - if you `ClearAllMeshes`, the BB is correct; if you clear them before orienting, it also workls as expected here. I’ll look into it.

-Pascal

I see that. the thing I don’t understand is why it’s there. I don’t have this problem with my other CAD programs. I can fix this by exporting the original file as an IGES file, then reorienting with my other CAD program, save it as an IGES file then Import it back into Rhino, and it’s perfectly flat on the World Top CPlane. so why can’t I do this directly in Rhino? The calculation is obviously able to be done, otherwise my other program would also be off.

This is not a good solution to re-orientate it with an external program because it defeats the whole purpose I am trying to resolve. I want to have 2 copies of the block in Rhino, one at the installed compound angle and one flat in World Top… So I can export the parts from the World Top oriented version for machining etc. this issue of things being almost, but not exactly flat is causing a huge problem with my CAM package, because it cannot do operations like “Mill Flatlands” if they are not actually flat… and yes this 0.0000006 is enough to not be considered flat and it’s difficult to fix them when they are just portions of a complicated solid model.

Also when I export them and re-import them, I loose all my layers and blocks… I have just exploded geometry… even solids become just a bunch of surfaces… it’s not a real solution at all… but it just proves that it can be done with double precision floating point math. My other CAD program just uses standard double precision floating point math, nothing special… pretty much all math on any PC is done with double precision floating point, I can’t imagine Rhino uses anything different.

When I align to a Flat surface in that program and check my boundaries, it ALWAYS shows 0.000000000000 for both minimum and maximum Z values with no errors… so the surface itself is actually flat the way Rhino created it… not a little bit twisted or something.

Flat Planes with Import.3dm (220.3 KB)

the 0 it shows is not because I put in 0… I put in something like 0.000000001 and then it changed it to a 0. but I have already tried it with some of the standard templates like “Small Objects - Inches” and the problem remains.

I’m just using this plane as an example that illustrates the problem… the things I am trying to re-orientate are very complicated blocks… so I can’t just project them to CPlane.

I’ll try clearing the meshes before I orient it and see what happens, thank you for the suggenstion

James

I created it with _Plane and I entered whole number coordinates in X,Y,Z format. I don’t remember what they were… just something like 5,13,3 72,18,12 24,48,36 to get a random diagonal plane to demonstrate the issue.

Indeed `ClearAllMeshes` does solve the problem completely… but it’s NOT something anyone would think about unless they knew how Rhino worked internally. I like to draw in Shaded… so I can see what the heck is going on… and I just figured that using Shaded was for my convenience, and that things like Orient3Pt were not being based on the meshes created by shading, but by the actual geometry the shading is based on… but apparently that is not the case… because it works as expected in wireframe IF I do `ClearAllMeshes` but as soon as I turn on shaded… I get the error.

I honestly think I should be getting the EXACT same results on Orient3Pt regardless of what my display mode is. and I think everyone else using Rhino would think that as well.

I really appreciate the suggestion… it does solve my problem! I would have NEVER guessed that. I hope some adjustment can be made so that all operations are done on the actual defined geometry not the meshes. I guess as a workaround maybe I can modify Orient3Pt to do ClearAllMeshes first, then turn shaded back on after it’s done… the only problem with that is its going to be kind of a mess of wireframes to pick out my points… I guess I can put some points where I want them first.

Please let me know if anything can be done. This issue of things being not flat when they come out of Rhino when we think they are is ALWAYS causing issues, and not just for me, a lot of my customers have the same exact issue as well. It would be GREAT if it worked the way I thought it would!

Hi James - I cannot make this happen from scratch, so far.

-Pascal

Here is how I do it… I am using
Version 7 SR24
(7.24.22308.15001, 2022-11-04)

I started with a new drawing and selected Small Objects - Inches
the hint something is off is the -0.000 on min and the 0.000 on max… when I expect 0.000 on both So all I did was change Display Precision so I could see the rest of the decimals and then I could see the error. I didn’t change anything else.

Command: _New
Command: _Plane
First corner of plane ( 3Point Vertical Center AroundCurve Deformable ): _3Point
Start of edge ( EdgeMidpoint Deformable ): 15,3,2
End of edge: 73,8,9
Width. Press Enter to use length: 36,40,20
Creating meshes… Press Esc to cancel
Command: Orient3Pt
Select objects to orient
Select objects to orient. Press Enter when done
Reference point 1 ( Copy=No Scale=No )
Reference point 2 ( Copy=No Scale=No )
Reference point 3 ( Copy=No Scale=No )
Target point 1 ( Copy=No Scale=No ): 0,0,0
Target point 2 ( Copy=No Scale=No ): 100,0,0
Target point 3 ( Copy=No Scale=No ): 0,100,0
Command: BoundingBox
Select objects to frame with a box
Select objects to frame with a box. Press Enter when done
Choose BoundingBox option. Press Enter when done ( CoordinateSystem=World Cumulative=Yes Output=Solids )
World coordinates:
min = -0.000,-0.000,-0.000
max = 58.634,38.131,0.000
dimensions = 58.634, 38.131, 0.000 inches
Creating meshes… Press Esc to cancel
Command: _DocumentProperties
1 closed polysurface added to selection.
Command: _Delete
Command: BoundingBox
Select objects to frame with a box
Select objects to frame with a box. Press Enter when done
Choose BoundingBox option. Press Enter when done ( CoordinateSystem=World Cumulative=Yes Output=Solids )
World coordinates:
min = -0.0000000,-0.0000000,-0.0000013
max = 58.6344609,38.1313481,0.0000000
dimensions = 58.6344609, 38.1313481, 0.0000013 inches
Creating meshes… Press Esc to cancel

If I repeat the same exact procedure but do not turn on Shaded at all, then the bounding box with the display precision is:
Choose BoundingBox option. Press Enter when done ( CoordinateSystem=World Cumulative=Yes Output=Solids )
World coordinates:
min = -0.0000000,-0.0000000,-0.0000000
max = 59.1607978,40.3605194,-0.0000000
dimensions = 59.1607978, 40.3605194, 0.0000000 inches

So having shaded on is defiantly causing a different result. I don’t know why Z Min and Z Max are both -0.0000000 but at least it is flat now.

James

I just noticed… not only is the Z different, but the X and Y are WAY different on the two versions, even though I put in the exact same coordinates for the plane

Command: _New
Command: _Plane
First corner of plane ( 3Point Vertical Center AroundCurve Deformable ): _3Point
Start of edge ( EdgeMidpoint Deformable ): 15,3,2
End of edge: 73,8,9
Width. Press Enter to use length: 36,40,20
Select objects to orient
Select objects to orient. Press Enter when done
Reference point 1 ( Copy=No Scale=No )
Reference point 2 ( Copy=No Scale=No )
Reference point 3 ( Copy=No Scale=No )
Target point 1 ( Copy=No Scale=No ): 0
Target point 2 ( Copy=No Scale=No ): 100,0
Target point 3 ( Copy=No Scale=No ): 0,100
1 open surface added to selection.
Command: BoundingBox
Choose BoundingBox option. Press Enter when done ( CoordinateSystem=World Cumulative=Yes Output=Solids )
Creating rendering meshes… Press Esc to cancel
World coordinates:
min = -0.000,-0.000,-0.000
max = 59.161,40.361,-0.000
dimensions = 59.161, 40.361, 0.000 inches
Command: _Undo
Undoing BoundingBox
Command: _DocumentProperties
1 open surface added to selection.
Command: BoundingBox
Choose BoundingBox option. Press Enter when done ( CoordinateSystem=World Cumulative=Yes Output=Solids )
World coordinates:
min = -0.0000000,-0.0000000,-0.0000000
max = 59.1607978,40.3605194,-0.0000000
dimensions = 59.1607978, 40.3605194, 0.0000000 inches

I don’t know how they can be THAT different. I am snappng on only End, Int, or Mid

I did the second one again, without turning on Shaded… now I get
Command: _New
Command: ClearAllMeshes
Command: _Plane
First corner of plane ( 3Point Vertical Center AroundCurve Deformable ): _3Point
Start of edge ( EdgeMidpoint Deformable ): 15,3,2
End of edge: 73,8,9
Width. Press Enter to use length: 36,40,20
Command: Orient3Pt
Select objects to orient
Select objects to orient. Press Enter when done
Reference point 1 ( Copy=No Scale=No )
Reference point 2 ( Copy=No Scale=No )
Reference point 3 ( Copy=No Scale=No )
Target point 1 ( Copy=No Scale=No ): 0,0,0
Target point 2 ( Copy=No Scale=No ): 100,0,0
Target point 3 ( Copy=No Scale=No ): 0,100,0
1 open surface added to selection.
Command: BoundingBox
Choose BoundingBox option. Press Enter when done ( CoordinateSystem=World Cumulative=Yes Output=Solids )
Creating rendering meshes… Press Esc to cancel
World coordinates:
min = -0.000,-0.000,0.000
max = 58.634,38.131,0.000
dimensions = 58.634, 38.131, 0.000 inches
Command: _DocumentProperties
1 closed curve added to selection.
Command: _Delete
1 open surface added to selection.
Command: BoundingBox
Choose BoundingBox option. Press Enter when done ( CoordinateSystem=World Cumulative=Yes Output=Solids )
World coordinates:
min = -0.0000000,-0.0000000,0.0000000
max = 58.6344609,38.1313481,0.0000000
dimensions = 58.6344609, 38.1313481, 0.0000000 inches

I must have done something wrong… now my X and Y are the same as the first try with Shaded turned on, but my Z is now 0.0000000 where with Shaded it was 0.0000013

James

But is that really the problem? The most popular MCAD software in the world, until some recent times, modeled everything internally with hard-coded tolerances rougher than that. My experience working with machinists and trying to patch up models machinists have made in their CAM software for 3D printing, is that CAM is actually astoundingly tolerant of geometry flaws.

Yes the problem is defiantly that things are not flat. I am using vectorcam and all of the milling 2D operations REQUIRE that the geometry is flat… IE NO Change in the Z axis whatsoever… and it has NO tolerance. Also the containments for all milling operations all the way to milling 5 axis must be truly flat… with no change in Z… those are easy to fix because you can just to a projection in vectorcam… but jobs that are designed to mill all the flat surfaces of a model from the actual surface geometry will not consider a surface ‘flat’ unless it really unless it is really flat… again with absolutely no change in Z… but those are the jobs that are not easy to just fix with a projection… because the flat surface needs to connect to all the other surfaces for all the other machining operations. you could machine it with a 3d milling operation but that’s not what should be done for something that is supposed to be flat… 3D milling is WAY slower than running the flatlands job on the flat sections. Fusion 360 has the EXACT same issues the EXACT same way. We need to extract sections of a project that were drawn at some compound angle and reference flat sections so that they are flat to “World Top” and they come out truly flat… as in no change in Z, not close to flat. The amount of time we spend dealing with this almost flat problem is really terrible, especially when it’s part of a really complicated model.

The problem is defiantly any change in Z for things that are supposed to be flat. I’ve fixed the problem many times, and the solution is always to get that section flat so that when you verify it, the Z Minimum and Z Maximum are exactly the same… and then the job works as expected.

This is not ever a problem with 3D printing, because everything gets sliced into layers anyway so anything that is within the thickness of a layer is close enough.

To be fair… if we were doing nothing but 3D milling (not 3D printing, but machining in X,Y, and Z at the same time) then it’s true that none of this matters and even a really sloppy model would come out just fine… even with big gaps between surfaces and things like that… so there is truth in what you say… you can get by with a lot… and I’ve seen a lot of people running a job in 3D milling just to get it done when it would have been done a LOT faster milling the flat sections with a job made for flat sections… but they just don’t want to deal with making the model flat… so they run the whole thing doing 3D Milling in a whole bunch of tedious slow 3D Milling passes. But there are jobs for flat geometry that are way faster and better… so it’s really worth it for me to find a solution to this issue.

James

`SetPt` can be used to set objects exactly at any desired z coordinate, either world coordinate system z or Cplane z. `SetPt` also works for x and y coordinates.
https://docs.mcneel.com/rhino/7/help/en-us/index.htm#commands/setpt.htm

The Absolute tolerance setting has no effect on the precision of the internal arithmetic in Rhino.

Absolute tolerance is used when geometry cannot be exactly represented using NURBS, for instance the intersection of two curved surfaces. Rhino then determines an approximation of the exact shape which is within the absolute tolerance of the exact shape. It is also used to determine if the edges of two surfaces coincide.

1 Like

Thats great to know! Thank you. I’ve been doing things like Move > Vertical > select what I want > then put in the Z coordinate. that mostly seems to work, but I will definitely try out SetPt

But of course there’s no such thing as “no tolerance,” digital floating-point math simply can’t do that, what you’re fighting with here is just noise, possibly just rounding errors between base-10 and binary, the “0.00000006” deviation being measured is quite likely not actually there, as Pascal said it’s likely some render mesh glitch. I dunno, the mesher doesn’t ‘know’ it’s an exact plane so it doesn’t try to make one?

Yeah, if I run RefreshShade on the transformed plane, BoundingBox gives 00000000 height, so it’s a matter of a flaw or just the limit of precision rotating that render mesh, or creating it on that angle then rotating it? Plus measuring it, since the boundingBox box sure doesn’t correspond to any variation visible on the surface.

I do see that now that I’ve been trying it different ways. My original idea was that it was a tolerance setting causing my issue, but Pascal’s recomendation to ClearAllMeshes has proven that the tolerance setting has nothing at all to do with it. I get the exact same results no matter what I put in Absolute tolerance. It’s exactly what I expect after ClearAllMeshes even if I don’t touch the tolerance setting.

You are right… it’s not really there… I just exported one of my tests where the bounding box reported 0.0000013 deviation on Z and my other program reported it as Z Min = 0 and Z Max = 0 and I have it set to display 13 decimal places.

I was able to duplicate your results… RefreshShade indeed did fix the problem. But I do notice one thing… If I do the bounding box before RefreshShade, then the bounding box that is drawn actually does have thickness to it… but the bounding box I get after I do RefreshShade is just a flat outline… with no thickness… it’s just a curve that goes around the boundary. So Boundingbox must be using the meshes not the surface itself.

so this does explain a lot of issues I have… because a lot of times to make it easier to get things flat, I set a CPlane to the object, then I will put a bounding box around it, thinking bounding box is a quick way for me to get a large rectangular plane, then use the corners of the bounding box to do Orient3Pt… so if the BoundingBox has some thickness to it, and I get the upper corner of it when I select one corner, and the lower corner of it when I select another corner, now my Orient3Pt is going to actually put it at an angle that makes that aligned… not what I wanted. So this is the very first time I have EVER seen BoundingBox only produce a curve… I’ve always thought it was drawing a flat plane… but it’s never been a flat plane, it’s always been a very thin solid… if it was flat, it would have been the curve I get when I am now doing RefreshShade before BoundingBox. So if it’s a very thin solid, and I am picking the corners of what I think is a plane, who knows if I am getting the one upper corner and two lower corners or what’s going on.

James

If you’re orienting a Cplane to the object already, then I would just use RemapCplane to flatten it–then see if it really is flat.

Sooooo… I wonder… would it solve all my problems if I just made my own button that does RefreshShade and then BoundingBox?

that way I can just leave my model in Shaded mode so I can see what I’m doing, RefreshShade will fix the selected items then BoundingBox seems to come out the way I thought it would, but I will get a curve instead of what I thought was a plane… but that’s ok… that will be a way to verify that the selected items were flat… all I care about is the corners anyway.

I’m thinking that Orient3Pt itself doesn’t have any issue at all… it just seems like it because of the way BonundingBox works with the meshes created be Shaded.

Ok, I’m going to try it…

James