Showing posts with label Tips. Show all posts
Showing posts with label Tips. Show all posts

Tuesday, December 15, 2015

I Get By With A Little Help From My Friends

Talking to a friend the other day it occurred to me how fantastic it would be if Vr could import and display OpenStreetMap data.  Nothing fancy mind you but maybe create an image that you could use as a background for a quick check of the surrounding area or even flight prep.  Wow that sounds like a lot of work unless of course someone else has already done it.  One of the many beauties of Python is the number of fantastic libraries out there if you just spend a little time tracking them down.  If you take that a step farther and are willing to pass a little of the responsibility outside python using system calls or batch files the possibilities are nearly endless.  Let's just say I can now display an OpenStreetMap map image in Vr and it only took about 90 lines of python.  Here are a few of the major helpers besides the map site which is so worthy of support, contribution, and praise.

I know I have mentioned it before but I can't say enough about pyproj which I use to convert my local coordinates to geographic for sending out to various places.

Once I have the corners in Lat / Long the rest will be done by a batch file which is about the only thing my python script creates.  It could be done in other ways but I liked the idea of creating something that could stick around and be easily modified for use again.  So the batch file next makes a call to the openstreetmap.org API for grabbing the map data.

Once the OSM file is in house it will be converted to a bitmap using Maperitive.  I only use such a tiny fraction of the capabilities of this amazing program, but for my purposes using it's command line version with a custom generated script will fit the bill perfectly.

The original bitmap is created in Web Mercator and can also throw in a TFW and KML file for generic use or display by anybody if you want to send them along.  I however want to display it behind my map in a local coordinate system in whatever system I choose so the last step is to re-project the image using GDAL.

Is this the most advanced, professional, elegant way of doing it?  Of course not, you obviously don't know me very well.  As usual it is something you can hack together in just a short time with minimal duplication of effort that gets the job done.  Hooray for real programmers!!!

Don't forget to support your favorite projects with contributions or cash when possible.


Tuesday, December 01, 2015

Note to self: Step backward through LiDAR when removing, and repr ( round ( a number )) is awsome

First, apparently I never noticed this before but while trying to step though a bunch of LiDAR points to remove a certain class it apparently changes something dynamically (like the point number in the buffer).  I noticed this because I was doing a

    for PointNum in range(Punt.GetCount()):
        if Punt.Cla(PointNum) == Whatever:
            Punt.DelPunt(PointNum)
To get rid of a certain type of point, in this case based on class.  What I noticed though was that each time it ran there were a bunch of points left over (half??).  I decided that even though I wasn't doing a record until the loop was done, the point number in the buffer must change as points are deleted.  So what to do?  How about starting at the last point and removing them from the top end of the buffer so as you work backwards the previous point numbers would not have changed.  I came up with
for PointNum in range(Punt.GetCount(),-1,-1):
and it seems to work fine.

Second and totally unrelated I needed to rebuild a tile naming structure for a local dataset.  There is a tile scheme that is based on 5000 foot tiles that is easy enough to get the names of.  The problem is that there is also a subset of 1250 foot tiles that starts from the corner of each 5k block but the names are based on 1000 foot increments.  When you digitize a random point in a block you can't necessarily round down to the lower 1000 because they just truncate the thousands from a rounded 1250.  Ok hard to imagine but the corners would be 0, 1250, 2500, 3750 so a number 3749 would fall in a 2500 block and truncate to 2000 meaning the tile would have 2 in the name, not to mention dropping a million off one of the coordinates.  Now for the why I love python part!
repr(round(1773691/1250)*1250)[1:4]
yields '772' just like is necessary to build the proper tile name. 

Wednesday, May 20, 2015

Note to self: Find a reason to use geopy

Full disclosure; This has nothing to do with anything except that I was playing with a really cool module today and need to make sure I remember what I just learned.  The module is geopy (which by the way I installed using pip for the first time ever ) which can be used to geocode natural language addresses using a variety of APIs.  Don't know when, how, or why I'll use it but I'm certain I will.

Info can be found at https://pypi.python.org/pypi/geopy
Doc at http://geopy.readthedocs.org/en/latest/

Here is what I just did (using my current address)

>>> import geopy
>>> geopy.geocoders.GoogleV3().geocode("4090 weaver ct s 43026")
Location((40.035917, -83.144145, 0.0))
>>> geopy.geocoders.GoogleV3().geocode("4090 weaver ct s 43026").raw
{u'geometry': {u'location': {u'lat': 40.035917, u'lng': -83.144145}, u'viewport': {u'northeast': {u'lat': 40.03726598029149, u'lng': -83.1427960197085}, u'southwest': {u'lat': 40.03456801970849, u'lng': -83.1454939802915}}, u'location_type': u'ROOFTOP'}, u'formatted_address': u'4090 Weaver Court, Hilliard, OH 43026, USA', u'place_id': u'ChIJpUOLF-iTOIgRT-Vqu5rHhLo', u'address_components': [{u'long_name': u'4090', u'types': [u'street_number'], u'short_name': u'4090'}, {u'long_name': u'Weaver Court', u'types': [u'route'], u'short_name': u'Weaver Ct'}, {u'long_name': u'Northwest Industrial Complex', u'types': [u'neighborhood', u'political'], u'short_name': u'Northwest Industrial Complex'}, {u'long_name': u'Hilliard', u'types': [u'locality', u'political'], u'short_name': u'Hilliard'}, {u'long_name': u'Norwich', u'types': [u'administrative_area_level_3', u'political'], u'short_name': u'Norwich'}, {u'long_name': u'Franklin County', u'types': [u'administrative_area_level_2', u'political'], u'short_name': u'Franklin County'}, {u'long_name': u'Ohio', u'types': [u'administrative_area_level_1', u'political'], u'short_name': u'OH'}, {u'long_name': u'United States', u'types': [u'country', u'political'], u'short_name': u'US'}, {u'long_name': u'43026', u'types': [u'postal_code'], u'short_name': u'43026'}, {u'long_name': u'1197', u'types': [u'postal_code_suffix'], u'short_name': u'1197'}], u'partial_match': True, u'types': [u'street_address']}

Wednesday, April 01, 2015

You gotta love a good library

The Columbus Metropolitan Library is arguably one of the best libraries in the nation.  I use it so much I have had my library card memorized for over 25 years.  The idea that there is information and services there at my fingertips any time I want is fantastic.  I was thinking about this yesterday when I started pulling functions out of PyVrGeom().  Libraries (modules) can be everything from little bits of code snippets that you want to reuse over and over to complex collections of classes that you could only dream up but never realistically code yourself. 

For example PyVrGeom is just a collection of math that some would find easy enough to code, but why do so when somebody has done the heavy lifting and offers you the calls to do it with some preexisting code.  In this case very professionally created and presented, but it is just as easy to hack together some snippets that just save you typing.  For example when I was working on a KML export routine I didn't need to learn something complex and universal (which libs probably exist), I just knew what it looked like and wanted to replicate those entities by passing along a few basic parameters.  In this case I slapped together some code to create the KML entities, but at the same time the coordinates needed to be in geodetic coordinates so I had to grab a projection library that someone way sharper than me had already put together. Then it struck me that a KMZ is just a file zipped using the standard algorithms so if I import that one I can just as easily write both KML and KMZ files.

I'm not going to offer any code this time just another reminder that there are some good reasons to install python if you are going to do some scripting.  Here are some of the libraries that I really enjoy and use often.

pyproj - for converting local coordinates to global (or from one to another).
liblas - for all things LiDAR related.
zipfile - for reading and writing compressed files.
xlrd/xlwt - for directly reading and writing Excel spreadsheets.

Along with some of the standard system libraries that you can find a million uses for like sys, os, time, and math.

And here is a tip I'll add for free, check out http://www.lfd.uci.edu/~gohlke/pythonlibs/


Friday, November 16, 2012

Projecting some thoughts about pyproj.

So I've been playing around with pyproj a little lately and have come up with a couple new thoughts.  As always I'm typing as I go so not everything is a clean example of good code or procedure, just something I've run as a test of my thoughts.

First, the application; below is showll.py which when run displays the lat long of the current cursor position in the DspMsg0 area (the top long line right below the command area).  I decided to do this as an app so it is running in real time and clicking the buttons just performs specific tasks.  Speaking of the buttons, B1 or the left mouse button prints the current position in the local coordinates, long lat, and notes the projection used. Something like

1369447.29077 471184.7857 (-84.66858719560254, 40.93954025528449) epsg:3753

In this part of the world we primarily deal with two projections so I kept it simple and just used B2 or the right mouse button to toggle between the two.  It would have been easy enough to bring up some kind of selection dialog, but for now I only need the two. The current projection is also displayed in the DspMsg area.

