Last active
June 22, 2023 22:30
-
-
Save BimManager/80de58d35a753be892285747999c1c35 to your computer and use it in GitHub Desktop.
RevitAPI
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Revit API Exploration Tools | |
RevitLookup | |
BipChecker | |
AdnRevitApiLabsXtra | |
RevitPythonShell | |
Revit SDK | |
the_building_coder_samples | |
// how to embed a page into a Revit add-in | |
use the WPF User Control Library type | |
if (elementId != ElementId.InvalidElementId) | |
Autodesk.Revit.UI.UIApplication uiapp; | |
Autodesk.Revit.UI.UIControlledApplication uicapp; | |
Autodesk.Revit.UI.Application app; | |
UIDocument uidoc; | |
UIDocument uidoc = new UIDocument(doc); | |
Document doc; | |
EVENTS | |
Application level events | |
Application | |
ControlledApplication | |
DB events and UI events | |
Application and Document | |
UIApplication | |
// Transactions | |
using (Transaction trxn = new Transaction(doc)) { | |
TransactionStatus status = trxn.Start("trxn description"); | |
// do something here | |
trxn.Commit(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
static class Globals { | |
public const String kApplicationName = "DockablePane"; | |
public const String kTabName = "Fohlio"; | |
public const String kPanelName = "DockablePane Panel"; | |
public static Guid kPanelGuid = new Guid(); | |
} | |
static class ReflectionData { | |
public static String GetAssemblyPath() { | |
if (null == _assemblyPath) { | |
_assemblyPath = Path.GetDirectoryName( | |
Assembly.GetExecutingAssembly().Location); | |
} | |
return _assemblyPath; | |
} | |
public static String GetAssemblyFullName() { | |
if (null == _assemblyFullName) { | |
_assemblyFullName = Assembly.GetExecutingAssembly().Location; | |
} | |
return _assemblyFullName; | |
} | |
public static String GetApplicationResourcesPath() { | |
if (null == _resourcesPath) { | |
_resourcesPath = GetAssemblyPath + "\\Resources\\"; | |
} | |
return _resourcesPath; | |
} | |
private static String _assemblyPath = null; | |
private static String _assemblyFullName = null; | |
private static String _resourcesPath = null; | |
} | |
static class Logging { | |
public static void LogMessage(String message, int level = 0) { | |
String log = String.Format("{0:MM-dd-yyyy HH:mm:ss} {1}", DateTime.Now, message); | |
Console.WriteLine(log); | |
Debug.WriteLine(log); | |
if (level > 0) TaskDialog.Show("Revit Logging", log); | |
} | |
public static void AddLogFile(String filepath) { | |
#if DEBUG | |
Debug.Listeners.Add(new TextWriterTraceListener(filepath + ".trace")); | |
Debug.AutoFlush = true; | |
#else | |
Trace.Listeners.Add(new TextWriterTraceListener(filepath + ".debug")); | |
Trace.AutoFlush = true; | |
#endif | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) | |
{ | |
Document doc = | |
commandData.Application.ActiveUIDocument.Document; | |
Selection selection = | |
commandData.Application.ActiveUIDocument.Selection; | |
Reference r = selection.PickObject(ObjectType.Element); | |
SpatialElement spElem = doc.GetElement(r) as SpatialElement; | |
SpatialElementBoundaryOptions boundaryOptins = | |
new SpatialElementBoundaryOptions | |
{ SpatialElementBoundaryLocation = SpatialElementBoundaryLocation.Center }; | |
IList<double> areas = new List<double>(); | |
foreach(IList<BoundarySegment> bndSegments in spElem.GetBoundarySegments(boundaryOptins)) | |
{ | |
areas.Add(CalculateArea(bndSegments)); | |
} | |
TaskDialog.Show("Result:", string.Format("Area={0}", areas.Sum())); | |
return Result.Succeeded; | |
} | |
private static double CalculateArea(IList<BoundarySegment> segments) | |
{ | |
IList<XYZ> vertices = segments | |
.Select<BoundarySegment, XYZ>(s => s.GetCurve().GetEndPoint(0)) | |
.ToList(); | |
double area = 0; | |
for (int i = 0, j; i < vertices.Count; i++) | |
{ | |
j = i + 1; | |
area = area + vertices[i].X * vertices[j].Y; | |
area = area + vertices[i].Y * vertices[j].X; | |
} | |
return area; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using System.Text; | |
using System.Linq; | |
using Autodesk.Revit.Attributes; | |
using Autodesk.Revit.DB; | |
using Autodesk.Revit.UI; | |
namespace Revit.SDK.Samples.HelloRevit.CS | |
{ | |
[Transaction(TransactionMode.Manual)] | |
public class Command : IExternalCommand | |
{ | |
public Result Execute(ExternalCommandData commandData, | |
ref string message, | |
ElementSet elements) | |
{ | |
Document doc = | |
commandData.Application.ActiveUIDocument.Document; | |
// Get access to all the TextNote Elements | |
FilteredElementCollector collectorUsed | |
= new FilteredElementCollector(doc); | |
ICollection<ElementId> textNotes | |
= collectorUsed.OfClass(typeof(TextNote)) | |
.ToElementIds(); | |
foreach (ElementId textNoteid in textNotes) | |
{ | |
TextNote textNote = doc.GetElement( | |
textNoteid) as TextNote; | |
Transaction trans = new Transaction(doc); | |
trans.Start("ChangeParam"); | |
// Create a duplicate | |
Element ele = | |
textNote.TextNoteType.Duplicate("ADSK_NewTextNoteType"); | |
TextNoteType noteType = ele as TextNoteType; | |
if (null != noteType) | |
{ | |
// Just for example sake, change the font parameter | |
noteType.get_Parameter("Text Font").Set("Arial Narrow"); | |
} | |
trans.Commit(); | |
} | |
return Result.Succeeded; | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
REVIT DESIGN AUTOMATION | |
it is an engine that can run add-ins in the cloud | |
1. upload data to a cloud storage (forge data services recommend) | |
2. send a link to the data to Forge DA | |
CLOUD -------> FORGE DA (runs your Revit add-in on the data provided) | |
<------- | |
V3 HTTP ENDPOINTS | |
/workitems (function call) | |
/activities (function definition) | |
/appbundles (shared library) | |
/engines (instruction set) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public void ElementOverride() | |
{ | |
Document doc = this.ActiveUIDocument.Document; | |
UIDocument uidoc = this.ActiveUIDocument; | |
ElementId id = uidoc.Selection.PickObject(ObjectType.Element,"Select an element").ElementId; | |
OverrideGraphicSettings ogs = new OverrideGraphicSettings(); | |
ogs.SetProjectionLineColor(new Color(0,255,0)); | |
using (Transaction t = new Transaction(doc,"Set Element Override")) | |
{ | |
t.Start(); | |
doc.ActiveView.SetElementOverrides(id, ogs); | |
t.Commit(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class App : IExternalApplication | |
{ | |
public Result OnShutdown(UIControlledApplication application) | |
{ | |
return Result.Succeeded; | |
} | |
public Result OnStartup(UIControlledApplication application) | |
{ | |
string assemblyPath = Assembly.GetExecutingAssembly().Location; | |
string panelName = "Tekta"; | |
// Produce a new ribbon panel | |
RibbonPanel ribbonPanel = | |
application.CreateRibbonPanel(Tab.AddIns, panelName); | |
// Add a push button to the ribbon panel | |
PushButton pushButton = ribbonPanel | |
.AddItem(new PushButtonData | |
("Splitter", "Splitter", assemblyPath, "TektaRevitPlugins.SplitterCommand")) | |
as PushButton; | |
// Set the image depicted on the button | |
pushButton.LargeImage = BmpImageSource("TektaRevitPlugins.Resources.axe_32x32.png"); | |
pushButton.Image = BmpImageSource("TektaRevitPlugins.Resources.axe_16x16.png"); | |
return Result.Succeeded; | |
} | |
#region Helper Methods | |
System.Windows.Media.ImageSource BmpImageSource(string embeddedPath) | |
{ | |
Stream stream = this.GetType().Assembly.GetManifestResourceStream(embeddedPath); | |
var decoder = new System.Windows.Media.Imaging.PngBitmapDecoder | |
(stream, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default); | |
return decoder.Frames[0]; | |
} | |
#endregion | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class ExternalEventHandler : IExternalEventHandler { | |
static ExternalEventHandler _instance; | |
ExternalEvent _externalEvent; | |
Action<UIApplication, Object> _callback; | |
Object _data; | |
public static ExternalEventHandler Instance { | |
get { | |
if (null == _instance) _instance = new ExternalEventHandler(); | |
return _instance; | |
} | |
} | |
public ExternalEvent ExternalEvent { | |
get { | |
if (null == _externalEvent) _externalEvent = ExternalEvent.Create(this); | |
return _externalEvent; | |
} | |
} | |
public void RegiserCallback(Action<UIApplication, Object> callback, | |
Object data) { | |
_callback = callback; | |
_data = data;x | |
} | |
public void Execute(UIApplication app) { | |
if (_callback != null) _callback.Invoke(app, _data); | |
} | |
public String GetName() { return "External Event Handler"; } | |
ExternalEventInstance() {} | |
} | |
// 1. Create the event in OnStartup() | |
ExternalEventHandler.Instance.ExternalEvent; | |
// 2. Register a callback function | |
ExternalEventHandler.Instance.RegisterCallback((data) => { ... }, someData); | |
// 3. Queue the event | |
ExternalEventHandler.Instance.ExternalEvent.Raise(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Filtering by means of the Revit API | |
RoomFilter roomFilter = new RoomFilter(); | |
AreaFilter areaFilter = new AreaFilter(); | |
ExtensibleStorageFilter storageFilter = new ExtensibleStorageFilter(); | |
ElementWorksetFilter worksetFilter; | |
FamilyInstanceFilter famInstFilter; | |
FamilySymbolFilter famSymFilter; | |
// Dealing with materials | |
//Materials materials = doc.Settings.Materials; no longer supported | |
Materials materials = elementsCollector | |
.WherePasses(new ElementClassFilter(typeof(Material)) //.OfClass(typeof(Material)) | |
.ToElements() | |
.Cast<Material>() | |
.ToList(); | |
// Only for category.HasMaterialQuantities(); | |
element.GetMaterialIds(bool returnPaintMaterials); | |
element.GetMaterialVolume(ElementId materialId); | |
element.GetMaterialArea(ElementId materialId, bool isPaintMaterial); | |
FilteredElementCollector collector = new FilteredElementCollector(); | |
IList<Element> materials = collector.WherePasses(new ElementClassFilter(typeof(Material)); | |
ElementCategoryFilter categoryFilter = new ElementCategoryFilter(BuiltInCategory); | |
ElementClassFilter classFilter = new ElementClassFilter(typeof(Level)); | |
ElementIsElementTypeFilter typeFilter = new ElementIsElementTypeFilter(); | |
ElementLevelFilter lvlFilter = new ElementLevelFilter(ElementId); | |
ElementMulticategoryFilter multicategoryFilter = | |
new ElementMulticategoryFilter(ICollection<BuiltInCategory>); | |
ElementIntersectsFilter intersectionFilter = new ElementIntersectsFilter(); | |
ElementIntersectsElementFilter intersectionFilter = new ElementIntersectsElementFilter(Element); | |
ElementIntersectsSolidFilter solidIntersectionFilter = new ElementIntersectsSolidFilter(Solid); | |
ElementDesignOptionFilter designOptionFilter = new ElementDesignOptionFilter(ElementId); | |
ElementPhaseStatusFilter phaseStatusFilter = new ElementPhaseStatusFilter(ElementId phaseId, ICollection<ElementOnPhaseStatus> phaseStatuses); | |
FilterRule fr = ParameterFilterRuleFactory.CreateEquals(ElementId, string, bool); // FilterRule factory | |
ElementParameterFilter paramFilter = new ElementParameterFilter(fr); | |
collector.WherePasses(paramFilter); | |
FilterNumericLess less; | |
FilterNumericLessOrEqual lessEqual; | |
FilterNumericGreater greater; | |
FilterNumericGreaterOrEqual greaterEqual; | |
FilterNumericEquals equals; | |
ExclusionFilter exclusionFilter = new ExclusionFilter(); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Filtering by means of the Revit API | |
/* | |
** Quick filters operate on only the ElementRecord, a low-memory class | |
** which has a limited interface to read element properties. | |
** Slow filters require that the Element be obtained and expanded in memory. | |
** | |
*/ | |
RoomFilter roomFilter = new RoomFilter(); | |
AreaFilter areaFilter = new AreaFilter(); | |
ExtensibleStorageFilter storageFilter = new ExtensibleStorageFilter(); | |
ElementWorksetFilter worksetFilter; | |
FamilyInstanceFilter famInstFilter; | |
FamilySymbolFilter famSymFilter; | |
// Dealing with materials | |
//Materials materials = doc.Settings.Materials; no longer supported | |
FilteredElementCollector collector = new FilteredElementCollector(); | |
Materials materials = collector | |
.WherePasses(new ElementClassFilter(typeof(Material))) //.OfClass(typeof(Material)) | |
.ToElements() | |
.Cast<Material>() | |
.ToList(); | |
// Only for category.HasMaterialQuantities(); | |
element.GetMaterialIds(bool returnPaintMaterials); | |
element.GetMaterialVolume(ElementId materialId); | |
element.GetMaterialArea(ElementId materialId, bool isPaintMaterial); | |
ElementCategoryFilter categoryFilter = new ElementCategoryFilter(BuiltInCategory); | |
ElementClassFilter classFilter = new ElementClassFilter(typeof(Level)); | |
ElementIsElementTypeFilter typeFilter = new ElementIsElementTypeFilter(); | |
ElementLevelFilter lvlFilter = new ElementLevelFilter(ElementId); | |
ElementMulticategoryFilter multicategoryFilter = | |
new ElementMulticategoryFilter(ICollection<BuiltInCategory>); | |
ElementIntersectsFilter intersectionFilter = new ElementIntersectsFilter(); | |
ElementIntersectsElementFilter intersectionFilter = new ElementIntersectsElementFilter(Element); | |
ElementIntersectsSolidFilter solidIntersectionFilter = new ElementIntersectsSolidFilter(Solid); | |
ElementDesignOptionFilter designOptionFilter = new ElementDesignOptionFilter(ElementId); | |
PrimaryDesignOptionMemberFiler primaryDesignOptionFilter = | |
new PrimaryDesignOptionMemberFilter(); | |
ElementPhaseStatusFilter phaseStatusFilter = | |
new ElementPhaseStatusFilter( | |
ElementId phaseId,ICollection<ElementOnPhaseStatus> phaseStatuses); | |
FilterRule fr = ParameterFilterRuleFactory.CreateEquals(ElementId, string, bool); // FilterRule factory | |
ElementParameterFilter paramFilter = new ElementParameterFilter(fr); | |
collector.WherePasses(paramFilter); | |
FilterNumericLess less; | |
FilterNumericLessOrEqual lessEqual; | |
FilterNumericGreater greater; | |
FilterNumericGreaterOrEqual greaterEqual; | |
FilterNumericEquals equals; | |
ExclusionFilter exclusionFilter = new ExclusionFilter(); | |
// OPTIMISATIONS | |
FilteredElementCollector collector | |
= new FilteredElementCollector(doc) | |
.OfCategory(BuiltInCategory.OST_Doors) | |
.OfClass(typeof(FamilySymbol)); | |
foreach (FamilySymbol fs in collector) { | |
Family family = fs.Family; | |
} | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// BASICS | |
// Autodesk.Viewing.Document | |
// Autodesk.Viewing.BubbleNode | |
// Autodesk.Viewing.Model | |
// Autodesk.Viewing.InstanceTree is an object for query nodes. | |
const tree = model.getInstanceTree(); | |
tree.enumNodeChildren(tree.getRootId(), (nodeId) => { | |
tree.enumNodeFragments(nodeId, (fragId) => { | |
const fragProxy = viewer.impl.getRenderProxy(model, fragId); | |
}, true); // recursive: true | |
}, true); // recursive: true | |
viewer.impl.scene.add(mesh); | |
viewer.impl.sceneUpdated(true); // update things that have been changed | |
viewer.impl.invalidate(true); // reprocess the entire scene | |
// In case of materials, using invalidated() is preferable because | |
// the material list is outside the scene. | |
viewer.impl.getMaterials().addMaterial('superMaterial', material, true); | |
viewer.impl.matman().addMaterial('superMaterial', material, true); | |
viewer.impl.getFragmentProxy(model, fragId); | |
viewer.setThemingColor(dbId, new THREE.Vector4(1, 0, 0, 1)); | |
function setMaterial(viewer, dbIds, material) { | |
const model = viewer.model; | |
model.unconsolidate(); | |
const tree = model.getInstanceTree(); | |
const frags = model.getFragmentList(); | |
} | |
// Autodesk.Viewing.Model model; | |
const model = NOP_VIEWER.model; | |
model.getInstanceTree(); | |
model.getFragmentList(); | |
model.getGeometryList(); | |
model.getGeomScenes(); | |
model.getData(); // geometry data | |
model.getDocumentNode(); | |
model.getRoot(); | |
model.getRootId(); | |
model.getMetadata(itemName, subitemName, defaultValue); | |
model.getPropertyDb(); | |
model.getProperties(dbId, onSuccessCallback, onErrorCallback); | |
model.getProperties2(dbId, onSuccessCallback, onErrorCallback, { | |
needsExternalId: false | |
}); | |
model.getBulkProperties(dbIds, options, onSuccessCallback, onErrorCallback); | |
model.getBulkProperties2(dbIds, options, onSuccessCallback, onErrorCallback); | |
model.getPropertySetAsync(dbIds, options) | |
.then(function(propertySet) { | |
propertySet.forEach(function(key, properties) { | |
/* ,,, */ | |
}); | |
}); | |
// PROPERTY OBJECT | |
{ | |
attributeName: 'Category', | |
dbId: 42, | |
displayCategory: '__document__', | |
displayName: 'Category', | |
displayValue: 'Revit Document', | |
hidden: 1, | |
parentName: 'Model', | |
precision: 0, | |
type: 20, | |
unit: null | |
} | |
// HOW TO OPEN A DOCUMENT | |
Autodesk.Viewing.Viewer3D.loadModel(urn, options, | |
onSuccessCallback, onFailureCallback); | |
Autodesk.Viewing.Viewer3D.loadDocumentNode( | |
Autodesk.Viewing.Document doc, Autodesk.Viewing.BubbleNode manifestNode, | |
options); | |
// METHOD A | |
Autodesk.Viewing.Document.load( | |
modelUrn, onDocumentLoadedSuccess, onDocumentLoadedFailure); | |
function onDocumentLoadedSuccess(doc) { | |
const defaultModel = doc.getRoot().getDefaultModel(); | |
viewer.loadDocumentNode(doc, defaultModel); // wraps loadModel() | |
// SVF2 models | |
const url = doc.getViewablePath(defaultModel); | |
viewer.loadModel(url, { acmSessionId: doc.getAcmSessionId(url) }); | |
} | |
function onDocumentLoadedFailure() {} | |
// METHOD B | |
// METHOD C | |
let doc = new Autodesk.Viewing.Document(dataJSON, path, acmSession); | |
// acmSession is required to load a SVF2 modeil | |
fetch('http://localhost:3000/api/forge/modelderivate/<urn>/manifest') | |
.then((res) => { | |
res.json().then((body) => { | |
doc = new Autodesk.Viewing.Document(body, 'urn:' + urn); | |
let defaultModel = doc.getRoot().search({ | |
type: 'geometry', role: '3d', isMasterView: true | |
}); | |
// getDefaultGeometry(searchMasterView, loadLargestView); | |
defaultModel = doc.getRoot().getDefaultGeometry(true); | |
if (manifestNodes.length > 0) { | |
viewer.loadDocumentNode(doc, manifestNodes[0]); | |
} | |
}); | |
}) | |
Autodesk.Viewing.Document.load( | |
modelUrn, onSuccessCallback, onFailureCallback, options); // a static method | |
function onSuccessCallback(doc) { | |
// Autodesk.Viewing.BubbleNode | |
const bubbleNodeRoot = doc.getRoot(); | |
const lmvDoc = bubbleNodeRoot.lmvDocument; | |
} | |
// HOW TO REGISTER AN EXTENSION | |
(function() { | |
'use strict' | |
function MyExtension(viewer, options) { | |
Autodesk.Viewing.Extension.call(this, viewer, options); | |
} | |
MyExtension.prototype = Object.create(Autodesk.Viewing.Extension.prototype); | |
MyExtension.prototype.constructor = MyExtension; | |
let proto = MyExtension.prototype; | |
proto.load = function() { | |
console.log("My extension loaded!"); | |
return true; | |
} | |
proto.unload = function() { | |
console.log("My extension unloaded"); | |
return true; | |
} | |
Autodesk.Viewing.theExtensionManager.registerExtension( | |
'MyExtension', MyExtension); | |
})(); | |
viewer.loadExtension('MyExtension') | |
.then((ext) => { | |
console.log("success"); | |
}) | |
.catch((err) => { | |
console.error(err); | |
}); | |
NOP_VIEWER.isExtensionLoaded('MyExtension'); | |
NOP_VIEWER.loadExtension('MyExtension'); | |
NOP_VIEWER.loadExtension('Autodesk.DocumentBrowser'); // 2D & 3D viewables | |
NOP_VIEWER.unloadExtension('MyExtension'); | |
// HOW TO ADD A BUTTON | |
viewer.loadDocumentNode(doc, items[0]) | |
.then(function(model) { | |
let group = viewer.toolbar.getControl('randomName'); | |
if (!group) { | |
group = new Autodesk.Viewing.UI.ControlGroup('randomName'); | |
viewer.toolbar.addControl(group); | |
} | |
button = new Autodesk.Viewing.UI.Button('printButton'); | |
button.setIcon('adsk-icon-layers'); | |
button.onClick = () => { | |
foo(viewer); | |
}; | |
button.setToolTip('Print Sheet'); | |
group.addControl(button); | |
}); | |
// added AEC data to models translated from Revit | |
function onDocumentLoadSuccess(doc) { | |
let defaultModel = doc.getRoot().getDefaultGeometry(); | |
doc.downloadAecModelData(); | |
viewer.loadDocumentNode(doc, defaultModel); | |
} | |
const aecData = viewer.model.getDocumentNode().getAecModelData(); | |
// HOW TO ADD A CUSTOM GEOMETRY | |
// 1. Create a custom geometry | |
let geometry = new THREE.SphereGeometry(10, 8, 8); | |
let material = new THREE.MeshBasicMaterial({ color: 0x0000ff }); | |
let mesh = new THREE.Mesh(sphereGeom, meshMaterial); | |
// 2. Create an overlay scene | |
const sceneName = 'customScene'; | |
if (!viewer.overlays.hasScene(sceneName)) { | |
viewer.overlays.addScene(sceneName); | |
} | |
// 3. Add the custom geometry to the scene | |
viewer.overlays.addMesh(mesh, sceneName); | |
// 4. Do the clean-up | |
viewer.overlays.removeMesh(mesh, sceneName); | |
viewer.overlays.removeScene(sceneName); | |
meshMaterial.dispose(); | |
sphereGeom.dispose(); | |
// HOW TO QUERY THE PROPERTY DATABASE (Autodesk.Globals.PropertyDatabase) | |
// the function must be named userFunction | |
function userFunction(pdb) { | |
pdb.enumAttribtes(function(i, attrDef, attrRaw) { | |
}); | |
pdb.enumObjects(function(dbId) { | |
pdb.enumObjectProperties(dbId, function(attrId, valId) { | |
const attrDef = pdb.getAttributeDef(attrId); | |
const attrVal = pdb.getAttrValue(attrId, valId); | |
}); | |
}); | |
return 42; | |
}); | |
viewer.model | |
.getPropertyDb() | |
.executeUserFunction(userFunction) | |
.then((result) => { }) | |
.catch((err) => console.error(err)); | |
// Since version 7.0.0 | |
function userFunction(pdb, userData) { | |
} | |
viewer.model | |
.getPropertyDb() | |
.executeUserFunction(userFunction, userData) | |
.then((result) => { }) | |
.catch((error) => { }) | |
// SELECTION | |
viewer.getSelection(); // [928, 42, 23] | |
viewer.select([42, 191]); | |
function onSelectionChanged(event) { | |
const dbId = event.dbIdArray[0]; | |
if (dbId) { | |
NOP_VIEWER.model.getProperties(dbId, (result) => { | |
_externalId = result.externalId; | |
}); | |
} | |
handleSelectionChangeed(event.fragIdsArray); | |
} | |
// ACCESSING METADATA WITHOUT THE VIEWER | |
// 1. GET :urn/metadata/:guid/properties | |
// 2. Sqlite database | |
// GET :urn/manifest | |
// sqlite> .tables | |
// sqlite> PRAGMA table_info(_objects_attr); | |
// sqlite> .schema _objects_eav | |
// sqlite> .headers on | |
// sqlite> .mode column | |
/* | |
** _objects_attr | |
** id | INTEGER | |
** name | TEXT | |
** category | TEXT | |
** data_type | INTEGER | |
** data_type_context | TEXT | |
** description | TEXT | |
** display_name | TEXT | |
** flags | INTEGER | |
** display_precision | INTEGER | |
** forge_parameter | TEXT | |
*/ | |
/* | |
** _objects_eav | |
** id | INTEGER | |
** entity_id | INTEGER | |
** attribute_id | INTEGER | |
** value_id | INTEGER | |
*/ | |
/* | |
** _objects_id | |
** id | INTEGER | |
** external_id | BLOB | |
** viewable_id | BLOB | |
*/ | |
/* | |
** _objects_val | |
** id | INTEGER | |
** value | BLOB | |
*/ | |
/* 3. Viewer-optimised database | |
** objects_attr.json.gz | |
** objects_avs.json.gz | |
** objects_ids.json.gz | |
** objects_vals.json.gz | |
*/ | |
SELECT id.external_id, id.viewable_id, attr.name, attr.category, val.value | |
FROM (((_objects_eav AS eav JOIN _objects_attr AS attr ON eav.attribute_id = attr.id) | |
JOIN _objects_val AS val ON eav.value_id = val.id) | |
JOIN _objects_id as id ON eav.entity_id = id.id) | |
/* | |
** HOW TO FIND ALL FAMILY TYPE INSTANCES BASED ON THE TYPE'S UNIQUE ID | |
*/ | |
SELECT val.value | |
FROM (((_objects_eav AS eav JOIN _objects_attr AS attr | |
ON eav.attribute_id = attr.id) | |
JOIN _objects_val AS val ON eav.value_id = val.id) | |
JOIN _objects_id as id ON eav.entity_id = id.id) | |
WHERE id.external_id LIKE '705%1bef' | |
AND attr.category LIKE '__child__'; | |
//SELECT id.external_id, id.viewable_id, attr.name, attr.category, val.value | |
SELECT * | |
FROM (((_objects_eav AS eav JOIN _objects_attr AS attr ON eav.attribute_id = attr.id) | |
JOIN _objects_val AS val ON eav.value_id = val.id) | |
JOIN _objects_id as id ON eav.entity_id = id.id) | |
WHERE attr.category LIKE '__parent__' | |
LIMIT 5; | |
// SELECT ALL INFO ABOUT | |
SELECT * FROM (((_objects_id AS id JOIN _objects_eav AS eav ON id.id = eav.entity_id) JOIN _objects_val AS val ON val.id = eav.value_id) JOIN _objects_attr AS attr ON attr.id = eav.attribute_id) WHERE val.value = 'Furniture'; | |
// CODE SNIPPETS | |
var viewer; | |
var objectIds = []; | |
function launchViewer(urn, object_id) { | |
objectIds = []; | |
objectIds.push( object_id); | |
var options = { | |
env: 'AutodeskProduction2', | |
api: 'streamingV2', | |
getAccessToken | |
}; | |
Autodesk.Viewing.Initializer(options, function onInitialized() { | |
viewer = new Autodesk.Viewing.GuiViewer3D(document.getElementById('forgeViewer')); | |
viewer.start(); | |
var documentId = 'urn:' + urn; | |
Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, onDocumentLoadFailure); | |
}); | |
} | |
function onDocumentLoadSuccess(doc) { | |
var viewables = doc.getRoot().getDefaultGeometry(); | |
viewer.loadDocumentNode(doc, viewables).then( async (model) => { | |
// Highlight the takeoff element after geometry is loaded | |
await Autodesk.Viewing.EventUtils.waitUntilGeometryLoaded(viewer); | |
viewer.isolate(objectIds); | |
viewer.fitToView(objectIds); | |
}); | |
} | |
function onDocumentLoadFailure(viewerErrorCode) { | |
console.error('onDocumentLoadFailure() - errorCode:' + viewerErrorCode); | |
} | |
async function getAccessToken(callback) { | |
const resp = await fetch('/api/forge/oauth/token'); | |
if (resp.ok) { | |
const { access_token, expires_in } = await resp.json(); | |
callback(access_token, expires_in); | |
} else { | |
alert('Could not obtain access token. See the console for more details.'); | |
console.error(await resp.text()); | |
} | |
} | |
/* | |
** VIEWER EXTENSIONS: TIPS AND TRICKS | |
*/ | |
// EXTENSION LOADING | |
Autodesk.Viewing.theExtensionManager | |
.registerExtension('FooExtensionId', FooExtension); | |
// Method A | |
const viewer = new Autodesk.Viewing.GuiViewer3D( | |
container, { extension: ['FooExtensionId'] }); | |
// Method B | |
const viewer = new Autodesk.Viewing.GuiViewer3D(container); | |
viewer.loadExtension('FooExtensionId'); | |
// Method C | |
Autodesk.Viewing.theExtensionManager.registerExternalExtension( | |
'FooExtensionId', 'https://foo.fohlio.com/public/FooExtension.js'); | |
const viewer = new Autodesk.Viewing.GuiViewer3D( | |
container, { extensions: ['FooExtensionId'] }); | |
// PASSING OPTIONS TO EXTENSIONS | |
viewer.loadExtension('FooExtensionId', { passcode: 'Fido' }); | |
// ... | |
constructor(viewer, options) { | |
super(viewer, options); | |
console.log(options.passcode); // 'Fido' | |
} | |
// ... | |
const viewer = new Autodesk.Viewing.GuiViewer3D(container, { | |
extensions: ['FooExtensionId'], | |
fooExtOptions: { passcode: 'Fido' } | |
}); | |
// ... | |
constructor(viewer, options) { | |
super(viewer, options); | |
console.log(options.fooExtOptions); // { passcode: 'Fido' } | |
} | |
// ... | |
// ASYNC LOADING AND UNLOADING | |
async load() { | |
const loadScript = (src) => new Promise(function(resolve, reject) { | |
const el = document.createElement('script'); | |
el.src = src; | |
el.onload = resolve; | |
el.onerror = reject; | |
document.head.appendChild(el); | |
}); | |
const loadCSS = (href) => new Promise(function(resolve, reject) { | |
const el = document.createElement('link'); | |
el.rel = 'stylesheet'; | |
el.href = href; | |
el.onload = resolve; | |
el.onerror = reject; | |
document.head.appendChild(el); | |
}); | |
await Promise.all([ | |
this.viewer.loadExtension('SomeOtherExtension'), | |
loadScript('https://foo.fohlio.com/public/js/foo.js'), | |
loadCSS('https://foo.fohlio.com/public/css/foo.css') | |
]); | |
return true; | |
} | |
// EXTENSION STATE | |
class FooExtension extends Autodesk.Viewing.Extension { | |
// ... | |
getState(state) { | |
state['fooExtState'] = state['fooExtState'] || {}; | |
state['fooExtState'].passcode = 'Fido'; | |
} | |
restoreState(state) { | |
const fooExtState = state['fooExtState'] || {}; | |
this.passcode = fooExtState.passcode || ''; | |
} | |
// ... | |
} | |
// PROXYING THE FORGE VIEWER | |
const options = { | |
shouldInitializeAuth: false, | |
endpoint: 'http://localhost:3000/forge/api/viewer-proxy', | |
}; | |
const FORGE_HOST = 'https://developer.api.autodesk.com'; | |
router.use('/viewer-proxy/*', function(req, res) { | |
try { | |
if (userAllowedToAccessResource(req)) { | |
const headers = { | |
'Authorization': 'Bearer ' + actualForgeToken | |
}; | |
fetch(FORGE_HOST + req.path, { headers }) | |
.then((res) => { return res.buffer }) | |
.then((buffer) => { return res.send(buffer); }) | |
.catch((err) => { res.status(400).send(err);}); | |
} else { | |
res.status(401).end(); | |
} | |
} catch (err) { | |
console.error(err); | |
res.status(500).send(err.message); | |
} | |
}); | |
/* | |
** LABELING | |
*/ | |
// HTML ELEMENTS on top of the model (SVG, DIV) | |
// AEC DATA | |
doc.downloadAecModelData(); | |
// viewports | |
// let cameraPos = viewports[0].cameraOrienataion; | |
// cameraPos[0] - cameraPos[2] => the camera's forward direction | |
// cameraPos[3] - cameraPos[5] => the camera's up vector | |
// cameraPos[6] - cameraPos[8] => the camera's origin (eye point) | |
// let viewportPos = viewports[0].viewportPosition; | |
// viewportPos[0] - viewportPos[2] => the viewport's low-left corner | |
// viewportPos[3] - viewportPos[5] => the viewport's upper-right corner | |
// DATA VISUALIZATION API | |
const dataVizExt = await viewer.loadExtension('Autodesk.DataVisualization'); | |
// modelInfo.getRoomList().then((rooms) => {}); | |
// modelInfo.getLevel(room); // returns string | |
// modelInfo.getLevelRoomsMap().then((levelRooms) => {}); | |
function createHeatmapForRooms(dataVizExt, model) { | |
const modelInfo = new Autodesk.DataVisualization | |
.Core.ModelStructureInfo(model); | |
let promise = modelInfo.getRoomList(); | |
promise = promise | |
.then((rooms) => { | |
const devices = []; | |
rooms.forEach((room) => { | |
const centroid = room.bounds.getCenter(); | |
devices.push({ | |
id: room.name, | |
position: { x: centroid.x, y: centroid.y, z: room.bounds.min.z }, | |
sensorType: ['temperature', 'humidity'] | |
}); | |
}); | |
return Promise.resolve(devices); | |
}); | |
promise.then((devices) => { | |
modelInfo.generateSurfaceShadingData(devices) | |
.then((shadingData) => { | |
dataVizExt.setupSurfaceShading(model, shadingData) | |
.then(() => { | |
const sensorColors = [ 0x0000ff, 0x00ff00, 0xff0000 ]; | |
const sensorType = 'temperature'; | |
dataVizExt.registerSurfaceShadingColors(sensorType, sensorColors); | |
function getSensorValue(surfaceShadingPoint, sensorType) { | |
const deviceId = surfaceShadingPoint.id; | |
let sensorValue = readSensorValue(deviceId, sensorType); | |
const maxSensorValue = getMaxSensorValue(sensorType); | |
const minSensorValue = getMinSensorValue(sensorType); | |
sensorValue = (sensorValue - minSensorValue) / | |
(maxSensorValue - sensorValue); | |
return clamp(sensorValue, 0.0, 1.0); | |
} | |
modelInfo.getLevelRoomsMap() | |
.then((levelRooms) => { | |
Object.keys(levelRooms).forEach((levelName) => { | |
dataVizExt.renderSurfaceShading( | |
levelName, sensorType, getSensorValue); | |
}); | |
}); | |
}); | |
}); | |
}); | |
} | |
// THREE.js | |
// mesh => geometry + material | |
// scene => meshes + lights | |
// renderScene => scene + camera | |
// Prefer THREE.BufferGeometry to THREE.Geometry; | |
function essentialSetups() { | |
const scene = new THREE.Scene(); | |
const axes = new THREE.AxisHelper(20); | |
scene.add(axes); | |
let geometry = new THREE.PlaneGeometry(60, 20, 1, 1); | |
geometry = new THREE.CubeGeometry(42, 42, 42); | |
geometry = new THREE.SphereGeometry(4, 20, 20); | |
let material = new THREE.MeshBasicMaterial({ | |
color: 0xff0000, wireframe: true | |
}); | |
material = new THREE.MeshLambertMaterial({ | |
color: 0xff0000 | |
}); | |
let mesh = new THREE.Mesh(geometry, material); | |
mesh.castShadow = true; // only for MeshLambertMaterials | |
mesh.position.set(10, 10, 0); | |
scene.add(mesh); | |
const spotLight = new THREE.SpotLight(0xffffff); | |
spotLight.position.set(10, 10, 20); | |
scene.add(spotLight); | |
const camera = new THREE.PerspectiveCamera( | |
45, window.innderWidth / window.innerHeight, 0.1, 1000); | |
camera.position.set(-30, 40, 30); | |
camera.lookAt(scene.position); | |
const renderer = new THREE.WebGLRenderer(); | |
renderer.setClearColor(new THREE.Color(0xeeeeee)); | |
renderer.setSize(window.innerWidth, window.innerHeight); | |
renderer.shadowMapEnabled = true; // for calculating shadows | |
function renderScene() { | |
requestAnimationFramer(renderScene); | |
renderer.render(scene, camera); | |
} | |
$('#viewer').append(renderer.domElement); | |
renderScene(); | |
} | |
// THREE.Scene | |
const scene = new THREE.Scene(); | |
scene.add(mesh); | |
scene.children; | |
scene.getChildByName(name); | |
scene.remove(mesh); | |
scene.traverse((child) => { | |
if (child instanceof THREE.Mesh) ; | |
}); | |
scene.fog = new THREE.Fog(0xffffff, 0.015, 100); | |
scene.overrideMaterial = new THREE.MeshLambertMaterial({ color: 0xff0000 }); | |
// THREE.Geometry | |
// A geometry is a collection of points (vertices) and a number of faces | |
// connecting all those points | |
// THREE.SphereGeometry | |
// THREE.CubeGeometry | |
const vertices = [ | |
new THREE.Vector3(1, 3, 1), | |
new THREE.Vector3(-1, 3, 1), | |
new THREE.Vector3(0, 0, 0), | |
]; | |
const faces = [ | |
new THREE.Face3(0, 1, 2); // creates a face by joining vertice 0, 1, and 2 | |
]; | |
/* THREE.Geometry IS OBSOLETE; USE THREE.BufferGeometry */ | |
let geometry = THREE.Geometry(); | |
geometry.vertices = vertices; | |
geometry.faces = faces; | |
geometry.computeCentroids(); | |
geometry.mergeVertices(); | |
function renderScene() { | |
mesh.geometry.vertices = vertices; | |
mesh.geometry.verticesNeedUpdate = true; | |
mesh.geometry.computeFaceNormals(); | |
} | |
// THREE.Mesh (Only THREE.mesh can be rendered) | |
const mesh = new THREE.Mesh(geometry, material); | |
const meshes = THREE.SceneUtils.createMultiMaterialObject(geometry, materials); | |
const line = new THREE.Line(geometry, new THREE.LineBasicMaterial({ | |
color: 0xff0000, linewidth: 2 | |
})); | |
// Method A | |
mesh.position.x = 42; | |
mesh.position.y = 42; | |
mesh.position.z = 42; | |
mesh.rotation.x = 0.5 * Math.PI; | |
mesh.scale.x = 1.2; | |
mesh.translateX(10); // move the mesh relative to its current positon | |
mesh.translateY(10); | |
mesh.translateZ(10); | |
// Method B | |
mesh.position.set(42, 42, 42); | |
mesh.rotation.set(0.5 * Math.PI, 0, 0); | |
mesh.scale.set(1.2, 0, 0); | |
// Method 3 | |
mesh.position = new THREE.Vector3(42, 42, 42); | |
mesh.rotation = new THREE.Vector3(0.5 * Math.PI, 0, 0); | |
mesh.scale = new THREE.Vector3(1.2, 0, 0); | |
// THREE.Camera | |
let camera = new THREE.PerspectiveCamera(fov, aspect, near, far); | |
camera = new THREE.OrthographicCamera(left, right, top, bottom, near, far); | |
camera.lookAt(new THREE.Vector(x, y, z)); | |
// THREE.JS LIGHT SOURCES | |
let ambientLight = new THREE.AmbientLight( // does not case shadows | |
new THREE.Color('#0c0c0c')); | |
scene.add(ambientLight); | |
let pointLight = new THREE.PointLight( | |
new THREE.Color('#ccffcc')); | |
pointLight.distance = 100; | |
pointLigth.intensity = 1; | |
pointLight.position.set(0, 1, 3); | |
scene.add(pointLight); | |
// THREE.JS MATERIALS | |
LineBasicMaterial | |
LineDashedMaterial | |
new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true }); | |
new THREE.MeshNormalMaterial({ side: THREE.DoubleSide }); | |
let meshes = THREE.SceneUtils.createMultiMaterialObject( | |
geometry, [meshMaterial, wireframeMaterial] | |
); | |
// THREE.JS GEOMETRIES | |
// 2D | |
const geometry = new THREE.Geometry(); | |
geometry.vertices.push(new THREE.Vector3(-10, 0, 0)); | |
geometry.vertices.push(new THREE.Vector3(0, 10, 0)); | |
geometry.vertices.push(new THREE.Vector3(10, 0, 0)); | |
const line = new THREE.Line(geometry, new THREE.LineBasicMaterial({ color: 0xff0000 })); | |
const plane = new THREE.PlaneGeometry(width, height, widthSegments, heightSegments); | |
const circle = new THREE.CircleGeometry(radius, segments, thetaStart, thetaLength); | |
function drawShape() { | |
const shape = new THREE.Shape(); | |
shape.moveTo(x, y); | |
shape.lineTo(x, y); | |
shape.quadraticCurveTo(aCPx, aCPy, x, y); | |
shape.bezierCurveTo(aCPx1, aCPy1, aCPx2, aCPy2, x, y); | |
shape.splineThru([ | |
new THREE.Vector2(32, 30), | |
new THREE.Vector2(28, 20), | |
new THREE.Vector2(30, 10) | |
]); | |
shape.arc(aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise); | |
shape.absArc(aX, aY, aRadius, sStartAngle, aEndAngle, aClockwise); | |
shape.ellipse(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise); | |
shape.absellipse(aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise); | |
return shape; | |
} | |
const shapeGeometry = new THREE.ShapeGeometry(drawShape()); | |
// 3D | |
const cube = new THREE.CubeGeometry(widthX, heightY, depthZ, | |
widthSegments = 1, heightSegments = 1, | |
depthSegments = 1); | |
const sphere = new THREE.SphereGeometry(radius = 5, | |
widthSegment = 8, heightSegments = 6, | |
phiStart = 0, phiLength = 2 * Math.PI, | |
thetaStart = 0, thetaLength = Math.PI); | |
const cylinder = new THREE.CylinderGeometry(radiusTop = 20, radiusBottom = 20, | |
height = 100, segmentsX = 8, | |
segmentsY = 1, openEnded = false); | |
const torus = new THREE.TorusGeometry(radius = 100, tube = 40, radialSegments = 8, | |
tubularSegments = 6, arc = 2 * Math.PI); | |
const torusKnot = new THREE.TorusKnotGeometry(radius = 100, tube = 40, | |
radialSegments = 64, | |
tubularSegments = 8, | |
p = 2, q = 3, heightScale = 1); | |
const polyhedron = new THREE.PolyhedronGeometry(vertices, faces, radius = 1, | |
details = 1); | |
const octahedron = new THREE.OctahedronGeometry(); | |
const tetrahedron = new THREE.TetrahedronGeometry(); | |
const convex = new THREE.ConvexGeometry(); | |
const lathe = new THREE.LatheGeometry(); | |
const extrude = new THREE.ExtrudeGeometry(); | |
const tube = new THREE.TubeGeometry(); | |
const parametric = new THREE.ParametricGeometry(); | |
const text = new THREE.TextGeometry(); | |
// Convert a ttf font into typeface.js | |
// gero3.github.io/facetype.js/ c:\windows\fonts | |
// self._typeface_js = { faces: THREE.FontUtils.faces, loadFace: THREE.FontUtils.loadFace }; | |
// <script src="js/arialRegular.facetype.js"></script> | |
let geometry = new THREE.TextGeometry('Foo', { | |
font: 'arial', | |
weight: 'normal', | |
style: 'normal', | |
size: 25, | |
height: 5, | |
curveSegments: 3 | |
}); | |
// LOADING GEOMETERIES FROM EXTERNAL RESOURCES | |
// JSON | |
// <script src="GeometryExporter.js"></script> | |
function saveGeometryLocally(key, geometry) { | |
const exporter = new THREE.GeometryExporter(); | |
const parsedGeometry = exporter.parse(geometry); | |
localStorage.setItem(key, JSON.stringify(parsedGeometry)); | |
} | |
function loadGeometryBack(key) { | |
const result = localStorage.getItem(key); | |
if (!result) { return null; } | |
const geomJson = JSON.parse(result); | |
const loader = new THREE.JSONLoader(); | |
return loader.parse(geomJson); | |
} | |
// <script src="SceneExporter.js"></script> | |
function saveSceneLocally(key, scene) { | |
const exporter = new THREE.SceneExporter(); | |
const parsedGeometry = exporter.parse(scene); | |
const sceneJson = JSON.stringify(parsedGeometry); | |
localStorage.setItem(key, sceneJson); | |
} | |
function localSceneBack(key) { | |
const sceneJson = localStorage.getItem(key); | |
if (!sceneJson) { return null; } | |
const loader = new THREE.SceneLoader(); | |
sceneLoader.parse(JSON.parse(sceneJson), function (e) { | |
scene = e.scene; | |
}, '.'); // '.' defines the relative URL for other assets such as images | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
LocationCurve lc = wall.Location as LocationCurve; | |
Transform curveTransform = lc.Curve.ComputeDerivatives(0.5, true); | |
XYZ origin = curveTransform.Origin; | |
XYZ viewDirection = curveTransform.BasisX.Normalize(); | |
XYZ normal = viewDirection.CrossProduct(XYZ.BasisZ).Normalize(); | |
BoundingBoxXYZ sectionBox = new BoundingBox(); | |
sectionBox.Transform = transform; | |
sectionBox.Min = new XYZ(-10, 0, 0); | |
sectionBox.Max = new XYZ(10, 12, 5); | |
/** | |
Object <= APIObject <= GeometryObject | |
<= Curve | |
<= Arc | |
<= CylindricalHelix | |
<= Ellipse | |
<= HermiteSpline | |
<= Line | |
<= NurbSpline | |
<= Edge | |
<= Face | |
<= ConicalFace | |
<= CylindricalFace | |
<= HermiteFace | |
<= PlanarFace | |
<= RevolvedFace | |
<= RuledFace | |
IEnumerable<GeometryObject> <= GeometryElement | |
<= GeometryInstance (Nested GeometryObjects and GeometryInstances) | |
<= Mesh | |
<= Point | |
<= PolyLine | |
<= Profile | |
<= Solid | |
**/ | |
DB.Options options = new Options(); | |
// To create transient geometry objects | |
GeometryCreationUtilities // no transaction is necessary | |
BooleanOperationUtils | |
HostObjectUtils | |
BRepBuilder | |
TessellatedShapeBuilder | |
// Revit has a left-handed, Z-up coordinate system. | |
// TRANSFORMATION OF ELEMENTS | |
// Transform represents a transformation of the affine three-space. | |
// Positive angles rotate anticlockwise | |
Transform.BasisX // => a tangent vector | |
Transform.BasisY // => a normal vector | |
Transform.BasisZ // => a binormal vector | |
Transform transform = Transform.Identity; | |
transform.Origin = origin; | |
transform.BasisX = normal; | |
transform.BasisY = XYZ.BasisZ; | |
transform.BasisZ = normal.CrossProduct(XYZ.Basis).Normalize(); | |
var transformedSolid = SolidUtils.CreateTransformed(solid, transform); | |
ElementTransformUtils.CopyElement(); // from links to the active doc | |
ElementTransformUtils.MoveElement() | |
ElementTransformUtils.RotateElement() | |
ElementTransformUtils.MirrorElement() | |
ElementTransformUtils.GetTransformFromViewToView(srcView, dstView); | |
// ElementIntersectsSolidFilter | |
// Typically transformations are right-handed, but mirror operations | |
// will produce left-handed coordinate systems. Furthermore, Revit | |
// can produce left-handed coordinate systems via flip operations | |
// on certain elements. | |
FamilyInstance inst = GetFamliyInstnace(); | |
XYZ orientation = inst.FacingOrientation; | |
// The head-to-tail method is a graphical way to add vectors | |
// XYZ point; | |
// XYZ u = XYZ.BasisZ; | |
// double dist = 400; | |
// XYZ translatedPoint = point * dist + u; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Trace = System.Diagnostics.Trace; | |
[Autodesk.Revit.Attributes.Journaling(Autodesk.Revit.Attributes.JournalingMode.NoCommandData)] | |
[Autodesk.Revit.Attributes.Transaction(Autodesk.Revit.Attributes.TransactionMode.Manual)] | |
[Autodesk.Revit.Attributes.Regeneration(Autodesk.Revit.Attributes.RegenerationOption.Manual)] | |
class ClassName : Autodesk.Revit.UI.IExternalCommand | |
{ | |
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements) { | |
// Add an EventLogTraceListener object | |
System.Diagnostics.Trace.Listeners.Add( | |
new System.Diagnostics.EventLogTraceListener("Application")); | |
// Lay the hands on the active document | |
UIDocument uidoc = commandData.Application.ActiveUIDocument; | |
Document doc = uidoc.Document; | |
// Set up a timer | |
Timing myTimer = new Timing(); | |
myTimer.StartTime(); | |
try { | |
return Result.Succeeded; | |
} | |
catch (Autodesk.Revit.Exceptions.OperationCanceledException) { | |
return Result.Cancelled; | |
} | |
catch (Exception ex) { | |
TaskDialog.Show("Exception", | |
string.Format("{0}\n{1}", ex.Message, ex.StackTrace)); | |
System.Diagnostics.Trace.Write(string.Format("{0}\n{1}", | |
ex.Message, ex.StackTrace)); | |
return Result.Failed; | |
} | |
finally { | |
myTimer.StopTime(); | |
System.Diagnostics.Trace | |
.Write(string.Format("Time elapsed: {0}s", | |
myTimer.Duration.TotalSeconds)); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define DEBUG | |
static EventLog log=new EventLog | |
{ | |
Log="Application", | |
Source="Application" | |
}; | |
EventLogTraceListener eventLogTraceListener= | |
new EventLogTraceListener(log); | |
TraceSwitch generalSwitch= | |
new TraceSwitch("General", "Entire macro"); | |
generalSwitch.Level=TraceLevel.Verbose; | |
// Get the hold of the active document | |
Document doc=this.ActiveUIDocument.Document; | |
Selection sel=this.ActiveUIDocument.Selection; | |
// Add the EventLogTraceListener | |
Trace.Listeners.Add(eventLogTraceListener); | |
try | |
{ | |
Trace.WriteLineIf(generalSwitch.TraceVerbose, "Hello, World!"); | |
} | |
catch(Autodesk.Revit.Exceptions.OperationCanceledException) | |
{ | |
} | |
catch(Exception ex) | |
{ | |
Trace.WriteLineIf(generalSwitch.TraceError,string.Format("StackTrace:\n{0}\nMessage:\n{1}", | |
ex.StackTrace, ex.Message)); | |
TaskDialog.Show("Exception",string.Format("StackTrace:\n{0}\nMessage:\n{1}", | |
ex.StackTrace, ex.Message)); | |
} | |
finally | |
{ | |
Trace.Flush(); | |
Trace.Close(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
WORKSETS | |
Z-LINKED-AIM-B1 | |
Z-LINKED-SIM-B3 | |
Z-LINKED-BSIM-ECHV | |
Z-LINKED-BSIM-ECLV | |
Workset1 | |
Shared Levels and Grids | |
WALLS | |
F1-F2-<F3>-[<F4>]-[<F5>]-[<F6>] | |
F1: | |
E - Exterior | |
I - Interior | |
F2: | |
Fire resistance classes | |
F3 - Fn: | |
<RC200> - Reinforced Concrete 200 mm | |
Examples: | |
I(E)-REI60-<RC200> | |
BROWSER ORGANISATION | |
C-[COORDINATION] | |
D-[DOCUMENTATION] | |
W-[WORKING] | |
P-[PRESENTATION] | |
Z-[MISCELLANEOUS] | |
// Parameters | |
VW_FOLDER | |
VW_SUBFOLDER | |
VIEW NAMING | |
F1-F2-F3-F4 | |
e.g. | |
D-XX-L01(0.000)-FL01 | |
W-XX-B01(-3.000)-FL03 | |
W-(01-08)-XX-SEC01 | |
W-(А-Г)-XX-ELEV04 | |
Field 1 (Subcategory): | |
C-[COORDINATION] | |
D-[DOCUMENTATION] | |
P-[PRESENTATION] | |
W-[WORKING] | |
Field 2 (Zone/Area): | |
LG1 - Basement under Buildings 1A and 1B | |
LG2 - Basement under building 2 | |
LG3 - Basement under building 3 | |
B1 - Building 1 | |
B2 - Building 2 | |
B3 - Building 3 | |
TH - Townhouse | |
Field 3 (Level): | |
B02(-6.000) - Basement Level 2 at -6.000 | |
B01(-3.300) - Basement Level 1 at -3.300 | |
GL(-0.500) - Ground Level at -0.500 | |
P01(1.000) - Podium Level 1 at +1.000 | |
P02(3.000) - Podium Level 2 at +3.000 | |
L01(0.000) - Level 1 at 0.000 | |
L02(3.000) - Level 2 at +3.000 | |
M02(5.000) - Mezzanine above level 1 at +5.000 | |
Field 4(Comments) | |
Reserved for comments |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
User Addins: | |
%appdata%\Autodesk\Revit\Addins\20XX | |
Machine Addins (for all users of the machine): | |
C:\ProgramData\Autodesk\Revit\Addins\20XX | |
Addins packaged for the Autodesk Exchange store: | |
C:\ProgramData\Autodesk\ApplicationPlugins\ | |
Autodesk servers and services: | |
C:\Program Files\Autodesk\Revit 20XX\AddIns\ | |
Revit journals | |
C:\Users\username\AppData\Local\Autodesk\Revit\Autodesk Revit 20XX\Journals | |
Omniclass Taxonomy | |
C:\Users\username\AppData\Roaming\Autodesk\Revit\Autodesk Revit 20XX\OmniClassTaxonomy.txt | |
Uniformat Classification | |
C:\ProgramData\Autodesk\RVT 2020\Libraries\US Metric\UniformatClassifications.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
WHAT IS REVIT? | |
REVIT ELEMENT CLASSIFICATIONS/REVIT ELEMENT HIERARCHY | |
ELEMENT PROPERTIES | |
SCHEDULING AND AREA PLANS | |
FAMILY EDITOR | |
CLASSIFICATION SYSTEMS IN REVIT | |
ANNOTATING DESIGN | |
GROUPS | |
DESIGN OPTIONS | |
PHASING | |
WHAT IS REVIT? | |
Revit, which stands for 'Revise it', is a BIM application for authoring parametric 3D models that generate geometry with embedded information for the design and construction of buildings and infastructure. It is from these intelligent models that plans, elevations, sections, perspectives details, and schedules - all of the necessary instruments to document the design of a building - can be derived. Drawings created using Revit are live views extracted from virtual building models. These models are a compilation of intelligent components that contain not only geometric attributes but also data informing decisions about the building at every stage of the process, including occupancy. | |
Elements in Revit are managed and manipulated through a series of parameters. These elements have bidirectional associativity, allowing the user to change the 2D views to change the 3D model. If a door is moved in a plan, that door is moved in all other views. When contrasted with traditional CAD tools, Revit gives the opportunity to more easily input, manage and export project data for project coordination and execution. | |
ELEMENT PROPERTIES | |
using the properties palette | |
type and instance parameters | |
Type parameters control information about every element of the same type. For instance, ... | |
Instance parameters control only the instances that are selected. | |
PARAMETERS | |
builtin | |
project | |
family | |
shared | |
global | |
CLASSIFICATION SYSTEMS IN REVIT | |
Omniclass (only families) | |
Masterclass (keynotes) | |
Uniformat (assembly code) | |
HANDY PHRASES | |
revit for energy simulations | |
the heating, ventilation, and air-conditioning (HVAC) system | |
solar heat gain | |
the number of occupants and their activity levels | |
sunshading devices | |
daylight dimming | |
lighting levels | |
Understand a BIM workflow and leverage BIM processes. | |
I see here a dead end. | |
Next up, let us look at how to apply Revit tools to ... | |
It helps to understand ... | |
Generate sth on the fly | |
working in the construction phase | |
establish the settings | |
as you can see, the central concept used by ... is | |
in general; as a rule; basically; in essence; | |
to associate x with y | |
the association between x and y | |
x represents y | |
to retrieve data | |
to pull out quantitative data | |
to collaborate with other designers | |
a federated model (architectural, strcutural, mechanical, plumbing, electrical) | |
a host/linked model | |
to run a interference check in revit | |
the revit interference checking process | |
to wrap up | |
data is organized in tables |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Revit.TestRunner | |
// Revit.TestRunner/Main.cs | |
// Main.cs => class Main : IExternalApplication | |
public Result OnStartUp(UIControlledApplication uicapp) { | |
_controller = new RunnerController(); | |
_controller.Start(uicapp); | |
return Result.Succeeded; | |
} | |
// RunnerController | |
void Start(UIControlledApplication uicapp) { | |
_server = new FileServer(FileNames.WatchDirectory); | |
_server.RegisterRoute<NoParameterDto, HomeDto>(String.Empty, ProcessHome, true); | |
_server.StartConcurrentRoutes(); | |
uicapp.OnIdle = (sender, e) => { | |
UIApplication uiapp = sender as UIApplication; | |
_server.ProceedNextNotConcurrent(); | |
}; | |
} | |
// Revit.TestRunner.Shared/Communication/FileNames.cs | |
String WatchDirectory = Path.Combine(Environment.GetFolderPath( | |
Environment.GetSpecialFolder.ApplicationData), "Revit.TestRunner"); // $env:AppData\Revit.TestRunner | |
// Revit.TestRunner.Shared/Communication/Server/FileServer.cs | |
// Revit.TestRunner.Shared/Dto/BaseRequestDto.cs | |
public enum DtoType { | |
NoParameterDto, HomeDto, ExploreRequestDto, | |
ExploreResponseDto, TestRequestDto, TestResponseDto, Unknow | |
} | |
class BaseRequestDto { | |
public DtoType DtoType { get; } | |
public String RequestId { get; set; } | |
public DateTime Timestamp { get; set; } | |
public String ClientName { get; set; } | |
public String ClientVersion { get; set } | |
} | |
class NoParameterDto : BaseRequestDto {} | |
class ExploreRequestDto : BaseRequestDto { | |
public String AssemblyPath { get; set; } | |
} | |
class HomeDto : BaseRequestDto { | |
public String LogFilePath { get; set; } | |
public String RevitVersion { get; set; } | |
public String ExplorePath { get; set; } | |
public String TestPath { get; set; } | |
} | |
class BaseResponseDto { | |
public DtoType DtoType { get; } | |
public String RequestId { get; set; } | |
public DateTime Timestamp { get; set; } | |
public String ThisPath { get; set; } | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment