/// <summary> /// Update a piece of furniture. /// Return true if anything was changed. /// </summary> bool UpdateBimFurniture( DbFurniture f) { Document doc = _uiapp.ActiveUIDocument.Document; bool rc = false; if (!_roomUniqueIdDict.ContainsKey(f.RoomId)) { Debug.Print("Furniture instance '{0}' '{1}'" + " with UniqueId {2} belong to a room from" + " a different model, so ignore it.", f.Name, f.Description, f.Id); return(rc); } Element e = doc.GetElement(f.Id); if (null == e) { Util.ErrorMsg(string.Format( "Unable to retrieve element '{0}' '{1}' " + "with UniqueId {2}. Are you in the right " + "Revit model?", f.Name, f.Description, f.Id)); return(rc); } if (!(e is FamilyInstance)) { Debug.Print("Strange, we received an " + "updated '{0}' '{1}' with UniqueId {2}, " + "which we ignore.", f.Name, f.Description, f.Id); return(rc); } // Convert SVG transform from string to int // to XYZ point and rotation in radians // including flipping of Y coordinates. string svgTransform = f.Transform; char[] separators = new char[] { ',', 'R', 'T' }; string[] a = svgTransform.Substring(1).Split(separators); int[] trxy = a.Select <string, int>(s => int.Parse(s)).ToArray(); double r = Util.ConvertDegreesToRadians( Util.SvgFlipY(trxy[0])); XYZ p = new XYZ( Util.ConvertMillimetresToFeet(trxy[1]), Util.ConvertMillimetresToFeet(Util.SvgFlipY(trxy[2])), 0.0); // Check for modified transform LocationPoint lp = e.Location as LocationPoint; XYZ translation = p - lp.Point; double rotation = r - lp.Rotation; bool modifiedTransform = (0.01 < translation.GetLength()) || (0.01 < Math.Abs(rotation)); // Check for modified properties List <string> modifiedPropertyKeys = new List <string>(); Dictionary <string, string> dbdict = f.Properties; Dictionary <string, string> eldict = Util.GetElementProperties(e); Debug.Assert(dbdict.Count == eldict.Count, "expected equal dictionary length"); string key_db; // JavaScript lowercases first char string val_db; // remove prepended "r " or "w " string val_el; foreach (string key in eldict.Keys) { Parameter pa = e.LookupParameter(key); Debug.Assert(null != pa, "expected valid parameter"); if (Util.IsModifiable(pa)) { key_db = Util.Uncapitalise(key); Debug.Assert(dbdict.ContainsKey(key_db), "expected same keys in Revit model and cloud database"); val_db = dbdict[key_db].Substring(2); if (StorageType.String == pa.StorageType) { val_el = pa.AsString() ?? string.Empty; } else { Debug.Assert(StorageType.Integer == pa.StorageType, "expected only string and integer parameters"); val_el = pa.AsInteger().ToString(); } if (!val_el.Equals(val_db)) { modifiedPropertyKeys.Add(key); } } } if (modifiedTransform || 0 < modifiedPropertyKeys.Count) { using (Transaction tx = new Transaction( doc)) { tx.Start("Update Furniture and " + "Equipmant Instance Placement"); if (.01 < translation.GetLength()) { ElementTransformUtils.MoveElement( doc, e.Id, translation); } if (.01 < Math.Abs(rotation)) { Line axis = Line.CreateBound(lp.Point, lp.Point + XYZ.BasisZ); ElementTransformUtils.RotateElement( doc, e.Id, axis, rotation); } foreach (string key in modifiedPropertyKeys) { Parameter pa = e.LookupParameter(key); key_db = Util.Uncapitalise(key); val_db = dbdict[key_db].Substring(2); if (StorageType.String == pa.StorageType) { pa.Set(val_db); } else { try { int i = int.Parse(val_db); pa.Set(i); } catch (System.FormatException) { } } } tx.Commit(); rc = true; } } return(rc); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; if (null == doc) { Util.ErrorMsg("Please run this command in a valid" + " Revit project document."); return(Result.Failed); } // Iterate over all pre-selected rooms Selection sel = uidoc.Selection; ICollection <ElementId> ids = sel.GetElementIds(); if (0 < ids.Count) { foreach (ElementId id in ids) { if (!(doc.GetElement(id) is Room)) { Util.ErrorMsg("Please pre-select only room" + " elements before running this command."); return(Result.Failed); } } } // If no rooms were pre-selected, // prompt for post-selection if (null == ids || 0 == ids.Count) { IList <Reference> refs = null; try { refs = sel.PickObjects(ObjectType.Element, new RoomSelectionFilter(), "Please select rooms."); } catch (Autodesk.Revit.Exceptions .OperationCanceledException) { return(Result.Cancelled); } ids = new List <ElementId>( refs.Select <Reference, ElementId>( r => r.ElementId)); } // Upload selected rooms to cloud database foreach (ElementId id in ids) { UploadRoom(doc, doc.GetElement(id) as Room); } DbUpdater.SetLastSequence(); return(Result.Succeeded); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; //IWin32Window revit_window // = new JtWindowHandle( // ComponentManager.ApplicationWindow ); // pre-2020 IWin32Window revit_window = new JtWindowHandle(uiapp.MainWindowHandle); // 2020 if (null == doc) { Util.ErrorMsg("Please run this command in a valid" + " Revit project document."); return(Result.Failed); } // Interactive sheet selection. FrmSelectSheets form = new FrmSelectSheets(doc); if (DialogResult.OK == form.ShowDialog( revit_window)) { List <ViewSheet> sheets = form.GetSelectedSheets(); int n = sheets.Count; string caption = Util.PluralString( n, "Sheet") + " Selected"; string msg = string.Join(", ", sheets.Select <Element, string>( e => Util.SheetDescription(e))) + "."; // Determine all floor plan views displayed // in the selected sheets. Dictionary <View, int> views = new Dictionary <View, int>( new ElementEqualityComparer()); int nFloorPlans = 0; foreach (ViewSheet sheet in sheets) { foreach (View v in sheet.GetAllPlacedViews() .Select <ElementId, View>(id => doc.GetElement(id) as View)) { if (!views.ContainsKey(v)) { if (IsFloorPlan(v)) { ++nFloorPlans; } views.Add(v, 0); } ++views[v]; } } msg += (1 == n) ? "\nIt contains" : "\nThey contain"; n = views.Count; msg += string.Format( " {0} including {1}: ", Util.PluralString(n, "view"), Util.PluralString(nFloorPlans, "floor plan")); msg += string.Join(", ", views.Keys.Select <Element, string>( e => e.Name)) + "."; Util.InfoMsg2(caption, msg, false); // Determine all categories occurring // in the views displayed by the sheets. List <Category> categories = new List <Category>( new CategoryCollector(views.Keys).Keys); // Sort categories alphabetically by name // to display them in selection form. categories.Sort( delegate(Category c1, Category c2) { return(string.Compare(c1.Name, c2.Name)); }); // Interactive category selection. FrmSelectCategories form2 = new FrmSelectCategories(categories); if (DialogResult.OK == form2.ShowDialog( revit_window)) { categories = form2.GetSelectedCategories(); n = categories.Count; caption = Util.PluralString(n, "Category") + " Selected"; msg = string.Join(", ", categories.Select <Category, string>( e => e.Name)) + "."; Util.InfoMsg2(caption, msg, false); // Convert category list to a dictionary for // more effective repeated lookup. // //Dictionary<ElementId, Category> catLookup = // categories.ToDictionary<Category, ElementId>( // c => c.Id ); // // No, much better: set up a reusable element // filter for the categories of interest: ElementFilter categoryFilter = new LogicalOrFilter(categories .Select <Category, ElementCategoryFilter>( c => new ElementCategoryFilter(c.Id)) .ToList <ElementFilter>()); // Instantiate a container for all // cloud data repository content. SheetModelCollections modelCollections = new SheetModelCollections( DbUpload.GetProjectInfo(doc).Id); foreach (ViewSheet sheet in sheets) { // Define preview form caption. caption = "Sheet and Viewport Loops - " + Util.SheetDescription(sheet); // This is currently not used for anything. ListSheetAndViewTransforms(sheet); // Determine the polygon loops representing // the size and location of given sheet and // the viewports it contains. JtLoops sheetViewportLoops = GetSheetViewportLoops( modelCollections, sheet); // Determine graphics for family instances, // their symbols and other BIM parts. GetBimGraphics(modelCollections, sheet, categoryFilter); // Display sheet and viewports with the // geometry retrieved in a temporary GeoSnoop // form generated on the fly for debugging // purposes. Bitmap bmp = GeoSnoop.DisplaySheet( sheet.Id, sheetViewportLoops, modelCollections); GeoSnoop.DisplayImageInForm( revit_window, caption, false, bmp); // Upload data to the cloud database. DbUpload.DbUploadSheet(sheet, sheetViewportLoops, modelCollections); } DbUpdater.SetLastSequence(); } } return(Result.Succeeded); }
/// <summary> /// Upload the selected rooms and the furniture /// they contain to the cloud database. /// </summary> public static void UploadRoom( Document doc, Room room) { BoundingBoxXYZ bb = room.get_BoundingBox(null); if (null == bb) { Util.ErrorMsg(string.Format("Skipping room {0} " + "because it has no bounding box.", Util.ElementDescription(room))); return; } JtLoops roomLoops = GetRoomLoops(room); ListLoops(room, roomLoops); List <Element> furniture = GetFurniture(room); // Map symbol UniqueId to symbol loop Dictionary <string, JtLoop> furnitureLoops = new Dictionary <string, JtLoop>(); // List of instances referring to symbols List <JtPlacement2dInt> furnitureInstances = new List <JtPlacement2dInt>( furniture.Count); int nFailures; foreach (FamilyInstance f in furniture) { FamilySymbol s = f.Symbol; string uid = s.UniqueId; if (!furnitureLoops.ContainsKey(uid)) { nFailures = 0; JtLoops loops = GetPlanViewBoundaryLoops( f, ref nFailures); if (0 < nFailures) { Debug.Print("{0}: {1}", Util.ElementDescription(f), Util.PluralString(nFailures, "extrusion analyser failure")); } ListLoops(f, loops); if (0 < loops.Count) { // Assume first loop is outer one furnitureLoops.Add(uid, loops[0]); } } furnitureInstances.Add( new JtPlacement2dInt(f)); } IWin32Window revit_window = new JtWindowHandle( ComponentManager.ApplicationWindow); string caption = doc.Title + " : " + doc.GetElement(room.LevelId).Name + " : " + room.Name; Bitmap bmp = GeoSnoop.DisplayRoom(roomLoops, furnitureLoops, furnitureInstances); GeoSnoop.DisplayImageInForm(revit_window, caption, false, bmp); DbUpload.DbUploadRoom(room, furniture, roomLoops, furnitureLoops); }
public Result Execute( ExternalCommandData commandData, ref string message, ElementSet elements) { UIApplication uiapp = commandData.Application; UIDocument uidoc = uiapp.ActiveUIDocument; Application app = uiapp.Application; Document doc = uidoc.Document; if (null == doc) { Util.ErrorMsg("Please run this command in a valid" + " Revit project document."); return(Result.Failed); } if (-1 == DbUpdater.LastSequence) { DbUpdater.SetLastSequence(); return(Result.Succeeded); } //// Retrieve all room unique ids in model: //FilteredElementCollector rooms // = new FilteredElementCollector( doc ) // .OfClass( typeof( SpatialElement ) ) // .OfCategory( BuiltInCategory.OST_Rooms ); //IEnumerable<string> roomUniqueIds // = rooms.Select<Element, string>( // e => e.UniqueId ); ////string ids = "?keys=[%22" + string.Join( //// "%22,%22", roomUniqueIds ) + "%22]"; //// Retrieve furniture transformations //// after last sequence number: //CouchDatabase db = new RoomEditorDb().Db; //ChangeOptions opt = new ChangeOptions(); //opt.IncludeDocs = true; //opt.Since = LastSequence; //opt.View = "roomedit/map_room_to_furniture"; //// I tried to add a filter to this view, but //// that is apparently not supported by the //// CouchDB or DreamSeat GetChanges functionality. ////+ ids; // failed attempt to filter view by room id keys //// Specify filter function defined in //// design document to get updates ////opt.Filter = //CouchChanges<DbFurniture> changes // = db.GetChanges<DbFurniture>( opt ); //CouchChangeResult<DbFurniture>[] results // = changes.Results; //DbUpdater updater = new DbUpdater( // doc, roomUniqueIds ); //foreach( CouchChangeResult<DbFurniture> result // in results ) //{ // updater.UpdateBimFurniture( result.Doc ); // LastSequence = result.Sequence; //} //DbUpdater updater = new DbUpdater( doc ); DbUpdater updater = new DbUpdater(uiapp); updater.UpdateBim(); return(Result.Succeeded); }