I recently discovered why I always had to send and receive meters even though the EPSG code clearly specified at foot based projection.  It was by design so there was never any question what was expected or returned.  The answer was always meters, however the code has since been modified to include an init keyword

preserve_units=True 

which handily enough, does exactly what it says. I understand the value of the consistency, but appreciate the option. I have also discovered in testing that you can take a proj4 definition and paste it straight into an object init function in quotes and get the exact same functionality as using the EPSG codes.  For example...

ohs=pyproj.Proj('+proj=lcc +lat_1=40.03333333333333 +lat_2=38.73333333333333 +lat_0=38 +lon_0=-82.5 +x_0=600000 +y_0=0 +ellps=GRS80 +to_meter=0.3048006096012192 +no_defs' )

Well in any case here is the app, it isn't worth much except by way of example, but pyproj itself is really handy when working with things like flight prep or control layouts when you want to give somebody geodetic coordinates to work from.

print 'showll modified 12:17 PM 11/14/2012'
# Show Longitude Latitude of current position.
'''
Copyright 2012 Dennis Shimer
Vr Mapping copyright Cardinal Systems, LLC
No warranties as to safety or usability expressed or implied.
Free to use, copy, modify, distribute with author credit.

Only two projections are supported. Both are NAD83(HARN) / Ohio (ftUS).
EPSG:3753 for North Zone
EPSG:3754 for South Zone
Button 2 (right mouse) toggles the projection, Button 1 (left mouse)
will print out the current position in local coordinate and it
Longitude, Latitude decimal degrees.
'''
MYAPPID = 10011

Gui = PyVrGui()

import pyproj,sys

global Projection

Projection=pyproj.Proj(init='EPSG:3754', preserve_units=True)
Gui.DspMsg('OH S EPSG:3754')

def MyAppDigCB (x, y, z, key, id):

 global Projection
 Gui.DspMsg0(repr(Projection(x,y,inverse=True)))
 if (key == 1):
  print x,y,repr(Projection(x,y,inverse=True)),Projection.srs.split('=')[1]
 elif (key == 2):
  if Projection.srs.count('3754'):
   Projection=pyproj.Proj(init='EPSG:3753', preserve_units=True)
   Gui.DspMsg('OH N EPSG:3753')
  elif Projection.srs.count('3753'):
   Projection=pyproj.Proj(init='EPSG:3754', preserve_units=True)
   Gui.DspMsg('OH S EPSG:3754')
 elif (key == 11):
  MyApp.Close ()
  MyApp.StopRunning ()

def MyAppKeyCB (key):

 MyAppDigCB (x,y,z, key, 0)

try:
 MyApp = PyVrApp (MYAPPID, "ShowLL")
except:
 print "Could not start application:", sys.exc_info()[0]
 
try:
 Mk = PyVrMenuKeys ("ShowLL", 10)
 Mk.SetMkLabels ("ShowLL","1 Print pt","2 Tog N/S", "3", "4", "5", "6", "7", "8", "9", "*", "0", "# Quit")
except:
 print "Could not create menukeys:", sys.exc_info()[0]

try: 
 MyApp.SetDigCB (MyAppDigCB)
 Mk.SetKeyCB (MyAppKeyCB)
 MyApp.KeepRunning ()
 
 Mk.Delete ()
except:
 print "Exception during application:", sys.exc_info()[0]
 Mk.Delete()
 MyApp.Close ()
 MyApp.StopRunning ()

How about one more bonus snippet with regard just switching from on projection to another. Thanks to Proj4 and pyproj, this is just how easy it can be.

>>> ohs=pyproj.Proj(init='EPSG:3754', preserve_units=True)
>>> ohn=pyproj.Proj(init='EPSG:3753', preserve_units=True)
>>> pyproj.transform(ohs,ohn,1759595.61,661026.83)
(1759551.3008025475, 54039.04746006191)

Tuesday, October 23, 2012

Where in the world... (and by that I mean geographically, not disappearing for 3 years)

Honestly,  first post in 3 years?  Well yes in fact it is, not much to say and probably nobody that really cares so it is what it is.  Been busy coding and there are some truly awesome libraries out there.  Lots of work extracting information out of Vr and dropping it directly into XLS spreadsheets using xlwt and of course the switch over to 2.7 (and 64 bit) has provided plenty of interesting experience. However, what is so important that I'm actually going to sit and type for a few minutes? It is pyproj of course.  Up to now I had done all my re-projection using the corpscon dll libraries which to date I can not find any way of porting to 2.7 64bit.  In the mean time I have learned a lot more about great open libraries like PROJ.4 but just never had the time to investigate.  Necessity being the mother of invention (or in this case studying) I needed a replacement for CorpsCon and the answer was pyproj.  A snippet is worth a million words so here goes.


After downloading and installing pyproj I start by importing the library
import pyproj

Next we create a Projection object and initialize it with a particular projection in this case Ohio State Plane North 1938 EPSG code 2834 
Projection=pyproj.Proj(init='EPSG:2834')

If I have an X,Y coordinate I can just allow the Projection object to compute the Long, Lat.  Notice that the default must be to go from geodetic to X,Y so the "inverse=True" is there and also that it is expecting (and returns) meters so we need to convert.  Both these statements may be a little off but I've only worked with the library for about 30 minutes so far and haven't actually read the docs.
Projection(1600000/3.280833333,700000/3.280833333,inverse=True)
(-83.84694414368035, 41.58018579703697)


So what we get back is a list with X and Y.  If I had passed in a Long and Lat position it would again return a list of coordinates in meters so lets create a quick function to take the coordinate list and return feet.
def to_ft((x,y)):
    return x*3.280833333333333,y*3.280833333333333


Then simply do the projection without the inverse.   
to_ft(Projection(-83.0,41.0))
(1830492.2997760142, 486159.352289076)


In the docs there are easy ways to create two different Projection objects and go directly from one to the other, but I pretty much just needed to go from state plane to geodetic as the basis for creating KML output. The change in libraries dropped about 75 lines of code, you gotta love python libraries.

