// // (C) Copyright 2003-2019 by Autodesk, Inc. // // Permission to use, copy, modify, and distribute this software in // object code form for any purpose and without fee is hereby granted, // provided that the above copyright notice appears in all copies and // that both that copyright notice and the limited warranty and // restricted rights notice below appear in all supporting // documentation. // // AUTODESK PROVIDES THIS PROGRAM "AS IS" AND WITH ALL FAULTS. // AUTODESK SPECIFICALLY DISCLAIMS ANY IMPLIED WARRANTY OF // MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE. AUTODESK, INC. // DOES NOT WARRANT THAT THE OPERATION OF THE PROGRAM WILL BE // UNINTERRUPTED OR ERROR FREE. // // Use, duplication, or disclosure by the U.S. Government is subject to // restrictions set forth in FAR 52.227-19 (Commercial Computer // Software - Restricted Rights) and DFAR 252.227-7013(c)(1)(ii) // (Rights in Technical Data and Computer Software), as applicable. // using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Text; using System.IO; using System.Windows.Forms; using System.Linq; using Autodesk.Revit; using Autodesk.Revit.DB; using Autodesk.Revit.UI; using Creation = Autodesk.Revit.Creation; namespace Revit.SDK.Samples.Journaling.CS { public class Journaling { /// /// Define a comparer which compare WallType by name property /// class WallTypeComparer : IComparer { int IComparer.Compare(WallType first, WallType second) { return String.Compare(first.Name, second.Name); } } // Private members ExternalCommandData m_commandData; // Store the reference of command data bool m_canReadData; // Indicate whether has journal data Autodesk.Revit.DB.XYZ m_startPoint; // Store the start point of the created wall Autodesk.Revit.DB.XYZ m_endPoint; // Store the end point of the created wall Level m_createlevel; // Store the level which the created wall on WallType m_createType; // Store the type of the created wall List m_levelList; // Store all levels in revit List m_wallTypeList; // Store all wall types in revit // Properties /// /// Give all levels in revit, and this information can be showed in UI /// public ReadOnlyCollection Levels { get { return new ReadOnlyCollection(m_levelList); } } /// /// Give all wall types in revit, and this information can be showed in UI /// public ReadOnlyCollection WallTypes { get { return new ReadOnlyCollection(m_wallTypeList); } } // Methods /// /// The default constructor /// /// the external command data which revit give RevitAPI public Journaling(ExternalCommandData commandData) { // Initialize the data members m_commandData = commandData; m_canReadData = (0 < commandData.JournalData.Count) ? true : false; // Initialize the two list data members m_levelList = new List(); m_wallTypeList = new List(); InitializeListData(); } /// /// This is the main deal method in this sample. /// It invoke methods to read and write journal data and create a wall using these data /// public void Run() { // According to it has journal data or not, this sample create wall in two ways if (m_canReadData) // if it has journal data { ReadJournalData(); // read the journal data CreateWall(); // create a wall using the data } else // if it doesn't have journal data { if (!DisplayUI()) // display a form to collect some necessary data { return; // if the user cancels the form, only return } CreateWall(); // create a wall using the collected data WriteJournalData(); // write the journal data } } /// /// Set the necessary data which support the wall creation /// /// the start point of the wall /// the end point of the wall /// the level which the wall base on /// the type of the wall public void SetNecessaryData(Autodesk.Revit.DB.XYZ startPoint, Autodesk.Revit.DB.XYZ endPoint, Level level, WallType type) { m_startPoint = startPoint; // start point m_endPoint = endPoint; // end point m_createlevel = level; // the level information m_createType = type; // the wall type } /// /// Get the levels and wall types from revit and insert into the lists /// private void InitializeListData() { // Assert the lists have been constructed if (null == m_wallTypeList || null == m_levelList) { throw new Exception("necessary data members don't initialize."); } // Get all wall types from revit Document document = m_commandData.Application.ActiveUIDocument.Document; FilteredElementCollector filteredElementCollector = new FilteredElementCollector(document); filteredElementCollector.OfClass(typeof(WallType)); m_wallTypeList = filteredElementCollector.Cast().ToList(); // Sort the wall type list by the name property WallTypeComparer comparer = new WallTypeComparer(); m_wallTypeList.Sort(comparer); // Get all levels from revit FilteredElementIterator iter = (new FilteredElementCollector(document)).OfClass(typeof(Level)).GetElementIterator(); iter.Reset(); while (iter.MoveNext()) { Level level = iter.Current as Level; if (null == level) { continue; } m_levelList.Add(level); } } /// /// Read the journal data from the journal. /// All journal data is stored in commandData.Data. /// private void ReadJournalData() { // Get the journal data map from API Document doc = m_commandData.Application.ActiveUIDocument.Document; IDictionary dataMap = m_commandData.JournalData; String dataValue = null; // store the journal data value temporarily // Get the wall type from the journal dataValue = GetSpecialData(dataMap, "Wall Type Name"); // get wall type name foreach (WallType type in m_wallTypeList) // get the wall type by the name { if (dataValue == type.Name) { m_createType = type; break; } } if (null == m_createType) // assert the wall type is exist { throw new InvalidDataException("Can't find the wall type from the journal."); } // Get the level information from the journal dataValue = GetSpecialData(dataMap, "Level Id"); // get the level id Autodesk.Revit.DB.ElementId id = Autodesk.Revit.DB.ElementId.Parse(dataValue); // get the level by its id m_createlevel = doc.GetElement(id) as Level; if (null == m_createlevel) // assert the level is exist { throw new InvalidDataException("Can't find the level from the journal."); } // Get the start point information from the journal dataValue = GetSpecialData(dataMap, "Start Point"); m_startPoint = StirngToXYZ(dataValue); // Get the end point information from the journal dataValue = GetSpecialData(dataMap, "End Point"); m_endPoint = StirngToXYZ(dataValue); // Create wall don't allow the start point equals end point if (m_startPoint.Equals(m_endPoint)) { throw new InvalidDataException("Start point is equal to end point."); } } /// /// Display the UI form to collect some necessary information for create wall. /// The information will be write into the journal /// /// private bool DisplayUI() { // Display the form and allow the user to input some information for wall creation using (JournalingForm displayForm = new JournalingForm(this)) { displayForm.ShowDialog(); if (DialogResult.OK != displayForm.DialogResult) { return false; } } return true; } /// /// Create a wall with the collected data or the data read from journal /// private void CreateWall() { // Get the create classes. Creation.Application createApp = m_commandData.Application.Application.Create; Creation.Document createDoc = m_commandData.Application.ActiveUIDocument.Document.Create; // Create geometry line(curve) Line geometryLine = Line.CreateBound(m_startPoint, m_endPoint); if (null == geometryLine) // assert the creation is successful { throw new Exception("Create the geometry line failed."); } // Create the wall using the wall type, level and created geometry line Wall createdWall = Wall.Create(m_commandData.Application.ActiveUIDocument.Document, geometryLine, m_createType.Id, m_createlevel.Id, 15, m_startPoint.Z + m_createlevel.Elevation, true, true); if (null == createdWall) // assert the creation is successful { throw new Exception("Create the wall failed."); } } /// /// Write the support data into the journal /// private void WriteJournalData() { // Get the StringStringMap class which can write support into. IDictionary dataMap = m_commandData.JournalData; dataMap.Clear(); // Begin to add the support data dataMap.Add("Wall Type Name", m_createType.Name); // add wall type name dataMap.Add("Level Id", m_createlevel.Id.ToString()); // add level id dataMap.Add("Start Point", XYZToString(m_startPoint)); // add start point dataMap.Add("End Point", XYZToString(m_endPoint)); // add end point } /// /// The helper function which convert a format string to a Autodesk.Revit.DB.XYZ point /// /// a format string /// the converted Autodesk.Revit.DB.XYZ point private static Autodesk.Revit.DB.XYZ StirngToXYZ(String pointString) { // Define some temporary data double x = 0; // Store the temporary x coordinate double y = 0; // Store the temporary y coordinate double z = 0; // Store the temporary z coordinate String subString; // A part of the format string // Get the data string from the format string subString = pointString.TrimStart('('); subString = subString.TrimEnd(')'); String[] coordinateString = subString.Split(','); if (3 != coordinateString.Length) { throw new InvalidDataException("The point information in journal is incorrect"); } // Return a Autodesk.Revit.DB.XYZ point using the collected data try { x = Convert.ToDouble(coordinateString[0]); y = Convert.ToDouble(coordinateString[1]); z = Convert.ToDouble(coordinateString[2]); } catch (Exception) { throw new InvalidDataException("The point information in journal is incorrect"); } return new Autodesk.Revit.DB.XYZ(x, y, z); } /// /// The helper function which convert a Autodesk.Revit.DB.XYZ point to a format string /// /// A Autodesk.Revit.DB.XYZ point /// The format string which store the information of the point private static String XYZToString(Autodesk.Revit.DB.XYZ point) { String pointString = "(" + point.X.ToString() + "," + point.Y.ToString() + "," + point.Z.ToString() + ")"; return pointString; } /// /// Get the data which is related to a special key in journal /// /// the map which store the journal data /// a key which indicate which data to get /// The gotten data in string format private static String GetSpecialData(IDictionary dataMap, String key) { String dataValue = dataMap[key]; if (String.IsNullOrEmpty(dataValue)) { throw new Exception(key + "information is not exist in journal."); } return dataValue; } } }