API overhaul for Autodesk Design Review
My old friend Volker Joseph, over on Beyond the Paper, wrote recently about a planned overhaul of the Autodesk Design Review API.
If you currently use the ADR API, please be sure to check the list of interfaces that are slated for removal and let Volker know of any you consider important.
Thanks!
April 10, 2008 in DWF | Permalink | Comments (0) | TrackBack
Using AJAX to generate pages hosting Freewheel views
I touched on this subject a few weeks ago in part 2 of my DWF-related AU handout, but thought I'd come back and describe in more depth some of the fun (although a more accurate word might be "difficulty" :-) I had solving this problem.
I've been playing around with web services and XML since SaaS was still known as ASP, and have tried to stay up-to-date with the technology as best I can. I'm really a client-side programmer, all things considered: I've created some server-side code, but have mostly involved myself with desktop-oriented programming and creation of samples that developers can execute locally, rather than having to set up a host environment.
So when working with web services, I really want to provide a simple application that can be run locally and connects to these services via simple, understandable client code.
The problem I wanted to solve with my AU demo was fairly simple (at least so I thought): for a particular DWF file I wanted to create a page linking to - and embedding - Freewheel views of the DWF's various sheets. The logical way to do this was to use the DWFRender web service to query the number of sheets contained in the DWF, and then create a page using DHTML that had some content for each of these sheets.
The logic seemed sound, and I created a nice prototype with hardcoded sections for the two sheets of my DWF file. Here's the HTML code:
<html>
<!-- saved from url=(0017)http://localhost/ -->
<head>
<title>Freewheel</title>
<style>
legend { font-size: 10pt;
font-family: Calibri, Arial;
color: black; }
button { font-size: 10pt; }
input { font-size: 10pt;
font-family: Calibri, Arial; }
</style>
</head>
<body bgcolor="#E6E6E6">
<table width="620">
<tr>
<td>
<fieldset>
<legend>Sheet 1</legend>
<table>
<tr>
<td valign="middle">
<fieldset>
<legend>Clickable Thumbnail</legend>
<a
href="http://freewheel.labs.autodesk.com/dwf.aspx?sec=1&dwf=http://through-the-interface.typepad.com/presentations/DWF/solids.dwf"
target="New"
>
<img
frameborder="0"
height="150"
width="200"
scrolling="no"
src="http://freewheel.labs.autodesk.com/dwfImage.aspx?page=1&width=200&height=150&path=http://through-the-interface.typepad.com/presentations/DWF/solids.dwf" /
>
</a>
</fieldset>';
</td>
<td>
<iframe
frameborder="0"
height="300"
width="400"
scrolling="no"
src="http://freewheel.labs.autodesk.com/dwf.aspx?sec=1&dwf=http://through-the-interface.typepad.com/presentations/DWF/solids.dwf">
</iframe>
</td>
</tr>
</table>
</fieldset>
</td>
</tr>
<table>
<table width="620">
<tr>
<td>
<fieldset>
<legend>Sheet 2</legend>
<table>
<tr>
<td valign="middle">
<fieldset>
<legend>Clickable Thumbnail</legend>
<a
href="http://freewheel.labs.autodesk.com/dwf.aspx?sec=2&dwf=http://through-the-interface.typepad.com/presentations/DWF/solids.dwf"
target="New"
>
<img
frameborder="0"
height="150"
width="200"
scrolling="no"
src="http://freewheel.labs.autodesk.com/dwfImage.aspx?page=2&width=200&height=150&path=http://through-the-interface.typepad.com/presentations/DWF/solids.dwf"/>
</a>
</fieldset>';
</td>
<td>
<iframe
frameborder="0"
height="300"
width="400"
scrolling="no"
src="http://freewheel.labs.autodesk.com/dwf.aspx?sec=2&dwf=http://through-the-interface.typepad.com/presentations/DWF/solids.dwf">
</iframe>
</td>
</tr>
</table>
</fieldset>
</td>
</tr>
<table>
</body>
</html>
And here's what it looked like when displayed:
So far, so good.
To generate the DHTML code for each of the sections, which could then be called in a loop once we knew the number of sheets, was also pretty straightforward:
var freewheel =
'http://freewheel.labs.autodesk.com';
function createViews(sheets)
{
var container = document.getElementById('views');
var htm = '<table width="620"><tr><td>';
for(i=1; i<= sheets; i++)
{
htm += '<fieldset><legend>Sheet ' + i + '</legend>'
htm += '<table><tr><td valign="middle">';
htm += '<fieldset><legend>Clickable Thumbnail</legend>'
htm += '<a href="' + freewheel + '/dwf.aspx?'
htm += 'sec=' + i + '&dwf=' + path + '" target="New">';
htm += '<img frameborder="0" height="150" ';
htm += 'width="200" scrolling="no" src="' + freewheel;
htm += '/dwfImage.aspx?page=' + i + '&';
htm += 'width=200&height=150&path=' + path + '"/>'
htm += '</a></fieldset>';
htm += '</td><td>';
htm += '<iframe frameborder="0" height="300" ';
htm += 'width="400" scrolling="no" src="' + freewheel;
htm += '/dwf.aspx?sec=' + i + '&dwf=' + path + '">';
htm += '</iframe>';
htm += '</td></tr>';
htm += '</table></fieldset>';
}
htm += '</td></tr><table>';
container.innerHTML = htm;
}
The only challenge remaining was to call our DWFRender web service from out JavaScript code.
Back in the old days I used a component from Microsoft to call web services from HTML & JavaScript, called the Web Service Behavior, or webservice.htc. This seemed to work fine, but is no longer supported, so I thought I'd find a more modern approach, something from the AJAX bandwagon, perhaps. AJAX is "Asynchronous JavaScript and XML", and is the latest & greatest technology for developing smart yet thin applications. Or so the buzz goes.
After searching around a while, I ended up trying a couple of approaches. The first was based a technique provided by IBM. It took me a while to get the code to run, and even then it wasn't getting the result I wanted. So I implemented another approach using a technique shown at The Code Project.
Once again it didn't return anything helpful, but then I noticed this statement on the page:
Please note that many browsers do not allow cross-domain calls for security reasons.
I researched this for some time, and realised that my JavaScript code was hitting a browser security problem. It seems that cross-domain SOAP requests are an issue: if your web-page is considered to be in one domain, it will not call out across to a web service hosted on another domain. Even the Web Service Behavior I'd used in the past didn't solve the problem (thinking back I'd been calling web services hosted in the same domain, so it hadn't been an issue I'd come across).
The security problem is actually with the XMLHTTP component, which is at the core of AJAX and is now implemented by various (probably all, but I'm no expert) browsers.
There are a few ways around this limitation: it seems that most commonly developers implement server-based code that calls across to the problematic domain, basically provided a local cache of the results. In terms of clarifying the problem and spelling out the alternatives, I found this site extremely helpful, as well as this follow-up post.
Anyway, it turns out that for the purposes of my demo I could cobble something that worked together based on fairly simply client-side code. I didn't go to the effort of implementing a cross-browser solution, as the main purpose is to demonstrate calling the Freewheel web service and not to solve the problem of World (well, Internet) Peace.
There were two points that I hadn't realised were issues. The first was the Mark of the Web (MOTW). I had added this to my HTML header sometime in the past, to gain Internet Exporer's trust for it not to bother me with requests to approve the running of ActiveX Controls:
<!-- saved from url=(0017)http://localhost/ -->
Removing this was part of the trick - the other part was to adjust my browser settings to allow cross-domain access:
That then allowed my client code to run and actually get results. Here's the HTML code for the page:
<html>
<head>
<title>Freewheel</title>
<style>
legend { font-size: 10pt;
font-family: Calibri, Arial;
color: black; }
button { font-size: 10pt; }
input { font-size: 10pt;
font-family: Calibri, Arial; }
</style>
<script type="text/javascript">
var freewheel =
'http://freewheel.labs.autodesk.com';
var http_request = false;
var xmldoc;
var path;
function makeRequest(url)
{
try
{
http_request =
new ActiveXObject("Msxml2.XMLHTTP");
}
catch (e)
{
try
{
http_request =
new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e)
{ }
}
if (http_request)
{
http_request.onreadystatechange = alertContents;
http_request.open('GET', url, true);
http_request.send(null);
}
}
function alertContents()
{
if (http_request.readyState == 4)
{
if (http_request.status == 200)
{
var string = http_request.responseText;
var xmldoc;
xmldoc = http_request.responseXML;
var secs =
xmldoc.getElementsByTagName(
"unsignedInt"
)[0].firstChild.nodeValue;
createViews(secs);
}
else
{
alert('There was a problem with the request.');
}
}
}
function replaceAll(strText, strTarget, strSubString)
{
var intIndexOfMatch = strText.indexOf( strTarget );
while (intIndexOfMatch != -1)
{
strText = strText.replace( strTarget, strSubString )
intIndexOfMatch = strText.indexOf( strTarget );
}
return( strText );
}
function createViews(sheets)
{
var container = document.getElementById('views');
var htm = '<table width="620"><tr><td>';
for(i=1; i<= sheets; i++)
{
htm += '<fieldset><legend>Sheet ' + i + '</legend>'
htm += '<table><tr><td valign="middle">';
htm += '<fieldset><legend>Clickable Thumbnail</legend>'
htm += '<a href="' + freewheel + '/dwf.aspx?'
htm += 'sec=' + i + '&dwf=' + path + '" target="New">';
htm += '<img frameborder="0" height="150" ';
htm += 'width="200" scrolling="no" src="' + freewheel;
htm += '/dwfImage.aspx?page=' + i + '&';
htm += 'width=200&height=150&path=' + path + '"/>'
htm += '</a></fieldset>';
htm += '</td><td>';
htm += '<iframe frameborder="0" height="300" ';
htm += 'width="400" scrolling="no" src="' + freewheel;
htm += '/dwf.aspx?sec=' + i + '&dwf=' + path + '">';
htm += '</iframe>';
htm += '</td></tr>';
htm += '</table></fieldset>';
}
htm += '</td></tr><table>';
container.innerHTML = htm;
}
function OnGenerateSheetViews()
{
path = document.getElementById('URL').value;
var url = freewheel + '/dwfrender.asmx/sectionCount?path=';
var dwf = path;
dwf = replaceAll(dwf, '/', '%2F');
dwf = replaceAll(dwf, ':', '%3A');
url += dwf;
makeRequest(url);
}
</script>
</head>
<body bgcolor="#E6E6E6">
<input
type="text"
id="URL"
size="60"
value="http://through-the-interface.typepad.com/presentations/DWF/solids.dwf" /
>
<input
id="GenerateSheetViews"
type="button"
value="Generate Sheet Views"
onclick="return OnGenerateSheetViews()" /
>
<div id="views"></div>
</body>
</html>
You'll notice that the page is nearly all script: the static elements are minimal - just somewhere to enter the URL of our DWF file and a <div> for our DHTML tags to be squirted into.
When the page loads there's not a great deal to see:
And it generates our sample pretty successfully:
The application comes into its own when we run it with a DWF with lots of sheets: the sample file, http://freewheel.autodesk.com/sample/Hotel5.dwf, has 29 sheets in case you really want to put it through its paces. :-)
Additional note:
A colleague kindly reminded me about something I had meant to mention. The code in this post makes use of the Autodesk Labs Freewheel server (http://freewheel.labs.autodesk.com). When you're developing applications based on Freewheel, you should really use the production Freewheel server (http://freewheel.autodesk.com), wherever possible. I used the Labs version (which is hosted on a single server, rather than being on a load-balanced, production-capable server farm) simply because it was able to render the specific DWF I was hosted in my site: fixes are generally rolled out first on the Labs server and migrate over time to the production server, as you'd expect, and in this case my DWF wasn't yet viewable via the production system.
To adjust the above code to use the production server, simply change the value of the "freewheel" variable:
var freewheel =
'http://freewheel.autodesk.com';
November 9, 2007 in AJAX, DWF, Freewheel, HTML | Permalink | Comments (1) | TrackBack
AU Handouts: Enriching Your DWF™ - Part 2
[This post continues from part 1 of this series. The source for the below applications is available here: DWF Toolkit application source, Design Review application source & Freewheel application source.]
Mining the data with the DWF Toolkit
Now we’re going to look at using the DWF Toolkit – the freely available, cross platform toolkit for creating and reading DWF files – to extract the “identity” and “material” metadata associated with our geometry.
The DWF Toolkit is a C++ toolkit, so we have two components to our project:
- A C++ DLL that uses the DWF Toolkit to read a DWF, storing the data we care about in XML
- A VB.NET module that implements a user interface for viewing the XML content.
By its nature, DWF Toolkit client code tends to be somewhat complex, as it closely follows the internal structure of the DWF format, so I’m not going to go into the code. I will just say that you need to be a competent C++ programmer to work with the DWF Toolkit – it is not for the casual developer to dip into. There are clearly cases where using the DWF Toolkit makes a lot of sense – such as using it to modify or post-process DWFs non-graphically - but where possible I would recommend using a “higher level” API such as the API to Design Review or the publishing APIs within AutoCAD (just as we saw earlier).
The full source code for the project is posted to my blog, and here is what the application looks like:
Figure 12 – a DWF Toolkit application to extract our metadata
Linking 2D with 3D DWF data in an application embedding Design Review
In the next part of our demo, we’re going to make use of the metadata embedded in our DWF file to link the 2D and 3D sheets of our DWF.
Emedded 2D and 3D view onto DWF data actually have quite different API capabilities: 2D views have a set of events that you can respond to, to determine when objects are hovered over or selected (which you cannot receive for objects in 3D views), while 3D views allow you to manipulate object visibility and transparency (something you cannot control for objects in 2D views).
So we’re actually going to play to the strengths of the two API sets: we’re going to respond to an event when objects are hovered over in the 2D view, and during that callback we’re going to manipulate the 3D view to “isolate” the object in that view. And the way we’re going to link the two views is via the metadata that’s attached to our objects.
The HTML code is too long to include in its entirety here, so I’m going to describe the overall functionality and leave it to the reader to work through the code at their own pace. I will post the full source in a blog entry, though (as well as making it available for download there).
One of the key things is that in our “OnOverObject” callback (which we respond to with JavaScript code in our HTML), is that we receive a geometry index (a node ID) for the object that’s being hovered over. This, in itself, isn’t directly useful, so we need to find a way to map it to the objects in question. I managed to do this by hosting the object identity (handle) metadata in a combobox, populated in the same order as the geometry IDs we receive. So it’s very important that we populate the combobox appropriately, even if it’s hidden (which in our case it isn’t – we also make it available for the user to select objects by their handle).
Let’s look at how we embed our two views – both onto the same DWF file. Here’s the object tag for the 3D view:
<object
id="ObjectView"
width="100%"
height="100%"
classid="clsid:A662DA7E-CCB7-4743-B71A-D817F6D575DF"
codebase= "http://www.autodesk.com/global/dwfviewer/installer/DwfViewerSetup.cab#version=7,0,0,928"
VIEWASTEXT
>
<param name="src" value="solids.dwf?section=1">
</object>
We have used the src property to set the appropriate section by using “?section=1” to specify the first one.
With the 2D sheet we’ve taken a slightly different approach:
<object
id="Canvas"
width="100%"
height="100%"
classid="clsid:A662DA7E-CCB7-4743-B71A-D817F6D575DF"
codebase= "http://www.autodesk.com/global/dwfviewer/installer/DwfViewerSetup.cab#version=7,0,0,928"
VIEWASTEXT
>
<param name="src" value="solids.dwf">
</object>
We have not selected the sheet here – to avoid timing issues we’ve done so in the EndLoadItem JavaScript callback of the 2D view’s document:
if (Canvas.SourcePath != "solids.dwf?section=2")
{
Canvas.SourcePath = "solids.dwf?section=2";
}
Much of the rest of the code is around user interface tweaks, such as forcing the “Orbit” mode by default in the 3D view, and the “Select Object” mode in the 2D view. We also disable the toolbars etc., to reduce dialog clutter.
Figure 13 - embedding and linking multiple Design Review windows in an HTML application
Hosting an embedded Freewheel view in a custom web-page
Freewheel – and its Labs sibling, Project Freewheel – is a zero-client AJAX (Asynchronous JavaScript and XML) technology for working with both 2D & 3D DWF content. The DWF file resides on a server – whether uploaded securely by the user or hosted on a publicly-accessible web-page – and the graphics for the current view on the DWF content are piped down to the HTML client via raster. It’s impressively responsive, even when orbiting in 3D.
We don’t get the same ability to view and work with metadata (at least not right now), but it is still a compelling experience if you want to embed lightweight navigation for DWF without forcing an install of Design Review on the client machine. It’s also getting some very cool collaborative review capabilities, to allow multiple people to mark 2D or 3D designs up in real-time. Very cool stuff, but not today’s subject, I’m afraid.
The first thing is to get our design into Freewheel. One option is to use the “Share Now” utility available from Autodesk Labs, which publishes to DWF and uploads to Freewheel, or we could upload it via the Freewheel user-interface, as we have a DWF file ready-to-go.
In our case, however, I’ve already posted a version of the DWF file to a publicly-accessible internet location, so we’re going to use that:
http://through-the-interface.typepad.com/presentations/DWF/solids.dwf
A quick note on using Autodesk Freewheel vs. Project Freewheel. Autodesk Freewheel (http://freewheel.autodesk.com) is the production environment for Freewheel, and is hosted on a high-availability, load-balanced server farm. Project Freewheel (http://freewheel.labs.autodesk.com) is hosted on a PC under someone’s desk (OK, that’s an exaggeration :-), but contains the latest & greatest functionality. I’ve found that the DWF files I’ve been creating for this demo are best viewed with the Project Freewheel server, so I’m using that, today, but I recommend you first try with the production system when implementing your own Freewheel-powered sites.
The two basic approaches for including a Freewheel view in your website are to link or to embed. Linking is simple: you create a standard HTML link with a URL pointing Freewheel to your DWF file:
<a href="http://freewheel.labs.autodesk.com/dwf.aspx?dwf=http://through-the-interface.typepad.com/presentations/DWF/solids.dwf">My link</a>
This creates a straight link to the Freewheel view. As with any HTML link, you can choose to launch this in a new window using the target property. You might also want to show a different page – you do this using the “sec” argument, which is the page/sheet number starting from 1:
<a href="http://freewheel.labs.autodesk.com/dwf.aspx?sec=2&dwf=http://through-the-interface.typepad.com/presentations/DWF/solids.dwf">My link</a>
Next we’re going to embed a view. We do this using an HTML iframe:
<iframe
frameborder="0"
height="300"
width="400"
scrolling="no"
src="http://freewheel.labs.autodesk.com/dwf.aspx?sec=2&dwf=http://through-the-interface.typepad.com/presentations/DWF/solids.dwf">
</iframe>
Once again, you can use the “sec” parameter to select a particular sheet. This creates a navigable view on your DWF file.
Aside from linking or embedding, Freewheel exposes an ever-growing set of web services APIs, to allow you to render a particular view of a DWF to raster or to get information about a DWF, such as the number of pages, etc.
We can use the dwfImage web service to get an image of a DWF to use as a thumbnail:
<img
frameborder="0"
height="150"
width="200"
scrolling="no"
src=
"http://freewheel.labs.autodesk.com/dwfImage.aspx?page=1&width=200&height=150&path=http://through-the-interface.typepad.com/presentations/DWF/solids.dwf" /
>
We can throw these together and create a web-page that links from the sheet thumbnails to full instances of Freewheel, as well as embedding interactive views of the same sheets. (The HTML source for this page is posted on my blog – it’s not complicated, but too long to include here.)
Figure 14 – embedding and linking to Freewheel in a custom web-page
The code that defines the above page could actually be generated manually – and that’s the next bit of fun… :-)
Using AJAX you can call web services from your client code: there are limitations as to what you can do (especially with regards to security limitations accessing web services across domains - which will make a great advanced topic for my blog), but this should give you a rough idea of what’s possible. In the below sample we query the number of sheets for a particular DWF, and use DHTML to generate the tags that allow us to view the content, as in the above hard-coded sample:
Figure 15 – our Freewheel generator on load
Figure 16 – our completed Freewheel generator
October 30, 2007 in AJAX, DWF, Freewheel, HTML, Training | Permalink | Comments (7) | TrackBack
AU Handouts: Enriching Your DWF™ - Part 1
Introduction
This session focuses on technologies that can be used to view and access DWF content downstream from Autodesk’s design products. Yesterday’s session focused on DWG – we’re going to take the model containing 3D solids that we created during that session and publish it to DWF, adding custom metadata. We can then look at how to harness this data in lightweight applications, whether to access it non-graphically or to view it.
Firstly, why are we using 3D solids in this example? The choice was somewhat arbitrary – the point is really to demonstrate the ability to access properties of objects stored in a DWG file without AutoCAD running – but it does suit our overall purpose for a few reasons:
- As 3D entities, 3D solids allow us to evaluate the 3D capabilities of the viewing technologies we’re looking at.
- While they have precise geometric properties (such as volume), as DWF is not a double-precision format we’re going to focus on accessing data of a less precision-oriented nature: the solids’ materials.
A quick word on the programming technology used in this demonstration. The code samples are in a mixture of languages: the AutoCAD .NET sample that adds metadata is in C#, the downstream DWF Toolkit sample is in C++ (for the DWF Toolkit component) and in VB.NET (for the user interface), while the Design Review and Freewheel samples are in HTML.
These handouts, along with the sample projects demonstrated within them, have been posted to my blog: http://blogs.autodesk.com/through-the-interface. Only significant portions of code will be highlighted in this document, and even those should not need to be typed back in. :-)
Creating DWFx files
In AutoCAD 2008, the PUBLISH command creates DWF files. In the future, however, Autodesk will increasingly publish to the DWFx format, one which more based on industry (particularly Microsoft) standard technology. For more information on DWFx, search for it on the Autodesk website, and search for XPS on Microsoft’s website.
To create DWFx files from AutoCAD 2008 today, you need to download and install the DWFx Printer Driver, which can then be selected from the PLOT dialog:
http://usa.autodesk.com/adsk/servlet/ps/dl/item?siteID=123112&id=9124615&linkID=9240618
AutoCAD’s PLOT mechanism does support multiple sheet printing, but won’t let you plot both 2D and 3D sheets to the same file (unlike the PUBLISH command, which does).
The other technique for creating DWFx files is to save DWFs from Design Review 2008 as DWFx. This approach has the benefit of including any 3D and metadata content in the resultant DWFx file.
Publishing DWF and plotting DWFx from AutoCAD
Now we’re going to take a quick look at the contents of DWF and DWF files. For the purpose of this example, we’ll simply PUBLISH our 2D layout to DWF and PLOT it using the DWFx driver to DWFx.
Let's launch PUBLISH and remove the modelspace sheet, and then hit the “Publish” button, selecting a DWF file as the destination (in our case solids-Layout1.dwf):
Figure 1 – publishing a single-sheet DWF file from AutoCAD
Now we launch the PLOT command and select the DWFx driver, using it to PLOT our 2D layout to a DWFx file (in our case solids-Layout1.dwfx):
Figure 2 – plotting a single-sheet DWFx file from AutoCAD
So now we have two files, solids-Layout1.dwf & solids-Layout1.dwfx. To look at their contents, we rename them to .zip and open them with WinZIP (both DWF and DWFx are package formats which are implemented as ZIP files of different types of data):
Figure 3 – the contents of our DWF file
The interesting piece of our 2D DWF file is the .w2d file. If we extract it and open it in Notepad, we can see it’s contains both ASCII and binary information:
Figure 4 – the contents of the W2D stream of our DWF
The big change between DWF and DWFx is the move away from the W2D format (which harks back to the days of the Whip! format) and adopting the more modern XML-based XPS format.
Let’s take a look at our DWFx file, now:
Figure 5 – the contents of our DWFx file
We can see straight away that there’s more to it: to start with there are more files included (and the DWFx file is 16KB while our DWF file is 8KB, but the ratio shifts as the files get larger – the overhead in this example is high relative to the amount of content we’re storing). The interesting file is the selected XML file – let’s load that into Internet Explorer to view it:
Figure 6 – the contents of the W2X stream of our DWFx
This XML content defines the 2D geometry in our DWFx file, and is read by the XPS Viewer when we load it.
That’s it for our brief look at the DWF and DWFx formats. We could certainly go into greater depth – especially when it comes to the storage of metadata and 3D, but this is left as an exercise for the reader.
Publishing additional metadata to DWF files from AutoCAD
Now we’re going to take a look at the more advanced capabilities of the PUBLISH command in AutoCAD. Our DWG file contains 3D content in the modelspace and 2D content in its paperspace layout, and we ideally want a DWF file containing both. Not only that, but we’d like to attach metadata to both our 2D and 3D geometry.
We’re going to use an AutoCAD .NET module to attach this information. Here’s the C# code:
using Autodesk.AutoCAD.ApplicationServices;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.EditorInput;
using Autodesk.AutoCAD.Runtime;
using Autodesk.AutoCAD.Publishing;
namespace DWFMetadata
{
public class SolidsPublisher : IExtensionApplication
{
private bool mbPublishingTo3D = false;
public SolidsPublisher() {}
public void Initialize()
{
// Register for publishing events
Publisher pb = Application.Publisher;
pb.AboutToBeginPublishing +=
new AboutToBeginPublishingEventHandler(
OnAboutToBeginPublishing
);
pb.BeginEntity +=
new BeginEntityEventHandler(
OnBeginEntity
);
pb.BeginSheet +=
new BeginSheetEventHandler(
OnBeginSheet
);
}
public void Terminate()
{
// Unregister from publishing events
Publisher pb = Application.Publisher;
pb.AboutToBeginPublishing -=
new AboutToBeginPublishingEventHandler(
OnAboutToBeginPublishing
);
pb.BeginEntity -=
new BeginEntityEventHandler(
OnBeginEntity
);
pb.BeginSheet -=
new BeginSheetEventHandler(
OnBeginSheet
);
}
// Although an empty handler, responding to
// this events allows the subsequent ones
// to fire
void OnAboutToBeginPublishing(
object sender,
AboutToBeginPublishingEventArgs e
){}
// Check whether we're publishing to 2D or 3D
private void OnBeginSheet(
object sender,
PublishSheetEventArgs e
)
{
mbPublishingTo3D = e.PublishingTo3DDwf;
}
// This event does the real work
private void OnBeginEntity(
object sender,
PublishEntityEventArgs e
)
{
try
{
Solid3d solid = e.Entity as Solid3d;
if (solid != null)
{
if (mbPublishingTo3D)
{
// Adding 3D metadata is easy
e.Add3DDwfProperty(
"Material",
"Name",
solid.Material
);
e.Add3DDwfProperty(
"Identity",
"Handle",
solid.Handle.ToString()
);
}
else
{
// 2D is more complicated...
ObjectIdCollection objIds =
new ObjectIdCollection();
System.Int32 nodeId =
e.GetEntityNode(
e.Entity.ObjectId,
objIds
);
if (nodeId <= 0)
{
// Create node with next sequential number
// and a unique name
nodeId =
e.GetNextAvailableNode();
string strUnique =
e.UniqueEntityId;
string nodeName =
"ASDK" + strUnique;
DwfNode node =
new DwfNode(nodeId, nodeName);
// Create a string property in
// the Material category
EPlotProperty matprop =
new EPlotProperty(
"Name",
solid.Material
);
matprop.Category = "Material";
matprop.Type = "string";
// Create a string property in
// the Identity category
EPlotProperty handprop =
new EPlotProperty(
"Handle",
solid.Handle.ToString()
);
handprop.Category = "Identity";
handprop.Type = "string";
// Create a property bag, containing
// the properties and references
EPlotPropertyBag bag =
new EPlotPropertyBag();
// This should set the ID of the property bag,
// to be used in the property definition
bag.Id = nodeName;
// Add it to the object/instance references
bag.References.Add(nodeName);
// The properties themselves needs adding
bag.Properties.Add(matprop);
bag.Properties.Add(handprop);
// Add properties and relationships to the DWF
e.AddPropertyBag(bag);
e.AddNodeToMap(
&nbs

Atom












