Hi John,
Your script can be broken down into a few steps
In this situation, we can make things more simple with a few assumptions.
If we assume that the db is open in Creator, we don't have to save and close the db. This little step makes the code less prone to errors and it makes it work in our Batch Run Script tool.
Note: Batch Run Script will let you take a script that functions on the current db and apply it to lots of files and even folders of files. it takes care of opening and saving these files. It also allows for Creator tools to be invoked in the script.
With this simplification, the script will now only need to:
#------------------------------------------------------------------------- # First I am going to get the current db. I am assuming this is the master # This assumption makes the code easier and it makes it more usable. # It is more usable because it means this script can be run inside # of the batch run script tool and applied to multiple databases in batch. #------------------------------------------------------------------------- db = mgGetCurrentDb() #------------------------------------------------------------------------- # Now let's find the lower left vertex. Instead of doing what you desribed # I decided to get the lower left vertex of all the tiles. This makes it # more flexible. The script would not depend on a particular file's tile # names. #------------------------------------------------------------------------- MasterSpaceMin = mgMakeCoord3d (0,0,0) # this will hold our lowest x,y,z FirstCoordSet = False # this will tell us if we have a valid x,y,z # This function is called for every node in the master and in the xrefs. # Even vertices are visited. It also maintains a matrix stack of any transforms # above the node. # MWALK_MATRIXSTACK - tells mgWalk to maintain a matrix stack so we can use it in the function # MWALK_VERTEX - tells mgWalk to visit vertices # MWALK_MASTER_ALL - tells mgWalk to visit all external reference nodes def FindSmallest (db, parent, rec, userData): global MasterSpaceMin global FirstCoordSet ok, mat = mgWalkGetMatrix(userData) if mgGetCode(rec) == fltVertex: # we have a vertex and the matrix that is transforming it, # convert the vertex coordinate to a world coordinate ok, x,y,z = mgGetVtxCoord(rec) localCoord = mgMakeCoord3d(x,y,z) worldCoord = mgCoord3dTransform(mat, localCoord) # we have teh world position of this vertex, update our MasterSpaceMin if not FirstCoordSet: MaseterSpaceMin = worldCoord FirstCoordSet = True else: if MasterSpaceMin.x > worldCoord.x: MasterSpaceMin.x = worldCoord.x if MasterSpaceMin.y > worldCoord.y: MasterSpaceMin.y = worldCoord.y if MasterSpaceMin.z > worldCoord.z: MasterSpaceMin.z = worldCoord.z return MG_TRUE mgWalk(db, FindSmallest, None, None, MWALK_VERTEX | MWALK_MATRIXSTACK | MWALK_MASTERALL ) #------------------------------------------------------------------------- # Now we should have the lowest corner of the entire set of tiles stored in # the variable MasterSpaceMin and it is in world space. Now we have to # translate all the tiles below it using this value. The easiest way to do # this is to add a transform to a parent node to all the children #------------------------------------------------------------------------- g1 = mgGetChild(db) xform = mgNewRec (fltXmTranslate) mgSetCoord3d (xform, fltXmTranslateFrom, MasterSpaceMin.x, MasterSpaceMin.y, MasterSpaceMin.z) mgSetCoord3d (xform, fltXmTranslateDelta, -MasterSpaceMin.x, -MasterSpaceMin.y, -MasterSpaceMin.z) mgAttach(g1, xform)
The basic functions that are most vital to understand:
mgWalk
mgSetAttList / mgGetAttList
These functions are the core of 90% of all scripts you will come across. Taking the time to fully understand them will greatly benefit your scripting. In this situation, we didn't need to use mgGetAttList because we used mgGetCoord3d which is a similar function but specific to mgcoord3ds. Even so, if you were wondering where the fltXmTranslateFrom and fltXmTranslateDelta values came from, these types of functions have an entire document called the data dictionary that describes every possible parameter that can be used to access data in nodes.
thank you sir, I am hand jamming this over to my workstation. have run into a few errors, im working through those atm.
For some reason, I cannot follow along the Reference guide, but I can open a script up and figure out what it is doing and pick,pull,apply it to what I need it to do. I really only started working with the API about 3 weeks ago. I am understanding it more and more daily, but I was stuck and getting nowhere.
I will let you know how it goes here shortly.
worked through some missed characters and alignment issues and it moved everything to the right place except for Z. looking to see what i can figure out
ok, the script is set to move z to the lowest z value. You can prevent moving z alltogether by modifying two lines of code. Change the z values of both mgSetCoord3d functions to zero.
mgSetCoord3d (xform, fltXmTranslateFrom, MasterSpaceMin.x, MasterSpaceMin.y, 0) mgSetCoord3d (xform, fltXmTranslateDelta, -MasterSpaceMin.x, -MasterSpaceMin.y, 0)
replacing the MasterSpaceMin.z's with 0 set the tiles higher up than leaving the Spacemins alone. Im trying to get vertex to touch x,y,z at 0
I see. The script as written tries to put the lower left bounding volume of the tile at 0,0, not any particular vertex. It is a little more complicated to do what you are asking because there is no clear way to decide what vertex is best. If you just want any vertex from one of the tiles put there, it would be easy to just take the first vertex found and use it
yeah, I was thinking it could just find the vertex on the bottom left of a specific tile and move everything else with it.
Finding the bottom left would just need some more math.
ok, let me wrap my head around what we have so far and I will see what I can come up with. Thank you for the help already. I will post back what i come up with
ok, so I just copied everything with min
pasted in the editor
renamed all the mins to max swapped the > with < for the max z
setup new def, for a max set
new mg_walk
new mgsetcoord3d for the max data
so close..its just over 21m off in the negative z..
will keep going
skipped over the part on getting a vector value
will hit this in the am. again, thanks for getting me started in the right direction.
tried again before i left for home. I got the one tile to move to the correct location using the script by trying it on a specific tile by itself. but once I try on the master.flt, same results as before. I will sleep on it.
I thought of an easier way than testing along the center line would be to to instead test all vertices based on distance to the min point already calculated with the script.
Try this out:
#------------------------------------------------------------------------- # First I am going to get the current db. I am assuming this is the master # This assumption makes the code easier and it makes it more usable. # It is more usable because it means this script can be run inside # of the batch run script tool and applied to multiple databases in batch. #------------------------------------------------------------------------- db = mgGetCurrentDb() #------------------------------------------------------------------------- # Now let's find the lower left vertex. Instead of doing what you desribed # I decided to get the lower left vertex of all the tiles. This makes it # more flexible. The script would not depend on a particular file's tile # names. #------------------------------------------------------------------------- MasterSpaceMin = mgMakeCoord3d (0,0,0) # this will hold our lowest x,y,z FirstCoordSet = False # this will tell us if we have a valid x,y,z # This function is called for every node in the master and in the xrefs. # Even vertices are visited. It also maintains a matrix stack of any transforms # above the node. # MWALK_MATRIXSTACK - tells mgWalk to maintain a matrix stack so we can use it in the function # MWALK_VERTEX - tells mgWalk to visit vertices # MWALK_MASTER_ALL - tells mgWalk to visit all external reference nodes def FindSmallest (db, parent, rec, userData): global MasterSpaceMin global FirstCoordSet ok, mat = mgWalkGetMatrix(userData) if mgGetCode(rec) == fltVertex: # we have a vertex and the matrix that is transforming it, # convert the vertex coordinate to a world coordinate ok, x,y,z = mgGetVtxCoord(rec) localCoord = mgMakeCoord3d(x,y,z) worldCoord = mgCoord3dTransform(mat, localCoord) # we have teh world position of this vertex, update our MasterSpaceMin if not FirstCoordSet: MaseterSpaceMin = worldCoord FirstCoordSet = True else: if MasterSpaceMin.x > worldCoord.x: MasterSpaceMin.x = worldCoord.x if MasterSpaceMin.y > worldCoord.y: MasterSpaceMin.y = worldCoord.y if MasterSpaceMin.z > worldCoord.z: MasterSpaceMin.z = worldCoord.z return MG_TRUE mgWalk(db, FindSmallest, None, None, MWALK_VERTEX | MWALK_MATRIXSTACK | MWALK_MASTERALL ) #------------------------------------------------------------------------- # This section will find the closest vertex to the MasterSpaceMin point # that was calculated above. #------------------------------------------------------------------------- bestVertex = mgMakeCoord3d(0,0,0) bestVertexDistance = 0 bestVertexSet = False def FindClosest (db, parent, rec, userData): global MasterSpaceMin global bestVertex global bestVertexDistance global bestVertexSet ok, mat = mgWalkGetMatrix(userData) if mgGetCode(rec) == fltVertex: ok, x,y,z = mgGetVtxCoord(rec) localCoord = mgMakeCoord3d(x,y,z) worldCoord = mgCoord3dTransform(mat, localCoord) dist = mgCoord3dDistance(worldCoord, MasterSpaceMin) # we have the world position of this vertex, update our MasterSpaceMin if not bestVertexSet or dist < bestVertexDistance: bestVertex = worldCoord bestVertexDistance = dist bestVertexSet = True return MG_TRUE mgWalk(db, FindClosest, None, None, MWALK_VERTEX | MWALK_MATRIXSTACK | MWALK_MASTERALL ) #------------------------------------------------------------------------- # Now we should have the lowest corner of the entire set of tiles stored in # the variable MasterSpaceMin and it is in world space. Now we have to # translate all the tiles below it using this value. The easiest way to do # this is to add a transform to a parent node to all the children #------------------------------------------------------------------------- g1 = mgGetChild(db) xform = mgNewRec (fltXmTranslate) mgSetCoord3d (xform, fltXmTranslateFrom, bestVertex.x, bestVertex.y, 0) mgSetCoord3d (xform, fltXmTranslateDelta, -bestVertex.x, -bestVertex.y, 0) mgAttach(g1, xform)
John
New to the API, learning a little but really struggling on how to even think of a way to do more complicated tasks.
What I am wanting to do:
inside the master.flt
find the lower left vertex of the tile filename0_0
translate all the tiles in the master.flt from said vertex to 0,0,0
save file
I'm really trying to learn how to do too many things at once, and not really succeeding on grasping the basics. I can look for older scripts, pick and pull and make a few things work, but if I don't have a file to reference, I'm pretty much lost.
any help would be greatly appreciated.