Thursday, April 26, 2012

Project 2



Project 2 Video:




Goals

The objectives for project 2 were to create an extruded panel from the basic rhomboid shape with a point that could be controlled and moved about for different effects (parametric). The second objective was to use that base form to create screening elements to serve as shading for glazing reducing heat gains. A bitmap image of a coral reef was used to create the the holes in the screen.

bitmap

screen

Azimuth/Altitude Controller


Used 3 reference lines connected with angle measurement parameters (above) to control rhomboid pattern family (below).


The pattern family has several panels with visibility parameters with simple on/off characteristics which can be controlled with API using 0/1 in an external Excel spreadsheet.

Data Col1
Row1 0    1st
Row2 0
Row3 0
Row4 0
Row5 0
Row6 0
Row7 0
Row8 1
Row9 0
Row10 0
Row11 0    2nd
Row12 0
Row13 0
Row14 0
Row15 0
Row16 1


After loading a mass family in the project level I ran the API code with the corresponding excel spreadsheet. 
Before
 After



Link to controller tutorial




API Language for Controlling Revit Panels with Excel



// Sample external data functions. Two DLLs (CommonLibrary and TableAccess) 
// are added in References, made for ARCH 653 Building Information Modeling 
// in Architecture, Department of Architecture, Texas A&M University, by
// instructor: Wei Yan, Ph.D.
// Using Revit API 2012.
// Version 2011.11.14 - V1


// Windows System libraries
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
// Revit libraries
using Autodesk.Revit;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;
using Autodesk.Revit.DB.Structure;
using Autodesk.Revit.DB.Architecture;
// Excel libraries reference: 
// http://www.codeproject.com/KB/office/microsoftexcelclient.aspx
using ExcelDB;
// CSV libraries source: 
// http://commonlibrarynet.codeplex.com/
using ComLib.Entities;
using ComLib.Account;
using ComLib;
using ComLib.CsvParse;
using ComLib.Application;
using ComLib.Logging;


namespace CurtainPanels
{
    /// <summary>
    /// Demonstrate parametric design that reads a room parameters and changes the size
    /// of a table-chair family automatically.
    /// </summary>
    [Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)]
    [Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)]
    /// <summary>
    /// Implements the Revit add-in interface IExternalCommand
    /// </summary>
    public class Command : IExternalCommand
    {
        #region 0. Declare global variables
        int m;
        #endregion


        /// <summary>
        /// Implement this method as an external command for Revit.
        /// <param name="commandData">An object that is passed to the external application 
        /// which contains data related to the command, 
        /// such as the application object and active view.</param>
        /// <param name="message">A message that can be set by the external application 
        /// which will be displayed if a failure or cancellation is returned by 
        /// the external command.</param>
        /// <param name="elements">A set of elements to which the external application 
        /// can add elements that are to be highlighted in case of failure or cancellation.</param>
        /// <returns>Return the status of the external command. 
        /// A result of Succeeded means that the API external method functioned as expected. 
        /// Cancelled can be used to signify that the user cancelled the external operation 
        /// at some point. Failure should be returned if the application is unable to proceed with 
        /// the operation.</returns>
        /// </summary>
        public Autodesk.Revit.UI.Result Execute(ExternalCommandData commandData, ref string message,
            ElementSet elements)
        {
            #region 1. Initialize, get the project, and start a project transaction




            Result retRes = Result.Failed;  // set out default result to failure. Failure will let Revit to undo the changes made during 
            // the execution of this command.
            Document doc = commandData.Application.ActiveUIDocument.Document; // the current Revit project model
            Document familyDoc = null; // family loaded in this project and needs editing (using EditFamily method)          
            ElementId id;
            Material material;
            Random random = new Random(); // Create a random object to generate random numbers for calculation.
            m = random.Next(1, 10000); // This random number will be used to avoid duplicated names of Materials. Revit doesn't like duplicating materials with the same names.
            int[] IDS;


            Transaction transaction = new Transaction(doc, "Update Project by API"); //A transaction is a change to the model to be made. The text will show in Revit -> Undo/Redo            
            Transaction familyTransaction = null; //Needed for creating the new material in familyDoc. Different from the need to change the Thinkness in family. 


            transaction.Start(); // Start a transation to allow changes to the model         
            #endregion


            #region 2. If we are dealing with CurtainPanelByPattern in a family loaded into the project


            {


                id = new ElementId(1404942); //ID value of the Mass family instance, obtained from the Revit model
                //by selecting the mass and using menu Manage->IDs of Selection.
                FamilyInstance massInstance = doc.get_Element(id) as FamilyInstance; //Get the element by ID and cast it to FamilyInstance
                // Get the family associated with this intance
                Family family = massInstance.Symbol.Family;
                // Get Family document for the family
                familyDoc = doc.EditFamily(family);


                familyTransaction = new Transaction(familyDoc, "Update Family by API"); //A transaction is a change to the model to be made. The text will show in Revit -> Undo/Redo            
                familyTransaction.Start(); // Start a transation to allow changes to the model 
                //Create the material
                ElementId materialId = Material.Create(familyDoc, "My Material" + m); // adding random m to avoid same names used when running the program multiple times.
                material = familyDoc.get_Element(materialId) as Material;


                //In Revit Project or Family Editor, tab to highlight a panel, right click and use Select All Instances, 
                // and Manage->IDs of selections, to find all panel Ids. Copy them to the IDS array.
                // The Ids of the panels in Family Editor (not in the Project! They are different.)
                IDS = new int[] { 31861, 31862, 31863, 31864, 31865, 31866, 31867, 31868, 31869, 31870, 31811, 31812, 31813, 31814, 31815, 31816, 31839, 31840, 31841, 31805, 31806, 31807, 31808, 31809, 31810, 31837, 31838, 31859, 31860, 31799, 31800, 31801, 31802, 31803, 31804, 31834, 31835, 31836, 31793, 31794, 31795, 31796, 31797, 31798, 31832, 31833, 31857, 31858, 31787, 31788, 31789, 31790, 31791, 31792, 31829, 31830, 31831, 31781, 31782, 31783, 31784, 31785, 31786, 31827, 31828, 31855, 31856, 31775, 31776, 31777, 31778, 31779, 31780, 31824, 31825, 31826, 31769, 31770, 31771, 31772, 31773, 31774, 31822, 31823, 31853, 31854, 31763, 31764, 31765, 31766, 31767, 31768, 31819, 31820, 31821, 31757, 31758, 31759, 31760, 31761, 31762, 31817, 31818, 31851, 31852, 31842, 31843, 31844, 31845, 31846, 31847, 31848, 31849, 31850 };
                SetThicknessColor(IDS, familyDoc, material);
                familyDoc.LoadFamily(doc, new FamilyOption());
            }
            #endregion






            #region 4. Commit the transaction(s) and terminate the API program
            if (familyTransaction != null)
            {
                familyTransaction.Commit(); //Let Revit make the change to the family.
            }
            transaction.Commit(); //Let Revit make the change to the project.
            // if the program can run to this line, the execution is successful
            retRes = Result.Succeeded;
            // inform Revit the result (if succeeded, Revit will keep all 
            // the changes made during the execution of the command).
            return retRes;
            #endregion
        }


        /// <summary>
        /// Set Thickness and Color of panels
        /// </summary>
        /// <param name="IDS"></param>
        /// <param name="document"></param>
        /// <param name="material"></param>
        private void SetThicknessColor(int[] IDS, Document document, Material material)
        {
            ElementId id;
            Random random = new Random(); // Create a random object to generate random numbers for calculation, just for fun (we can't imagine the building design will change each time we run our API program, or can we?)
            //Loop through all panel instances, and change each one's Thichness and Color
            int a = 1;






            for (int n = 0; n < IDS.Length; n++)
            {
                #region 1 Get objects
                // use id to get the table-chair family instance
                //ElementId id;
                id = new ElementId(IDS[n]); //ID value of the panel family instance, obtained from the Revit model
                FamilyInstance panelInstance;
                panelInstance = document.get_Element(id) as FamilyInstance; //Get the element by ID and cast it to FamilyInstance
                #endregion


                #region 2 Get instance parameters of the objects
                Parameter panelYorNParam = panelInstance.get_Parameter("screen");




                #endregion


                #region 3 Calculate new values




                int YorN = CsvDB("Row" + a, "Col1");




                #endregion


                #region 4 Set parameters of objects using new values
                panelYorNParam.Set(YorN);


                #endregion




                a++;


            }
        }


        private int CsvDB(string row, string col)
        {
            string csvSourceFile = typeof(Csv).Assembly.Location.Replace("CommonLibrary.dll", "PV_pattern.csv");
            CsvDoc csv = Csv.Load(csvSourceFile, false);


            // By default, this csv parser only takes (int row, int col) or (int row, string col) as input
            // but we would like to use (string row, string col) to retrieve cell values.
            // Iterate over all the cells in column named "Data" starting at row 0.
            int rowCount = 0;
            csv.ForEach<string>("Data", 0, (rowNum, colNum, val) =>
            {
                if (val.ToString() == row)
                {
                    rowCount = rowNum;
                    return; //stop looping as we found the row number
                }
            });
            return csv.Get<int>(rowCount, col);
            //other types, e.g. string can be returned if the cell value has quotations, like 'my value'    
            //also, "csv.Get<double>(int row, int col);" is possible
            //also, "csv.Get<double>(int row, string col);" is possible
        }




    }
}