<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-37876710</id><updated>2011-09-12T14:34:41.587-05:00</updated><category term='Vr'/><category term='Introduction'/><category term='Tips'/><category term='Basics'/><category term='Advanced'/><category term='NonVr'/><title type='text'>Squeeze the most out of Vr with Python</title><subtitle type='html'>Occasional ramblings on the topic of Python.  Maybe some general info, but more than likely fairly limited to programming within the VrOne mapping environment using VrPython.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>36</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-37876710.post-9183383610985378476</id><published>2009-05-18T07:16:00.008-05:00</published><updated>2009-05-19T06:05:18.018-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tips'/><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><title type='text'>We all have our limits</title><content type='html'>&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(153, 0, 0);font-size:85%;" &gt;Note that I am trying a new method of posting code, hope it works better but of course the original code itself can always be downloaded from the website where it is stored.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Quite often when writing some sort of import function I would like to limit the data imported to certain physical constraints. I started out asking the user if they want to only act on coordinate values that fall within a bounding box, then if they said yes, prompt them to ID the bounding line. This works great as far as it goes, as part of the ID function I would set a flag (in this case BoundrySet) to 1 then later in the program if BoundrySet was true the IsPointInside method of the Line class could be called. Something like....&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;if BoundrySet :&lt;br /&gt;if BoundingLine.IsPointInside (X,Y): Do something&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;But then I got thinking, there are several easy ways to check for bounding areas without having a line already digitized. How about using the screen boundaries, or digitizing a rectangle based on the lower left and upper right corners, or for that matter just start digitizing points and create a line in memory on the fly. Well it turns out that I already had the snippets I needed in other functions so just copied them out, cleaned them up a bit (and I do mean a bit, it still isn't particularly pretty, but it works) and created a basic function that I can paste into any program where spatial filtering is helpful.&lt;br /&gt;&lt;br /&gt;There are a couple of caveats. Using the rectangle select mode requires that you select the lower left point first, then the upper right based on the screen orientation. I'll probably clean this up some day and allow for more flexibility but it falls into the "quick hack for some purpose, and I know how it acts" category of code that gets the job done but isn't as attractive as it should be. Using the "Digitize" mode allows the user to start clicking on positions and builds the boundary line on the fly, if it would be helpful it would be just as easy to record the line for future interaction but for now I just throw it on the screen. The nice thing about this dialog is that it behaves just the way you expect so if the focus is in the drop down and you hit an 'r' rectangle mode will be activated and so on.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;pre style="border: 1px dashed rgb(153, 153, 153); padding: 5px; overflow: auto; font-family: Andale Mono,Lucida Console,Monaco,fixed,monospace; color: rgb(0, 0, 0); background-color: rgb(238, 238, 238); font-size: 12px; line-height: 14px; width: 100%;"&gt;&lt;code&gt;print 'SetBoundary.py modified 8:00 AM 5/15/2009'&lt;br /&gt;# Set spatial bounding for processing&lt;br /&gt;'''&lt;br /&gt;Copyright 2009 Dennis Shimer, M.A.N. Mapping Services Inc.&lt;br /&gt;No warranties as to safety or usability expressed or implied.&lt;br /&gt;Free to use, copy, modify, distribute with author credit.&lt;br /&gt;&lt;br /&gt;Really just a container for the code snippet that would do spatial&lt;br /&gt;filtering as part of a larger program. Just written as working code&lt;br /&gt;here for testing purposes.&lt;br /&gt;&lt;br /&gt;Variables of interest:&lt;br /&gt;None&lt;br /&gt;'''&lt;br /&gt;import math&lt;br /&gt;&lt;br /&gt;BoundingLine=PyVrLine()&lt;br /&gt;Gr=PyVrGr ()&lt;br /&gt;Gui=PyVrGui()&lt;br /&gt;BoundrySet=0&lt;br /&gt;&lt;br /&gt;PromBox = VrPromBox ("Set Boundry", 30, 1)&lt;br /&gt;PromBox.AddCombo ('Boundry', 5, 0, 0)&lt;br /&gt;PromBox.AddComboItem ('Line')&lt;br /&gt;PromBox.AddComboItem ('Screen')&lt;br /&gt;PromBox.AddComboItem ('Rectangle')&lt;br /&gt;PromBox.AddComboItem ('Digitize Points')&lt;br /&gt;PromBox.AddComboItem ('None (whole file)')&lt;br /&gt;PromBox.SetFocus()&lt;br /&gt;if PromBox.Display(1)==0:&lt;br /&gt;BoundryType=PromBox.GetComboByPrompt ('Boundry')&lt;br /&gt;if BoundryType==0:&lt;br /&gt;   BoundingLine.Id()&lt;br /&gt;   BoundrySet=1&lt;br /&gt;elif BoundryType==1:&lt;br /&gt;   for corner in range(4):&lt;br /&gt;       x,y,z=Gr.GetWinCorner (corner,0)&lt;br /&gt;       BoundingLine.AddPoint(x,y,z)&lt;br /&gt;   BoundrySet=1&lt;br /&gt;elif BoundryType==2:&lt;br /&gt;   Stat,llx,lly,z=Gui.GetCoord('Boundry')&lt;br /&gt;   Gr.DrawMode (1,-1)&lt;br /&gt;   Gr.PenNum (1)&lt;br /&gt;   Gr.DrawMarker (llx,lly,z,MARK_CROSS,Gr.GetWinScale ()*.2,-1)&lt;br /&gt;   Stat,urx,ury,z=Gui.GetCoord('Boundry')&lt;br /&gt;   Gr.EraseMarker ()&lt;br /&gt;   ScreenAngle=Gr.GetWinRot()[2]&lt;br /&gt;   Angle=math.atan((ury-lly)/(urx-llx))-Gr.GetWinRot()[2]&lt;br /&gt;   Diagonal=PyVrGeom().Dist(llx,lly,urx,ury)&lt;br /&gt;   Height=math.sin(Angle)*Diagonal&lt;br /&gt;   if Height &amp;lt; 0.0: Height=Height*-1.0&lt;br /&gt;   Width=math.cos(Angle)*Diagonal&lt;br /&gt;   if Width &amp;lt; 0.0: Width=Width*-1.0&lt;br /&gt;   BoundingLine.AddPoint(llx,lly,z)&lt;br /&gt;   lrx=llx+(Width*math.cos(ScreenAngle))&lt;br /&gt;   lry=lly+(Width*math.sin(ScreenAngle))&lt;br /&gt;   BoundingLine.AddPoint(lrx,lry,z)&lt;br /&gt;   urx=lrx-(Height*math.sin(ScreenAngle))&lt;br /&gt;   ury=lry+(Height*math.cos(ScreenAngle))&lt;br /&gt;   BoundingLine.AddPoint(urx,ury,z)&lt;br /&gt;   ulx=urx-(Width*math.cos(ScreenAngle))&lt;br /&gt;   uly=ury-(Width*math.sin(ScreenAngle))&lt;br /&gt;   BoundingLine.AddPoint(ulx,uly,z)&lt;br /&gt;   BoundingLine.AddPoint(llx,lly,z)&lt;br /&gt;   BoundingLine.Plot()&lt;br /&gt;   BoundrySet=1&lt;br /&gt;elif BoundryType==3:&lt;br /&gt;   Stat=0&lt;br /&gt;   while Stat==0:&lt;br /&gt;       Stat,x,y,z=PyVrGui().GetCoord('Dig Boundry')&lt;br /&gt;       BoundingLine.AddPoint (x,y,0.0)&lt;br /&gt;       BoundingLine.Plot()&lt;br /&gt;   BoundingLine.Close(2)&lt;br /&gt;   BoundingLine.Plot()&lt;br /&gt;   BoundrySet=1&lt;br /&gt;&lt;br /&gt;&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://python4vr.googlepages.com/SetBoundry.png"&gt;&lt;img style="margin: 0px auto 10px; display: block; text-align: center; cursor: pointer; width: 800px; height: 600px;" src="http://python4vr.googlepages.com/SetBoundry.png" alt="" border="0" /&gt;&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-9183383610985378476?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/9183383610985378476/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=9183383610985378476' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/9183383610985378476'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/9183383610985378476'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2009/05/we-all-have-our-limits.html' title='We all have our limits'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-1795446597549222191</id><published>2009-04-29T06:49:00.002-05:00</published><updated>2009-04-29T06:57:41.659-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><title type='text'>The 5 minute function.</title><content type='html'>No I'm not actually going to put a lot of time into a post since there doesn't really seem to be much interest in what's going on. However a recent conversation in the Vr Python Forum is a perfect example of the whole purpose of having Python in Vr.  If you are a member you can check it out there.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.cardinalsystems.net/forum/index.php?topic=51.0"&gt;http://www.cardinalsystems.net/forum/index.php?topic=51.0&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The basic premise is that you need a simple function to automate a fairly simple task, in this case labeling all symbols in specified layers with a piece of text in which the label is the symbols feature code. It could be any attribute, or any entity type, but the point is; rather than waiting for the feature to show up in Vr, with a little practice, you can write it yourself (usually from existing snippets) in about 5 minutes and be on your way.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-1795446597549222191?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.cardinalsystems.net/forum/index.php?topic=51.0' title='The 5 minute function.'/><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/1795446597549222191/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=1795446597549222191' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/1795446597549222191'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/1795446597549222191'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2009/04/5-minute-function.html' title='The 5 minute function.'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-8607739373777615920</id><published>2007-11-01T07:33:00.000-05:00</published><updated>2007-11-02T14:09:00.851-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><title type='text'>Inherit everything but the kitchen sink.</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Back when I was just a young map maker, I was actually fairly sharp, and had a memory that was quite useful. I worked on a CAD system that until VrOne came along seemed like one of the fastest, most practical, easy to use map collection systems around. It used a numeric command set that allowed you to set any combination of insert parameters to a 3 digit code. Alas you were limited to 120 codes which seemed like plenty and were quickly memorized. Of course now I can't remember what I had for breakfast (I did have breakfast didn't I), but I can remember all 120 of those codes. The flexibility of Vr allowed me to easily make macros that do those 120 tasks, but over the years we continued to add things. Now I know there is a function key that will put in a double yellow road centerline, but what combination of letters did we use for the function key (there are 26 letters and 5 unique words in that description). Sometimes when I'm collecting I think good grief, there is what I want right there, it sure would be nice to just change my current parameters to match that existing entity. Well, &lt;/span&gt;&lt;a style="font-family: arial;" href="http://dshimer.blogspot.com/2007/01/need-new-command.html"&gt;back in January I added a quick command&lt;/a&gt;&lt;span style="font-family:arial;"&gt; that came in handy more often than I thought and has grown up since then. The premise was simple, a command that allowed you to Id a line, then start digitizing using the attributes of that line. Remember it looked something like this&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line = PyVrLine ()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui=PyVrGui()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line.Id()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;lay,gp,wid=Line.GetLayer(),Line.GetGpoint(),Line.GetWidth()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui.PushKeyin ('inslin,lay=%d,grp=%d,wid=%d'%(lay,gp,wid))&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;It was so handy that I made one that did the same thing for fly-lines, and symbols. This way when I'm tying to an edge or come across something I forgot, and can't remember the function key, all I need is the short mnemonics for my inhlin, inhfly, and inhsym commands. Then I got thinking, what if I'm already digitizing a line or symbol and want to match something I happen upon? Well here is my inhent.py which some folks might find a bit odd but it also gives examples of a couple of useful Vr Objects&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;print 'inhent.py Inherit From Entity modified 8:52 AM 10/31/2007'&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;'''&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;Copyright 2007 Dennis Shimer, M.A.N. Mapping Services Inc.&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;Vr Mapping copyright Cardinal Systems, LLC&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;No warranties as to safety or usability expressed or implied.&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;Free to use, copy, modify, distribute with author credit.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;Asks user to identify an entity, then sets certain&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;parameters inherited from the identified entity.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;'''&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;Line=PyVrLine()&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;Sym=PyVrSym()&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;Text=PyVrText()&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;Gui=PyVrGui()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;Ws=PyVrWs()&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold; color: rgb(153, 102, 51);font-family:courier new;" &gt;# There are a couple of times we'll need to multiply by the scale because ground&lt;br /&gt;# units are returned, and we'll need to set based on map units.&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;Scale=PyVrWs().GetTargetScaleIn(Ws.Aws())&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;EntWs,EntNum,EntType,LinePtNum,x,y,z=Ws.IdEnt(-1,-1,-1,-1)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold; color: rgb(153, 102, 51);font-family:courier new;" &gt;# Man I love IdEnt, it isn't in the documentation yet but by using&lt;br /&gt;# -1 in the SeaEnttype spot, it remembers the last state.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;if EntType==1:&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold; color: rgb(153, 102, 51);font-family:courier new;" &gt;# If it's a line grab the appropriate settings&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;...Line.Load(EntWs, EntNum)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;...Layer,Graphic,Width=Line.GetLayer(),Line.GetGpoint(),Line.GetWidth()&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold; color: rgb(153, 102, 51);font-family:courier new;" &gt;# This line is left over from when I forced the user to hit end after&lt;br /&gt;# identifying the entity, which was useful if you grabbed the wrong one&lt;br /&gt;# but I found I liked it this way better, so the following line doesn't&lt;br /&gt;# really matter because it just does it after you id something.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;...Gui.DspMsg0 ('lay=%d, grp=%d, wid=%d'%(Layer,Graphic,Width))&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;...Type='Line'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;if EntType==3:&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold; color: rgb(153, 102, 51);font-family:courier new;" &gt;# Ditto if it's a symbol.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;...Sym.Load(EntWs, EntNum)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;...Layer,Graphic,Radius,Rotation=Sym.GetLayer(),Sym.GetGpoint(),(Sym.GetRad()/Scale),Sym.GetRot()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;...Gui.DspMsg0 ('lay=%d, grp=%d,rad=%.3lf,rot=%.3lf'%(Layer,Graphic,Radius,Rotation))&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;...Type='Symbol'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;if EntType==4:&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold; color: rgb(153, 102, 51);font-family:courier new;" &gt;# or even a piece of text.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;...Text.Load(EntWs, EntNum)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;...Layer,Font,Height,Width,Rotation,Label=Text.GetLayer(),Text.GetFontNum(),(Text.GetHgt()/Scale),(Text.GetWdt()/Scale),Text.GetRot(),Text.GetText()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;...Gui.DspMsg0('lay=%d,fnt=%d,hgt=%.3lf,wdt=%.3lf,rot=%.3lf,txt=%s'%(Layer,Font,Height,Width,Rotation,Label))&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;...Type='Text'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold; color: rgb(153, 102, 51);font-family:courier new;" &gt;# Once you grab the settings desired, the only thing left to do is&lt;br /&gt;# push the proper key-ins.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;if Type=='Line':&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;...Gui.PushKeyin ('lay=%d,grp=%d,wid=%d'%(Layer,Graphic,Width))&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;elif Type=='Symbol':&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;...Gui.PushKeyin ('lay=%d,grp=%d,rad=%.3lf,rot=%.3lf'%(Layer,Graphic,Radius,Rotation))&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;elif Type=='Text':&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;...Gui.PushKeyin ('lay=%d,fnt=%d,hgt=%.3lf,wdt=%.3lf,rot=%.3lf,txt=%s'%(Layer,Font,Height,Width,Rotation,Label))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Given that there probably aren't 3 people in the world that read this on a regular basis, I'll probably hit it about once a month from now on. Don't forget to contribute to the forum.&lt;br /&gt;&lt;br /&gt;Happy coding.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-8607739373777615920?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/8607739373777615920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=8607739373777615920' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/8607739373777615920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/8607739373777615920'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/11/inherit-everything-but-kitchen-sink.html' title='Inherit everything but the kitchen sink.'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-8720049902235251753</id><published>2007-08-07T02:08:00.000-05:00</published><updated>2007-08-07T02:34:43.955-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='NonVr'/><title type='text'>Time out</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: arial;"&gt;It is that time of year when I begin to pursue my second job as middle school soccer coach, and high school referee (and parent spectator). Because of this, I'm not even going to think about posting until late October.&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-8720049902235251753?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/8720049902235251753/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=8720049902235251753' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/8720049902235251753'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/8720049902235251753'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/08/time-out.html' title='Time out'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-2629634965553122195</id><published>2007-07-19T15:10:00.000-05:00</published><updated>2007-07-24T14:27:10.413-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Advanced'/><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><title type='text'>Finally A Vr Command</title><content type='html'>&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;Well enough playing around with external files. It's about time to head back to what VrPython was intended for and write a new function. This one in particular allows the user to parallel part of an existing line. This is a good example of how a program evolves (to say it was intelligently designed probably infers too much), because as it started off the user had to digitize the offset distance. Then with the advent of VrArgs in 3.3.? it seemed like a good idea to put in the option to enter an offset as a argument after the user typed parpart. Of course with the opportunity to put in a argument as an offset, it seemed silly to not have a dialog somewhere. The problem was that I didn't want dialog every time, and you already had to Id the line, start point, end point, and offset which was approaching the limits of how much I wanted the user to have to do. Hence the decision that if you got all the way to the point of digitizing the offset and hadn't specified one but hit an "end" or "#" without doing so the program would bring up a dialog to allow typing one in. Well let's take a look&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt; &lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;span&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;#This has become the standard I use to start each program.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;print 'parprt.py ParallelPartial modified 8:23 AM 7/13/2007'&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;'''&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;Copyright 2007 Dennis Shimer, M.A.N. Mapping Services Inc.&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;Vr Mapping copyright Cardinal Systems, LLC&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;No warranties as to safety or usability expressed or implied.&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;Free to use, copy, modify, distribute with author credit.&lt;/span&gt;  &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;br /&gt;Inserts a line parallel to the identified line.&lt;br /&gt;Allows for picking start and&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;end points of new line, and offset.&lt;br /&gt;If a number is passed it as the first&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;it will be used as an offset.&lt;br /&gt;If the &lt;#&gt; End button is pressed during offset&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;measurement a&lt;br /&gt;dialog will come up prompting for offset.&lt;/span&gt;  &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;'''&lt;br /&gt;&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;Ws=PyVrWs()&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;Line=PyVrLine()&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;Gui=PyVrGui()&lt;/span&gt;  &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;WsNum=Ws.Aws()&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;span&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;# Create all the objects we will use.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;while Line.Id() != -1:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;#&lt;/span&gt; &lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;span&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;In theory you could partially parallel many lines&lt;br /&gt;# though in reality it doesn't happen much, but will do so&lt;br /&gt;# until the user doesn't Id a line which returns -1.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;....Ws.UndoBegin(WsNum,"inspar_part")&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;span&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;# The undo is inside the Id loop so each line paralleled&lt;br /&gt;# could be undone individually.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:85%;" &gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;br /&gt;....Gui.DspMsg0('Dig start of new line')&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;span&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;# Since GetCoord() isn't very customizable as far as buttons&lt;br /&gt;# and messages, we'll display instructions in the message area.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:85%;" &gt; &lt;span style="font-family:courier new;"&gt;....Stat1,NewX1,NewY1,NewZ1=Gui.GetCoord('Point1')&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;span&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;# And get a coordinate for where the newly paralleled line&lt;br /&gt;# Should begin.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;....Gui.DspMsg0('Dig end of new line')&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;....Stat2,NewX2,NewY2,NewZ2=Gui.GetCoord('Point2')&lt;br /&gt;&lt;/span&gt; &lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;span&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;# And the same on the other end.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;....if VrArgs:&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;........print VrArgs&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;........Offset=float(VrArgs[0])&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;span&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;# This whole if statement was added later after the introduction&lt;br /&gt;# of VrArgs. If a string (or multiple strings) are placed after&lt;br /&gt;# the script name, they are passed in as a list of strings. So the&lt;br /&gt;# test would fail if VrArgs was empty (nothing passed) and would&lt;br /&gt;# pass to the else statement. If however something was passed,&lt;br /&gt;# convert it to a real number and assign it to the offset. Bonus&lt;br /&gt;# points for anyone who identifies the huge bug I just noticed in&lt;br /&gt;# this 3 line block.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;....else:&lt;br /&gt;&lt;/span&gt; &lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;span&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;# In other words if VrArgs is not true (is empty).&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;........Gui.DspMsg0('Dig offset # End for dialog')&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;........StatS,SnapX,SnapY,SnapZ=Gui.GetCoord('Offset')&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;span&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;# Same as above, display instructions and read a coordinate&lt;br /&gt;# that represents how far the cursor is from the line.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;........Offset=-1.0*(Line.SnapPoint (SnapX, SnapY)[3])&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;span&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;# Use the computed offset. The -1 is just to correct for&lt;br /&gt;# how SnapPoint computes the distance.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;........if StatS:&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;span&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;# This comes about if the user hits the end button instead&lt;br /&gt;# of a 1 to cancel the digitize offset.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;............PromBox=VrPromBox('Prompt title',20,1)&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;............PromBox.AddDouble('Enter a real number',.5,2)&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;............if (PromBox.Display(0) == 0):&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;................Offset=PromBox.GetDouble(0)&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;span&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;# Just a simple prombox to allow for entering the offset if&lt;br /&gt;# it wasn't passed or computed in any other way.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;....Num1=Line.SnapPointAdd (NewX1,NewY1,0.0)&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;....Num2=Line.SnapPointAdd (NewX2,NewY2,0.0)&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;span&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;# We are adding points to the line object that was identified&lt;br /&gt;# this is ok because later we will Rec() instead of ReRec() which&lt;br /&gt;# will create a new line.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;....if Num1&gt;Num2:&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;........tmp=Num1&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;........Num1=Num2&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;........Num2=tmp&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;span&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;# At one point DelPoints didn't work properly if the beginning&lt;br /&gt;# point was higher than the end point (it may not still, but doesn't&lt;br /&gt;# really matter if it is checked and swapped if necessary.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;....Line.DelPoints (Num1, Num2, 1)&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;span&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;# Mode 1 in effect deletes points outside begin and end rather&lt;br /&gt;# than between them (which would be mode 0)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;....Line.Offset(Offset)&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;....Line.Rec(WsNum)&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;....Line.Plot()&lt;/span&gt; &lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;&lt;span&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;# Take that line object, offset it by the distance entered or&lt;br /&gt;# computed, record it as a new entity, plot it and there you go.&lt;br /&gt;# Part of the original line has been stored as a new line parallel&lt;br /&gt;# to it.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;....Ws.UndoEnd(WsNum)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;Reminder that as with all other scripts, you can either copy and paste what you see here (substituting your prefered indentation for the holding characters "....", or find the original at http://python4vr.googlepages.com&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-2629634965553122195?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/2629634965553122195/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=2629634965553122195' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/2629634965553122195'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/2629634965553122195'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/07/finally-vr-command.html' title='Finally A Vr Command'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-3417194371065773911</id><published>2007-07-10T21:45:00.000-05:00</published><updated>2007-07-10T21:56:26.143-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Advanced'/><category scheme='http://www.blogger.com/atom/ns#' term='NonVr'/><title type='text'>Life Outside Vr Wrap Up (almost)</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: arial;"&gt;Before going back to writing functions for Vr let's wrap up a couple of things. First binary files, I have recently begun to like the idea of persistent parameters for several of my programs. I really need to create some basic generic parameter code to paste in. In the end I'll probably settle on ascii files with keywords, or at least comments. But what if you want to use binary, or what if you want to read a binary file that you know (or could guess) the structure of. An example is the old .COO coordinate files used by orientp3 in pre-Vr days. We still use it and often want to work directly with the .COO files for various things. But they are binary, here are some basics working with something similar to the parameter file we used before. This will be plain python, you can copy and paste this, download testbinary.py from my source code website, then either run it from a command line like&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;python testbinary.py&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;or open or paste it into pyedi and run it inside Vr. The only requirement is that you will need to have python installed because it uses two standard modules. By this time I am going to assume some python knowledge and ability to read the code. I am thrilled to answer any questions that come up, but I will post this code in a very plain, line at a time manner rather than using multiple methods on a single line. I'm also going to use my favorite method of accessing binary data since as is common in python there are probably dozens of ways of doing it. You could probably do this in about 8 lines but the point is to explain what is going on. I'll also assume that anyone interested in this would take the time to look up the modules listed to see how many cool things they will do... So here goes&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;If you were to run this script 3 consecutive times it would give 3 different responses. First that the parameter file was created but without any values read. Second it would read the default values, tell you what the values are and modify them. Third it will read the modified values print them out and tell you that it found modified values and not the defaults.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;import os,struct&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;# We'll use os to test for the existence of the file, an struct to &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;# interact with the binary data.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;FormatString='10sddi'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;'''&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;The format string tells several parts of the program what we are working&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;with in regards to binary data. The format string listed above represents&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;a 10 character string, 2 double precision real numbers, and an integer.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;Same as before but I added the int to show by example. Note that it is&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;just a string with letters representing different kinds of data.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;'''&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;ParFileName='testbinary.par'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;# The file by this name will show up in the directory the script is run in.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;print 'Bytes occupied by binary data',struct.calcsize(FormatString),'\n\n'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;'''&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;Sometimes you need to know how many bytes to read from a file in order&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;to get one set of data when multiple sets exist, a good example goes&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;back to the coordinate file mentioned earlier. In order to read and process&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;one point at a time you can only read the necessary bytes. the calcsize&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;method in struct will read a format string and tell how many bytes are&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;represented. You can go into a python interpreter, import struct then&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;evaluate some single item format strings like the following for a&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;float, a double, an int, and a 1 character string.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&gt;&gt;&gt; struct.calcsize('f')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;4&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&gt;&gt;&gt; struct.calcsize('d')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;8&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&gt;&gt;&gt; struct.calcsize('i')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;4&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&gt;&gt;&gt; struct.calcsize('s')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;'''&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;if not os.path.isfile(ParFileName): # If the file doesn't exist.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;ParFile=open(ParFileName,'wb')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;# Then open it in write (create or erase) mode with a binary modifier&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;BinaryData=struct.pack(FormatString,'Word',.2,.0,0)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;'''&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;The pack method in the struct module uses the format string to process&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;the data that comes next into the bytes which represent them in binary&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;form. It is important that the amount and type of data following the&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;format string match, notice I am passing in a string (less than 10&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;characters allowed, 2 real numbers and an integer.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;'''&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;ParFile.write(BinaryData)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;ParFile.close()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;# We have a binary file and binary data so just and write and close it.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;print 'Program run with no existing file'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;print 'Data set to defaults.'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;print 'testbinary.par should now exist.'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;else:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;ParFile=open(ParFileName,'r+b')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;# If it does exist open for reading + writing with binary modifier.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;BinaryData=ParFile.read()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;'''&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;This time since the file exists we are going to get the binary data&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;right out of the file with a read. Since we want the whole file there &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;is no reason to use calcsize to tell it how many bytes to read.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;'''&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;DataList=struct.unpack(FormatString,BinaryData)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;# Going the other direction, lets use unpack to use the format string&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;# to convert the binary data into a list of values.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;print 'Data from file, note it is a list\n   ',DataList&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;# and print the list.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;ParFile.seek(0,0)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;'''&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;Now assuming that there are new values that need to be used to update&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;the parameter file. The first thing we need to do is go back to the&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;beginning of the file, read up on seek, but this basically moves you&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;0 bytes from the beginning. If in the coordinate file example I had a&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;data structure that require 24 bytes and wanted to get the 3rd value &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;from the file I could to the 48th byte and read 24. This way you can&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;read, write, and overwrite data in place within a file.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;'''&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;print 'File position after seek ',ParFile.tell()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;# Every open file has a tell method which gives the current position.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;BinaryData=struct.pack(FormatString,'Updated',1,2,3)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;ParFile.write(BinaryData)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-size:85%;" &gt;&lt;span style="font-family: courier new; font-weight: bold;"&gt;...&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;# Same idea as above, just using the changed data (wherever it came from)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...if DataList[0].split('\x00')[0]=='Updated':&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;......&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;print 'You have seen it all.'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;......&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;print 'Remove testbinary.par to start over'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;......&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;'''&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;......&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;There may be a better way to convert this 10 character string to&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;......&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;what you normally think of as a string, but it comes back padded&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;......&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;with the 0 bytes and this works simply enough. Think of it this&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;......&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;way 'Updated\x00\x00\x00' has 3 extra bytes, if you split on that&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;......&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;character you get back ['Updated', '', '', ''] of which 'Updated'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;......&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;is the first or [0] element. Ugly but I've never really look into&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;......a better way.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;......'''&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;        &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...else:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;......print 'Program run with an existing file'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;......print 'Data was updated run again to see change'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;......# 2nd run string doesn't equal 'Updated' so print appropriate message.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;    &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...ParFile.close()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(153, 102, 51);"&gt;...# Good form to explicitely close files.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;I need to wrap it up for now, I'll have to save the parsing command for next time.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-3417194371065773911?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/3417194371065773911/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=3417194371065773911' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/3417194371065773911'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/3417194371065773911'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/07/life-outside-vr-wrap-up-almost.html' title='Life Outside Vr Wrap Up (almost)'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-5080502666163911406</id><published>2007-06-21T21:03:00.000-05:00</published><updated>2007-06-21T21:14:09.582-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><category scheme='http://www.blogger.com/atom/ns#' term='NonVr'/><title type='text'>Life Outside Vr 4</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: arial;"&gt;We've looked at external files with the goal of getting useful information out of them. At the same time how about saving something there. We use a program that takes symbols in a certain layer, compares their elevation to an active dtm, and if they are over a specified distance from the elevation displays the error. It is a very useful program and when it was first written had all the variables hard coded, but stored at the beginning of the file so they could be easily found and changed. With the advent of PromBox it just became too easy to allow the user to confirm and change the variables each time. You could even easily use the old hard coded values as defaults. However it seemed like a certain set of values would be used over and over again based on job specifications. The obvious solution would be to have the last values used stored between runs to be used as the new defaults. Storing values like this is easy enough, but what elements would the most elegant solution contain? I have no idea but I did come up with a couple of features I really wanted. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;First lets store them in a logical location like /vr/hostdir where all the other function parameter files are stored. Truthfully it would probably be better to make a user parameter directory, but I'll be lazy for now because the next thing I wanted was a test to see if the parameter file existed already and if not, would create one with the original default values. Yes I could test for a folder and if it wasn't there create it but maybe that will come in the next version but for now I didn't really want to change the directory structure.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255); font-weight: bold;"&gt;import os&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(153, 102, 51);"&gt;# os is necessary to test the existence of the parameter file.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255); font-weight: bold;"&gt;ParFileName='c:/vr/hostdir/save_params.par'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(153, 102, 51);"&gt;# Call it what you want, this is great code to save for later use in other&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(153, 102, 51);"&gt;# programs that require persistence.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255); font-weight: bold;"&gt;if not os.path.isfile(ParFileName): # Does the file exist.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255); font-weight: bold;"&gt;     open(ParFileName,'w').write('%d %.3f %.3f'%(86,.2,0.0))&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(153, 102, 51);"&gt;# If not then create it in write mode and write an integer and 2 floating&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(153, 102, 51);"&gt;# point numbers with 3 decimal places.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255); font-weight: bold;"&gt;Params=open(ParFileName,'r').read().split()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(153, 102, 51);"&gt;# Since it either existed or was created all we need to do now is open, read&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(153, 102, 51);"&gt;# and split the values into a list that would look like ['86','.2','0.0']&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255); font-weight: bold;"&gt;PromBox=VrPromBox('Display Sym to Dtm',20,1)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255); font-weight: bold;"&gt;PromBox.AddInt('Layer to Check',int(Params[0]),1,1000)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255); font-weight: bold;"&gt;PromBox.AddDouble('Display delta &gt;',float(Params[1]),2)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255); font-weight: bold;"&gt;PromBox.AddDouble('Text Rotation',float(Params[2]),1)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(153, 102, 51);"&gt;# Using the values stored in the Params list make a prombox which will allow&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(153, 102, 51);"&gt;# the user to change the values.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255); font-weight: bold;"&gt;if (PromBox.Display(0) == 0):&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255); font-weight: bold;"&gt;...LayerToCheck=PromBox.GetInt(0)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255); font-weight: bold;"&gt;...DisplayDelta=PromBox.GetDouble(1)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255); font-weight: bold;"&gt;...TextRot=(PromBox.GetDouble(2))&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(153, 102, 51);"&gt;# Grab the new values.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255); font-weight: bold;"&gt;open(ParFileName,'w').write('%d %.3f %.3f'%(LayerToCheck,DisplayDelta,TextRot))&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(153, 102, 51);"&gt;# And write them out to a file.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;I won't spend the time on all the uses for keeping persistent variables between sessions, but this is the basics.&lt;br /&gt;&lt;br /&gt;This just about wraps it up for reading and writing files, except for maybe writing parameters as a binary file, just for the fun of it and maybe walking through the single line parser I posted on the forum. It isn't very flexible but offers some interesting lessons. Here's a peek.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255); font-weight: bold;"&gt;alist=[]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255); font-weight: bold;"&gt;for line in open('hughes.pxyzopk','r').readlines():Alist.append(line.split())&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-5080502666163911406?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/5080502666163911406/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=5080502666163911406' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/5080502666163911406'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/5080502666163911406'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/06/life-outside-vr-4.html' title='Life Outside Vr 4'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-8923391594472613329</id><published>2007-06-08T23:06:00.000-05:00</published><updated>2007-06-22T06:39:22.370-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Advanced'/><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><category scheme='http://www.blogger.com/atom/ns#' term='NonVr'/><title type='text'>Life Outside Vr 3 (well not very far outside)</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Actually not at all, but the point isn't that we need to work outside Vr, it is that there is a whole world of files available using some straight python functionality. Now that we have a little file opening and reading under our belts, lets come back into Vr and bring a little of that technique with us. Let's also work on tightening up the code a little. If you are fairly new to VrPython, I think you'll really like this one. We are going to let Vr tell us the name of the file to open (in this case the current function key file) then using standard python we'll open, read, and parse the data we want out of the file, then use Vr to build a prompt box. For this example the data we want is all the function key names, and the prompt box will allow us to pick a function key name. Why? Well how about if you were going to write a parallel function using the existing inspar command but wanted to change the PARMOD= to "Function Key" and wanted to select the function key from a list then send it using the FKEY= key-in. If so, here is one way to get the function key name. It is rather long and convoluted but I'll try to make it worth what you are paying for the look.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;Cfig=VrCfg()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span style="color: rgb(204, 153, 51);"&gt;# We'll need a Vr config object to access the name of the currently&lt;br /&gt;# loaded function key file name.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;FileName=Cfig.GetFkeyFileName()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# Grab the name.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;FkeyFile=open(FileName,'r')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# Open the file &lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;FileData=FkeyFile.read()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# We're going to read the file twice. This time as a string so we can count the&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# instances of the key-word "KeyName" to figure out how many entries our&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# prompt box will need.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;NumberOfFunctionKeys=FileData.count('Fkey KeyName')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# Use the string method count to do just that.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;PromBox = VrPromBox ("Function Keys", 60, 1)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# Create a PromBox object.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;PromBox.AddList ("Select a Function Key",NumberOfFunctionKeys , 40, 0)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# I'll skip helpful text and just get right to the listbox of length equal to&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# the number of function keys.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;FkeyFile.seek(0,0)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# Rewind the file to read it again.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;FileData=FkeyFile.readlines()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# This time read it as a list, each element of which is a line from the file.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;for FileLine in FileData:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# For each line in the data list.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;..if FileLine.count('Fkey KeyName') != 0:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# Test to see if it is a line containing the function key name.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;....FkeyName=FileLine.split()[2]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# If so split the line data into the three words&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# 'Fkey','KeyName','ActualName' which is in itself a list, the third element&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# of which ( [2] ) is the actual name of the function key.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;....PromBox.AddListItem(FkeyName)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# Add that to the list of items to be displayed.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;FkeyFile.close()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# Could have closed it after the readlines() but just go ahead and do it now.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;if (PromBox.Display(0) == 0):&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;..FunctionKey=PromBox.GetList (0)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# Standard prompt box usage to grab a list item&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;print FunctionKey&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(204, 153, 51);font-family:courier new;" &gt;# and print it out (or use it in an interesting way)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Now as far as tightening it up. I could have read the file only once and built a for loop to count the instances of the KeyName key-word, but I'm going to go in a totally different direction. I'm still going to read the file twice, as a matter of fact I'm going to open it twice. The goal of this exercise is to get as few lines of code as I can. I'm not going to profess that this is the tightest and most efficient. It just has a lot less lines of code and is intended to make you think. Look at it first, then read the explanation.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;PromBox = VrPromBox ("Function Keys", 60, 1)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;PromBox.AddList ("Select a Function Key", open(VrCfg().GetFkeyFileName (),'r').read().count('Fkey KeyName'), 40, 0)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;for FileLine in open(VrCfg().GetFkeyFileName (),'r').readlines():&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;..if FileLine.count('Fkey KeyName'):PromBox.AddListItem(FileLine.split()[2])&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;if (PromBox.Display(0) == 0):print PromBox.GetList (0)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold;"&gt;Line 1:&lt;/span&gt; We have to create a prompt box object because I can't find any way around it and we'll need to use methods of this specific object in the next line.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold;"&gt;Line 2:&lt;/span&gt; Let's take this a step at a time.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold;"&gt;A)&lt;/span&gt; Add to the list using the formula AddList (Prompt, NumItems, Height, DefaultItem) Prompt is set to "Select a Function Key", NumItems is the tricky part, Height is 40 and DefaultItem is 0.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold;"&gt;B)&lt;/span&gt; Look at the NumItems formula and read it as follows&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Open a file using the string returned by a VrCfig() object method GetFkeyFileName in read mode ( 'r' ) which open file object you should read() the data, of which data you should count() the number of occurrences of 'Fkey KeyName'. Notice that when all this is said and done it just give a number which represents the number of function key names and therefore the number of function keys&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Now that we have a prompt box which contains a list set to the length equal to the number of function key names, let's populate the list with those names.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold;"&gt;Line 3:&lt;/span&gt; For each element in a list, the list comes from opening the same file again, in read mode again, but this time instead of read() to get one solid string, we use a method that will return a list which is exactly what the for loop is working on. We are looping on a list that was created and populated just for the loop, each element of which is a line from that file.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold;"&gt;Line 4:&lt;/span&gt; FileLine represents the line of data out of the file which is being examined as we loop over the entire list of lines. count() tells how many occurrences of a work exist in the string 0 means none which in terms of an if means false so any other number that comes back means true (the string exists, therefore it is a function key name). if it is true we want to add the actual name to the list. The actual name as we saw above means splitting the string, which creates a list, from which we want element [2]. So add to the list the third word which is the result of splitting the string because it does (true) contain the phrase 'Fkey KeyName'. I didn't add another line and indent it because there is only one statement to execute if true which allows you to just put it after the colon and be done with it.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold;"&gt;Line 5:&lt;/span&gt; Same idea, standard prombox syntax, but since there is only one action, just put it on the same line. Ugly code but remember my only goal was to reduce the line count. And why put the string in a variable just to print it on the next line, print it as it returns from GetList()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;And I haven't even taken the time to explain the forum post regarding reading and parsing aerosys .pxyzopk files, a great example of the kind of data we mappers work with all the time. Maybe next time.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-8923391594472613329?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/8923391594472613329/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=8923391594472613329' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/8923391594472613329'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/8923391594472613329'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/06/life-outside-vr-well-not-very-far.html' title='Life Outside Vr 3 (well not very far outside)'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-4377498078070772034</id><published>2007-05-21T09:48:00.000-05:00</published><updated>2007-05-21T12:03:22.692-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><category scheme='http://www.blogger.com/atom/ns#' term='NonVr'/><title type='text'>Life Outside Vr 2</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Ok I have a few minutes so let's look at actually reading some data out of an open file. We'll stick with ascii files for now. There are so many fun reasons to work with files outside Vr that it would take too long to enumerate all of them but a few of my favorites include.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;ul  style="font-family:arial;"&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Reading info out of an ImageUtil project and creating all the Vr2Ori project and all models with 1 click.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Converting all Vr2Ori and VrAt files to or from their corresponding equivalents in orientp3 (yes we still use it and get along fine) so a setup in the analytical equals a setup in softcopy or vice versa.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Reading a PATB and plotting it graphically in VrOne for visual analysis and blunder checking.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;Reading and plotting AT results including photos, layout data, computed extents and photo scale based on image centers and control averages.&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;You get the idea, there are just so many files out there that can be of easy use with a click or two. Sometimes there is already a way to do the same things, but a custom program allows you to set things up exactly the way you want without any further intervention. As in the last post we'll be working with vr.cfg in read only mode because it is a file that exists on everyones system (if you are working in Vr, which I assume) and has the same basic patterns. Again I will suggest you work in some kind of python IDE, I suggest pythonwin but you could even work from the python command interpreter if you want.&lt;br /&gt;&lt;br /&gt;Let's start by creating a python file object like we did last time, it will be called f (for file).&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;f=open('/vr/hostdir/vr.cfg','r') # 'r' means read mode.&lt;/span&gt;&lt;br /&gt;now if I&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;print f&lt;/span&gt;&lt;br /&gt;there should be some obscure text describing the object. Hopefully there was some time to look over the file object docs to study up on the simple methods, let's look at a few.&lt;br /&gt;Read one line out of the open file&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&gt;&gt;&gt; f.readline()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;'# VR Configuration File\n'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;I&lt;/span&gt; should note here that once it reads the line, the address in the file that python is sitting at is the beginning of the next line so if you do it again&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&gt;&gt;&gt; f.readline()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;'# FileName       : c:\\vr\\hostdir\\vr.cfg\n'&lt;/span&gt;&lt;br /&gt;if for some reason it is necessary to go back to the beginning of the file we need to "seek" the new position. seek takes two arguments "offset" (how much to jump from the position passed in) and "whence" (where to start the offset). "Whence" defaults to the beginning of the file, so if you want to go the the beginning you can say "see" with an offset of 0 (don't move at all from the position passed in) and a whence of 0 (or if you pass nothing for whence this is the default) so&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;f.seek(0,0) # 0 offset, 0 whence&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;f.seek(0) # 0 offset, default whence which is 0&lt;/span&gt;&lt;br /&gt;will both take python to the beginning of the file, so do that then readline() again and you should see the first line again. Let's read that first line and store it as a string we'll call "s"&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&gt;&gt;&gt; s=f.readline()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&gt;&gt;&gt; print s&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;# VR Configuration File&lt;/span&gt;&lt;br /&gt;It would of course be possible to do this with each line of the file, though there are better methods to be discussed later, but lets look a what we could do with that string now that we have it.&lt;br /&gt;I can split it based on white spaces (the default for split) which returns a list of the words in the string.&lt;br /&gt;&gt;&gt;&gt; s.split()&lt;br /&gt;['#', 'VR', 'Configuration', 'File']&lt;br /&gt;For that matter we could split it based on any character like commas, or in this case the "i"&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&gt;&gt;&gt; s.split('i')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;['# VR Conf', 'gurat', 'on F', 'le\n']&lt;/span&gt;&lt;br /&gt;Note that splitting on white spaces takes off the newline character but splitting on a printable character doesn't. Of course there are plenty of ways to take the newline off, but just take note for now. How about if we needed to test for a sub string inside the string, well let's count occurrences.&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&gt;&gt;&gt; s.count('i')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;3&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&gt;&gt;&gt; s.count('ig')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&gt;&gt;&gt; s.count('z')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;0&lt;/span&gt;&lt;br /&gt;So a test would look something like&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;&gt;&gt;&gt; if s.count('ig') : print 'yes'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;... &lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;yes&lt;/span&gt;&lt;br /&gt;I didn't say if s.count equals something or is greater than something because I just wanted to know if it was non zero and anything non zero is true for the if test.&lt;br /&gt;&lt;br /&gt;There is no sense typing out all the things you can do with strings because they are &lt;a href="http://docs.python.org/lib/string-methods.html"&gt;documented in the python docs&lt;/a&gt;, it is worth noting that there used to be a string module, but now each of these methods is a built-in which is why there was never an import statement above.&lt;br /&gt;&lt;br /&gt;Let's go back to the split step and put the resulting list in a variable called "l", then we can loop over the list and do whatever we want, in this example just print each item.&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&gt;&gt;&gt; l=s.split()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&gt;&gt;&gt; l&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;['#', 'VR', 'Configuration', 'File']&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&gt;&gt;&gt; for item in l:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...     print item&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;...     &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;#&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;VR&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;Configuration&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;File&lt;/span&gt;&lt;br /&gt;or grab individual elements of the list.&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&gt;&gt;&gt; l[3]&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;'File'&lt;/span&gt;&lt;br /&gt;or test to see if the list contains certain values.&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&gt;&gt;&gt; l.count('File')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&gt;&gt;&gt; l.count('Nothing')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;0&lt;/span&gt;&lt;br /&gt;Like strings I'll leave the explanation of lists and their methods to the professionals,&lt;a href="http://docs.python.org/tut/node7.html"&gt; in this case the python tutorials&lt;/a&gt;.&lt;br /&gt;But I'll leave with a couple of thoughts:&lt;br /&gt;First, check out readlines() it will come in handy and will probably bear heavily in the next post.&lt;br /&gt;Second, one of the real beauties of python is it's ability to get a lot done with a little code, this can be accomplished by taking whatever data a method returns and acting on it with the appropriate method. Consider the following lines typed into the interpreter.&lt;br /&gt;&lt;br /&gt;open() is going to return a file object with all it's accompanying methods.&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-family: courier new; font-weight: bold;"&gt;&gt;&gt;&gt; open('/vr/hostdir/vr.cfg','r')&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(204, 0, 0); font-family: courier new;"&gt;obscure text describing an open file object&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;let's just tack the readline() onto the end and let it return the first line which is a string.&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&gt;&gt;&gt; open('/vr/hostdir/vr.cfg','r').readline()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;'# VR Configuration File\n'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It it is a string we can split it to get a list of words that were included.&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&gt;&gt;&gt; open('/vr/hostdir/vr.cfg','r').readline().split()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;['#', 'VR', 'Configuration', 'File']&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Of course the list is made up of elements that can be addressed lets get the second element whose index is 1.&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold; font-family: courier new;"&gt;&gt;&gt;&gt; open('/vr/hostdir/vr.cfg','r').readline().split()[1]&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold; font-family: courier new;"&gt;'VR'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Which is a string and can be forced to lower case using the lower() method.&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;&gt;&gt;&gt; open('/vr/hostdir/vr.cfg','r').readline().split()[1].lower()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(51, 51, 255);"&gt;'vr'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Is this stuff cool or what.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-4377498078070772034?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/4377498078070772034/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=4377498078070772034' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/4377498078070772034'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/4377498078070772034'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/05/life-outside-vr-2.html' title='Life Outside Vr 2'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-5525982070057863977</id><published>2007-05-10T18:04:00.000-05:00</published><updated>2007-05-14T09:52:31.883-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><category scheme='http://www.blogger.com/atom/ns#' term='NonVr'/><title type='text'>Life outside Vr</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;I have had several folks ask about opening reading and parsing external files. There are so many applications that I don't even know where to begin. Whether plain ascii text files, or binary, python is loaded with tools for doing what you want or need. I think I'll just start rambling and see where we head. One thing that you will notice immediately is that there can be literally dozens of ways of accomplishing the same task. I'm not going to pretend that what I am putting forward is the best or most efficient, I'll just mention some tools that come in handy quite often. For today lets just open a file and grab some data from it. Let's pick a file that everyone should have, that being your Vr configuration file \vr\hostdir\vr.cfg. Don't worry, for now we'll just open it in read only mode. In your favorite python editor or pyedi within VrOne type and run the following.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:arial;" &gt;f=open('\vr\hostdir\vr.cfg','r')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;Ok, I'll admit that was a trick, it shouldn't have worked, even though everything about the command is totally correct, except that is for the backslashes "\". But wait you say, we are working in windows, and the backslash is what is always used to specify path hierarchy, and you would be correct. The problem is that the backslash is a special character in python (and several other languages, not to mention unix). Python uses a forward slash to separate path elements, or to use backslashes you have to tell python you are sending it a "raw" string and that it should not treat the backslashes as escape characters. I don't start here to be bothersome, but it is important to understand that python expects certain things and may send back something you aren't expecting if you aren't careful. Note the paste of a session where I open the file using 3 valid commands, look at what comes back, and realize that this is outside VrOne in the PythonWin editor.&lt;br /&gt;&lt;br /&gt;First I open it with forward slashes because I grew up on unix, the forward slash is always in the same place no matter what keyboard you have, it is what python prefers, and I just like it better. I'll use "f" as the open file object and will open it, display it, and close it. The 'r' means to open it in read-only mode, we'll talk about modes later but I digress.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;&gt;&gt;&gt; f=open('/vr/hostdir/vr.cfg','r')&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;&gt;&gt;&gt; f&lt;/span&gt;&lt;br /&gt;&lt;open&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;&lt;open&gt;&lt;/open&gt;&lt;/span&gt;&lt;span style="font-style: italic; color: rgb(204, 0, 0);"&gt;Text describing file object which blogger deletes for some reason.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;&gt;&gt;&gt; f.close()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Next we'll use backslashes, but they have to be protected by another character so they aren't evaluated as an escape sequence, by coincidence the character that does this is a backslash so each occurence must be entered as&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&gt;&gt;&gt; f=open('\\vr\\hostdir\\vr.cfg','r')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&gt;&gt;&gt; f&lt;/span&gt;&lt;br /&gt;&lt;open&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;open&gt;&lt;/open&gt;&lt;/span&gt;&lt;/open&gt;&lt;/open&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-style: italic; color: rgb(204, 0, 0);"&gt;Text describing file object which blogger deletes for some reason.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;open&gt;&lt;open&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&gt;&gt;&gt; f.close()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Next we'll use the backslashes but we'll tell python that the name string is a raw string and that the backslashes shouldn't be evaluated as anything else. Just put an r in front of it and we're good to go.&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&gt;&gt;&gt; f=open(r'\vr\hostdir\vr.cfg','r')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&gt;&gt;&gt; f&lt;/span&gt;&lt;br /&gt;&lt;open&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;open&gt;&lt;/open&gt;&lt;/span&gt;&lt;/open&gt;&lt;/open&gt;&lt;/open&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-style: italic; color: rgb(204, 0, 0);"&gt;Text describing file object which blogger deletes for some reason.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;open&gt;&lt;open&gt;&lt;open&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&gt;&gt;&gt; f.close()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;It is worth noting that if you grab a filename inside Vr using either of the following, it returns forward slashes.&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;print PyVrGui().OpenFileNameDialog('title','c:/vr/hostdir','*.cfg')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;C:/vr/hostdir/vr.cfg&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;print PyVrGui().OpenFileNameDialog('title','c:\\vr\\hostdir','*.cfg')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;C:/vr/hostdir/vr.cfg&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;That will do for now. Yeah it's pretty slim, but I need to go and we'll actually read something next time. For now though it wouldn't hurt to get familiar with some of the &lt;a href="http://docs.python.org/lib/bltin-file-objects.html"&gt;python file methods, from the python docs&lt;/a&gt;. You can also get a little more information on the open function from the &lt;a href="http://docs.python.org/lib/built-in-funcs.html"&gt;built-in functions docs&lt;/a&gt; (just scroll down to open()), this will come in handy when we move to appending, writing, and binary files.&lt;br /&gt;&lt;br /&gt;&lt;/open&gt;&lt;/open&gt;&lt;/open&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-5525982070057863977?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/5525982070057863977/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=5525982070057863977' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/5525982070057863977'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/5525982070057863977'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/05/life-outside-vr.html' title='Life outside Vr'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-4828349512978357835</id><published>2007-05-07T09:59:00.000-05:00</published><updated>2007-05-07T10:02:28.667-05:00</updated><title type='text'>Still breathing</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: arial;"&gt;Just a quick apology that with one graduating college, one high school, and another 2 with year end activities to take in, I just haven't had time to get into anything. I even know where I would like to head but will have to put it on hold for a few weeks. Check back.&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-4828349512978357835?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/4828349512978357835/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=4828349512978357835' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/4828349512978357835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/4828349512978357835'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/05/still-breathing.html' title='Still breathing'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-8750905980790134386</id><published>2007-04-20T14:27:00.000-05:00</published><updated>2007-04-24T06:12:39.950-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><title type='text'>Tag team programming</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Not long ago I was corresponding with W. &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Chesson&lt;/span&gt; Godfrey aka Wild_Bill from the forum and he shared a little script with me. As so often happens when two people look at an issue from two different perspectives they will each solve the puzzle as it best suits their office culture. This is a little something I hadn't thought about before, which I changed to use some functions he wasn't using and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;shazam&lt;/span&gt; (is that a word) we have &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;WsMan&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;py&lt;/span&gt; or workspace manager.  Another reason why discussion is almost always a good thing. This stuff is just too cool.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_JNszxXRCkiw/RikZLhnX-aI/AAAAAAAAABo/O5-P05DAPxw/s1600-h/wsman.jpg"&gt;&lt;img style="cursor: pointer;" src="http://bp0.blogger.com/_JNszxXRCkiw/RikZLhnX-aI/AAAAAAAAABo/O5-P05DAPxw/s400/wsman.jpg" alt="" id="BLOGGER_PHOTO_ID_5055599742492866978" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;PromBox&lt;/span&gt;=&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;VrPromBox&lt;/span&gt;('Set Active &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;Ws&lt;/span&gt;',60,1)&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(102, 51, 51);font-family:courier new;" &gt;# The whole app revolves around a single convenient Prompt box, so create an object.&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;PromBox&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;AddMessage&lt;/span&gt; ("Don't change &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;workspaces&lt;/span&gt;\n in the middle of a function")&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(102, 51, 51);font-family:courier new;" &gt;# A little helpful text.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;PromBox&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;AddCombo&lt;/span&gt; ('&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;Workspaces&lt;/span&gt;',&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;PyVrWs&lt;/span&gt;().&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;GetWsCount&lt;/span&gt;(),0,0)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(102, 51, 51);font-family:courier new;" &gt;'''&lt;br /&gt;We'll use a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;ComboBox&lt;/span&gt; as the user interface, so create it with the&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(102, 51, 51);font-family:courier new;" &gt;number of items set to the number of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;workspaces&lt;/span&gt;. In this case I'm not &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_17"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(102, 51, 51);font-family:courier new;" &gt;&lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_17"&gt;implicitly&lt;/span&gt; creating a workspace object. I just use the class to call&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(102, 51, 51);font-family:courier new;" &gt;a method. Someday I'll test to see if this method of creating a&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(102, 51, 51);font-family:courier new;" &gt;temporary object causes memory problems in things like large loops,&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(102, 51, 51);font-family:courier new;" &gt;but for now I'm just illustrating that you don't necessarily need to&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(102, 51, 51);font-family:courier new;" &gt;do the Ws=PyVrWs() thing.&lt;br /&gt;'''&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;for &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;WsNum&lt;/span&gt; in range(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;PyVrWs&lt;/span&gt;().&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;GetWsCount&lt;/span&gt;()):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;....PromBox.AddComboItem (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;PyVrWs&lt;/span&gt;().&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;GetFileName&lt;/span&gt; (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;WsNum&lt;/span&gt;))&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(102, 51, 51);font-family:courier new;" &gt;# For every workspace, get it's name and add it to the combo box.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;if (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;PromBox&lt;/span&gt;.Display(0) == 0):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;....PyVrWs().SetAws(PromBox.GetCombo(0))&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(102, 51, 51);font-family:courier new;" &gt;# If the user didn't hit cancel, then set the active workspace&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(102, 51, 51);font-family:courier new;" &gt;# &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(102, 51, 51);font-family:courier new;" &gt;to match the one selected.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Get involved in the forums, there is a wealth of experience to be shared.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-8750905980790134386?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/8750905980790134386/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=8750905980790134386' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/8750905980790134386'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/8750905980790134386'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/04/tag-team-programming.html' title='Tag team programming'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_JNszxXRCkiw/RikZLhnX-aI/AAAAAAAAABo/O5-P05DAPxw/s72-c/wsman.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-3649068919791161501</id><published>2007-04-16T04:38:00.000-05:00</published><updated>2007-04-16T05:18:20.106-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><category scheme='http://www.blogger.com/atom/ns#' term='NonVr'/><title type='text'>Utility programs 3</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Ok, time flies and all, but we better get some actual working code in this thing. In post 1 all we did was create a usage string and test argv to see if anything had been passed in (in this case we don't want anything). In the second we used glob to build a list of files matching a certain extension in the directory we're working in. Eventually we could us a windows file select dialog but for now this will be a simple command line utility. Let's get right to the pertinent section then put it all together in the end. Using th same indentation as where we left off, lets replace&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;........print os.path.splitext(File)&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;which was just used to show that something was working and to illustrate os.path functions with&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(153, 102, 51);font-family:courier new;" &gt;# Step through the list of files processing each&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;....for File in Filelist:&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);font-family:courier new;" &gt;# Each file will need to be opened&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;........OppFile=open(File,'r')&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(153, 102, 51);font-family:courier new;" &gt;# readlines() reads every line in a file, returns a list in which each member&lt;br /&gt;# of the list is a line in the file, including the end of line character.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;........FileData=OppFile.readlines()&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(153, 102, 51);font-family:courier new;" &gt;# Step through the list of lines in the open file&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;........for Line in FileData:&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(153, 102, 51);font-family:courier new;" &gt;# This isn't real tricky or elegant, but it turns out that the coordinate&lt;br /&gt;# positions stored in the .opp file are on lines which have an "l" as the&lt;br /&gt;# second character, so let's just determine first of all if the data line&lt;br /&gt;# is a coordinate&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;............if Line[1]=='l':&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(153, 102, 51);font-family:courier new;" &gt;# Then if it is, the first character determines which coordinate it is.&lt;br /&gt;# If it's an X, Y, or Z we'll use the split(function) to break the line&lt;br /&gt;# into a list of strings, which contains the number as the second&lt;br /&gt;# element, then use float() to convert it to a real number, and store it&lt;br /&gt;# in the appropriate variable.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;................if Line[0]=='X':&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;....................X=float(Line.split()[1])&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;................elif Line[0]=='Y':&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;....................Y=float(Line.split()[1])&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;................elif Line[0]=='Z':&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;....................Z=float(Line.split()[1])&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(153, 102, 51);font-family:courier new;" &gt;# Once we have parsed each line in the file to pull out the coordinates&lt;br /&gt;# lets use some formatted printing to output the file name and values.&lt;br /&gt;# Remember that "File" contains the name of the file with the extension&lt;br /&gt;# so the split using the dot will give a list ['filename','extension']&lt;br /&gt;# so the base name is element 1 or [0]&lt;br /&gt;# Close the file and your on your way.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;........print '%s %.3lf %.3lf %.3lf'%(File.split('.')[0],X,Y,Z)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);font-family:courier new;" &gt;........OppFile.close()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;so in the end after removing the modules that were only temporary, the final program looks like&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;import sys,glob&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;def usage():&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....'''&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....Explanation text to print if anything is entered as an argument.&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....'''&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....print '\nUsage:  python opp2txt.py\nThere are no arguments, it will just look in the current directory\n for files with a .opp extension, strip the coordinates out of them\n and output them to the screen\n\nListings can be redirected into a file.\n eg: python opp2txt.py &gt; photos.txt'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....sys.exit(1)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;if len(sys.argv)==1:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....Filelist=glob.glob('*.opp')&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....if Filelist==[]:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;........print "There don't appear to be any .opp files in this directory"&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;........sys.exit(2)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....for File in Filelist:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;........OppFile=open(File,'r')&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;........FileData=OppFile.readlines()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;........for Line in FileData:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;............if Line[1]=='l':&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;................if Line[0]=='X':&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....................X=float(Line.split()[1])&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;................elif Line[0]=='Y':&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....................Y=float(Line.split()[1])&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;................elif Line[0]=='Z':&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....................Z=float(Line.split()[1])&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;........print '%s %.3lf %.3lf %.3lf'%(File.split('.')[0],X,Y,Z)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;........OppFile.close()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;else: usage()&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Now this just prints to the screen and would have to be redirected to a text file. For the fun of it the first modification once we know it is running would be to send it directly to a file.   As always, final working code is found on my &lt;a href="http://python4vr.googlepages.com/"&gt;personal VrPython website&lt;/a&gt;.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-3649068919791161501?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/3649068919791161501/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=3649068919791161501' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/3649068919791161501'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/3649068919791161501'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/04/utility-programs-3.html' title='Utility programs 3'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-7330641321605814283</id><published>2007-04-07T07:10:00.000-05:00</published><updated>2007-04-16T05:18:59.257-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><category scheme='http://www.blogger.com/atom/ns#' term='NonVr'/><title type='text'>Utility programs 2</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Rather than retyping the code from the previous post, I'm just going back to the line with &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;argv&lt;/span&gt; and proceed from there with some actual working code. This time I want to focus on getting the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;filenames&lt;/span&gt; that will be processed. Remember the test of &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;argv&lt;/span&gt; was just to determine if any arguments were passed. Since this program doesn't take any, having something else appear on the command line indicates a lack of understanding so we printed some usage instructions. Now let's assume the user knows that if he types "python opp2&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;txt&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;py&lt;/span&gt;" he will get every opp file in the directory processed. But how to build a list of file names? Today we'll just build the list and print the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;filenames&lt;/span&gt; to show that it worked. The magic we want is contained in the glob module, no I don't know why it is named that, but isn't that just about the coolest name around? Here is the code that could be inserted into opp2&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;txt&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;py&lt;/span&gt; to grab &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;filenames&lt;/span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;if &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;len&lt;/span&gt;(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;sys&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;argv&lt;/span&gt;)==1:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;....Filelist=glob.glob('*.opp')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;....if &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;Filelist&lt;/span&gt;==[]:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;........print "There don't appear to be any .opp files in this directory"&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;........sys.exit(2)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;....for File in &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;Filelist&lt;/span&gt;:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;/span&gt;&lt;span style="font-family:courier new;"&gt;........print os.path.splitext(File)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;else: usage()&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;First let's look at glob.  The module itself is fairly simple and can be found in the &lt;/span&gt;&lt;a style="font-family: arial;" href="http://docs.python.org/lib/module-glob.html"&gt;python module docs&lt;/a&gt;&lt;span style="font-family:arial;"&gt;.  The short story is that you can return &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;filenames&lt;/span&gt; matching a pattern in a specified directory into a list of strings. Really the best way to illustrate is to try it. In your favorite python editor do the following.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;import glob&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;font-family:courier new;" &gt;glob.glob(r'\vr\hostdir\*.par')&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;This should return a list which contains the names of every .par file in that directory. Something like...&lt;br /&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;'\\&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;vr&lt;/span&gt;\\&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;hostdir&lt;/span&gt;\\&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;drivefile&lt;/span&gt;.par', '\\&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;vr&lt;/span&gt;\\&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;hostdir&lt;/span&gt;\\&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;editline&lt;/span&gt;.par',&lt;/span&gt;&lt;br /&gt;The lower case r before the path name just tells python to treat the string that follows as a raw string and not to see the backslashes as special characters. You could also put in forward slashes without the 'r' since that is a valid path separator in python but the return list comes back as an odd mix of forward and backward slashes.&lt;br /&gt;&lt;br /&gt;We are storing the returned list in a variable called &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;Filelist&lt;/span&gt;. If there are no .opp files in the directory the list will be empty in which case we print a message to that effect and exit, I just picked a random exit code of 2 to indicate no files found.&lt;br /&gt;&lt;br /&gt;Next the for loop will step through the list and process each name string in the list. The variable which represents the name string will be "File".&lt;br /&gt;&lt;br /&gt;Meaningful processing will come next time, but for now we could just use the code "&lt;span style="color: rgb(51, 51, 255);"&gt;print File&lt;/span&gt;" to display each &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;filename&lt;/span&gt; but let's take this opportunity to explore the extremely useful &lt;a href="http://docs.python.org/lib/module-os.path.html"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;os&lt;/span&gt;.path functions&lt;/a&gt;. These are most helpful in separating components of full &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;filenames&lt;/span&gt; into paths, extensions, base &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;filenames&lt;/span&gt;, etc. In the program which will be run in a directory that includes the .opp files and will not contain a path component the list would look something like...&lt;br /&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;['1.opp', '2.opp']&lt;/span&gt;&lt;br /&gt;and the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;splitext&lt;/span&gt;() will just return a name and an extension similar to...&lt;br /&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;('1', '.opp')&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;('2', '.opp')&lt;/span&gt;&lt;br /&gt;which could be accessed individually using indexes&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&gt;&gt;&gt; print ('2', '.opp')[0]&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;2&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&gt;&gt;&gt; print ('2', '.opp')[1]&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;.opp&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&gt;&gt;&gt; &lt;/span&gt;&lt;br /&gt;However to really have some fun lets go back to the previous example in the editor and try some examples with the name list returned from the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;vr&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;hostdir&lt;/span&gt; directory.  Here are some truncated examples of what would be returned. Take time to play with the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_29"&gt;os&lt;/span&gt;.path functions, there is some real usefulness there.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&gt;&gt;&gt; for name in glob.glob(r'\vr\hostdir\*.par'):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;...     print os.path.basename(name)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;... &lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;drivefile.par&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;editline.par&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;or if we run it through splitext() after it has been stripped to basename.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&gt;&gt;&gt; for name in glob.glob(r'\vr\hostdir\*.par'):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;...     print os.path.splitext(os.path.basename(name))&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;... &lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;('drivefile', '.par')&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;('editline', '.par')&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;or how about just running splitext to get the filename so that you can create another file with the same name, but with a different extension.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&gt;&gt;&gt; for name in glob.glob(r'\vr\hostdir\*.par'):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;...     print os.path.splitext(name)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;... &lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;('\\vr\\hostdir\\drivefile', '.par')&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;('\\vr\\hostdir\\editline', '.par')&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;or what about if you want to get the path name so you can create a file in the same directory.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&gt;&gt;&gt; for name in glob.glob(r'\vr\hostdir\*.par'):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;...     print os.path.split(name)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;... &lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;('\\vr\\hostdir', 'drivefile.par')&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;('\\vr\\hostdir', 'editline.par')&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;or just test whether or not the file exists, of course all these do because we're just passing in existing file names, but you get the idea.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&gt;&gt;&gt; for name in glob.glob(r'\vr\hostdir\*.par'):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;...     print os.path.exists(name)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;... &lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;True&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;True&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Cool stuff, and we haven't even done anything useful yet, hopefully next time.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-7330641321605814283?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/7330641321605814283/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=7330641321605814283' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/7330641321605814283'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/7330641321605814283'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/04/utility-programs-2.html' title='Utility programs 2'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-5558528303545302032</id><published>2007-04-06T07:39:00.000-05:00</published><updated>2007-04-06T07:44:04.741-05:00</updated><title type='text'>The forums are back!</title><content type='html'>I'll post more on opp2&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;txt&lt;/span&gt; more this weekend but I just had to mention that the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Vr&lt;/span&gt; Forums are back. As I understand it they aren't technical support forums so much as a gathering place for users to share information. In that sense if used properly they could be an invaluable place to discuss problems, questions, tips, tricks and other useful information. Check them out at &lt;a href="http://www.cardinalsystems.net/forum/"&gt;http://www.cardinalsystems.net/forum/&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-5558528303545302032?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/5558528303545302032/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=5558528303545302032' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/5558528303545302032'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/5558528303545302032'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/04/forums-are-back.html' title='The forums are back!'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-4917858424205097822</id><published>2007-04-03T12:26:00.000-05:00</published><updated>2007-04-03T13:28:19.162-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><category scheme='http://www.blogger.com/atom/ns#' term='NonVr'/><title type='text'>Utility programs 1</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Ok so I said I was going to talk about function key parsing and python dictionaries, and I will... eventually. I got off on a small tangent though and decided that it would be beneficial to start out talking about external utility programs first. There are probably many uses for a nice organized function key data set, both inside Vr and out. But lets start small. I love little command line utilities that take the place of actually working, as a matter of fact if I have a motto it would be "It beats working" and the more times I have reason to say that on any give day the better. Here is an example...&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:arial;"&gt;When I am working with ortho's there are times that I would like to have the photo centers plotted in a file. Because almost everything in Vr is stored in easy to read, easy to interpret text files it is a piece of cake to go into the opp files and pull out the xyz coordinates in any text editor. But do that on 100 separate files and you are bordering on work. What if you could just run a simple little command line utility that would give you a space separated listing of the photo name and it's coordinates. That my friend "beats working". Let's think through this program a few lines at a time, when it's all said and done I'll post the final code on the &lt;a href="http://python4vr.googlepages.com/"&gt;repository web site&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family:arial;"&gt;First for the preliminaries&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(153, 102, 51);"&gt;# Lets start out with a docstring to explain what the program is for.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;'''&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Extracts photo center coordinates from all .opp files in a directory&lt;br /&gt;and sends &lt;/span&gt;&lt;span style="font-weight: bold;"&gt;the output to the screen, which can then be redirected into&lt;br /&gt;a text file.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;'''&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(153, 102, 51);"&gt;# For now just trust me that these are the modules we'll need.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(153, 102, 51);"&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;import os,sys,string,glob&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(153, 102, 51);"&gt;# It's always a good idea to put in a usage function. In this case since&lt;br /&gt;# (like it says) there won't be any arguments, will force the usage string&lt;br /&gt;# to print if the user enters any argument at all.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(153, 102, 51);"&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;def usage():&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;....'''&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;....Explanation text to print if anything is entered as an argument.&lt;br /&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;....'''&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;....print '\nUsage:  python opp2txt.py'&lt;br /&gt;....print 'There are no arguments, it will just look in the current '&lt;br /&gt;....print '&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(153, 102, 51);"&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;directory &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(153, 102, 51);"&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;for files with a .opp extension, strip the '&lt;br /&gt;....print '&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(153, 102, 51);"&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;coordinates out of them &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(153, 102, 51);"&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;and output them to the screen'&lt;br /&gt;....print '\n\nListings can be redirected into a file.'&lt;br /&gt;....print 'eg: python opp2txt.py &gt; photos.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;txt&lt;/span&gt;'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;....sys.exit(1)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(153, 102, 51);"&gt;# This is the main part of the program. First we'll make sure no&lt;br /&gt;# arguments were entered. &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;sys&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;argv&lt;/span&gt; is the command itself the program&lt;br /&gt;# name is always the first argument, if there is only 1 thing in the&lt;br /&gt;# list then no arguments besides the program name were passed.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;&lt;span style="color: rgb(153, 102, 51);"&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;if &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;len&lt;/span&gt;(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;sys&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;argv&lt;/span&gt;)==1:&lt;br /&gt;....print 'no code yet run\&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;npython&lt;/span&gt; opp2&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;txt&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;py&lt;/span&gt; -h\&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;nfor&lt;/span&gt; help'&lt;br /&gt;else: usage()&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;Ok&lt;/span&gt; that's it for now. Copy the above to a python file called opp2&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;txt&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;py&lt;/span&gt; , replace the indent holders (....) with your normal indentation and run it with an argument and it will describe where we are headed. You need python installed and in the path. Type "python opp2&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;txt&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;py&lt;/span&gt; -h" and the usage should print. &lt;br /&gt;&lt;br /&gt;If you want to get a better idea what &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;argv&lt;/span&gt; does just create a python script that contains nothing except&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255); font-family: courier new;"&gt;import &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;sys&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255); font-family: courier new;"&gt;print &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;sys&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;argv&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;Then run the script with different (or no) arguments.&lt;br /&gt;More to come...&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold; color: rgb(51, 51, 255);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(153, 102, 51);"&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-4917858424205097822?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/4917858424205097822/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=4917858424205097822' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/4917858424205097822'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/4917858424205097822'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/04/utility-programs-1.html' title='Utility programs 1'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-5756027400074627142</id><published>2007-03-30T12:39:00.000-05:00</published><updated>2007-03-30T13:07:51.409-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><title type='text'>Solid gold</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: arial;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Ok&lt;/span&gt; I haven't posted in too long and this one is going to be really short, but I have some really fun plans along the lines of a function key parser, editor, etc. that will really push into the python dictionary data type.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;For now though let me pass along huge kudos to the team at Cardinal. I often have thoughts of the guys  slaving away in the salt mines at the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Vr&lt;/span&gt; Development lab. Poorly used and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;un&lt;/span&gt;-appreciated for the efforts that spring forth. However in the latest patch versions (usual disclaimers about beta software, or anything that isn't in official full release, blah..blah..) there are a couple of nuggets of pure gold. One is attaching in fly-line, granted this doesn't have anything to do with python, but along with things like all the different snap options, overloading (I better stop before I get carried away) attaching a fly-line is one of those things that will make me pause and think "wow, I love this stuff". The python related gold nugget is &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;Ws&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;IdEnt&lt;/span&gt;() which allows the user to just start a generic ID routine then select anything on the screen, or cycle through entity types. This is the same ID that is used for &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;fasdel&lt;/span&gt; and others like it. Check it out on the &lt;/span&gt;&lt;a style="font-family: arial;" href="http://www.cardinalsystems.net/help/PythonVrWs.html#_IdEnt_%28SeaWs,_SeaLines,"&gt;python help pages&lt;/a&gt;&lt;span style="font-family: arial;"&gt;, it is absolutely too cool.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;I'll also toss in a little utility that I use to save the current layer display status. Disclaimer here is that it only works with 3.2 and above because before that &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;PyVrLayer&lt;/span&gt; had it's own module. It could be modified to work like that, but this version doesn't.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;"&gt;Layer = &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;VrLayer&lt;/span&gt; ()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;"&gt;Gui=&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;PyVrGui&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: arial;"&gt;# Initialize &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;Vr&lt;/span&gt; objects to be used.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255); font-weight: bold;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;parfile&lt;/span&gt;=open('c:/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;vr&lt;/span&gt;/&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;hostdir&lt;/span&gt;/save_lay_stat.par','w')&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: arial;"&gt;# Open a parameter file to save the layer status in. 'w' is write mode.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;&lt;span style="color: rgb(51, 51, 255);"&gt;for &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;laynum&lt;/span&gt; in range(1000):&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;&lt;span style="font-family: arial;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;..parfile.write("%d %d\n"%(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;laynum&lt;/span&gt;,Layer.Stat(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;laynum&lt;/span&gt;)))&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;Gui.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;DspMsg&lt;/span&gt;0('Layer state saved')&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: arial;"&gt;# I'm only going to save the status of the first 1000 layers, I rarely use any others.&lt;br /&gt;# Then write the &lt;a href="http://www.cardinalsystems.net/help/pythonvrlayer.html#Stat"&gt;Stat()&lt;/a&gt; or current status along with the layer number.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-weight: bold;font-size:85%;" &gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;parfile&lt;/span&gt;.close()&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: arial;"&gt;# Always close files when done. Python is smart this way, but it's good practice.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-5756027400074627142?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/5756027400074627142/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=5756027400074627142' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/5756027400074627142'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/5756027400074627142'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/03/solid-gold.html' title='Solid gold'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-4901062469816660495</id><published>2007-03-02T08:38:00.000-05:00</published><updated>2007-03-12T06:46:46.170-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><category scheme='http://www.blogger.com/atom/ns#' term='NonVr'/><title type='text'>A touch of class</title><content type='html'>&lt;span style=";font-family:arial;font-size:85%;"  &gt;You can do an amazing amount of good with &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;VrPython&lt;/span&gt; without knowing anything about Object Oriented Programming (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;OOP&lt;/span&gt;). For that matter most, or at least many things you can do without even knowing much about Python. In my opinion though, knowing more is always better than knowing less. Let's talk a little about how I understand &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;OOP&lt;/span&gt; working out in &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;Vr&lt;/span&gt;. To begin with there is a very good explanation of the &lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/Object-oriented_programming#Fundamental_concepts"&gt;&lt;span style=";font-family:arial;font-size:85%;"  &gt;basic concepts on &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;Wikipedia&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;span style=";font-family:arial;font-size:85%;"  &gt;. I could make up my own example of the biggies like class, object, inheritance but they do such a good job &lt;/span&gt;&lt;a href="http://en.wikipedia.org/wiki/Object-oriented_programming#Fundamental_concepts"&gt;&lt;span style=";font-family:arial;font-size:85%;"  &gt;there&lt;/span&gt;&lt;/a&gt;&lt;span style=";font-family:arial;font-size:85%;"  &gt; that I'll just trust anyone who needs a basic understanding to read it (3-5 minutes tops).&lt;br /&gt;Let's look at a line. In &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;VrPython&lt;/span&gt; there is a class called &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;PyVrLine&lt;/span&gt;. Any object which is created from that class has many attributes, characteristics, data (whatever you want to call it) which describes it's state. Examples of these attributes (the word I'll stick with) are it's layer, graphic pointer, width, coordinate list and so on. A line also has many methods, or functions it can perform based primarily on it's current state. When ever I create an individual object or instance of that class, I have access to all the attributes and methods that go with it. In &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;Vr&lt;/span&gt; the individual object is created with the command&lt;br /&gt;Line=&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;PyVrLine&lt;/span&gt;()&lt;br /&gt;I have often wondered if I am confusing things by using the word "Line" as the name of the particular object. Sure it is descriptive and relevant, but for example purposes it needs to be clear that I could use any name for the object being created which is of the class &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;PyVrLine&lt;/span&gt;. It is just an identifier of the unique entity I'll be using just like Dennis is just a name used to identify this particular object of the Human class.&lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:arial;font-size:85%;"  &gt;In any case, whatever we call a particular instance, once we have a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;PyVrLine&lt;/span&gt;(), the fun can begin. On of the most useful functions when starting off is Id(). Once there is a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;PyVrLine&lt;/span&gt; object, Id() will use the function built into it to bring up a familiar set of identification menu keys and wait for the user to click button #1. If the click meets all the criteria to find a line Id() will not only return the line number of the line it found, but will populate the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;PyVrLine&lt;/span&gt; object with all the attributes of the identified entity. It does the exact same thing as Load() but allows for visual identification in the current workspace. Once the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;PyVrLine&lt;/span&gt; object is loaded (or I suppose created from scratch with default values) the whole host of methods that can get, set, or compute information based on the current state become available. &lt;/span&gt;&lt;br /&gt;&lt;span style=";font-family:arial;font-size:85%;"  &gt;The key is that a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;Vr&lt;/span&gt; object can't just be looked at even as a complex collection of data, but also as the family of functions that allow user interaction with it. This frees the developers to grant access to the power of the internal magic in a secure manner, and the user from having to understand what is going on (or having to re-invent the wheel for typical data interaction).&lt;br /&gt;Ok I'm rambling and really need to bring this to a close. Besides the fact that OOP is really cool, and it helps to have a simple understanding of how it works out in Vr, what is the point? Is there any reason that a person might want to learn to use classes in everyday programming? I very rarely do, and most of the true object oriented modules I've written were done because I wanted to give it a try, but here is an example. I have a module which contains an angle class. An object created from this class of course stores the value of the angle it represents, but it also contains methods that allow it to represent itself in radians, degree-minutes-seconds, decimal degrees, bearings with quadrant, any of the above in varying text formats along with an overloaded repr(). Along with this there are methods that allow for conversion between the varying systems. All these things are easy enough to do on the fly, but a consistent interface and descriptive names make programs that use the class easier to read, and playing with basics like this makes understanding modules written by really intelligent programmers a bit easier to follow.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-4901062469816660495?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/4901062469816660495/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=4901062469816660495' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/4901062469816660495'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/4901062469816660495'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/03/touch-of-class.html' title='A touch of class'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-3382769777565503378</id><published>2007-02-20T08:58:00.000-05:00</published><updated>2007-03-12T07:08:26.358-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><title type='text'>I can already do that</title><content type='html'>&lt;span style=";font-family:arial;font-size:85%;"  &gt;Why are there 4672 different word processors or hundreds of CAD programs available (I made the numbers up)? Because somewhere, sometime, a programmer was sitting at his keyboard whacking away on something he felt was truly important and when someone said "I can already do that", the first words out of the programmers mouth were "yeah, but....". I am today formally proposing that this be adopted as the official motto of petty programmers everywhere. For example there are at least two perfectly good ways to remove the arc codes from a Vr line entity. If you want to clear entire layers of the pesky point flags, delarc is the ticket. For a single line or two edilin has the ever popular&lt;b6&gt; B6,B6&lt;b6&gt; combo that will do the same thing for any line you latch on to. "Yeah, but" what if I want clear 5 individual lines in a point and click method where each line identified is cleared of arc codes (or any other flags which is part of the moral of this post).  How about clear_arc.py?&lt;br /&gt;&lt;br /&gt;As a whole it looks like.&lt;br /&gt;&lt;br /&gt;&lt;/b6&gt;&lt;/b6&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Ws=PyVrWs()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line=PyVrLine()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;WsNum=Ws.Aws()&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;while Line.Id() != -1:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..Ws.UndoBegin(WsNum,"clear_arc")&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..for PointNum in range (0, Line.GetNumXyz()):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....p, a, c, f, m = Line.GetPointFlags (PointNum)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....Line.SetPointFlags (PointNum,p,0,c,f,m)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..Line.ReRec ()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..Line.SetWidth(2)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..Line.Plot()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..Ws.UndoEnd(WsNum)&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=";font-family:arial;font-size:85%;"  &gt;Taken apart.&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Ws=PyVrWs()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line=PyVrLine()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;WsNum=Ws.Aws()&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;Initialize what will be needed.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt; &lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;while Line.Id() != -1:&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;Been a while since we've used the Id() function, remember that it returns an open object, ready to interact with.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..Ws.UndoBegin(WsNum,"clear_arc")&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;This time the undo points are set inside the Id() loop so if the wrong one is identified the user could just exit and undo the last modification while anything else would remain cleared.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..for PointNum in range (0, Line.GetNumXyz()):&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;For every point on the identified line.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....p, a, c, f, m = Line.GetPointFlags (PointNum)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;Get the existing point flags.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....Line.SetPointFlags (PointNum,p,0,c,f,m)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;Set them all back as they were except for the arc flag which will be set to 0.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..Line.ReRec ()&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;Re-record the line that is loaded.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..Line.SetWidth(2)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..Line.Plot()&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;Change the graphics as a verification and plot it (after the ReRec so graphic changes aren't stored).&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..Ws.UndoEnd(WsNum)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;Set the undo endpoint for each line identified.&lt;br /&gt;&lt;br /&gt;Note that point flags are documented in the VrPython documentation as follows.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(102, 51, 51);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;p, a, c, f, m  Flags&lt;br /&gt;&lt;br /&gt;p-Pen code (0=None 1=Up 2=Continue 4=End)&lt;br /&gt;a-Arc flag (0=None 1=Beginning, end or PRC 2=Mid point 3=Point on arc)&lt;br /&gt;c-Code (0-255)&lt;br /&gt;f-Bit encoded flag (0-255)&lt;br /&gt;m-Mosaic width (0-255)&lt;br /&gt;&lt;br /&gt;If a parameter is passed as –1 then the original number is not changed&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Example Line.SetPointFlags (PntNum, PenCode, ArcFlag, Code, BitFlags, MosaicWidth)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;The bit encoded flag isn't used much that I know of and can be a handy way to mark a point for further consideration, Always check with someone at Cardinal Systems before using this flag because if it is implemented for something then there could be conflicts between a python program and Vr functions that use the same bit. A good example of this is to run batnod, id a line that was noded, move to a node point, and look at the f display in the menukeys dialog.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-3382769777565503378?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/3382769777565503378/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=3382769777565503378' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/3382769777565503378'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/3382769777565503378'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/02/i-can-already-do-that.html' title='I can already do that'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-1182287957564412262</id><published>2007-02-12T13:03:00.000-05:00</published><updated>2007-02-16T10:42:37.495-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tips'/><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><category scheme='http://www.blogger.com/atom/ns#' term='NonVr'/><title type='text'>Computing without errors</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Wouldn't it be a lot more fun to write code if you could guarantee that those pesky end users would never enter the wrong type of data? Not to mention, shouldn't it be their responsibility to know the bounds of whatever is entered or passed to the program. After all isn't it enough that some helpful soul is writing code to make &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_0"&gt;every one's&lt;/span&gt; life easier, why should I care if the "File does not exist". Well we all know that errors happen (sometimes even the program isn't perfect). One helpful tool when unexpected problems arise is the &lt;span style="font-weight: bold;"&gt;try: - except:&lt;/span&gt; block. In simple terms anything that falls within a try: block and causes a potentially fatal error, should cause execution to jump directly to the except: block. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;#try-except.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;py&lt;/span&gt;&lt;br /&gt;print '\&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;nTesting&lt;/span&gt; try:'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;try:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..print "divide 1 by 3 and it's &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;ok&lt;/span&gt;",1.0/3.0&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;except:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..print 'it worked so this never prints'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;try:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..print "This prints until it does the division of 1 by 'a' then ",1.0/'a'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;except:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..print '\&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;nThere&lt;/span&gt; is an error that would normally end the program\&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;nbut&lt;/span&gt; instead jumps to the exception'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;print '\n'&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Should print.&lt;br /&gt;&lt;span style="color: rgb(153, 102, 51);font-family:courier new;" &gt;divide 1 by 3 and it's &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;ok&lt;/span&gt; 0.333333333333&lt;br /&gt;This prints until it does the division of 1 by 'a' then&lt;br /&gt;There is an error that would normally end the program&lt;br /&gt;but instead jumps to the exception&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;try-except.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;py&lt;/span&gt;&lt;br /&gt;print '\&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;nTesting&lt;/span&gt; try:'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;try:&lt;/span&gt;&lt;br /&gt;..&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;print "divide 1 by 3 and it's &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;ok&lt;/span&gt;",1.0/3.0&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family: arial;"&gt;Anything that should happen as part of normal execution goes inside the "try" block, probably including a proper exit code if you are a good programmer and this is a non-Vr program.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt; &lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;except:&lt;/span&gt;&lt;br /&gt;..&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;print 'it worked so this never prints'&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family: arial;"&gt;Anything that should be done if there is any kind of error encountered in the try block should go in the "except" block. This is a good place to inform the user that something went wrong. In this example this line never gets printed because there is no error in the code.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt; &lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;try:&lt;/span&gt;&lt;br /&gt;..&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;print "This prints until it does the division of 1 by 'a' then ",1.0/'a'&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family: arial;"&gt;Here the error is that there is a division by a string, notice that if it had worked there would have been some characters printed directly after the word "then", since the error is in the division the error comes at this point and execution would normally print out a bunch of cryptic python like error statements.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt; &lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;except:&lt;/span&gt;&lt;br /&gt;..&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;print '\&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;nThere&lt;/span&gt; is an error that would normally end the program\&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;nbut&lt;/span&gt; instead jumps to the exception'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;print '\n'&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family: arial;"&gt;However since we "trapped the exception", execution continues with the first statement in the except block.&lt;br /&gt;&lt;br /&gt;I don't use try for every line of code I write, mostly because I'm lazy and they are for personal or in-house usage. The more likely an important program is to leave the building, the more likely I am to worry about exceptions. Within VrPython I tend to use them where there is a reasonable expectation that the same problem could come up on a regular basis. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-1182287957564412262?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/1182287957564412262/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=1182287957564412262' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/1182287957564412262'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/1182287957564412262'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/02/computing-without-errors.html' title='Computing without errors'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-1564812655068663019</id><published>2007-02-09T14:10:00.000-05:00</published><updated>2007-02-09T13:34:47.345-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tips'/><category scheme='http://www.blogger.com/atom/ns#' term='NonVr'/><title type='text'>News flash for the slow to catch on</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: arial;"&gt;While posting on &lt;a href="http://www.thescripts.com/forum/forum152.html"&gt;The Scripts Developer's Network python forum&lt;/a&gt;, someone pointed out to me that string.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;atoi&lt;/span&gt; (and &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;atof&lt;/span&gt;) have been deprecated ( I hope I'm never deprecated, it sounds painful) and the preferred methods are the built-in functions int() and float(). I'm not sure when it happened because I apparently didn't get the memo, but especially if you have moved up to &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;Vr&lt;/span&gt; 3.2 and Python 2.5, it is probably something to take note of.&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-1564812655068663019?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/1564812655068663019/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=1564812655068663019' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/1564812655068663019'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/1564812655068663019'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/02/news-flash-for-slow-to-catch-on.html' title='News flash for the slow to catch on'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-3176949298484474420</id><published>2007-02-07T06:43:00.000-05:00</published><updated>2007-02-09T13:30:18.866-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><title type='text'>It keeps growing, and growing....</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Some programs seem a little like Frankenstein's monster. You know, you start out to re-animate a little dead flesh in your spare time, and the next thing you know the peasants are in a uproar. Well, not quite, but it really seems like some of the smallest projects eventually take on a life of their own. (Note that in many places, this would be considered humor, poor humor, but humor.  Apologies if it seems offensive where you are)&lt;br /&gt;&lt;br /&gt;Here is an example that also shows some interesting concepts. History: One day I was doing something and thought "It sure would be nice if I could throw a north arrow on the screen any time I like to remind me which way north is". Just a simple little thought, easily enough accomplished with a couple of lines of python, nothing stored in the file, just displayed and then erased at the next refresh.. Later I thought, "Sometimes when I'm adjusting a display it would be nice to know where the exact center of the display and it's edges are".  Then because we still do the majority of work on analytical instruments, I have always missed the ability in &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Vr's&lt;/span&gt; predecessor to show me where the instrument was in relation to the screen. Well as long as I'm showing North, and the centers of all the edges, why not draw a line from the screen center to the current cursor (instrument) location that would indicate where the instrument is.&lt;br /&gt;&lt;br /&gt;See how it goes, next thing you know there are lines and symbols all over the screen, but each one helpful in it's own way.  I call this ugly duck screen_center.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;py&lt;/span&gt; (for reasons which now escape me).&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;def Rad2&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;DecDeg&lt;/span&gt;(Radians=0):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..return Radians*(180.00/3.1415926535897931)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui = &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;PyVrGui&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gr=&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;PyVrGr&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line=&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;PyVrLine&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;Sym&lt;/span&gt;=&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;PyVrSym&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;LineLayer&lt;/span&gt;=105&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;LineGraphic&lt;/span&gt;=1&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;NorthGraphic&lt;/span&gt;=58&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;TickGraphic&lt;/span&gt;=41&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;SymLayer&lt;/span&gt;=102&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Radius=.75&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;DspMsg&lt;/span&gt;0('Rotation = %.2f'%(Rad2DecDeg(Gr.GetWinRot()[2])))&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Sym.SetCoord(Gr.GetWinOrg()[0],Gr.GetWinOrg()[1],Gr.GetWinOrg()[2])&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;Sym&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;SetLayer&lt;/span&gt;(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;SymLayer&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;Sym&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;SetGpoint&lt;/span&gt;(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;NorthGraphic&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Sym.SetRad(Gr.GetWinScale()*Radius)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;Sym&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;SetRot&lt;/span&gt;(0)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;Sym&lt;/span&gt;.Plot()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;x,y,z,key = Gr.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;GetCursor&lt;/span&gt; ()&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;SetLayer&lt;/span&gt; (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;LineLayer&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;SetGpoint&lt;/span&gt; (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;LineGraphic&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line.AddPoint(Gr.GetWinOrg()[0],Gr.GetWinOrg()[1],Gr.GetWinOrg()[2])&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;AddPoint&lt;/span&gt; (x, y, z)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line.Plot()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_29"&gt;Sym&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_30"&gt;SetGpoint&lt;/span&gt;(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_31"&gt;TickGraphic&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Sym.SetRad(Gr.GetWinScale()*.25)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;for corner in range(4):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..x1,y1,z1=Gr.GetWinCorner (corner,0)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..Sym.SetCoord(x1,y1,z1)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..Sym.Plot()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..if corner==3:x2,y2,z2=Gr.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_32"&gt;GetWinCorner&lt;/span&gt; (0,0)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..else:x2,y2,z2=Gr.GetWinCorner (corner+1,0)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..Sym.SetCoord(((x1+x2)/2.0),((y1+y2)/2.0),z1)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..Sym.Plot()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;And away we go...&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;def Rad2&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_33"&gt;DecDeg&lt;/span&gt;(Radians=0):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..return Radians*(180.00/3.1415926535897931)&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;We'll be grabbing some parameters later that will be returned in radians. In the US we (or at least I) visualize decimal degrees more easily. The rotation is just going to be displayed in a message area, so we might as well make it readable.  In the actual program I import math, and use math.pi instead of the 3.14 number but I'm trying harder to make these posts independent of python.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui = &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_34"&gt;PyVrGui&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gr=&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_35"&gt;PyVrGr&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line=&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_36"&gt;PyVrLine&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_37"&gt;Sym&lt;/span&gt;=&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_38"&gt;PyVrSym&lt;/span&gt;()&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;All this is typical, except this may be the first time that &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_39"&gt;PyVrGr&lt;/span&gt; has been mentioned. This is a class that allows us to interact with the graphics window. In this case we'll mostly be getting information from it.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_40"&gt;LineLayer&lt;/span&gt;=105&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_41"&gt;LineGraphic&lt;/span&gt;=1&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_42"&gt;NorthGraphic&lt;/span&gt;=58&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_43"&gt;TickGraphic&lt;/span&gt;=41&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_44"&gt;SymLayer&lt;/span&gt;=102&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Radius=.75&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;Once it is all said and done there will be a north arrow in the exact center of the display, ticks (simple cross) in the center of the edges, and a line from the screen center to the current cursor position. Radius is in inches and will be set based on the screen scale later. All the symbols will go in the same layer, though there will be a different graphic for the side ticks, and the center north arrow.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_45"&gt;DspMsg&lt;/span&gt;0('Rotation = %.2f'%(Rad2DecDeg(Gr.GetWinRot()[2])))&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;If we end it here, there will just be a message in the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_46"&gt;Vr&lt;/span&gt; message area that give us the screen rotation, helpful in it's own right, but let's add a graphic display.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt; &lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Sym.SetCoord(Gr.GetWinOrg()[0],Gr.GetWinOrg()[1],Gr.GetWinOrg()[2])&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;Here is a python concept, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_47"&gt;GetWinOrg&lt;/span&gt; returns a 3 number list with x,y, and z as the values.  In the above line &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_48"&gt;SetCoord&lt;/span&gt; will set the symbols x,y,z location values with the list values returned by &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_49"&gt;GetWinOrg&lt;/span&gt;.  If the list returned would be (1,2,3) then list member [0] (the first member) would be 1, member [1] (second) would be 2 and so on. So Gr.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_50"&gt;GetWinOrg&lt;/span&gt;()[0], means the first member of a list returned by the function &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_51"&gt;GetWinOrg&lt;/span&gt;() which is a part of the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_52"&gt;PyVrGr&lt;/span&gt; class of which Gr is an instance.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_53"&gt;Sym&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_54"&gt;SetLayer&lt;/span&gt;(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_55"&gt;SymLayer&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_56"&gt;Sym&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_57"&gt;SetGpoint&lt;/span&gt;(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_58"&gt;NorthGraphic&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Sym.SetRad(Gr.GetWinScale()*Radius)&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_59"&gt;Sym&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_60"&gt;SetRot&lt;/span&gt;(0)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_61"&gt;Sym&lt;/span&gt;.Plot()&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;Just set the center symbols visual display based on the attributes decided on above and plot it, again; since &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_62"&gt;GetWinScale&lt;/span&gt; returns the scale in units per inch (or mm) we will multiply it out so the display will be set in screen inches.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt; &lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;x,y,z,key = Gr.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_63"&gt;GetCursor&lt;/span&gt; ()&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;Get the current position of the cursor. This function will really come in handy later, but for now we just want a one time reading of where the current input device is located whether it is a stereo instrument or the mouse.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_64"&gt;SetLayer&lt;/span&gt; (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_65"&gt;LineLayer&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_66"&gt;SetGpoint&lt;/span&gt; (&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_67"&gt;LineGraphic&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line.AddPoint(Gr.GetWinOrg()[0],Gr.GetWinOrg()[1],Gr.GetWinOrg()[2])&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;Start by setting the display properties then using the method illustrated above, set the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_68"&gt;xyz&lt;/span&gt; to the window center.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_69"&gt;AddPoint&lt;/span&gt; (x, y, z)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line.Plot()&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;Then add the second point based on the cursor location grabbed earlier, and plot the line.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_70"&gt;Sym&lt;/span&gt;.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_71"&gt;SetGpoint&lt;/span&gt;(&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_72"&gt;TickGraphic&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Sym.SetRad(Gr.GetWinScale()*.25)&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;Change the symbol attributes to those used for the corner tics.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;for corner in range(4):&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;There are four corners, numbered 0-3 and the range function will just create a list starting at 0 and ending at the number before whatever is entered. In this case it would return (0,1,2,3). range() actually has a lot more &lt;span class="blsp-spelling-corrected" id="SPELLING_ERROR_73"&gt;flexibility&lt;/span&gt; including setting start point, end point, and increment, but for now we just need a list from 0-3.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..x1,y1,z1=Gr.GetWinCorner (corner,0)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_74"&gt;GetWinCorner&lt;/span&gt; needs a corner number and a window number, in case there are multiple graphics windows open.&lt;br /&gt;Corner numbers are LL=0, LR=1,UR=2, UL=3&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..Sym.SetCoord(x1,y1,z1)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..Sym.Plot()&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;Plot a symbol in whichever corner is currently up in the list.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..if corner==3:x2,y2,z2=Gr.&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_75"&gt;GetWinCorner&lt;/span&gt; (0,0)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;There will also be tics at the midpoints between corners, to do this we'll get the average between current corner and next, but if current corner is 3 (UL) then next would be 0 (LL).&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..else:x2,y2,z2=Gr.GetWinCorner (corner+1,0)&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;If the current isn't 3 then get the values from the next corner.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..Sym.SetCoord(((x1+x2)/2.0),((y1+y2)/2.0),z1)&lt;br /&gt;&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;set a symbol at the average between current and next.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..Sym.Plot()&lt;span style="color: rgb(0, 0, 0);"&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;and plot it.&lt;br /&gt;&lt;br /&gt;Here are the end results.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://bp0.blogger.com/_JNszxXRCkiw/Rcy-aieY8EI/AAAAAAAAABU/Y8oPGp4E0DM/s1600-h/sc.png"&gt;&lt;img style="cursor: pointer;" src="http://bp0.blogger.com/_JNszxXRCkiw/Rcy-aieY8EI/AAAAAAAAABU/Y8oPGp4E0DM/s400/sc.png" alt="" id="BLOGGER_PHOTO_ID_5029604247006146626" border="0" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-3176949298484474420?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/3176949298484474420/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=3176949298484474420' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/3176949298484474420'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/3176949298484474420'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/02/it-keeps-growing-and-growing.html' title='It keeps growing, and growing....'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://bp0.blogger.com/_JNszxXRCkiw/Rcy-aieY8EI/AAAAAAAAABU/Y8oPGp4E0DM/s72-c/sc.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-7584632296784759920</id><published>2007-01-29T06:26:00.000-05:00</published><updated>2007-01-30T07:18:58.562-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><title type='text'>Rounding line coordinates</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Things have been a little sparse here, but on the plus side I have made considerable progress on my BeginnersVrPython script. While discussing it with a co-worker it seemed much more productive to just give him some very simple examples to show the absolute basics, digging into the documentation, playing with different functions, and learning python will follow naturally with curiosity.  Vr actually comes with lots of great example scripts that would give a newbie everything necessary, I just decided to do this as a way of organizing things I would go over with someone new to VrPython as if I were walking them through it.&lt;br /&gt;&lt;br /&gt;Anyway, let's look at another example of looping over all the lines in a file, but we'll narrow it to a specific layer. Sometime later remind me to post my Vr number line parser, but for now we'll work with single layers. The task was that it was necessary to take every line in a particular layer and round the coordinates to the nearest even foot. To accomplish this we'll create a function that will do the rounding when passed a number and rounding factor. For example instead of the nearest foot, the user may want to round to the nearest 100 feet or something similar, so even though the math is easy enough to put in the working code, it will be more flexible if we define a function. This will involve two loops, one to check every line in the file to see if it matches the layer of interest, then if so to manipulate every vertex on the line.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;def roundto(NumberToRound,By):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..return (round(NumberToRound/By))*By&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;import string&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Ws=PyVrWs()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line=PyVrLine()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui=PyVrGui()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;WsNum=Ws.Aws()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Ws.UndoBegin(WsNum,"round_xy")&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;input=Gui.InputDialog('Set Layer','Enter layer for box &lt;105&gt;')&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;if input[1]=='':&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..layer=105&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;else: layer=string.atoi(input[1])&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;for EntNum in range (Ws.GetLineCount(WsNum)):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..if layer==(Ws.GetLineLayer(WsNum,EntNum)):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....Line.Load (WsNum, EntNum)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....for PntNum in range (WsNum, Line.GetNumXyz()):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;......(x, y, z) = Line.GetPoint (PntNum)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;......(p, a, c, f, m) = Line.GetPointFlags (PntNum)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;......Line.ChgPoint (PntNum, roundto(x,1.0), roundto(y,1.0), z,p, a, c, f, m)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....Line.ReRec()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....Line.Plot()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Ws.UndoEnd(WsNum)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;Line by line it looks like this.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;def roundto(NumberToRound,By):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..return (round(NumberToRound/By))*By&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Straight python here, defining a new function called roundto. It takes a number and a factor for rounding and returns the original number rounded by the factor. Tried and true formula but if it's new for some reason here are some examples.&lt;br /&gt;roundto(106.6,.5) = 106.5&lt;br /&gt;roundto(106.6,1.0) = 107&lt;br /&gt;roundto(106.6,5.0) = 105&lt;br /&gt;roundto(106.6,10.0) = 110&lt;br /&gt;roundto(106.6,25.0) = 100&lt;br /&gt;and so on&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt; &lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;import string&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;There are other more complex ways of doing what I want later, but for this example I really wanted it short and simple which meant using the atoi() function to convert a numeric string to an integer. A good example of why it is helpful to have python installed.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt; &lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Ws=PyVrWs()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line=PyVrLine()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui=PyVrGui()&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Initialize all the Vr objects we will be using.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt; &lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;WsNum=Ws.Aws()&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;When loading or saving entities it is necessary to specify a workspace number. Typically it would probably be the currently active workspace.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Ws.UndoBegin(WsNum,"round_xy")&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Setting an undo point is always a good idea.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;input=Gui.InputDialog('Set Layer','Enter layer for box &lt;105&gt;')&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;if input[1]=='':&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..layer=105&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;else: layer=string.atoi(input[1])&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;The PromBox functions are actually a much better way of doing this, but it's an old script and I'll throw in those functions at a later date. The if statement just sets the default layer if none is entered, and the else sets the layer if one was. The main problem here is that there is no error checking. If the user enters an alpha character it will just crash, this could be fixed with a try/except test (a very worthwhile subject to look up or discuss later). The other option is just to use PromBox functions, which is what they were designed for.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt; &lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;for EntNum in range (Ws.GetLineCount(WsNum)):&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;This is only the second time it's been used so let's talk about the for loop. In my mind one of the most powerful features of python is how it handles sequence data, I may discuss it later but the concept of a "list" is, in my mind, one of the coolest parts of python. If I had a list called Alist which contained data [1,2,3,4] and said&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(0, 102, 0); font-weight: bold;"&gt;for data in Alist:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(0, 102, 0); font-weight: bold;"&gt;..print data&lt;/span&gt;&lt;br /&gt;I would get the return&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(0, 102, 0);"&gt;1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(0, 102, 0);"&gt;2&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(0, 102, 0);"&gt;3&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; font-weight: bold; color: rgb(0, 102, 0);"&gt;4&lt;/span&gt;&lt;br /&gt;In essence the for loop is going to work over a sequence of data and process each member, whether it is a list, a dictionary, or a string. If you don't have a list, but just want to run a loop a certain number of times the range() function can build a list of numbers which can be processed.  In this case we want to process every entity number from the first to the last up to the limit of the linecount.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..if layer==(Ws.GetLineLayer(WsNum,EntNum)):&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;However we already determined that only the lines which match the desired layer will be processed. The Ws version of getting the layer is used because it is much faster and it won't even be necessary to load lines that don't match the criteria.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....Line.Load (WsNum, EntNum)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;If however it does, load it up to be processed.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....for PntNum in range (Line.GetNumXyz()):&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Same idea but this time for every point number up to the limit of the number of xyz coordinates do the following.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;......(x, y, z) = Line.GetPoint (PntNum)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Get the position.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;......(p, a, c, f, m) = Line.GetPointFlags (PntNum)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Get the flag data, these are extremely useful and important at times for now they will just be preserved, and straight out of the Vr documentation are....&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;p - Pen code (0=None 1=Up 2=Continue 4=End)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;a - Arc flag (0=None 1=Beginning, end or PRC 2=Mid point 3=Point on arc)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;c - Code (0-255)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;f - Bit encoded flag (0-255)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new;"&gt;m - Mosaic width (0-255)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;......Line.ChgPoint (PntNum, roundto(x,1.0), roundto(y,1.0), z,p, a, c, f, m)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Using the roundto function defined earlier the point is going to be changed to reflect the new x and new y.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....Line.ReRec()&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Of course once it's changed it needs to be re-recorded.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....Line.Plot()&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;To really be elegant, the line should probably be erased prior to being changed and re-plotted. Many times however I like to to leave both versions on the screen (of course here there isn't any visual difference, I'm speaking in generalities) so I can see something happening or verify a change. A re-plot takes care of it.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Ws.UndoEnd(WsNum)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Close the undo and it's good to go.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-7584632296784759920?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/7584632296784759920/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=7584632296784759920' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/7584632296784759920'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/7584632296784759920'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/01/rounding-line-coordinates.html' title='Rounding line coordinates'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-6485722076217194960</id><published>2007-01-23T09:37:00.000-05:00</published><updated>2007-01-23T09:57:24.753-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><category scheme='http://www.blogger.com/atom/ns#' term='NonVr'/><title type='text'>All the way to the beginning</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family: arial;"&gt;What if you have never learned to write a program in any language, or for that matter had the desire to do so.  I'm not really going to post much today, other than to mention that I am working on a script I'm calling BeginnersVrPython.py. I am building it as a reference for anyone in the office that may want to jump right in programming in VrPython without any real knowledge of python.  In my mind that is a bit of a limitation because to really get the most out of the language itself, well, you need to know a little about it. There are however an awful lot of things that can be done with even the most basic background.  BeginnersVrPython.py will be a guided step through the simplest commands which should prompt the user to get into the &lt;/span&gt;&lt;a style="font-family: arial;" href="http://www.cardinalsystems.net/help/PythonVrOne.html"&gt;VrPython&lt;/a&gt;&lt;span style="font-family: arial;"&gt; documentation to expand the capabilities. It has always seemed to me that looking at examples, changing them a little, then taking off in varying directions, is the easiest way to learn programming. When done, the beginners script should offer just that kind of examples in a guided fashion. Eventually it will be posted somewhere, but until then I'll just &lt;a href="mailto:dshimer@gmail.com?subject=Beginners%20VrPython%20Script"&gt;email it&lt;/a&gt; to anyone interested in the current state.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;Along the same lines of, going to the very beginning, there is another beginners ebook available called "&lt;/span&gt;&lt;a style="font-family: arial;" href="http://www.greenteapress.com/thinkpython/"&gt;How to Think Like a Computer Scientist: Learning With Python&lt;/a&gt;&lt;span style="font-family: arial;"&gt;" available.  I've looked over a little bit of it and it seems like a good read for someone very early in the game. If you are going to use this, install &lt;/span&gt;&lt;a style="font-family: arial;" href="http://www.python.org/download/releases/2.5/"&gt;python 2.5&lt;/a&gt;&lt;span style="font-family: arial;"&gt; since that is where VrOne is at as of the current release (3.2 as of 01/07)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-6485722076217194960?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/6485722076217194960/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=6485722076217194960' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/6485722076217194960'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/6485722076217194960'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/01/all-way-to-beginning.html' title='All the way to the beginning'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-3408962805984762691</id><published>2007-01-11T05:44:00.000-05:00</published><updated>2007-01-17T05:46:58.919-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><title type='text'>Exactly the way you want it</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;There are times where Vr gives you all the tools you need to do something, but there may be just a little twist that still makes it worthwhile to write some quick code. In this case all that was necessary was to digitize some locations and have those written to a text file. There are several ways I can think of to do the exact same thing using tools that exist, but in this case there was no reason (or desire) to actually store points in the file, and there was a specific very simple output format desired (which of course could be easily modified for other purposes. This will also give us a reason to interact with a separate external file.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;fprintf = lambda afile,fmt,*args: afile.write(fmt%args)&lt;br /&gt;&lt;br /&gt;Gui=PyVrGui()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;TextFileName='dig'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;PointsFound=0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Stat=0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;TextFile=open(TextFileName+'.txt','w')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;while Stat==0:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;..Stat,x,y,z=Gui.GetCoord('Dig_Txt')&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;..fprintf(TextFile,'%12.2lf%12.2lf%10.2lf\n',x,y,z)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;..PointsFound=PointsFound+1&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;print '\n\a',PointsFound,' Points found and written to file ',TextFileName,'.txt\n'&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;TextFile.close()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Line by line.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;fprintf = lambda afile,fmt,*args: afile.write(fmt%args)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;This is mentioned elsewhere as one of my favorite tricks, it exactly reproduces the functionality of the C fprintf statement which formats text for output. Python has some very easy tricks for formatting, this just give me a familiar interface.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;Gui=PyVrGui()&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Always remember to create the Vr objects you are going to interact with, whether line, symbol, dtm, or in this case gui.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt; &lt;span style="font-family:courier new;"&gt;TextFileName='dig'&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Points are going to be stored in a file, the name isn't important but let's put it in the block of code that is at the top and easy to find if someone needs to modify it.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt; &lt;span style="font-family:courier new;"&gt;PointsFound=0&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Stat=0&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;These need to start at zero so we'll go ahead and initialize them as well.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt; &lt;span style="font-family:courier new;"&gt;TextFile=open(TextFileName+'.txt','w')&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;In this example we'll use the string addition method to add an extension which will end up creating a file named "dig.txt". This is just included to illustrate how if you have a base file name you can open several files with different extensions by just adding a different one. &lt;span style="color: rgb(51, 51, 255);"&gt;TextFile &lt;/span&gt;will become an instance of an open file object in "w" or write mode, there are several modes which mirror their c counterparts. Interacting with files is one of the more helpful actions to pick up.  Here we will just be dumping formatted text to an ascii file, but there are times when it will be necessary to read and write from both binary and ascii files, all of which is controlled by the "mode".&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt; &lt;span style="font-family:courier new;"&gt;while Stat==0:&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;GetCoord is going to return a status flag which is determined by if the user actually digitized a coordinate or hit End. This loop will just keep it running as long as they keep reading points, and to answer the most obvious question a status of 0 means yes a point was digitized; no I don't know why 0 is yes and 1 is no.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;..&lt;span style="font-family:courier new;"&gt;Stat,x,y,z=Gui.GetCoord('Dig_Txt')&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Digitize a point, as a side note the text string there is a title that is said to "show up in the VrOne message area". I have never actually seen it show up anywhere, but something is required to be there and I just enter relevant text in case it ever does.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;..&lt;span style="font-family:courier new;"&gt;fprintf(TextFile,'%12.2lf%12.2lf%12.2lf\n',x,y,z)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;The fprintf is discussed elsewhere but suffice it to say the text file we set up is going to get a piece of text formatted to 12 columns, 2 decimal places for each coordinate.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt; ..&lt;span style="font-family:courier new;"&gt;PointsFound=PointsFound+1&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;print '\n\a',PointsFound,' Points found and written to file ',TextFileName,'.txt\n'&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;No real point, I just like to keep track of things like this and print the status when done.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt; &lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;TextFile.close()&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Python is supposed to clean up after itself and close files when it exits, but as a rule it is a good habit of always doing the housekeeping explicitly.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Want to just see the least common denominator for a couple of the things mentioned.&lt;br /&gt;To digitize a point, open pyedi and copy in&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;Gui=PyVrGui()&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-size:85%;" &gt;&lt;span style="font-family:courier new;"&gt;print Gui.GetCoord('')&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Want to write something to a file, do the same (or open a python editor) with the following&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;file=open('/tmp/tmp.txt','w')&lt;span style="color: rgb(153, 102, 51);"&gt;#change the directory to something you have&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;file.write('a line of text')&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;file.close()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;As an addendum, I want to plug a python forum that I mentioned earlier.  I can even see it as a place that VrPython users could interact in a conversational way.  I enjoy the forum so much that I tend to monitor it on a semi-regular basis and am likely to find a Vr related post fairly quick. Information is power, and sharing it has benefit for everyone. Check it out at &lt;a href="http://www.thescripts.com/forum/forum152.html"&gt;The Scripts Developers Network or otherwise known as thescripts.com&lt;/a&gt; see you there!&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-3408962805984762691?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/3408962805984762691/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=3408962805984762691' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/3408962805984762691'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/3408962805984762691'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/01/exactly-way-you-want-it.html' title='Exactly the way you want it'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-4824647790845304739</id><published>2007-01-08T13:41:00.000-05:00</published><updated>2007-01-08T13:46:33.358-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><category scheme='http://www.blogger.com/atom/ns#' term='NonVr'/><title type='text'>Non-Programmer's Tutorial for Python</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;I don't really have time for anything earth shattering here, but if you are brand new to both programming, and Python I highly recommend the site "&lt;/span&gt;&lt;a style="font-family: arial;" href="http://en.wikibooks.org/wiki/Non-Programmer%27s_Tutorial_for_Python/Contents"&gt;Non-Programmer's Tutorial for Python&lt;/a&gt;&lt;span style="font-family:arial;"&gt;"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-4824647790845304739?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://en.wikibooks.org/wiki/Non-Programmer&apos;s_Tutorial_for_Python/Contents' title='Non-Programmer&apos;s Tutorial for Python'/><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/4824647790845304739/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=4824647790845304739' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/4824647790845304739'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/4824647790845304739'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/01/non-programmers-tutorial-for-python.html' title='Non-Programmer&apos;s Tutorial for Python'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-33665095347275747</id><published>2007-01-05T14:48:00.000-05:00</published><updated>2007-01-05T15:08:50.045-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><title type='text'>Need a new command?</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;A quick end of week freebie. Here is an example of a really useful program that a person could think themselves justified in griping that it doesn't exist in &lt;/span&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_0"  style="font-family:arial;"&gt;Vr&lt;/span&gt;&lt;span style="font-family:arial;"&gt;. Emailing someone and asking for it, looking in each beta release hoping that a life of clean living and good fortune deems that your suggestion is incorporated. OR...... learn a little python and spend 5 minutes writing it yourself. Sure we could each come up with a hundred examples of tools we would like to see, the problem is that half the suggestions on each list would be unique, to which each would say, "How can you want that, this idea is much more important" while at the same time the poor &lt;/span&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-corrected" id="SPELLING_ERROR_1"  style="font-family:arial;"&gt;beleaguered&lt;/span&gt; programmers struggle to keep up with dumb questions ( note: comic aside which I only mention because I have a string of about 3 for 6 that were total time wasters on the order of "what do I do with the 3 prong cord hanging out the back", to which the answers were still gracious and helpful)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;User question: What would it take to write a command that would essentially be insert line in which you ID a line to inherit properties from then start digitizing with the those properties?&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;How this works is fairly obvious, let me just explain what I think the more elegant points of python are.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line = PyVrLine ()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui=PyVrGui()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line.Id()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;lay,gp,wid=Line.GetLayer(),Line.GetGpoint(),Line.GetWidth()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui.PushKeyin ('inslin,lay=%d,grp=%d,wid=%d'%(lay,gp,wid))&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We're going to need a Line(), and a Gui() object, then grab the line to inherit from using Id(). What I love is that on the next line we are declaring 3 variables and setting them to the proper values at the same time without ever worrying what kind of variable they are. Then sending the inslin command and all the keyins on one line using python text formatting. So the answer to "what would it take?", not much, cool eh.&lt;blockquote&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-33665095347275747?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/33665095347275747/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=33665095347275747' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/33665095347275747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/33665095347275747'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/01/need-new-command.html' title='Need a new command?'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-6465903832206703862</id><published>2007-01-04T04:09:00.000-05:00</published><updated>2007-01-04T15:38:01.671-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tips'/><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><category scheme='http://www.blogger.com/atom/ns#' term='NonVr'/><title type='text'>Think ahead and start right</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Let me back off a bit and offer some general opinions that may save some time in the end. When I first started playing around with python, it was primarily porting old programs from other languages or mapping utilities from Vr's predecessor. It became almost a game to discover how few lines I could accomplish a task in, and how many basic utilities I could port. After the dust settled a little I realized that I was hooked and would be doing most (if not all) my future programming in python. At this point organization became much more important, but I also had some catching up to do. Here are a few things that helped that I would recommend, pardon as I randomly throw thoughts around.&lt;br /&gt;&lt;br /&gt;First, develop a coding style that is consistent.  One of the things I like about Python is the ease of use, as a result I am constantly passing code around and encouraging people to use, modify, and learn it. As things get passed around, or when you come back to it months later, a consistent style really helps. It has even made it possible to write a program that parses a script looking for certain cues and then writes an html documentation file for it. As examples of coding style the following aren't necessarily the best way to do things but at least I try to do them consistently and they seem to help.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Keep small reusable code snippets in a module for that purpose. For example I mentioned a Python incarnation of a C-like printf function, I keep that in my personal util module.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;When importing and calling a module, I always use the full module name, for example if my printf function is in my dsutil module, I &lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;import dsutil&lt;/span&gt; then call &lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;dsutil.printf()&lt;/span&gt; rather than doing a &lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;from dsutil import *&lt;/span&gt; then just calling &lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;printf()&lt;/span&gt;. This is a small thing but even for standard modules it always shows where something is coming from.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Have some rudimentary version control. I have a function that prints the program name and last date modified at run time. Very basic, but at least if there is a problem I can ask the user what copy they are running.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;I always put a small block of text at the beginning of a script to make notes in, import all necessary modules next, then declare and initialize what I call "variables of interest" that either need to have a particular starting value or which a user may look for at a later date. If there are more generic variables that are just needed to hold values at run-time I generally let those get created in situ. A good example of this would be something like &lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;x,y,z=Sym.GetCoord()&lt;/span&gt; where there is no need to initialize the coordinates, just let the function create and set them.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Second, document everything. As mentioned above it doesn't have to be fancy but it is amazing how quickly I forget what I was trying to accomplish with a perfectly functional piece of code like.&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;os.path.splitext(os.path.split(FullName)[1])[0]&lt;/span&gt;&lt;br /&gt;A little reminder goes a long way next year when something similar is necessary.&lt;br /&gt;&lt;br /&gt;Maintain a simple database of programs written. Just a simple delimited file that contains things like name, function, misc notes, state of completion. With that available I wrote another fairly simple script that parses that file and creates an html document with everything in a table, and links to the files created by the self documented files.  In the end if everything goes correct, one program writes the documentation for the script, and another creates the index file from which it can be referenced all based on the information inside the program, or entered in the database.&lt;br /&gt;&lt;br /&gt;And just so we don't go too long without a little VrPython code, here are several (though not nearly all) ways to do the old "hello world" program from within Vr. Yes this should have been the very first post, oh well, copy and paste into pyedi and watch the fun begin.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;Gui = PyVrGui()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;print 'hello world'          # to console&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;Gui.DspMsg0('hello 1')       # top Vr status box&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;Gui.DspMsg('hello 2')        # bottom Vr status box&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;Gui.DspShortMsg(0,'hello 3') # top small status box&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;Gui.DspShortMsg(1,'hello 4') # bottom small status box&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: courier new; color: rgb(51, 51, 255);"&gt;Gui.MsgBox ('hello 5','window title') # dialog popup&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-6465903832206703862?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/6465903832206703862/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=6465903832206703862' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/6465903832206703862'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/6465903832206703862'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2007/01/think-ahead-and-start-right.html' title='Think ahead and start right'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-3523305802982450259</id><published>2006-12-28T08:55:00.000-05:00</published><updated>2006-12-28T15:35:22.359-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Advanced'/><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><title type='text'>Simple task offers many examples</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Let's look at a very simple task that will offer a wealth of examples of using various &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;Vr&lt;/span&gt; modules and tasks. This will go beyond the idea of using as a simple macro language into the early stages of writing what I consider true programs that extend &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;Vr&lt;/span&gt; functionality and will include some basic ideas as well as some more advanced concepts. This example will include...&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;using python modules (non-&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;vr&lt;/span&gt; straight python)&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;selecting entities&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;creating new entities&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;displaying information in various forms&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;and grabbing window attributes.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;The problem is that there are several lines in the file for which the area is required, along with the total of all areas. It would be nice to allow the user to ID as many lines as necessary, display the area for each line, then present the total at the end. We'll throw in some variations at the end that make for interesting exercises, and more useful programs.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;Here is the code....&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;import math&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui = &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;PyVrGui&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;Ws&lt;/span&gt;=&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;PyVrWs&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gr=&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;PyVrGr&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line=&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;PyVrLine&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;TotalArea&lt;/span&gt;=0.0&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;NumberOfLines&lt;/span&gt;=0&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;text=&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;PyVrText&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;text.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;SetFontNum&lt;/span&gt;(4)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;text.SetRot(45.0)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;text.SetSize(Gr.GetWinScale ()*.15)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;WsNum&lt;/span&gt;=&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;Ws&lt;/span&gt;.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;Aws&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;while Line.Id() != -1:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..TotalArea=TotalArea+math.fabs(Line.Area())&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;NumberOfLines&lt;/span&gt;=&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;NumberOfLines&lt;/span&gt;+1&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..print &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;TotalArea&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..label='%.1f ac' % math.fabs((Line.Area()/43560.0))&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..text.SetText(label)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..(&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;MinX&lt;/span&gt;, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;MinY&lt;/span&gt;, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;MinZ&lt;/span&gt;, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;MaxX&lt;/span&gt;, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;MaxY&lt;/span&gt;, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;MaxZ&lt;/span&gt;) = &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;Ws&lt;/span&gt;.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;GetLineMinMax&lt;/span&gt; (&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;WsNum&lt;/span&gt;, Line.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;GetLineNum&lt;/span&gt;())&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..text.SetCoord((MinX+MaxX)/2,(MinY+MaxY)/2,(MinZ+MaxZ)/2)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..text.SetJustX(2)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..text.SetJustY(2)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..text.SetLayer(88)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..text.Plot()&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;print 'Total Area ',&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;TotalArea&lt;/span&gt;,' Sq Units ',&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_29"&gt;TotalArea&lt;/span&gt;/43560.0,' acres'&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_30"&gt;MsgBox&lt;/span&gt;('%d Lines contain %.2f acres'%(&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_31"&gt;NumberOfLines&lt;/span&gt;,(&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_32"&gt;TotalArea&lt;/span&gt;/43560.0)),'Area by Selection')&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;Taken a line or two at a time&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;import math&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;We are going to use a purely math function later. It would be easy enough to write the function needed (math.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_33"&gt;fabs&lt;/span&gt;() to get the absolute value of a real number), but this illustrates why it is nice to have python installed even though it isn't strictly necessary for &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_34"&gt;VrPython&lt;/span&gt; to work, there are times that accessing standard (or very exotic) modules that are already available can be nice.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui = &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_35"&gt;PyVrGui&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_36"&gt;Ws&lt;/span&gt;=&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_37"&gt;PyVrWs&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gr=&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_38"&gt;PyVrGr&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Line=&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_39"&gt;PyVrLine&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;text=&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_40"&gt;PyVrText&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;text.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_41"&gt;SetFontNum&lt;/span&gt;(4)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;text.SetRot(45.0)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;text.SetSize(Gr.GetWinScale ()*.15)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;text.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_42"&gt;SetJustX&lt;/span&gt;(2)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;text.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_43"&gt;SetJustY&lt;/span&gt;(2)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;text.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_44"&gt;SetLayer&lt;/span&gt;(88)&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_45"&gt;TotalArea&lt;/span&gt;=0.0&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_46"&gt;NumberOfLines&lt;/span&gt;=0&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;img src="file:///C:/WINNT/TEMP/moz-screenshot.jpg" alt="" /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;First create or initialize all the &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_47"&gt;Vr&lt;/span&gt; objects that will be used (first 5 lines), &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_48"&gt;pre&lt;/span&gt;-set any entity parameters that the user may want quick access to later (lines 6-11), and initialize variables that need to start with a &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_49"&gt;pre&lt;/span&gt;-determined value.&lt;br /&gt;In this case Gui will be used to display a message box, I always initialize &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_50"&gt;Ws&lt;/span&gt; out of habit, Gr will give us access to the &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_51"&gt;Vr&lt;/span&gt; graphics window, Line will be used to ID line entities, and text will be used to display the areas on the screen in the graphics window as text entities. We'll discuss all these as we use them but text values are declared early and in the variable area I put at the beginning because they directly affect how the text displays and the user may want to change the appearance. The one important thing to notice here is the use of the Gr.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_52"&gt;GetWinScale&lt;/span&gt; to grab the map scale of the current graphics window which is then multiplied by the size (in inches) I want it to appear on the screen since the text object expects size in ground units, also note that &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_53"&gt;SetSize&lt;/span&gt; is used rather than setting height and width independently&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_54"&gt;WsNum&lt;/span&gt;=&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_55"&gt;Ws&lt;/span&gt;.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_56"&gt;Aws&lt;/span&gt;()&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;I just always throw this in to make sure we all know what workspace is active.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;while Line.Id() != -1:&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;The line object has a function called Id which not only contains all the overhead of allowing the user to identify a line in the graphics window complete with button dialog, but also returns with that line loaded and ready to work on.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..TotalArea=TotalArea+math.fabs(Line.Area())&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_57"&gt;NumberOfLines&lt;/span&gt;=&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_58"&gt;NumberOfLines&lt;/span&gt;+1&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;The names give away the purpose, and each time a line is selected we bump the accumulated area and the line count. The reason these were initialized to zeros before is that we want to make sure they start from there.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..print &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_59"&gt;TotalArea&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Sometimes I just like to send things to the console screen as a debugging tool or so there is something of a temporary record.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..label='%.1f ac' % math.fabs((Line.Area()/43560.0))&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..text.SetText(label)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;For this program I decided to display individual line areas in the &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_60"&gt;Vr&lt;/span&gt; graphics window as text entities so the first thing that needs to be done is setting the text to the area of the line. Here is where the math module is used to make sure the area is positive. The single quote marks and % symbols convert the floating point number returned to a formatted text string with only one decimal place. If I wasn't worried about the formatting I could also use the python &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_61"&gt;repr&lt;/span&gt;() function to simply change the number to a string because the &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_62"&gt;SetText&lt;/span&gt; function expects to be handed a string. These two lines could also be easily written as one line but that makes it a little more obscure for this example.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..(&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_63"&gt;MinX&lt;/span&gt;, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_64"&gt;MinY&lt;/span&gt;, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_65"&gt;MinZ&lt;/span&gt;, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_66"&gt;MaxX&lt;/span&gt;, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_67"&gt;MaxY&lt;/span&gt;, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_68"&gt;MaxZ&lt;/span&gt;) = &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_69"&gt;Ws&lt;/span&gt;.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_70"&gt;GetLineMinMax&lt;/span&gt; (&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_71"&gt;WsNum&lt;/span&gt;, Line.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_72"&gt;GetLineNum&lt;/span&gt;())&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Since the text needs to be place somewhere on the screen, I decide to just place it in the middle of the lines extents. In order to do that we need the &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_73"&gt;Mins&lt;/span&gt;, and &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_74"&gt;Maxs&lt;/span&gt;. Those values are stored with the line header in the workspace so within the workspace object &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_75"&gt;Ws&lt;/span&gt; we use the &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_76"&gt;GetLineMinMax&lt;/span&gt; on &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_77"&gt;WsNum&lt;/span&gt; (which we set to the current earlier) to pull the data for the entity number of the currently loaded line.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..text.SetCoord((MinX+MaxX)/2,(MinY+MaxY)/2,(MinZ+MaxZ)/2)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Once we have the extents just take the average and set the text to be displayed at those coordinates.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..text.Plot()&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;The have &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_78"&gt;Vr&lt;/span&gt; plot the text entity on the screen. Note that there is no save done on the text so if the screen is refreshed or overwritten it will disappear.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;print 'Total Area ',&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_79"&gt;TotalArea&lt;/span&gt;,' Sq Units ',&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_80"&gt;TotalArea&lt;/span&gt;/43560.0,' acres'&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;When the selection is all done (note that we are out of the indented block) print various numbers and text to the console screen for the same reasons listed above..&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_81"&gt;MsgBox&lt;/span&gt;('%d Lines contain %.2f acres'%(&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_82"&gt;NumberOfLines&lt;/span&gt;,(&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_83"&gt;TotalArea&lt;/span&gt;/43560.0)),'Area by Selection')&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;More importantly display it all in a message box that will come up nicely formatted and with an "OK" button to dismiss.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Variations include:&lt;/span&gt;&lt;br /&gt;Prompting for a layer number and just summing the areas for all lines in a given layer rather than selecting them.&lt;br /&gt;&lt;br /&gt;As the lines are selected, how about changing some graphic attributes (again don't save anything) that make the line stand out so it is obvious which lines have been &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_84"&gt;ID'd&lt;/span&gt;.&lt;br /&gt;&lt;br /&gt;As lines are computed the individual areas along with some identifying info (entity number, or feature code) could be written to a file followed by the total.&lt;br /&gt;&lt;br /&gt;Fix it so that if the user identifies the same line multiple times it only gets added to the total once. (caution geeky hint: I would probably use the entity number, a list, and the list.count function)&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-3523305802982450259?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/3523305802982450259/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=3523305802982450259' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/3523305802982450259'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/3523305802982450259'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2006/12/simple-task-offers-many-examples.html' title='Simple task offers many examples'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-5642934900043136549</id><published>2006-12-19T15:24:00.000-05:00</published><updated>2006-12-19T15:26:41.910-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Tips'/><category scheme='http://www.blogger.com/atom/ns#' term='NonVr'/><title type='text'>Quickie tip</title><content type='html'>&lt;span style="font-family: arial;"&gt;Already posted for the week but found a forum that shows quite a bit of promise. It is at &lt;/span&gt;&lt;a style="font-family: arial;" href="http://www.thescripts.com/forum/forum152.html"&gt;TheScripts developer network&lt;/a&gt;&lt;span style="font-family: arial;"&gt;, and looks pretty interesting.  &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-5642934900043136549?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='related' href='http://www.thescripts.com/forum/forum152.html' title='Quickie tip'/><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/5642934900043136549/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=5642934900043136549' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/5642934900043136549'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/5642934900043136549'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2006/12/quickie-tip.html' title='Quickie tip'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-2040438106694427143</id><published>2006-12-19T06:23:00.000-05:00</published><updated>2007-01-04T13:07:03.783-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><title type='text'>Python as macro revisited</title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;In the first &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;VrPython&lt;/span&gt; example I gave which has now take on it's official name of fix_&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;sym&lt;/span&gt;_z.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;py&lt;/span&gt; my purpose was to show how it is possible to get some working code very fast just using some basic &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;Vr&lt;/span&gt; keystrokes. I very rarely use the &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;vr&lt;/span&gt; button (B1, B2, B# etc) commands to actually push the buttons, but it makes a point. The real problem with that script in a public setting is the drive point functionality that wasn't explained, not to mention that the person using it had several key suggestions to make it much more useful (don't end users drive you crazy like that sometimes). In any case, let's look at the current evolution of the script and the positive and negative effects of the changes. While I'm still going to use the button press commands at the end to actually do the work, by necessity this will start looking more like a python script and less like a simple extended macro, but then that's the whole point.&lt;br /&gt;&lt;span style="color: rgb(204, 0, 0);"&gt;Remember the dots are used for place holders and to visually represent the indentation which is life and death in python (2 dots = 1 tab)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui = &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;PyVrGui&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;stat=0&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Layer2Drive=25&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;Sym=PyVrSym()&lt;br /&gt;Ws&lt;/span&gt;=&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;PyVrWs&lt;/span&gt;()&lt;br /&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;WsNum&lt;/span&gt;=&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;Ws&lt;/span&gt;.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;Aws&lt;/span&gt;()&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;PushKeyin&lt;/span&gt; ("&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;digxyz&lt;/span&gt;")&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;for &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;EntNum&lt;/span&gt; in range (&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;Ws&lt;/span&gt;.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;GetSymCount&lt;/span&gt;(&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;WsNum&lt;/span&gt;)):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..if Layer2Drive==&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;Ws&lt;/span&gt;.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;GetSymLayer&lt;/span&gt;(&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;WsNum&lt;/span&gt;,&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_20"&gt;EntNum&lt;/span&gt;):&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....Sym.Load (&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;WsNum&lt;/span&gt;, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;EntNum&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....x,y,z=Sym.GetCoord()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....Gui.PushKeyin ('&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;xyz&lt;/span&gt; '+&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;repr&lt;/span&gt;(x)+' '+&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;repr&lt;/span&gt;(y)+' +0')&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....stat, x, y, z = Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;GetCoord&lt;/span&gt; ('Select Coordinate')&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....if stat==0:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;......Gui.PushKeyin ("&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;chaele&lt;/span&gt;")&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;PushKeyin&lt;/span&gt; ("&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_29"&gt;sealin&lt;/span&gt;=0")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_30"&gt;PushKeyin&lt;/span&gt; ("&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_31"&gt;seasym&lt;/span&gt;=1")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_32"&gt;PushKeyin&lt;/span&gt; ("b1")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_33"&gt;PushKeyin&lt;/span&gt; ("b1")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_34"&gt;PushKeyin&lt;/span&gt; ("b#")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_35"&gt;PushKeyin&lt;/span&gt; ("&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_36"&gt;chalay&lt;/span&gt;")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_37"&gt;PushKeyin&lt;/span&gt; ("&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_38"&gt;sealin&lt;/span&gt;=0")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_39"&gt;PushKeyin&lt;/span&gt; ("&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_40"&gt;seasym&lt;/span&gt;=1")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_41"&gt;PushKeyin&lt;/span&gt; ("lay=76")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_42"&gt;PushKeyin&lt;/span&gt; ("b1")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_43"&gt;PushKeyin&lt;/span&gt; ("b1")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_44"&gt;PushKeyin&lt;/span&gt; ("b#")&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Looking at it a line at a time&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui = &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_45"&gt;PyVrGui&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;stat=0&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Layer2Drive=25&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_47"&gt;Sym=PyVrSym()&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;As before, just setting up some variables. Creating an instance of the Gui object, same for a Symbol, and initializing the others. This is a good place to note that in Python you don't actually have to declare variables, or initialize them in any particular place. I could have put the &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Layer2Drive=25&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt; on the line right before the first place I used it, or if it were the result of a calculation, just let it be created in place. I am only setting them up early like this because I want to know what they are set to, and putting it all together seems like sound practice. In the first pass at this script the external "&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_46"&gt;drv&lt;/span&gt;2lay" script prompted for the layer, but in reality the user just wanted it to always use the same layer.  I could have used the desired number rather than a variable later, but using a variable and setting it at the outset makes it easy for other users to find and change if they want.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_47"&gt;Ws&lt;/span&gt;=&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_48"&gt;PyVrWs&lt;/span&gt;()&lt;br /&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_49"&gt;WsNum&lt;/span&gt;=&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_50"&gt;Ws&lt;/span&gt;.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_51"&gt;Aws&lt;/span&gt;()&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_52"&gt;PushKeyin&lt;/span&gt; ("&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_53"&gt;digxyz&lt;/span&gt;")&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Because &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_54"&gt;Vr&lt;/span&gt; allows several &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_55"&gt;workspaces&lt;/span&gt; to be open at the same time and in many cases you have to specify which one you are interacting with you need to create an instance of a workspace object, and in this case set it to the currently active workspace. Then let's make sure that the stereo digitizer is active before we start driving to points.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;for &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_56"&gt;EntNum&lt;/span&gt; in range (&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_57"&gt;Ws&lt;/span&gt;.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_58"&gt;GetSymCount&lt;/span&gt;(&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_59"&gt;WsNum&lt;/span&gt;)):&lt;br /&gt;..&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;..if Layer2Drive==&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_60"&gt;Ws&lt;/span&gt;.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_61"&gt;GetSymLayer&lt;/span&gt;(&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_62"&gt;WsNum&lt;/span&gt;,&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_63"&gt;EntNum&lt;/span&gt;):&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;This is going to represent one of the biggest changes to this script, driving to the points will actually become part of the script, but before we can drive, they have to be identified. The for loop in Python is fantastic and I won't take time to explain it now (remember the books recommended in the introduction). Let's just say that in plain &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-corrected" id="SPELLING_ERROR_64"&gt;English&lt;/span&gt; these two loops (the for and the if) would sound like "&lt;span style="font-style: italic;"&gt;For entity numbers in the range zero through how ever many symbols there are, if the desired layer to drive to is equal to the layer of the symbol with the entity number currently being checked&lt;/span&gt;". Yes we are going to loop over the entire file and check the layer of each symbol, the power behind this loop is the way the checking is done which I won't really go into, but suffice it to say it seems instant on even the largest files.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....Sym.Load (&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_21"&gt;WsNum&lt;/span&gt;, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_22"&gt;EntNum&lt;/span&gt;)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....x,y,z=Sym.GetCoord()&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;At this point if the symbol does match the layer we plan to drive to, load the symbol based on the workspace we are working in, and the entity number of the symbol currently being checked. Then from the loaded symbol grab the coordinates. Note that since GetCoord returns 3 numbers, I can assign all 3 at the same time. This is also an example of assigning data to a variable that has been neither declared nor initialized. It becomes a floating point variable because that's what I assigned to it.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....Gui.PushKeyin ('&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_23"&gt;xyz&lt;/span&gt; '+&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_24"&gt;repr&lt;/span&gt;(x)+' '+&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_25"&gt;repr&lt;/span&gt;(y)+' +0')&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Once I have the coordinates I can drive the instrument using the Vr command 'xyz' then supplying an x, a y, and the +0 just means rather than an absolute z use one relative to the current position and add zero. Since PushKeyin expects a string we have to construct one using a text+text method. In this case since x and y are numbers, they have to be converted to text before they can be added to the string using the Python &lt;span style="font-family:courier new;"&gt;repr() &lt;/span&gt;command. There are some extra spaces inserted after the xyz and before the +0 to keep things separated, so if x was 1.0, y was 2.0 the final string pushed to vr would be.&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;xyz 1.0 2.0 +0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....stat, x, y, z = Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_26"&gt;GetCoord&lt;/span&gt; ('Select Coordinate')&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;....if stat==0:&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Once the appropriate symbol has been found, and the instrument has been positioned there, use the same method as before to pause for the operator to put the dot on the ground and digitize the elevation at that point. The main difference from before is that now if the user digitized a point all the changes will be made. If they hit end, rather than abandoning the whole script, it simply doesn't change anything and continues looking for symbols that match the layer criteria. There really isn't any way to abandon the script, but in this case the user wanted it this way.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;......Gui.PushKeyin ("&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_27"&gt;chaele&lt;/span&gt;")&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_28"&gt;PushKeyin&lt;/span&gt; ("&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_29"&gt;sealin&lt;/span&gt;=0")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_30"&gt;PushKeyin&lt;/span&gt; ("&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_31"&gt;seasym&lt;/span&gt;=1")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_32"&gt;PushKeyin&lt;/span&gt; ("b1")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_33"&gt;PushKeyin&lt;/span&gt; ("b1")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_34"&gt;PushKeyin&lt;/span&gt; ("b#")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_35"&gt;PushKeyin&lt;/span&gt; ("&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_36"&gt;chalay&lt;/span&gt;")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_37"&gt;PushKeyin&lt;/span&gt; ("&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_38"&gt;sealin&lt;/span&gt;=0")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_39"&gt;PushKeyin&lt;/span&gt; ("&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_40"&gt;seasym&lt;/span&gt;=1")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_41"&gt;PushKeyin&lt;/span&gt; ("lay=76")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_42"&gt;PushKeyin&lt;/span&gt; ("b1")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_43"&gt;PushKeyin&lt;/span&gt; ("b1")&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;font-size:85%;"  &gt;......&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;Gui.&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_44"&gt;PushKeyin&lt;/span&gt; ("b#")&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Same basic set of changes, except that before we waited until the elevations had been changed, then globally changed the layer to put it in the dtm data set. Now since if there is no point digitized, no changes are made, we can put the layer change right into the symbol modifications which includes everything including and after the &lt;span style="font-family:courier new;"&gt;chalay &lt;/span&gt;line. Note that I hard coded the layer to 76. As I write this I'll probably change that to a variable for the same reasons I mentioned for the layer to check. The parameter for the PushKeyin will be something like..&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;("lay="+ChangeToLayer)&lt;/span&gt;&lt;br /&gt;There won't be a repr() command because I'll just store the variable as a string in the first place, something like...&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-family:courier new;"&gt;ChangeToLayer='76'&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;All in all still much more brute force than elegance, but now we are doing some basic looping over entities including loading and pulling information from them.&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-2040438106694427143?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/2040438106694427143/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=2040438106694427143' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/2040438106694427143'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/2040438106694427143'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2006/12/python-as-macro-revisited.html' title='Python as macro revisited'/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-923924241375200394</id><published>2006-12-15T11:31:00.000-05:00</published><updated>2006-12-15T11:56:44.737-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Advanced'/><category scheme='http://www.blogger.com/atom/ns#' term='Tips'/><title type='text'></title><content type='html'>&lt;span style=";font-family:arial;font-size:85%;"  &gt;I really only plan posting about once a week. I've already decided that the next "real" post will work on cleaning up the Vr script (which has come to be known as fix_sym_z) I mentioned earlier to make it much more useful and fully independent of the drive functions. However this quick one is just too cool to wait. But just in case the corpscon stuff is totally worthless to many folks who plan to write python in Vr, let me pass along one of my favorite tips, as pasted from one of my utility modules (dsutil). While the comment sections explain what it does, you may want to look up lambda, though it isn't necessary. If you understand printf, you understand this function.&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;printf = lambda fmt,*args: sys.stdout.write(fmt%args)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 102, 51);font-family:courier new;" &gt;'''&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 102, 51);font-family:courier new;" &gt;c like implemetation of printf, for example:&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 102, 51);font-family:courier new;" &gt;    dsutil.printf("this is %s test with the number %.2lf",'a',9)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 102, 51);font-family:courier new;" &gt;yields...&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 102, 51);font-family:courier new;" &gt;    this is a test with the number 9.00&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 102, 51);font-family:courier new;" &gt;'''&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 51, 255);font-family:courier new;" &gt;fprintf = lambda afile,fmt,*args: afile.write(fmt%args)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 102, 51);font-family:courier new;" &gt;'''&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 102, 51);font-family:courier new;" &gt;Same as printf but like c's fprintf sends output to open file&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 102, 51);font-family:courier new;" &gt;usage: dsutil.fprintf(AnOpenFile,"format",Values)&lt;/span&gt;&lt;br /&gt;&lt;span style="color: rgb(153, 102, 51);font-family:courier new;" &gt;'''&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Tom Blankenship is pretty high in my relatively short list of amazing programmers I actually know and can glean information from. As usual, if it is a matter of education on coding practices, Tom was fast to weigh in. The &lt;a href="http://crunch.tec.army.mil/software/corpscon/using_the_corpscon_dll.pdf"&gt;corpscondll is pretty well documented&lt;/a&gt;  but my problem was that I didn't know (and didn't know that I didn't know) how to pass a c style double pointer using c_double(). Tom put together a working script that has all the information necessary to incorporate corpscon transfomations into production programs, is this stuff amazing or what.&lt;br /&gt;&lt;br /&gt;As always a big thank you and hats off to Tom.&lt;br /&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-923924241375200394?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/923924241375200394/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=923924241375200394' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/923924241375200394'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/923924241375200394'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2006/12/i-really-only-plan-posting-about-once.html' title=''/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-2040762002300045770</id><published>2006-12-14T15:02:00.000-05:00</published><updated>2006-12-19T06:37:20.899-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Advanced'/><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><category scheme='http://www.blogger.com/atom/ns#' term='NonVr'/><title type='text'></title><content type='html'>&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;There is a patch up that includes python 2.5. I have installed it and want to make a quick report.&lt;br /&gt;The main implications include the facts that I...&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Rely heavily on standard imported libraries.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Have lots of my personal modules containing generic utilities.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Program everything in python and need to compile &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;exe&lt;/span&gt; files in many cases.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Utilize several &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-corrected" id="SPELLING_ERROR_1"&gt;open source&lt;/span&gt; libraries like &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;PIL&lt;/span&gt;, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;pyserial&lt;/span&gt;, etc.&lt;/span&gt;&lt;/span&gt;&lt;/li&gt;&lt;/ul&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;Before I installed the patch, I &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;un-installed&lt;/span&gt; all python 2.2 libraries as well as python itself. I then installed the patch and played with &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;vr&lt;/span&gt; a little to make sure that everything worked the way it should.  Next I installed python 2.5 and my most used extra libraries (primarily &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;pywin&lt;/span&gt;32, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;PIL&lt;/span&gt;, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;py&lt;/span&gt;2&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;exe&lt;/span&gt;, &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;pyserial&lt;/span&gt;). So far everything is working out fine except that I couldn't easily get &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;py&lt;/span&gt;2&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;exe&lt;/span&gt; to work the way it always did.  I'll admit that I didn't spend a huge amount of time and it is my problem, I just got frustrated trying to figure out how to configure everything to eliminate the message &lt;span style="font-family:courier new;"&gt;"&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;LoadLibrary&lt;/span&gt;(&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;pythondll&lt;/span&gt;) failed"&lt;/span&gt; when running a program without the full path. It works fine on simple programs, but there is apparently something in the way I code that is causing problems.&lt;br /&gt;&lt;br /&gt;While screwing around I found that &lt;a href="http://www.pyinstaller.org/"&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;pyinstaller&lt;/span&gt; &lt;/a&gt;worked fine for what I was doing and I was able to get it running in just a few minutes, so I'm going to migrate there for now.&lt;br /&gt;&lt;br /&gt;So far I'm quite pleased with the results of the upgrade. I've got as much weird stuff going on as most people so if it works here, I would think it would work for most anyone and I would suggest going for it.&lt;br /&gt;&lt;br /&gt;No major earth shattering changes but I like being on the latest python in case I find new libs I would like to use.  I'll also toss out that in 2.5 &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;ctypes&lt;/span&gt; is included in the standard install. My hope would be that this would make it possible for someone who knew what they were doing to use external &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_17"&gt;DLLs&lt;/span&gt;. So if you know of a way to use the &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_18"&gt;corpscon&lt;/span&gt; &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_19"&gt;DLL&lt;/span&gt; to write a coordinate transformation function within program, I would love to hear from you.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-2040762002300045770?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/2040762002300045770/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=2040762002300045770' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/2040762002300045770'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/2040762002300045770'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2006/12/there-is-patch-up-that-includes-python.html' title=''/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-6008173234418544128</id><published>2006-12-11T17:28:00.000-05:00</published><updated>2006-12-12T05:53:52.935-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Vr'/><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><title type='text'></title><content type='html'>&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;I'll come back to learning python but thought I would toss in a little &lt;/span&gt;Vr&lt;span style="font-family:arial;"&gt; as well. Had a situation where a &lt;/span&gt;colleague&lt;span style="font-family:arial;"&gt; wanted to perform a fairly simple and repetitive task.  When it came right down to it &lt;/span&gt;Vr&lt;span style="font-family:arial;"&gt; already had most of the tools he needed, I thought about stringing it together into a macro for him, but realized that some conditional statements would add a little zip to the solution.  In the end the solution is a good example of just using python as an extended macro language. Nothing earth shattering, just using basic &lt;/span&gt;Vr&lt;span style="font-family:arial;"&gt; commands, but putting a little of the power of python behind them.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;The situation was that he wanted to be able to quickly and visually throw points into a file in a random pattern using the mouse. Then to make these same points part of a valid 3d &lt;/span&gt;data set&lt;span style="font-family:arial;"&gt; he wanted to have the instrument drive back to the points, pause for the dot to be placed on the ground, set the elevation of the symbol to the current instrument position, then go on to the next point without having to issue any command other than ending the id process.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;The outline of the solution goes as follows.&lt;/span&gt;&lt;ol  style="font-family:arial;"&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;Digitize the symbols in a layer that makes them unique.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;Capture the xyz locations of those symbols by looping over the points in the file.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;Loop over the locations with a process that &lt;/span&gt;&lt;/li&gt;&lt;ol&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;Pauses to digitize a new z at each location&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;Set the symbol to that elevation.&lt;/span&gt;&lt;/li&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;Drive to the next point.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;li&gt;&lt;span style="font-size:100%;"&gt;When all done globally change the symbols to make them part of the normal data set.&lt;/span&gt;&lt;/li&gt;&lt;/ol&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;I'll address a couple of the redundant or &lt;/span&gt;wasteful&lt;span style="font-family:arial;"&gt; portions of the solution later, but to some extent this will also expose that fact that sometimes I write ugly code just to get something out for testing in a fairly short time, I regularly go back when things are slow and tighten up procedures.  This one definitely qualifies as one of the ugly ones, but it's still a good example.  Keep in mind that to this point I haven't found a way to make the proper indentation persistant in this blog so until further notice I'll use periods to fill the space where indentation belongs. Lets look at the code line by line...&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;Gui = PyVrGui()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;stat=0&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Gui.PushKeyin ("py drv2lay")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;Gui.PushKeyin ("digxyz")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;while stat==0:&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;..Gui.PushKeyin ("dri")&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;..stat, x, y, z = Gui.GetCoord ('Select Coordinate')&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;..if stat==0:&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;....Gui.PushKeyin ("chaele")&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;....Gui.PushKeyin ("sealin=0")&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;    &lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;....Gui.PushKeyin ("seasym=1")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;....Gui.PushKeyin ("b1")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;....Gui.PushKeyin ("b1")&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:courier new;"&gt;....Gui.PushKeyin ("b#")&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;Gui = PyVrGui()&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;This one just imports the appropriate library that will do most of the work in this script.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;stat=0&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;The routine used to grab the current instrument position returns a list which includes the process status to evaluate whether the used in fact digitized a point or just hit end.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;Gui.PushKeyin ("py drv2lay")&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;This is the most obscure part of the code. I already have a script that asks the user for a layer number (or number line), creates a drive file containing a drive point for every symbol in that layer, then opens the drive file. I will discuss that program in a later post but for now any function that grabs the xyz values for every symbol in a pre-determined layer would be fine.  I chose to go the drive route so the values would be stored temporarily, and I could just use the Vr "dri" function later. "&lt;span style="font-weight: bold;"&gt;PushKeyin&lt;/span&gt;" just sends the string in quotes to the Vr command line as if the user had typed it&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;Gui.PushKeyin ("digxyz")&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;Because the first time someone used it, they started the program while still set to the mouse which had been used to digitize the symbol locations, as well they should.  Just need a toggle it over if it hasn't already been done.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;while stat==0:&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;Python flow control is fairly standard, In this case if the user hits "End" rather than digitizing the new elevation at the symbol position the routine would return a  1, so if this happens "game over".&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;Gui.PushKeyin ("dri")&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;In the actual work part of the loop the first thing we want to do is drive to the next valid coordinate position, remember that there is already a drive file open with all the positions I want because of the other python program I called earlier.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;stat, x, y, z = Gui.GetCoord ('Select Coordinate')&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;Once we get to the position, pause and wait for the operator to put the dot on the ground and hit the button sending a status code and especially important the new Z.&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;if stat==0:&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;There is probably a more elegant way of doing this, but the fact is that after the user digitizes a point I needed to know if they had hit "End" and if so just skip the rest. If they digitized a new z location I want to do the following using the keyin routine.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;chaele - &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;start chaele because that's what I actually want to do.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;sealin=0 - &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;make sure that line search is off.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;seasym=1 - &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;make sure symbol search is on.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;b1 - &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;hit button 1 to identify the symbol at the location where the instrument is sitting.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;b1 - &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:100%;"&gt;&lt;span style="font-family:arial;"&gt;hit button 1 to release the point.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="color: rgb(0, 0, 153);font-size:100%;" &gt;&lt;span style="font-family:courier new;"&gt;b# - &lt;/span&gt;&lt;/span&gt;&lt;span style="font-size:85%;"&gt;&lt;span style="font-family:arial;"&gt;&lt;span style="font-size:100%;"&gt;hit the # to end chaele and resume the loop which then drives to the next point.&lt;br /&gt;&lt;br /&gt;So in this example I'm just using python to create the drive list, and the control flow to loop over it. I could also turn off any layers that aren't necessary to make sure that nothing errant gets identified. It could also have been done in one step without the second loop by not creating the drive file, but simply making a go to xyz statement part of the first loop which identifies the proper points.&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-6008173234418544128?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/6008173234418544128/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=6008173234418544128' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/6008173234418544128'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/6008173234418544128'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2006/12/ill-come-back-to-learning-python-but.html' title=''/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-8244083015210629196</id><published>2006-12-08T16:43:00.000-05:00</published><updated>2006-12-08T17:15:54.158-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Basics'/><title type='text'></title><content type='html'>I'll admit that when I get new hardware or software I'm the kind that installs and just jumps in with both feet playing and experimenting.  I've always thought that it is much better to get into the documentation with at least a basic grasp of what interfaces and such look like.  At the same time though I am a huge proponent of structured progressive training. That is really where I'm headed right now with the following recommendations.&lt;br /&gt;&lt;br /&gt;For anyone that is already programming in another language I think it is worthwhile to install Python on a computer even though it isn't strictly necessary for &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;VrPython&lt;/span&gt;. I actually think it's a good idea for anyone, but if you just want to jump into &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;VrPython&lt;/span&gt;, skip this for now you'll probably find other posts more helpful.&lt;br /&gt;&lt;br /&gt;As of the time of this writing the current implementation of Python in &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;Vr&lt;/span&gt; is 2.2. If that is what is installed then an extension called &lt;a href="https://sourceforge.net/projects/pywin32/"&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;pywin&lt;/span&gt;32 &lt;/a&gt;which not only adds windows elements to Python, but also includes an editor and programming environment that I like much better than Idle.&lt;br /&gt;&lt;br /&gt;Once you have the current Python that matches whatever is built into &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;Vr&lt;/span&gt;, I recommend the following books. Skip any reference to &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;gui&lt;/span&gt; programming and &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;tkinter&lt;/span&gt; for now.&lt;br /&gt;For basics start with.&lt;br /&gt;"&lt;b class="sans"&gt;&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;Sams&lt;/span&gt; Teach Yourself Python in 24 Hours"&lt;br /&gt;"&lt;/b&gt;&lt;b class="sans"&gt;The Quick Python Book"&lt;br /&gt;&lt;/b&gt;For more advanced reference.&lt;br /&gt;&lt;b class="sans"&gt;"Python Essential Reference"&lt;br /&gt;&lt;/b&gt;&lt;b class="sans"&gt;"Python Cookbook"&lt;br /&gt;&lt;/b&gt;I actually found all of them at my local library, though I like them so much I bought the last 3 to have around as a reference. I would read the first two at the same time or in that order. "Quick Python" was amazing in the information you can pick up fast if you have some programming experience.  It is especially helpful for someone who might switch over to Python for routine programming. Pay special attention to the concept of lists, I think they are by far one of the coolest things available in Python, and will offer a lot of power as time goes by.&lt;br /&gt;&lt;br /&gt;Why would a person want to switch to Python? Well for me it came down to the fact that I was spending time in it on a daily basis within &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;VrOne&lt;/span&gt; anyway. Now with the introduction of the "&lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;pyedi&lt;/span&gt;" command, coding within &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;Vr&lt;/span&gt; is even more convenient. However the more time I spend with it the more powerful and fast coding in this environment seems.  I decided to try rewriting some basic file manipulation programs and found that the lines of code dropped to about %25 of the original once I switched from something like C++. The more I tried, the less restrictions I found, for example by adding libraries like &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;PIL&lt;/span&gt; (Python Image Library) I was able to write a program that applies an external level file to an image. Sure I have that in &lt;span onclick="BLOG_clickHandler(this)" class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;ImageUtil&lt;/span&gt;, but I had mine a year earlier, and on every computer I own. So programming in general, and certainly Python, isn't for everyone, but it is a great place to start for beginners, and pure fun for those more experienced, in my opinion anyway.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-8244083015210629196?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/8244083015210629196/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=8244083015210629196' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/8244083015210629196'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/8244083015210629196'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2006/12/ill-admit-that-when-i-get-new-hardware.html' title=''/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-37876710.post-4644745078197618747</id><published>2006-12-06T05:46:00.000-05:00</published><updated>2006-12-07T06:55:52.870-05:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Introduction'/><title type='text'></title><content type='html'>By way of introduction let me just mention that I have been working with &lt;a href="http://www.cardinalsystems.net/"&gt;Vr&lt;/a&gt; or it's noble predecessor since 1989. While I always have suggestions on how it could be improved, I am not going to apologize for how much I like this software, or the fact that at times I may sound like too much of a cheerleader for it. I have no relationship with Vr other than satisfied customer, and have nothing to gain from the time spent here other than providing an outlet for my enthusiasm for programming and making maps. If anyone has some good tips or information that get passed along to me then that would just be a wonderful plus.&lt;br /&gt;My first introduction to computers as a working tools were HP-UX workstations, collecting data in CADMAP, and programming in C.  Over the years I have had the fortune to migrate to C++ and now to &lt;a href="http://www.python.org/"&gt;Python&lt;/a&gt;.  I have never been particularly clever or ambitious in my programming, but simply see it as a tool to take the task at hand, and either make it possible, or easier.  I have the blessing to &lt;a href="http://www.manmapping.com/"&gt;work&lt;/a&gt; in an environment that encourages me to think, code, and experiment.  Time spent learning and improving practices is considered time well spent. Thankfully most of the limited knowledge I do have about good programming flow and practices came from early discussions with Mike Kitaif who ranks up in the top handful of the sharpest people I personally know. I will go ahead and credit any good looking code I happen to come up with to him, though to be honest, most of it is just throwing something together to get a job done.&lt;br /&gt;My thoughts at the moment are to ramble a little about Python, VrPython, and Vr in general. I am a huge fan of stretching the capabilities of Vr with Python.  I may mention some of the 100+ tools that we have developed for specific tasks and need to be careful to say that I don't consider this to be  an indication of anything Vr is lacking, rather that while offering one of the most user friendly, practical, powerful data collection environments "out of the box", it goes beyond that to offer a potential for power and customization that is truly incredible. Not everyone would like the tools I like, but the beauty is that if not, they can create their own, and if they do the same tools are only minutes away with a few lines of Python.&lt;br /&gt;I have over time have begun to do all my coding in Python and also hope to share some of the ways it can be useful to folks to go ahead and install the full system and find uses for it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/37876710-4644745078197618747?l=dshimer.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://dshimer.blogspot.com/feeds/4644745078197618747/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=37876710&amp;postID=4644745078197618747' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/4644745078197618747'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/37876710/posts/default/4644745078197618747'/><link rel='alternate' type='text/html' href='http://dshimer.blogspot.com/2006/12/by-way-of-introduction-let-me-just.html' title=''/><author><name>Dennis Shimer</name><uri>http://www.blogger.com/profile/06120777710459207379</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='32' height='32' src='http://www.manmapping.com/face.jpg'/></author><thr:total>0</thr:total></entry></feed>
