Tag Archives: Plugins

Public Safety GIS 2: Python, MongoDB, C# and ArcGIS Desktop Explorer

17 Apr

I wrote a plugin for ArcGIS Desktop explorer that called a python script and passed the map center as an argument. The python script queried a MongoDB and wrote out a csv of closest points. The button then loads the csv as points. I had to do this because I didn’t know how to do it in C#. Well, I figured it out.

Now C# does all the work querying the database and drawing the points. I still have a python script that reads data from a csv export from sharepoint, geocodes it and creates the mongoDB.

Here is my code:

PYTHON TO CREATE THE DB:

from pymongo import Connection,GEO2D
import urllib, urllib2, simplejson
import csv

data = csv.reader(open(‘C:\Documents and Settings…\myfile.csv’))
fields=data.next()
db=Connection().rtcc
db.cnau.create_index([(“loc”,GEO2D)])

for row in data:
try:
address=row[0]
combinedaddress=address+”,albuquerque, NM”

param = {‘q’: combinedaddress,’output’: ‘json’, ‘oe’: ‘utf8’}
url = ‘http://maps.google.com/maps/geo?’ + urllib.urlencode(param)
rawreply = urllib2.urlopen(url).read()
reply = simplejson.loads(rawreply)
print reply[‘Placemark’][0][‘Point’][‘coordinates’][0]
long=reply[‘Placemark’][0][‘Point’][‘coordinates’][0]
lat=reply[‘Placemark’][0][‘Point’][‘coordinates’][1]
z={“loc”:[long,lat],”Activity”:row[1]}

db.cnau.insert(z)
except KeyError:
pass

 

C# TO PLUGIN ARCGIS DESKTOP EXLPORER:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ESRI.ArcGISExplorer;
using ESRI.ArcGISExplorer.Application;
using ESRI.ArcGISExplorer.Mapping;
using ESRI.ArcGISExplorer.Geometry;
using ESRI.ArcGISExplorer.Data;
using ESRI.ArcGISExplorer.Threading;

using MongoDB;
using MongoDB.Bson;
using MongoDB.Driver.Linq;
using MongoDB.Driver;
using MongoDB.Driver.Builders;

