Start a new topic

New API user No Clue what im doing.

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.



ok, i got it now. i was still waiting on dm to get the file to me so I tried to replace the 0's with bestVertex.z and -bestVertex.z


and it moved all the tiles correctly. 


I took a break from this task to try a few simpler  tasks, i have a long way to go. But I do feel like I am understanding what things do. I dont think Ill ever just be able to throw together a script without using bits and pieces of other scripts. 


I really appreciate the help. This will same me alot of time.

Python can be difficult to find logic errors. I suspect one of your lines is not indented to the correct level. For instance, in one of your walk functions, if the return statement is indented too far, it will not return true. If this happens it is a signal to stop the walk. This small change can break the entire script and will cause no errors.


The best way to find errors like this is to insert print statements

print 'in function xx'

Then you can follow the output in the window to see what is called, how often it is called and it will help to find things you did not expect. Be careful with print statements though as they are slow and your script will appear to stop functioning if it tries to print a few thousand of them. (easily done with one print statement in a walk that walks vertices for instance)


Ok with that said, you shouldn't have to retype this. You can copy and paste it into the script editor. I just gave it a try and it pasted in and functioned for me.

ive gone through this 3x and each time found a few spelling errors but fixing them has not made the script act any different

got this typed into the script, nothing moved at all. I tried replacing the 0's with bestVertex.z and -bestVertex.z, still no movement

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)

 

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.  

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.

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

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

Finding the bottom left would just need some more math. 

  • First you have to find the bottom left corner of the bounding box
  • Then you need to find the top right of the bounding box
  • Then you need to make a line from the bottom left to the top right
  • Then loop through every vertex and project it onto this line to see the closest one to the bottom left

The script I sent already calculates the bottom left corner of the bounding box by finding the min
The same thing can be done in reverse to find the top right by finding the max
Then you can create a vector from min to max
A second walk could be called with a different function to compare to this line.

The comparison would be a dot product between the vector (min,  max) and the vector (min, pt) where pt is the current vertex position
This would produce a single value and you can use this to determine the smallest of these values
Then you take the point that was used to make that smallest value and use it as the the bottom left.

yeah, I was thinking it could just find the vertex on the bottom left of a specific tile and move everything else with it. 

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

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



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)

 

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 

Login to post a comment