Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Re^6: Naming ordinals in the presence of 3D rotation? (Still looking?)

by bitingduck (Chaplain)
on Apr 29, 2015 at 04:16 UTC ( [id://1125083]=note: print w/replies, xml ) Need Help??


in reply to Re^5: Naming ordinals in the presence of 3D rotation? (Still looking?)
in thread Naming ordinals (directions/sides/faces) in the presence of 3D rotation?

I spend a lot of time looking at CAD models and assemblies with multiple coordinate systems, i.e. there's a global and then many of the parts have their own local, even with many instances of duplicate parts all rotated and shifted, each with their own local system, and I've never really thought about this as an issue!

I think in general when each part has its own coordinates one refers to partname->x, partname->y, partname->z (in much the same way you theaters use stage-left, stage-right and house-left, house-right.

For referring to a plane in a particular system it generally is partname->xy, partname->yz, and partname->xz where you'd refer to opposite faces either as + and - or by a coordinate reference on the third axis (e.g. partname->xz, y equals zero plane, partname->xz, y equals 1 plane). For something that's not a part (e.g. a graph of data) you'd use graphname instead of partname.

Things like top, bottom, front, back get really complicated because it's not unusual for the natural way to set a part on its own in gravity can be very different from how it's installed (with or without gravity) and what environment it might normally operate in (may or may not have gravity)

EDIT: to add the "y equals" to the description of plane naming

  • Comment on Re^6: Naming ordinals in the presence of 3D rotation? (Still looking?)

Replies are listed 'Best First'.
Re^7: Naming ordinals in the presence of 3D rotation? (A better explanation of the problem?))
by BrowserUk (Patriarch) on Apr 29, 2015 at 06:04 UTC

    Okay. I can see that I've made a total hash of explaining this in words; so I'll try with the aid of a couple of diagrams ('scuse the crudity).

    The first shows the 3 faces of a bounding box furthest from the viewer, complete with their grid (tick) lines and showing the local coordinate system (at the current rotations):

    +Z /________________________ /\ \ \ \ \ \ / \____\____\____\____\____\ /\ /\ \ \ \ \ \ / \/ \____\____\____\____\____\ /\ /\ /\ \ \b \ \ \ / \/ \/ \____\____\____\____\____\ /\ /\ /\ /\ \ \ \ \ \ / \/ \/ \/ \____\____\____\____\____\ +Y /\ /\ /\ /\ /\ \ \ \ \ \ \/ \/ \/a \/ \/ \____\____\____\____\____\ /\ /\ /\ /\ /\ / / / / / / -Z \/ \/ \/ \/ \/____/____/____/____/____/ \ /\ /\ /\ / / / / / / \/ \/ \/ \/____/____/____/____/____/ \ /\ /\ / / / c / / / \/ \/ \/____/____/____/____/____/ \ /\ / / / / / / \/ \/____/____/____/____/____/ \ / / / / / / _\/____/____/____/____/____/_ -X \ +X -Y

    Each of the points (ends of lines) is maintained internally as a 3D point (x,y,z) commensurate with the local coordinate system.

    The boundingBoxDraw() code:

    function _BoundingBoxDraw( ) { var minOrMaxX = ( ( this.Parent.Fi < 90 ) || ( this.Parent.Fi >= 2 +70 ) ); var minOrMaxY = ( this.Parent.Fi >= 180 ); + var minOrMaxZ = ( this.Parent.Th <= 0 ); + drawFace( this, 'z', 'x', 'y', 0, 0, 1, minOrMaxZ, minOrMaxX, minO +rMaxY ); drawFace( this, 'y', 'x', 'z', 1, 2, 3, minOrMaxY, minOrMaxX, minO +rMaxZ ); drawFace( this, 'x', 'y', 'z', 2, 4, 5, minOrMaxX, minOrMaxY, minO +rMaxZ ); }

    But, the same, single routine is used to draw the faces and gridlines. So, when drawing face?:

    1. The x-coordinate selects the face. (Actually, one of two: either at minX or maxX depending upon the rotation.)

      And the 'horizontal' index counter has to set the z-coordinate of the line segments;

      And the 'vertical' index counter sets the y-coordinate of the line segments;

    2. The z-coordinate selects the face. (Actually, one of two: either at minZ or maxZ depending upon the rotation.)

      And the 'horizontal' index counter has to set the x-coordinate of the line segments;

      And the 'vertical' index counter sets the y-coordinate of the line segments;

    3. The y-coordinate selects the face. (Actually, one of two: either at minY or maxY depending upon the rotation.)

      And the 'horizontal' index counter has to set the x-coordinate of the line segments;

      And the 'vertical' index counter sets the z-coordinate of the line segments;

    This diagram shows the 2D representations of the 3 faces from above:

    +Y +Y + +Z -Z +----+----+----+----+----+ +Z -X +----+----+----+----+----+ +X - +X +----+----+----+----+----+ +X | | | | | | | | | | | | + | | | | | | +----+----+----+----+----+ +----+----+----+----+----+ + +----+----+----+----+----+ | | | | | | | | | | | | + | | | | | | +----+----+----+----+----+ +----+----+----+----+----+ + +----+----+----+----+----+ | | | a | | | | | | b | | | + | | | c | | | +----+----+----+----+----+ +----+----+----+----+----+ + +----+----+----+----+----+ | | | | | | | | | | | | + | | | | | | +----+----+----+----+----+ +----+----+----+----+----+ + +----+----+----+----+----+ | | | | | | | | | | | | + | | | | | | +----+----+----+----+----+ +----+----+----+----+----+ + +----+----+----+----+----+ -Y -Y + -Z

    The drawFace() function (currently) looks like this:

    function drawFace( me, face, horizontal, vertical, planeIdx, line1, li +ne2, drawMinFace, cond2, cond3 ) { var world3D = new Vector( 0,0,0 ); world3D[face] = drawMinFace ? me.Min[face] : me.Max[face]; world3D[horizontal] = me.Min[horizontal]; world3D[vertical] = me.Min[vertical]; var screen2D = me.Parent.ScreenPos( world3D ); // calculate and construct Bbox rectangle path ss = "M " + screen2D.x + " " + screen2D.y + " "; // move to corner + 1 world3D[horizontal] = me.Max[horizontal]; screen2D = me.Parent.ScreenPos( world3D ); ss += "L " + screen2D.x + " " + screen2D.y + " "; // line to corne +r 2 world3D[vertical] = me.Max[vertical]; screen2D = me.Parent.ScreenPos( world3D ); ss += "L " + screen2D.x + " " + screen2D.y + " "; // line to corne +r 3 world3D[horizontal] = me.Min[horizontal]; screen2D = me.Parent.ScreenPos( world3D ); ss += "L " + screen2D.x + " " + screen2D.y + " z"; // line to corn +er 4 and close back to corner 1 me.Plane[planeIdx].setAttribute( "d", ss ); // [d]efine the path +for this panes Bbox world3D[face] = 1; world3D[horizontal] = 0; world3D[vertical] = 0; // and set its attributes me.Plane[planeIdx].setAttribute( "fill", me.Parent.GetColor( me.Fi +llColor, me.FillColor, world3D, drawMinFace ? me.Min : me.Max ) ); me.Plane[planeIdx].setAttribute( "stroke", me.StrokeColor ); me.Plane[planeIdx].setAttribute( "stroke-width", me.StrokeWeight ) +; me.Plane[planeIdx].setAttribute( "visibility", "visible" ); world3D[face] = drawMinFace ? me.Min[face] : me.Max[face]; // Draw the horizontal and vertical grid lines on this Bbox face drawGrid( me, face, horizontal, vertical, line1, cond3, world3D ); + // horizontal drawGrid( me, face, vertical, horizontal, line2, cond2, world3D ); + // vertical }

    Note that the nomenclature of the 3 minOrMax? conditions from the drawBoundingBox routine, now make no sense in this routine. At this level, the first of the 3 conditions simply selects which position (end) of the face coordinate this face is drawn at.

    The other two conditions aren't used at this (drawFace()) level. They are only used at the next level down, -- drawGrid(), which is called twice, once for the 'horizontal' lines, and once for the vertical, and each condition is only needed for one of those two calls -- to determine which end of each of the two sets of parallel lines, the tick marks, values and axis labels get drawn.

    This is the drawGrid() (which should probably be called drawHalfTheGrid()):

    function drawGrid( me, face, horizontal, vertical, idx, tickPosn, pp ) + { var ii = 0, uu = 0; var grid = _GetGrid( me.Min[horizontal] / me.Parent.Zoom[horizonta +l], me.Max[horizontal] / me.Parent.Zoom[horizontal], me.Scale[horizon +tal] ); if( me.GridDelta[horizontal] != 0 ) grid.step = me.GridDelta[horiz +ontal]; for( var jj = grid.max; jj >= grid.min; jj -= grid.step ) { pp[horizontal] = jj * me.Parent.Zoom[horizontal]; pp[vertical] = me.Min[vertical]; var vv = me.Parent.ScreenPos( pp ); fromOV( me.Line[idx][ii], vv.x, vv.y ); // Move to the start(m +in) of this gridline var xx = vv.x, yy = vv.y; // copy of start x/y for later pp[vertical] = me.Max[vertical]; vv = me.Parent.ScreenPos( pp ); // pp changed; get again toOV( me.Line[idx][ii], vv.x, vv.y ); // And draw to the othe +r(max) end me.Line[idx][ii].setAttribute( "stroke", me.StrokeColor ); // + Set the color me.Line[idx][ii].setAttribute( "visibility", "visible" ); // + and make visible if( tickPosn ) { // Move the tick labels to the appropriate en +d of the gridlines; 1.06 standoff of label; uu (fudge factor for zoom +ing (not used)) me.Text[idx][ii].setAttribute( "x", Math.floor( xx + ( vv. +x - xx ) * 1.06 ) - 50 * uu ); me.Text[idx][ii].setAttribute( "y", Math.floor( yy + ( vv. +y - yy ) * 1.06 ) - 7 * uu ); } else { me.Text[idx][ii].setAttribute( "x", Math.floor( vv.x + ( x +x - vv.x ) * 1.06 ) - 50 * uu ); me.Text[idx][ii].setAttribute( "y", Math.floor( vv.y + ( y +y - vv.y ) * 1.06 ) - 7 * uu ); } me.Text[idx][ii].setAttribute( "fill", me.StrokeColor ); me.Text[idx][ii].setAttribute( "visibility", "visible" ); if( ( ii == 1 ) && ( me.Label[horizontal] ) ) // if 1st (not +zeroth?) gridline, add the axis label innerTextOV( me.Text[idx][ii], me.Label[horizontal] ); else { // otherwise add the tick value if( isNaN( me.Scale[horizontal] ) ) { if( me.Scale[horizontal].substr( 0,9 ) == "function " +) { ff = eval( "window." + me.Scale[horizontal].substr +( 9 ) ); if( ff ) innerTextOV( me.Text[idx][ii], ff( _Scale +String( jj, grid.step ) ) ); } else innerTextOV( me.Text[idx][ii], _ScaleString( jj, +grid.step ) + me.Scale[horizontal] ); } else { if( me.Scale[horizontal] < 1 ) innerTextOV( me.Text[i +dx][ii], "" ); if( me.Scale[horizontal] == 1 ) innerTextOV( me.Text[i +dx][ii], _ScaleString( jj, grid.step ) ); if( me.Scale[horizontal] > 1 ) innerTextOV( me.Text[i +dx][ii], _DateFormat( jj, grid.step, me.Scale[horizontal] ) ); } } ii++; } }

    Note that the horizontal & vertical nomenclature is wrong at this level. Because the same routine is drawing both, the two coordinates (Z&Y or X&Y or X&Z depending upon the face the grid is being drawn on), switch when drawing the two sets of parallel lines; effectively rotating the 2D face in the process.

    I hope that explains the problem of naming things such that they make sense each (deeper) level of reused abstraction?

    (Final note: I'm still not happy with some of the naming in the above routines, but I'm getting there; however, the general question about finding a good way to deal with the problem remains.)


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority". I'm with torvalds on this
    In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked

      I think the nomenclature isn't so bad. Coordinate transformations often leave you with something that doesn't make sense if you think of it in the new frame or orientation, and if you walk up to them cold take a lot of time reading detailed specs to make sense of. They're tedious to read through and make sense of and easy to mess up when tracing through. I've had to work with stuff that had 7 C-sized sheets packed with notes (and some figures) to define the "base" coordinate system and the transformations to get to mine. You've got what looks like a relatively straightforward set of routines and a lot of detailed description, so I don't think I'd complain about your naming. Most of my experience with nomenclature for this is based on sitting next to someone saying "show me it sliced at the yz plane at x = 'about here' finger point looking from putting +x pointing this way another finger point." Where the finger points would refer to the global coordinates or vectors if I had to write code.

        I think the nomenclature isn't so bad.

        Well yeah! But I've been worrying away at this on and off for the best part of a week.

        You'd have to look back at what I started with and see the number of times I've vacillated and changed the names I currently have to appreciate the thought that's gone into what I have now. (And I just changed some of them again :)


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority". I'm with torvalds on this
        In the absence of evidence, opinion is indistinguishable from prejudice. Agile (and TDD) debunked

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://1125083]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others studying the Monastery: (4)
As of 2024-04-20 00:51 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found