namespace MongoC
{
public class Button : ESRI.ArcGISExplorer.Application.Button
{

public override void OnClick()
{

Folder folderMapItem = new Folder();
MapDisplay mdisp = ESRI.ArcGISExplorer.Application.Application.ActiveMapDisplay;

//use this to change the projections 35,-106
FeatureLayer proj = FeatureLayer.OpenShapefile(“C:\\Documents and Settings…\\forProjection.shp”);
// Path for Windows 7: FeatureLayer proj = FeatureLayer.OpenShapefile(“C:\\Users\\user\\…\\forProjection.shp”);
mdisp.CoordinateSystem2D = proj.CoordinateSystem;
string center = mdisp.Center.ToString();
folderMapItem.Name = “Close To Me”;
string[] c = center.Split(null);
String lon = c[3];
String lat = c[6];

MongoClient client = new MongoClient(); // connect to localhost. Deploy at: “mongodb://ip.of.host:27017”
MongoServer server = client.GetServer();
MongoDatabase db = server.GetDatabase(“rtcc”);

var collection = db.GetCollection<BsonDocument>(“cnau”);

var query = Query.Near(“loc”, double.Parse(c[3]), double.Parse(c[6]));
//var cursor = collection.Find(query); Put this in foreach so dont need it anymore.
foreach (BsonDocument item in collection.Find(query).SetLimit(5))
{
BsonElement loc = item.GetElement(“loc”);
string g = loc.Value.ToString();
string x = g.Trim(new Char[] { ‘[‘, ‘]’ });
String[] a = x.Split(‘,’);
// BsonElement name = item.GetElement(“name”); Work for all indexes in MongoDB
// Pass the other data to the notes popups below

ESRI.ArcGISExplorer.Geometry.Point mypoint = new ESRI.ArcGISExplorer.Geometry.Point(double.Parse(a[0]), double.Parse(a[1]));

// Create a Note using the Point geometry.
Note mypointNote = new Note(“MyNote”, mypoint, Symbol.Marker.Pushpin.Orange);

// Populate the Note popup with information about the Point geometry using the ToString method.
StringBuilder info = new StringBuilder(@”<p><a href=””http://google.com””>Google</a></p>&#8221;);
info.AppendLine(@”<p>” + mypoint.ToString() + @”</p>”);

//MapDisplay disp = ESRI.ArcGISExplorer.Application.Application.ActiveMapDisplay;
mypointNote.Popup.Content = info.ToString();

// Add the Note to the current Map.
//mdisp.Map.ChildItems.Add(mypointNote);
folderMapItem.ChildItems.Add(mypointNote);
}

mdisp.Map.ChildItems.Add(folderMapItem);
}
}
}

Advertisements

Interactive AutoCAD in Website

31 Oct

I have previously shown how to put a drawing in a website using DWF and OpenLayers. This time I will show how to use an image map created by Qgis.

Save your drawing as a DXF. I am interested in room polygons so here is my drawing:

Bring this drawing in to Qgis as a polygon using the dxf2shp converter plugin.

You now have a shapefile:

Open the editor and add a column for room names. I also added a column for URLs which will be used for a popup later.

Now we can export the drawing to an image map based website using the HTML Image Map Plugin.

Configure the webpage using the options provided. I am using the URL field for “href attr” option. This will make it a link that can be clicked. I will ignore the onlclick, and stick with a hover.

 

 

 

I opened up the HTML code and added a title, my face, and put the hover <DIV> at the bottom of the page. When you hover over a room, you will see the type of room displayed on the bottom of the page and as a tooltip. If you click a room, you will be taken to a website. You can fully customize this website. And I suggest you do.

Here are all my files in a ZIP┬áif you want to play with the webpage or see my awesome DXF. The File is named “Files.DOC” I had to do this to upload them. Rename the file to “Files.ZIP” and it will work fine. FYI – this is a cool trick to hide files. Windows reads the extension and makes it look like the extension. But it is really whatever you created originally.

Shapefiles in Revit: Method II

25 Oct

Need to get shapefiles from your GIS in to Revit? I will tell you how using open source software. But first, Revit does not like coverages of over 20 miles so you may need to crop your shapefile.

Download Qgis – a free and open source GIS.

Open your shapefile in Qgis.

It will appear in the table of contents on the left. Right click on it and select ‘Save as..’ Choose AutoCAD DXF.

You now have a DXF of your shapefile.

Want to bring AutoCAD – or Revit – to GIS? Do everything in Reverse. But first activate your plugins.

Go to ‘Plugins’ and ‘Manage Plugins’. Check DXF2SHP.

Now click DXF2SHP and select your DXF. Choose a name and location to save your shapefile. Select the type. Probably polyline.

Here is a DXF loaded

Now your CAD drawing can be used in a GIS.

RevitDB Link

5 Sep

One of the advantages of BIM is the ability to generate large amounts of data from a model with relative ease. In Revit, the data is there but the tools to create reports are lacking. A way around this has been to export Revit models to ODBC and use a database package to generate reports that are attractive and include fields that Revit prevents us from scheduling.

Autodesk has released a new plugin that takes exporting to ODBC to a new level — RevitDBLink. There are two features of this plugin that will revolutionize the way those of us involved in information modeling will work: the bidirectional flow of data, and the ability to store other data and fields within the same database as the model.

I will demonstrate how Revit allows the bidirectional flow of data by exporting a model to a database, changing wall heights in the database, and then sending these changes back to Revit.

I start with a simple Revit model.

Next, I export the model to a MS Access database using the RevitDBLink and selecting a new connection.

My Access database is now populated with a set of tables from Revit. The image below shows the table of walls.

Comparing this table with the data in the Revit model shows that the unconnected heights are all set to 20′.

Within the database I can change these values to new heights.

These changes are loaded back in to the Revit model by selecting ‘edit and import’ from the DBlink plugin dialog box. The changes are then automatically applied to the Revit model.

While Revit allows for the editing of properties within the program itself, it is no match for the power of MS Access in generating reports and performing advanced queries on the models.

When using the built in ‘export to ODBC’ function in Revit, the model would overwrite the existing database. With RevitDB Link, tables associated with the project, but not stored within Revit can be added to the database and will be preserved every time the model is exported. Furthermore, the data will not be loaded in to Revit. This allows us to include information that is relevant to our project but may not need to be in the model, or may not associate with a specific object.

With RevitDB Link we can now add fields to an object and make it invisible to Revit. For example, when we export a model with rooms, the database will show only those fields created in the model. In MS Access, additional fields can be added to the rooms table. When this table is uploaded back to Revit, the new fields are invisible.

Not allowing fields created in Access to be uploaded back in to the model may seem to be a flaw in the bidirectional functionality, but I see it as a brilliant move on the part of the developers.

Revit files can become very large. While we tend to think that file size is directly proportional to the number of objects in a model, the amount of information included in the model also adds to the size. A simple model with additional fields added to objects can be larger than a model with many objects and no information. Do we really need all those fields in Revit?

RevitDB Link allows for almost unlimited access to our models and the information contained within them. If anyone has any ideas that they would like to see implemented, post a comment.