Speaking of libraries, I found a site that hosts every python library I could think of (and about a hundred I couldn't) as a binary Windows installer in everything from Python 2.5 32bit to Python 3.2 64bit.  Find them at http://www.lfd.uci.edu/~gohlke/pythonlibs/

Monday, May 18, 2009

We all have our limits

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.

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....

if BoundrySet :
if BoundingLine.IsPointInside (X,Y): Do something


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.

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.

print 'SetBoundary.py modified 8:00 AM 5/15/2009'
# Set spatial bounding for processing
'''
Copyright 2009 Dennis Shimer, M.A.N. Mapping Services Inc.
No warranties as to safety or usability expressed or implied.
Free to use, copy, modify, distribute with author credit.

Really just a container for the code snippet that would do spatial
filtering as part of a larger program. Just written as working code
here for testing purposes.

Variables of interest:
None
'''
import math

BoundingLine=PyVrLine()
Gr=PyVrGr ()
Gui=PyVrGui()
BoundrySet=0

PromBox = VrPromBox ("Set Boundry", 30, 1)
PromBox.AddCombo ('Boundry', 5, 0, 0)
PromBox.AddComboItem ('Line')
PromBox.AddComboItem ('Screen')
PromBox.AddComboItem ('Rectangle')
PromBox.AddComboItem ('Digitize Points')
PromBox.AddComboItem ('None (whole file)')
PromBox.SetFocus()
if PromBox.Display(1)==0:
BoundryType=PromBox.GetComboByPrompt ('Boundry')
if BoundryType==0:
BoundingLine.Id()
BoundrySet=1
elif BoundryType==1:
for corner in range(4):
x,y,z=Gr.GetWinCorner (corner,0)
BoundingLine.AddPoint(x,y,z)
BoundrySet=1
elif BoundryType==2:
Stat,llx,lly,z=Gui.GetCoord('Boundry')
Gr.DrawMode (1,-1)
Gr.PenNum (1)
Gr.DrawMarker (llx,lly,z,MARK_CROSS,Gr.GetWinScale ()*.2,-1)
Stat,urx,ury,z=Gui.GetCoord('Boundry')
Gr.EraseMarker ()
ScreenAngle=Gr.GetWinRot()[2]
Angle=math.atan((ury-lly)/(urx-llx))-Gr.GetWinRot()[2]
Diagonal=PyVrGeom().Dist(llx,lly,urx,ury)
Height=math.sin(Angle)*Diagonal
if Height < 0.0: Height=Height*-1.0
Width=math.cos(Angle)*Diagonal
if Width < 0.0: Width=Width*-1.0
BoundingLine.AddPoint(llx,lly,z)
lrx=llx+(Width*math.cos(ScreenAngle))
lry=lly+(Width*math.sin(ScreenAngle))
BoundingLine.AddPoint(lrx,lry,z)
urx=lrx-(Height*math.sin(ScreenAngle))
ury=lry+(Height*math.cos(ScreenAngle))
BoundingLine.AddPoint(urx,ury,z)
ulx=urx-(Width*math.cos(ScreenAngle))
uly=ury-(Width*math.sin(ScreenAngle))
BoundingLine.AddPoint(ulx,uly,z)
BoundingLine.AddPoint(llx,lly,z)
BoundingLine.Plot()
BoundrySet=1
elif BoundryType==3:
Stat=0
while Stat==0:
Stat,x,y,z=PyVrGui().GetCoord('Dig Boundry')
BoundingLine.AddPoint (x,y,0.0)
BoundingLine.Plot()
BoundingLine.Close(2)
BoundingLine.Plot()
BoundrySet=1


Monday, February 12, 2007

Computing without errors

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 every one's 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 try: - except: 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.

#try-except.py
print '\nTesting try:'

try:
..print "divide 1 by 3 and it's ok",1.0/3.0
except:
..print 'it worked so this never prints'
try:
..print "This prints until it does the division of 1 by 'a' then ",1.0/'a'
except:
..print '\nThere is an error that would normally end the program\nbut instead jumps to the exception'
print '\n'

Should print.
divide 1 by 3 and it's ok 0.333333333333
This prints until it does the division of 1 by 'a' then
There is an error that would normally end the program
but instead jumps to the exception

try-except.py
print '\nTesting try:'

try:
..print "divide 1 by 3 and it's ok",1.0/3.0
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.
except:
..print 'it worked so this never prints'
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.
try:
..print "This prints until it does the division of 1 by 'a' then ",1.0/'a'
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.
except:
..print '\nThere is an error that would normally end the program\nbut instead jumps to the exception'
print '\n'
However since we "trapped the exception", execution continues with the first statement in the except block.

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.

Friday, February 09, 2007

News flash for the slow to catch on

While posting on The Scripts Developer's Network python forum, someone pointed out to me that string.atoi (and atof) 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 Vr 3.2 and Python 2.5, it is probably something to take note of.

Thursday, January 04, 2007

Think ahead and start right

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.

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.

  • 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.
  • 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 import dsutil then call dsutil.printf() rather than doing a from dsutil import * then just calling printf(). This is a small thing but even for standard modules it always shows where something is coming from.
  • 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.
  • 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 x,y,z=Sym.GetCoord() where there is no need to initialize the coordinates, just let the function create and set them.
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.
os.path.splitext(os.path.split(FullName)[1])[0]
A little reminder goes a long way next year when something similar is necessary.

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.

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.

Gui = PyVrGui()

print 'hello world' # to console
Gui.DspMsg0('hello 1') # top Vr status box
Gui.DspMsg('hello 2') # bottom Vr status box
Gui.DspShortMsg(0,'hello 3') # top small status box
Gui.DspShortMsg(1,'hello 4') # bottom small status box
Gui.MsgBox ('hello 5','window title') # dialog popup

Tuesday, December 19, 2006

Quickie tip

Already posted for the week but found a forum that shows quite a bit of promise. It is at TheScripts developer network, and looks pretty interesting.

Friday, December 15, 2006

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.

printf = lambda fmt,*args: sys.stdout.write(fmt%args)
'''
c like implemetation of printf, for example:
dsutil.printf("this is %s test with the number %.2lf",'a',9)
yields...
this is a test with the number 9.00
'''

fprintf = lambda afile,fmt,*args: afile.write(fmt%args)
'''
Same as printf but like c's fprintf sends output to open file

usage: dsutil.fprintf(AnOpenFile,"format",Values)
'''

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 corpscondll is pretty well documented 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.

As always a big thank you and hats off to Tom.

For anyone interested in trying VrPython for the first time or if you are early in the game, I suggest going to the earliest posts and working forward. I use VrPython every day for many wonderful things, needless to say it will change and could potentially damage a file. Any risk associated with using VrPython or any code or scripts mentioned here lies solely with the end user.

The "Personal VrPython page" in the link section will contain many code examples and an organized table of contents to this blog in a fairly un-attractive (for now) form.