The way this app breaks down is that the user will be presented with a dialog that they can enter an override for the image width and/or height if they choose. There is a browse button that they will use to select multiple image files for import. After the use selects their images, Revit will generate a new drafting view named the same as the image file and then import the image into it, repeating until complete. The updates made to the Revit API in the 2011 products make this process capable of importing over 500 images in less than a minute (somehow)...
This code and any code I ever provide is of course provided as-is... use at your own risk.
This example utility utilizes one helper class to access and describe the parameter objects, one user form, and a main command class. First lets get the familiar main command entry point class out of the way...
Imports Autodesk.Revit.DB
Imports Autodesk.Revit.UI
Imports Autodesk.Revit.Attributes
''' <summary>
''' Import Images to Drafting Views
''' </summary>
<Transaction(TransactionMode.Automatic)> _
<Regeneration(RegenerationOption.Manual)> _
Public Class cmdDraftingViews
' Implement the RevitAPI entry
Implements IExternalCommand
' Post version date to title of form objects
Public Const appVer As String = "V2011.07.15"
' Main Command Entry
Public Function Execute(ByVal commandData As ExternalCommandData, _
ByRef message As String, _
ByVal elements As ElementSet) As Result _
Implements IExternalCommand.Execute
Try
Dim dlg As New formMain(commandData, appVer)
dlg.ShowDialog()
Return Result.Succeeded
Catch ex As Exception
Return Result.Failed
End Try
End Function
End Class
Imports Autodesk.Revit
Imports Autodesk.Revit.DB
''' Helper class to define a parameter
Public Class clsPara
Private m_parameter As DB.Parameter
Public Sub New(ByVal parameter As DB.Parameter)
m_parameter = parameter
End Sub
Public Property Value() As String
Get
Try
Return GetParameterValue(m_parameter)
Catch
Return Nothing
End Try
End Get
Set(ByVal value As String)
Try
SetParameterValue(m_parameter, value)
Catch
End Try
End Set
End Property
Public Shared Function GetParameterValue(ByVal parameter As Parameter) As String
Select Case parameter.StorageType
Case StorageType.[Double]
Return parameter.AsDouble
Case StorageType.ElementId
Return parameter.AsElementId.ToString
Case StorageType.[Integer]
Return parameter.AsInteger
Case StorageType.None
Return parameter.AsValueString()
Case StorageType.[String]
Return parameter.AsString()
Case Else
Return ""
End Select
End Function
Public Shared Sub SetParameterValue(ByVal parameter As Parameter, ByVal value As Object)
If parameter.IsReadOnly Then
Exit Sub
End If
Select Case parameter.StorageType
Case StorageType.[Double]
parameter.SetValueString(TryCast(value, String))
Exit Select
Case StorageType.ElementId
Dim myElementId As DB.ElementId = DirectCast((value), DB.ElementId)
parameter.[Set](myElementId)
Exit Select
Case StorageType.[Integer]
parameter.SetValueString(TryCast(value, String))
Exit Select
Case StorageType.None
parameter.SetValueString(TryCast(value, String))
Exit Select
Case StorageType.[String]
parameter.[Set](TryCast(value, String))
Exit Select
Case Else
Exit Select
End Select
End Sub
End Class
The user form is very simple and only contains a few basic controls. Follow the steps below to setup the form. I've added two buttons. One for browsing to the images and a cancel button. Two textboxes are placed to accept the user's optional dimension overrides for the imported images. A progress bar is then added along the bottom for process posting...
The form code is fairly simple as well. There are only a few basic subs and a few key form events to prevent the user from entering invalid characters into our textbox inputs (TextBoxHeight_KeyPress and TextBoxWidth_KeyPress).
We will utilize a method to retrieve the last element in the database in our image import loop so that we can easily retrieve our new image element for setting its width and or height overrides.
Imports Autodesk.Revit
Imports Autodesk.Revit.DB
Imports Autodesk.Revit.UI
Imports System.IO
Public Class formMain
Private m_SelectedJPG() As String
Private m_RvtDoc As DB.Document
Private m_width As Double
Private m_height As Double
Public Sub New(ByVal cmd As ExternalCommandData, ByVal apv As String)
InitializeComponent()
m_RvtDoc = cmd.Application.ActiveUIDocument.Document
Me.ProgressBar1.Visible = False
Me.Text = "Generate Drafting Views for Image Files - " & apv
End Sub
Private Function GetElementCount() As Integer
Return GetElements.ToElements().Count
End Function
Private Function GetElements() As DB.FilteredElementCollector
Dim collector As New DB.FilteredElementCollector(m_RvtDoc)
Return collector.WhereElementIsNotElementType()
End Function
' Return all database elements after the given number n.
Private Function GetElementsAfter(ByVal eInt As Integer, ByVal rvtDoc As Document) As List(Of DB.Element)
Dim elems As New List(Of DB.Element)
Dim fec As DB.FilteredElementCollector = GetElements()
Dim i As Integer = 0
For Each e As DB.Element In fec
i += 1
If eInt < i Then
elems.Add(e)
End If
Next
Return elems
End Function
Private Sub ImportImages()
' Collect the list of drafting views
Dim ViewsElements As New List(Of DB.Element)
Dim CollectorSheets As New DB.FilteredElementCollector(m_RvtDoc)
CollectorSheets.OfCategory(DB.BuiltInCategory.OST_Views)
ViewsElements = CollectorSheets.ToElements
' Start adding the views and importing the images
For i = 0 To UBound(m_SelectedJPG)
Dim imgFileName As String = Path.GetFileNameWithoutExtension(m_SelectedJPG(i))
' Only create the view if it does not already exist
For Each el As DB.Element In ViewsElements
If el.Name.ToUpper = imgFileName.ToUpper Then GoTo prepNextView
Next
' Only continue here if the view does not exist
Dim dv As DB.ViewDrafting = m_RvtDoc.Create.NewViewDrafting
dv.Name = imgFileName
' Link the image
ImportJPG(m_SelectedJPG(i), dv)
prepNextView:
Me.ProgressBar1.Increment(1)
Next
Me.Close()
End Sub
Public Function ImportJPG(ByVal m_importFileFullName As String, ByVal m_View As DB.ViewDrafting) As Boolean
' Get the last elementID
Dim eCnt As Integer = GetElementCount()
' Setup the image import options
Dim options As New ImageImportOptions
options.Placement = DB.BoxPlacement.Center
options.View = m_View
' Import the image
Dim element As DB.Element = Nothing
Dim imported As Boolean = m_RvtDoc.Import(m_importFileFullName, options, element)
' Test if user requires the width or height overriden
If m_height > 0 Or m_width > 0 Then
' Get the imported image element
Dim myElements As New List(Of DB.Element)
myElements = GetElementsAfter(eCnt, m_RvtDoc)
' Get the newest element
For Each e As DB.Element In myElements
' Test to see if it is a rasterimage
Try
If e.Category.Name.ToUpper = "RASTER IMAGES" Then
' Set the Width
Dim wParam As DB.Parameter = e.Parameter("Width")
Dim myWPara As New clsPara(wParam)
If m_width > 0 Then
myWPara.Value = m_width
End If
' Set the Height
Dim hParam As DB.Parameter = e.Parameter("Height")
Dim myEPara As New clsPara(hParam)
If m_height > 0 Then
myEPara.Value = m_height
End If
End If
Catch ex As Exception
End Try
Next
End If
Return imported
End Function
Private Sub ButtonSelectImages_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonSelectImages.Click
' Select the files
Me.OpenFileDialogJPG.ShowDialog()
If Me.OpenFileDialogJPG.FileNames.Count = 0 Then
MsgBox("Nothing to Process!", MsgBoxStyle.Critical, "Terminating")
Me.Close()
End If
m_SelectedJPG = Me.OpenFileDialogJPG.FileNames
With Me.ProgressBar1
.Minimum = 0
.Value = 0
.Maximum = Me.OpenFileDialogJPG.FileNames.Count
.Visible = True
End With
If Me.TextBoxWidth.Text <> "" Then
m_width = (Me.TextBoxWidth.Text / 12)
Else
m_width = 0
End If
If Me.TextBoxHeight.Text <> "" Then
m_height = (Me.TextBoxHeight.Text / 12)
Else
m_height = 0
End If
ImportImages()
End Sub
Private Sub ButtonCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonCancel.Click
Me.Close()
End Sub
Private Sub TextBoxHeight_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBoxHeight.KeyPress
Dim allowedChars As String = "0123456789."
If allowedChars.IndexOf(e.KeyChar) = -1 Then
' Invalid Character
e.Handled = True
End If
End Sub
Private Sub TextBoxWidth_KeyPress(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBoxWidth.KeyPress
Dim allowedChars As String = "0123456789."
If allowedChars.IndexOf(e.KeyChar) = -1 Then
' Invalid Character
e.Handled = True
End If
End Sub
End Class
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.