/// <summary> /// Returns a list of class types to use as exclusions /// </summary> /// <param name="CobiePickLists">COBieSheet of COBiePickListsRow</param> /// <param name="reqType">Type object to filter selection on</param> /// <param name="colIndex">column index to get required classes from</param> /// <returns></returns> private List <Type> GetExcludedTypes(COBieSheet <COBiePickListsRow> CobiePickLists, Type reqType, int colIndex) { List <Type> classTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).Where(t => t.IsSubclassOf(reqType)).ToList(); if ((CobiePickLists.RowCount > 0) && (classTypes.Count > 0) ) { for (int i = 0; i < CobiePickLists.RowCount; i++) { COBiePickListsRow row = CobiePickLists[i]; var colvalue = row[colIndex]; if ((colvalue != null) && (!string.IsNullOrEmpty(colvalue.CellValue)) ) { IfcType ifcType; if (IfcMetaData.TryGetIfcType(colvalue.CellValue.Trim().ToUpper(), out ifcType)) { classTypes.Remove(ifcType.Type); } } } } return(classTypes); }
internal bool AppliesTo(IPersistIfcEntity SelectedEntity) { IfcType ifcType = IfcMetaData.IfcType(ConceptRoot.applicableRootEntity.ToUpperInvariant()); IfcType seltype = IfcMetaData.IfcType(SelectedEntity); return(ifcType == seltype || ifcType.IfcSubTypes.Contains(seltype)); }
private void FillTypeData() { if (_typeProperties.Count > 0) { return; //don't fill unless empty } var ifcObj = _entity as IfcObject; if (ifcObj == null) { return; } var typeEntity = ifcObj.GetDefiningType(); if (typeEntity == null) { return; } var ifcType = IfcMetaData.IfcType(typeEntity); _typeProperties.Add(new PropertyItem { Name = "Type", Value = ifcType.Type.Name }); _typeProperties.Add(new PropertyItem { Name = "Ifc Label", Value = "#" + typeEntity.EntityLabel }); _typeProperties.Add(new PropertyItem { Name = "Name", Value = typeEntity.Name }); _typeProperties.Add(new PropertyItem { Name = "Description", Value = typeEntity.Description }); _typeProperties.Add(new PropertyItem { Name = "GUID", Value = typeEntity.GlobalId }); _typeProperties.Add(new PropertyItem { Name = "Ownership", Value = typeEntity.OwnerHistory.OwningUser + " using " + typeEntity.OwnerHistory.OwningApplication.ApplicationIdentifier }); //now do properties in further specialisations that are text labels foreach (var pInfo in ifcType.IfcProperties.Where (p => p.Value.IfcAttribute.Order > 4 && p.Value.IfcAttribute.State != IfcAttributeState.DerivedOverride) ) //skip the first for of root, and derived and things that are objects { var val = pInfo.Value.PropertyInfo.GetValue(typeEntity, null); if (!(val is ExpressType)) { continue; } var pi = new PropertyItem { Name = pInfo.Value.PropertyInfo.Name, Value = ((ExpressType)val).ToPart21 }; _typeProperties.Add(pi); } }
/// <summary> /// Create an instance of an group object via a string name /// </summary> /// <param name="groupTypeName">String holding object type name we want to create</param> /// <param name="model">Model object</param> /// <returns></returns> public IfcSystem GetGroupInstance(string groupTypeName) { groupTypeName = groupTypeName.Trim().ToUpper(); IfcType ifcType; IfcSystem ifcSystem = null; if ((IfcMetaData.TryGetIfcType(groupTypeName, out ifcType)) && (typeof(IfcSystem).IsAssignableFrom(ifcType.Type)) //check it is a system class name ) { MethodInfo method = typeof(IXbimInstanceCollection).GetMethod("New", Type.EmptyTypes); MethodInfo generic = method.MakeGenericMethod(ifcType.Type); var eleObj = generic.Invoke(Model.Instances, null); if (eleObj is IfcSystem) { ifcSystem = (IfcSystem)eleObj; } } if (ifcSystem == null) { ifcSystem = Model.Instances.New <IfcSystem>(); } return(ifcSystem); }
public bool Resolve(ConcurrentDictionary <int, IPersistIfcEntity> references) { IPersistIfcEntity entity; if (references.TryGetValue(ReferenceEntityLabel, out entity)) { PropertyValue pv = new PropertyValue(); pv.Init(entity); try { ReferencingEntity.IfcParse(ReferencingPropertyId, pv); return(true); } catch (Exception) { IfcType ifcType = IfcMetaData.IfcType(ReferencingEntity); XbimModel.Logger.ErrorFormat("Data Error. Cannot set the property = {0} of entity #{1} = {2} to entity #{3}, schema violation. Ignored", ifcType.IfcProperties[ReferencingPropertyId + 1].PropertyInfo.Name, ReferencingEntity.EntityLabel, ReferencingEntity.GetType().Name, ReferenceEntityLabel); return(false); } } else { return(false); } }
private void LoadCobieMaps() { _cobieFieldMap = new Dictionary <string, string[]>(); var configMap = new ExeConfigurationFileMap { ExeConfigFilename = "COBieAttributes.config" }; var config = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel.None); var cobiePropertyMaps = (AppSettingsSection)config.GetSection("COBiePropertyMaps"); foreach (KeyValueConfigurationElement keyVal in cobiePropertyMaps.Settings) { var values = keyVal.Value.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries); _cobieFieldMap.Add(keyVal.Key, values); foreach (var cobieProperty in values) //used to keep a list of properties that are reserved for COBie and not written out as attributes { _cobieProperties.Add(cobieProperty); } } var ifcElementInclusion = (AppSettingsSection)config.GetSection("IfcElementInclusion"); foreach (KeyValueConfigurationElement keyVal in ifcElementInclusion.Settings) { if (String.Compare(keyVal.Value, "YES", StringComparison.OrdinalIgnoreCase) == 0) { var includedType = IfcMetaData.IfcType(keyVal.Key.ToUpper()); if (includedType != null) { _includedTypes.Add(includedType); } } } }
internal bool TrySetObjectValue(IPersistIfc host, int paramIndex, int refID) { if (_deferListItems) { return(false); } try { IPersistIfc refEntity; if (_entities.TryGetValue(refID, out refEntity) && host != null) { _propertyValue.Init(refEntity); (host).IfcParse(paramIndex, _propertyValue); return(true); } } catch (Exception) { if (_errorCount > MaxErrorCount) { throw new Exception("Too many errors in file, parser execution terminated"); } _errorCount++; IfcType ifcType = IfcMetaData.IfcType(host); string propertyName = paramIndex + 1 > ifcType.IfcProperties.Count ? "[UnknownProperty]" : ifcType.IfcProperties[paramIndex + 1].PropertyInfo.Name; Logger.ErrorFormat("Entity #{0,-5} {1}, error at parameter {2}-{3}", refID, ifcType.Type.Name.ToUpper(), paramIndex + 1, propertyName); } return(false); }
/// <summary> /// /// </summary> /// <param name="model"></param> /// <returns></returns> public IEnumerable <int> Run(XbimModel model) { foreach (var label in _entityLabelsToParse) { if (_transverse) { yield return(label); } else if (_queryCommand.Trim() == "") { yield return(label); } var entity = model.Instances[label]; if (entity != null) { IfcType ifcType = IfcMetaData.IfcType(entity); // directs first SquareBracketIndexer sbi = new SquareBracketIndexer(_queryCommand); var prop = ifcType.IfcProperties.Where(x => x.Value.PropertyInfo.Name == sbi.Property).FirstOrDefault().Value; if (prop == null) // otherwise test inverses { prop = ifcType.IfcInverses.Where(x => x.PropertyInfo.Name == sbi.Property).FirstOrDefault(); } if (prop != null) { object propVal = prop.PropertyInfo.GetValue(entity, null); if (propVal != null) { if (prop.IfcAttribute.IsEnumerable) { IEnumerable <object> propCollection = propVal as IEnumerable <object>; if (propCollection != null) { propCollection = sbi.GetItem(propCollection); foreach (var item in propCollection) { IPersistIfcEntity pe = item as IPersistIfcEntity; if (pe != null) { yield return(pe.EntityLabel); } } } } else { IPersistIfcEntity pe = propVal as IPersistIfcEntity; if (pe != null && sbi.Index < 1) // index is negative (not specified) or 0 { yield return(pe.EntityLabel); } } } } } } }
public XbimMeshFragment(int pStart, int tStart, Type productType, int productLabel, int geometryLabel, short modelId) { this.StartPosition = EndPosition = pStart; this.StartTriangleIndex = EndTriangleIndex = tStart; this._entityTypeId = IfcMetaData.IfcTypeId(productType); this.EntityLabel = productLabel; this.GeometryId = geometryLabel; this.ModelId = modelId; }
private void FillObjectData() { if (_objectProperties.Count > 0) { return; //don't fill unless empty } if (_entity != null) { IfcType ifcType = IfcMetaData.IfcType(_entity); _objectProperties.Add(new PropertyItem() { Name = "Type", Value = ifcType.Type.Name }); _objectProperties.Add(new PropertyItem() { Name = "Ifc Label", Value = "#" + _entity.EntityLabel }); IfcRoot root = _entity as IfcRoot; if (root != null) //should always be really { _objectProperties.Add(new PropertyItem() { Name = "Name", Value = root.Name }); _objectProperties.Add(new PropertyItem() { Name = "Description", Value = root.Description }); _objectProperties.Add(new PropertyItem() { Name = "GUID", Value = root.GlobalId }); _objectProperties.Add(new PropertyItem() { Name = "Ownership", Value = root.OwnerHistory.OwningUser.ToString() + " using " + root.OwnerHistory.OwningApplication.ApplicationIdentifier }); //now do properties in further specialisations that are text labels foreach (var pInfo in ifcType.IfcProperties.Where (p => p.Value.IfcAttribute.Order > 4 && p.Value.IfcAttribute.State != IfcAttributeState.DerivedOverride) ) //skip the first for of root, and derived and things that are objects { object val = pInfo.Value.PropertyInfo.GetValue(_entity, null); if (val != null && val is ExpressType) //only do express types { PropertyItem pi = new PropertyItem() { Name = pInfo.Value.PropertyInfo.Name, Value = ((ExpressType)val).ToPart21 }; _objectProperties.Add(pi); } } } } }
public static XbimMaterialProvider GetDefaultMaterial(string typeName) { Material mat; IfcType elemType = IfcMetaData.IfcType(typeName.ToUpperInvariant()); while (elemType != null) { if (_defaultMaterials.TryGetValue(elemType.Type.Name, out mat)) { return(new XbimMaterialProvider(mat)); } elemType = elemType.IfcSuperType; } return(null); }
//adds the content of the toAdd to this, it is added as a single mesh fragment, any meshes in toAdd are lost public void Add(IXbimMeshGeometry3D toAdd, int entityLabel, Type ifcType, short modelId) { var startPosition = Positions.Count; var fragment = new XbimMeshFragment(startPosition, TriangleIndexCount, modelId); Positions.AddRange(toAdd.Positions); Normals.AddRange(toAdd.Normals); foreach (var idx in toAdd.TriangleIndices) { TriangleIndices.Add(idx + startPosition); } fragment.EndPosition = PositionCount - 1; fragment.EndTriangleIndex = TriangleIndexCount - 1; fragment.EntityLabel = entityLabel; fragment.EntityTypeId = IfcMetaData.IfcTypeId(ifcType); _meshes.Add(fragment); }
public Int32 StartComparison(XbimModel baseline, XbimModel revision, string filter = "") { Baseline = baseline; Revision = revision; Int32 ret = 0; if (filter == "") { // default behaviour (maintained during code review) is to test only for IfcProducts // WorkingCopyBaseline = Baseline.Instances.OfType <IfcProduct>().ToList <IfcRoot>(); WorkingCopyDelta = Revision.Instances.OfType <IfcProduct>().ToList <IfcRoot>(); //get guids into dictionary var MyTemp = WorkingCopyBaseline.Select(p => new baselineitem { GUID = p.GlobalId, Label = p.EntityLabel, Name = p.Name, MyType = p.GetType() }).ToList(); //list duplicate Guids in Model DuplicateBaseItems.AddRange(MyTemp.GroupBy(k => k.GUID).Where(g => g.Count() > 1).Select(g => g.Key)); if (DuplicateBaseItems.Count > 0) { Message(String.Format("Warning {0} Duplicate Guids found in Model", DuplicateBaseItems.Count)); } var comparer = new VersionGuidComparitor(); var MyDictionary = MyTemp.Distinct <baselineitem>(comparer).ToDictionary(k => k.GUID, v => v); //think GroupBy? ret += StartProductsComparison(); } else { IfcType ot = IfcMetaData.IfcType(filter.ToUpper()); if (ot != null) { if (ot.Type.IsSubclassOf(typeof(IfcRoot))) { WorkingCopyBaseline = new List <IfcRoot>(Baseline.Instances.OfType(filter, false).Cast <IfcRoot>()); WorkingCopyDelta = new List <IfcRoot>(Revision.Instances.OfType(filter, false).Cast <IfcRoot>()); ret += StartProductsComparison(); } } } return(ret); }
private static void TestForClassificationOfIfcFeatureElements(Xbim3DModelContext context) { var excludedTypes = new HashSet <short> { IfcMetaData.IfcType(typeof(IfcFeatureElement)).TypeId, IfcMetaData.IfcType(typeof(IfcOpeningElement)).TypeId, IfcMetaData.IfcType(typeof(IfcProjectionElement)).TypeId }; var shapeInstances = context.ShapeInstances().Where(s => excludedTypes.Contains(s.IfcTypeId) && // ifcfeatures s.RepresentationType != XbimGeometryRepresentationType.OpeningsAndAdditionsOnly); // that are not classified as OpeningsAndAdditionsOnly Assert.IsFalse(shapeInstances.Any(), "Should not find any shapes of with this classification of typeid and representationType."); }
public Dictionary <string, XbimGeometryHandleCollection> GroupLayers(XbimGeometryHandleCollection InputHandles) { // creates a new dictionary and then fills it by type enumerating the known non-abstract subtypes of Product Dictionary <string, XbimGeometryHandleCollection> result = new Dictionary <string, XbimGeometryHandleCollection>(); IfcType baseType = IfcMetaData.IfcType(typeof(IfcProduct)); foreach (var subType in baseType.NonAbstractSubTypes) { short ifcTypeId = IfcMetaData.IfcTypeId(subType); XbimGeometryHandleCollection handles = new XbimGeometryHandleCollection(InputHandles.Where(g => g.IfcTypeId == ifcTypeId)); // only add the item if there are handles in it if (handles.Count > 0) { result.Add(subType.Name, handles); } } return(result); }
private void SetEntityParameter(string value) { try { if (_currentInstance.Entity != null) { _currentInstance.ParameterSetter(_currentInstance.CurrentParamIndex, _propertyValue); } } catch (Exception) { if (_errorCount > MaxErrorCount) { throw new Exception("Too many errors in file, parser execution terminated"); } _errorCount++; Part21Entity mainEntity = _processStack.Last(); if (mainEntity != null) { IfcType ifcType = IfcMetaData.IfcType(mainEntity.Entity); string propertyName = mainEntity.CurrentParamIndex + 1 > ifcType.IfcProperties.Count ? "[UnknownProperty]" : ifcType.IfcProperties[mainEntity.CurrentParamIndex + 1].PropertyInfo.Name; Logger.ErrorFormat("Entity #{0,-5} {1}, error at parameter {2}-{3} value = {4}", mainEntity.EntityLabel, mainEntity.Entity.GetType().Name.ToUpper(), mainEntity.CurrentParamIndex + 1, propertyName, value); } else { Logger.Error("Unhandled Parser error, in Parser.cs SetEntityParameter"); } } if (_listNestLevel == 0) { _currentInstance.CurrentParamIndex++; _deferListItems = false; } }
private void Init(Type ifcType) { IfcType ifcTypeLookup; if (IfcMetaData.TryGetIfcType(ifcType.Name.ToUpper(), out ifcTypeLookup)) { _type = ifcType; _errLog = new StringWriter(); //create input type from general type of persist entities inParam = Expression.Parameter(typeof(IPersistIfcEntity), "input"); //first condition must be at least type of the input input = Expression.Convert(inParam, ifcType); } else { FatalErr("Input type is not IFC type"); } }
internal override void EndEntity() { Part21Entity p21 = _processStack.Pop(); Debug.Assert(_processStack.Count == 0); _currentInstance = null; if (_currentType != null) { _binaryWriter.Write((byte)P21ParseAction.EndEntity); IfcType ifcType = IfcMetaData.IfcType(_currentType); MemoryStream data = _binaryWriter.BaseStream as MemoryStream; byte[] bytes = data.ToArray(); List <int> keys = new List <int>(_indexKeyValues); toStore.Add(new Tuple <int, short, List <int>, byte[], bool>(_currentLabel, ifcType.TypeId, keys, bytes, ifcType.IndexedClass)); if (this.modelCache.IsCaching) { toProcess.Add(new Tuple <int, Type, byte[]>(_currentLabel, ifcType.Type, bytes)); } } }
/// <summary> /// Create an Instance of a Object Type /// </summary> /// <param name="typeName">string name to create instance of</param> /// <param name="model">Model object</param> /// <returns>IfcTypeObject object of the type passed in of IfcTypeObject if failed to create passed in type</returns> public static IfcTypeObject GetTypeInstance(string typeName, IModel model) { typeName = typeName.Trim().ToUpper(); IfcType ifcType; IfcTypeObject ifcTypeObject = null; if (IfcMetaData.TryGetIfcType(typeName, out ifcType)) { MethodInfo method = typeof(IXbimInstanceCollection).GetMethod("New", Type.EmptyTypes); MethodInfo generic = method.MakeGenericMethod(ifcType.Type); var newObj = generic.Invoke(model.Instances, null); if (newObj is IfcTypeObject) { ifcTypeObject = (IfcTypeObject)newObj; } } if (ifcTypeObject == null) //if we cannot make a object assume base IfcTypeObject { ifcTypeObject = model.Instances.New <IfcTypeObject>(); } return(ifcTypeObject); }
internal override void SetType(string entityTypeName) { if (InHeader) { IPersistIfc currentHeaderEntity; switch (entityTypeName) { case "FILE_DESCRIPTION": currentHeaderEntity = _header.FileDescription; break; case "FILE_NAME": currentHeaderEntity = _header.FileName; break; case "FILE_SCHEMA": currentHeaderEntity = _header.FileSchema; break; default: throw new ArgumentException(string.Format("Invalid Header entity type {0}", entityTypeName)); } _currentInstance = new Part21Entity(currentHeaderEntity); _processStack.Push(_currentInstance); } else { _currentType = entityTypeName; IfcType ifcType = IfcMetaData.IfcType(_currentType); if (ifcType == null) { throw new ArgumentException(string.Format("Invalid entity type {0}", _currentType)); } _indexKeys = ifcType.IndexedValues; } }
/// <summary> /// Create an instance of an object via a string name /// </summary> /// <param name="elementTypeName">String holding object type name we eant to create</param> /// <param name="model">Model object</param> /// <returns></returns> public static IfcElement GetElementInstance(string elementTypeName, IModel model) { elementTypeName = elementTypeName.Trim().ToUpper(); IfcType ifcType; IfcElement ifcElement = null; if (IfcMetaData.TryGetIfcType(elementTypeName, out ifcType)) { MethodInfo method = typeof(IXbimInstanceCollection).GetMethod("New", Type.EmptyTypes); MethodInfo generic = method.MakeGenericMethod(ifcType.Type); var eleObj = generic.Invoke(model.Instances, null); if (eleObj is IfcElement) { ifcElement = (IfcElement)eleObj; } } if (ifcElement == null) { ifcElement = model.Instances.New <IfcFurnishingElement>(); //was IfcVirtualElement, but this is excluded in the import filters, so just using } return(ifcElement); }
public AttributeComparer(string attributeName, XbimModel revisedModel) { _attrName = attributeName; _revModel = revisedModel; //get possible types var rootType = IfcMetaData.IfcType(typeof(IfcRoot)); var rootSubTypes = rootType.NonAbstractSubTypes; _possibleTypes = rootSubTypes.Where(t => IsSimpleValueAttribute(t, attributeName)); //get possible objects var possibleObjects = revisedModel.Instances.Where <IfcRoot>(r => _possibleTypes.Contains(r.GetType())); foreach (var obj in possibleObjects) { var inf = obj.GetType().GetProperty(attributeName); var val = inf.GetValue(obj, null); if (val != null) { _cache.Add(new AttributeHasedRoot(obj, (IfcSimpleValue)val)); } } }
/// <summary> /// Appends a geometry data object to the Mesh, returns false if the mesh would become too big and needs splitting /// </summary> /// <param name="geometryMeshData"></param> public bool Add(XbimGeometryData geometryMeshData, short modelId = 0) { var transform = XbimMatrix3D.FromArray(geometryMeshData.DataArray2); if (geometryMeshData.GeometryType == XbimGeometryType.TriangulatedMesh) { var strm = new XbimTriangulatedModelStream(geometryMeshData.ShapeData); var fragment = strm.BuildWithNormals(this, transform, modelId); if (fragment.EntityLabel == -1) //nothing was added due to size being exceeded { return(false); } fragment.EntityLabel = geometryMeshData.IfcProductLabel; fragment.EntityTypeId = geometryMeshData.IfcTypeId; _meshes.Add(fragment); } else if (geometryMeshData.GeometryType == XbimGeometryType.BoundingBox) { var r3D = XbimRect3D.FromArray(geometryMeshData.ShapeData); Add(MakeBoundingBox(r3D, transform), geometryMeshData.IfcProductLabel, IfcMetaData.GetType(geometryMeshData.IfcTypeId), modelId); } else { throw new XbimException("Illegal geometry type found"); } return(true); }
/// <summary> /// Performs grouping based on the XML data provided. /// </summary> /// <param name="errLog">Stream for err output</param> /// <returns>True if grouping was successful. False otherwise.</returns> public bool PerformGrouping() { errLog = new StringWriter(); if (_xmlDoc == null) { errLog.WriteLine("No input XML data."); return(false); } //get all group nodes XmlNodeList groups = _xmlDoc.GetElementsByTagName("group"); if (groups == null || groups.Count == 0) { errLog.WriteLine("No group rules in the XML document"); return(false); } //clear groups from elements ClearGroups(_rootGroup); //create group for all non-grouped elements IfcGroup noGroup = GetGroup("No group"); if (noGroup == null) { noGroup = _model.Instances.New <IfcGroup>(gr => { gr.Name = "No group"; gr.Description = ""; }); _rootGroup.AddObjectToGroup(noGroup); } List <IfcElement> allElements = _model.Instances.OfType <IfcElement>().ToList(); List <IfcTypeObject> allTypes = _model.Instances.OfType <IfcTypeObject>().ToList(); foreach (XmlNode group in groups) { grpName = GetName(group); if (String.IsNullOrEmpty(grpName)) { errLog.WriteLine("Group without name detected. All information in this group specification will be skipped."); continue; } //search for the existing group with the same name (convert to upper case for the comparison) and create new group if none exists. IfcGroup iGroup = GetGroup(grpName); if (iGroup == null) { iGroup = _model.Instances.New <IfcGroup>(gr => gr.Name = grpName); _rootGroup.AddObjectToGroup(iGroup); } //process all ifc objects specified for the group XmlNodeList elements = ((XmlElement)group).GetElementsByTagName("element"); foreach (XmlNode element in group) { eName = GetName(element); if (String.IsNullOrEmpty(eName)) { errLog.WriteLine("Element without name detected in group '" + grpName + "'. This element will NOT be included in the"); continue; } //get elemType for reflection of attributes IfcType ifcType; if (!IfcMetaData.TryGetIfcType(eName, out ifcType)) { continue; } else { elemType = ifcType.Type; } XbimQueryBuilder qBuilder = new XbimQueryBuilder(elemType); //process all element attributes XmlNodeList attributeGroups = ((XmlElement)element).GetElementsByTagName("attributes"); //there could be different grouping rules for attribute rules inside (all, none, oneOf, any) foreach (XmlNode attrGroup in attributeGroups) { CreateAttributeCondition(qBuilder, attrGroup); } //process element properties XmlNodeList propertyGroups = ((XmlElement)element).GetElementsByTagName("properties"); //there could be different grouping rules for attribute rules inside (all, none, oneOf, any) foreach (XmlNode propGroup in propertyGroups) { CreatePropertyCondition(qBuilder, propGroup); } //element type processing IEnumerable <IPersistIfcEntity> types = null; XmlNodeList elTypeNodeList = (element as XmlElement).GetElementsByTagName("elementType"); foreach (XmlNode elTypeNode in elTypeNodeList) //there should be just one 'elTypeNode' { XbimQueryBuilder typeQueryBuilder = null; elTypeName = elTypeNode.InnerText; if (string.IsNullOrEmpty(elTypeName)) { errLog.WriteLine("Name of the element type is not specified for element of type '" + eName + "'. Element type conditions will not be applied. "); continue; } IfcType ifcTypeLookup; if (!IfcMetaData.TryGetIfcType(eName, out ifcTypeLookup)) { continue; } else { elemType = ifcTypeLookup.Type; } if (!typeof(IfcTypeObject).IsAssignableFrom(elemType)) { errLog.WriteLine("'" + elTypeName + "' is not type object."); continue; } typeQueryBuilder = new XbimQueryBuilder(elTypeName); //type attributes XmlNodeList typeAttrGroups = ((XmlElement)element).GetElementsByTagName("typeAttributes"); foreach (XmlNode typeAttrGrpNode in typeAttrGroups) { CreateAttributeCondition(typeQueryBuilder, typeAttrGrpNode); } //process element type properties XmlNodeList typePropGroups = ((XmlElement)element).GetElementsByTagName("typeProperties"); //there could be different grouping rules for attribute rules inside (all, none, oneOf, any) foreach (XmlNode propGroup in typePropGroups) { CreatePropertyCondition(typeQueryBuilder, propGroup); } types = _model.Instances.Where <IPersistIfcEntity>(typeQueryBuilder.BuildQuery()); break; } //get elements and element type IEnumerable <IPersistIfcEntity> instances = allElements.Where(qBuilder.BuildQuery().Compile()).ToList(); //check elements against element type (if defined) if (types != null) { instances = FilterElementsByType(instances, types); } //add result to the group foreach (var inst in instances) { IfcElement el = inst as IfcElement; if (el != null && allElements.Remove(el)) { IfcTypeObject type = el.GetDefiningType(); if (allTypes.Remove(type)) //ensure that it is not added twice { iGroup.AddObjectToGroup(type); } //get all elements of this type IEnumerable <IfcRelDefinesByType> rels = _model.Instances.Where <IfcRelDefinesByType>(r => r.RelatingType == type); foreach (var rel in rels) { IEnumerable <IfcElement> elemOfType = rel.RelatedObjects.OfType <IfcElement>(); foreach (var item in elemOfType) { allElements.Remove(item); } } //IfcObjectDefinition objDef = inst as IfcObjectDefinition; //if (objDef != null) iGroup.AddObjectToGroup(objDef); } } } } //fill the no-group group with elements which are not in any group foreach (IfcTypeObject element in allTypes) { noGroup.AddObjectToGroup(element); } return(true); }
public void Run() { //to start we need an ifc file, here it is Clinic_Example.ifc string ifcFile = @"IfcFiles/Clinic_Example.ifc"; string xbimFile = Path.ChangeExtension(ifcFile, "xBIM"); //will generate if not existing if (File.Exists(ifcFile)) { using (XbimModel model = new XbimModel()) { if (File.Exists(xbimFile)) { //assume the xbim file has the geometry already generated from ifc file, as below model.Open(xbimFile, XbimDBAccess.Read); } else { //create the xbim file from the ifc file model.CreateFrom(ifcFile, xbimFile, delegate(int percentProgress, object userState) { Console.Write("\rReading File {0}", percentProgress); }); model.Open(xbimFile, XbimDBAccess.ReadWrite); //readwrite as we need to add the geometry //add the the geometry information to the model int total = (int)model.Instances.CountOf <IfcProduct>(); ReportProgressDelegate progDelegate = delegate(int percentProgress, object userState) { Console.Write("\rGeometry {0} / {1}", total, (total * percentProgress / 100)); }; XbimMesher.GenerateGeometry(model, null, progDelegate); } //get all the IfcDoors in the model IEnumerable <IfcDoor> ifcDoors = model.IfcProducts.OfType <IfcDoor>(); //get all the ifcdoors for this model if (ifcDoors.Any()) { IfcDoor ifcDoor = ifcDoors.First(); //we use the first door to get the bounding box from XbimGeometryData geoData = model.GetGeometryData(ifcDoor, XbimGeometryType.BoundingBox).FirstOrDefault(); if (geoData != null) { XbimRect3D boundBox = XbimRect3D.FromArray(geoData.ShapeData); //size information for the IfcDoor, but the information is for the bounding box which encloses the door //if want want in World space XbimMatrix3D worldMatrix = geoData.Transform; //if we want to convert to World space we can use the geoData.Transform property and create the world matrix XbimPoint3D MinPtOCS = new XbimPoint3D(boundBox.X, boundBox.Y, boundBox.Z); XbimPoint3D MaxPtOCS = new XbimPoint3D(boundBox.X + boundBox.SizeX, boundBox.Y + boundBox.SizeY, boundBox.Z + boundBox.SizeZ); //transformed values, may no longer a valid bounding box in the new space if any Pitch or Yaw, i.e. stairs ceiling supports XbimPoint3D MinPtWCS = worldMatrix.Transform(MinPtOCS); XbimPoint3D MaxPtWCS = worldMatrix.Transform(MaxPtOCS); //if you product is at any angle to the World space then the bounding box can be recalculated, //a example of this can be found here https://sbpweb.svn.codeplex.com/svn/SBPweb.Workbench/Workbench%20Framework%202.0.0.x/Presentation/Windows.WPF/Utils/Maths.cs //in the TransformBounds function Console.WriteLine("\n-------------Bounding Box Information-------------"); Console.WriteLine("Entity Type = {0}", IfcMetaData.GetType(geoData.IfcTypeId).Name); Console.WriteLine("Entity Label = {0}", Math.Abs(ifcDoor.EntityLabel).ToString()); Console.WriteLine("Size X = {0:F2}", boundBox.SizeX.ToString()); Console.WriteLine("Size Y = {0:F2}", boundBox.SizeY.ToString()); Console.WriteLine("Size Z = {0:F2}", boundBox.SizeZ.ToString()); Console.WriteLine("Object space minimum point {0}", MinPtOCS); Console.WriteLine("Object space maximum point {0}", MaxPtOCS); Console.WriteLine("World space minimum point {0}", MinPtWCS); Console.WriteLine("World space maximum point {0}", MaxPtWCS); Console.WriteLine("---------------------------------------------"); } } else { Console.WriteLine(string.Format("Failed to find any IfcDoor's in {0}", ifcFile)); return; //exit } } } else { Console.WriteLine(string.Format("Failed to find {0} in executable directory", ifcFile)); } Console.WriteLine("\nFinished"); }
public void Add(byte[] mesh, Type productType, int productLabel, int geometryLabel, XbimMatrix3D?transform = null, short modelId = 0) { Add(mesh, IfcMetaData.IfcTypeId(productType), productLabel, geometryLabel, transform, modelId); }
public static bool PassesRule(this IPersistIfc Entity, MvdRule DataNode, MvdPropertyRuleValue requirement = null, PassMode PassMode = PassMode.Undefined) { // todo: add controls for schema cardinality // IfcType EntType = IfcMetaData.IfcType(Entity); #if SYSDEBUG Debug.WriteLine(string.Format("testing {0} for {1}", Entity.ToString(), DataNode.Type)); #endif string RuleId = ""; bool bEvaluateRule = false; if (DataNode.Properties.ContainsKey("RuleID") && requirement != null) { RuleId = DataNode.Properties["RuleID"]; bEvaluateRule = (requirement.Name == RuleId); // here the property is evaluated. if (bEvaluateRule) { #if SYSDEBUG Debug.Write("-- Evaluating"); #endif if (Entity is IPersistIfcEntity) { Debug.Write(string.Format("Req: {0} Ent: {1}{2}\r\n", requirement.Name, Math.Abs(((IPersistIfcEntity)Entity).EntityLabel), EntType)); } if (requirement.Prop == "Type") { string cmpVal = IfcMetaData.IfcType(Entity).Name; return(requirement.Val == cmpVal); } } } if (DataNode.Type == "AttributeRule") { string propName = DataNode.Properties["AttributeName"]; var prop = EntType.IfcProperties.Where(x => x.Value.PropertyInfo.Name == propName).FirstOrDefault().Value; if (prop == null) // otherwise test inverses { prop = EntType.IfcInverses.Where(x => x.PropertyInfo.Name == propName).FirstOrDefault(); } if (prop == null) { #if SYSDEBUG Debug.WriteLine("AttributeRule failed on null value"); #endif return(false); } object propVal = prop.PropertyInfo.GetValue(Entity, null); if (propVal == null) { return(false); } if (propVal != null) { if (bEvaluateRule) { if (requirement.Prop == "Value") { string cmpVal = propVal.ToString(); bool retVal = (requirement.Val == cmpVal); #if SYSDEBUG if (requirement.Val.StartsWith("")) { } if (!retVal) { Debug.WriteLine("AttributeRule failed on value"); } #endif return(retVal); } } else if (requirement == null && propVal is IPersistIfc) { var v = (IPersistIfc)propVal; bool AnyChildFail = false; foreach (var nestedRule in DataNode.NestedRules) { Debug.Indent(); if (!v.PassesRule(nestedRule)) { AnyChildFail = true; Debug.Unindent(); break; } Debug.Unindent(); } return(!AnyChildFail); } if (prop.IfcAttribute.IsEnumerable) { IEnumerable <object> propCollection = propVal as IEnumerable <object>; if (propCollection == null) { return(false); } foreach (var child in propCollection) { if (child is IPersistIfc) { // todo: this might actually have to return fail if any nested rule fail, not if the first passes. foreach (var nestedRule in DataNode.NestedRules) { Debug.Indent(); var loopret = ((IPersistIfc)child).PassesRule(nestedRule, requirement, PassMode); Debug.Unindent(); if (loopret) { return(true); } } } } } else { IPersistIfc pe = propVal as IPersistIfc; if (pe == null) { #if SYSDEBUG Debug.WriteLine("AttributeRule failed: not found"); #endif return(false); } foreach (var nestedRule in DataNode.NestedRules) { if (pe.PassesRule(nestedRule, requirement)) { return(true); } } } } } else if (DataNode.Type == "EntityRule") { string EName = DataNode.Properties["EntityName"]; IfcType ENameType = IfcMetaData.IfcType(EName.ToUpperInvariant()); if (ENameType != null) { // run type validation only if type matches if (!(ENameType == EntType || ENameType.NonAbstractSubTypes.Contains(EntType.Type))) { #if SYSDEBUG Debug.WriteLine("EntityRule failed: expected " + EName + " found: " + EntType.ToString()); #endif return(false); } // if test is passed and no sub rules then return true if (!DataNode.NestedRules.Any()) { return(true); } } else { Debug.WriteLine("Probably IFC4 Type specified:" + EName); } foreach (var subRule in DataNode.NestedRules) { var passed = Entity.PassesRule(subRule, requirement); if (passed) { return(true); } } } return(false); }
public XbimScene <WpfMeshGeometry3D, WpfMaterial> BuildScene(XbimModel model, Xbim3DModelContext context, List <Type> exclude = null) { var tmpOpaquesGroup = new Model3DGroup(); var retScene = new XbimScene <WpfMeshGeometry3D, WpfMaterial>(model); var red = PrepareMesh(new XbimColour("Red", 1.0, 0.0, 0.0, 0.5)); var green = PrepareMesh(new XbimColour("Green", 0.0, 1.0, 0.0, 0.5)); red.WpfModel.SetValue(FrameworkElement.TagProperty, red); green.WpfModel.SetValue(FrameworkElement.TagProperty, green); red.BeginUpdate(); green.BeginUpdate(); tmpOpaquesGroup.Children.Add(red); tmpOpaquesGroup.Children.Add(green); var i = 0; foreach (var shapeInstance in context.ShapeInstances() .Where(s => s.RepresentationType == XbimGeometryRepresentationType.OpeningsAndAdditionsIncluded && !typeof(IfcFeatureElement).IsAssignableFrom(IfcMetaData.GetType(s.IfcTypeId)) /*&& * !typeof(IfcSpace).IsAssignableFrom(IfcMetaData.GetType(s.IfcTypeId))*/)) { IXbimShapeGeometryData shapeGeom = context.ShapeGeometry(shapeInstance.ShapeGeometryLabel); WpfMeshGeometry3D targetMergeMesh; switch (i++ % 2) { case 0: targetMergeMesh = red; break; default: targetMergeMesh = green; break; } switch ((XbimGeometryType)shapeGeom.Format) { case XbimGeometryType.Polyhedron: var shapePoly = (XbimShapeGeometry)shapeGeom; targetMergeMesh.Add( shapePoly.ShapeData, shapeInstance.IfcTypeId, shapeInstance.IfcProductLabel, shapeInstance.InstanceLabel, XbimMatrix3D.Multiply(shapeInstance.Transformation, Control.ModelPositions[model].Transfrom), model.UserDefinedId); break; case XbimGeometryType.PolyhedronBinary: targetMergeMesh.Add( shapeGeom.ShapeData, shapeInstance.IfcTypeId, shapeInstance.IfcProductLabel, shapeInstance.InstanceLabel, XbimMatrix3D.Multiply(shapeInstance.Transformation, Control.ModelPositions[model].Transfrom), model.UserDefinedId ); break; default: throw new ArgumentOutOfRangeException(); } } red.EndUpdate(); green.EndUpdate(); var mv = new ModelVisual3D { Content = tmpOpaquesGroup }; Control.OpaquesVisual3D.Children.Add(mv); // Control.ModelBounds = mv.Content.Bounds.ToXbimRect3D(); return(retScene); }
/// <summary> /// Get the space name holding the element /// </summary> /// <param name="el">IfcElement to get containing space for</param> /// <returns>Space name</returns> internal string GetSpaceHoldingElement(IfcElement el) { //see if we have space information, if not fill information list if (SpaceBoundingBoxInfo.Count == 0) { if (ifcSpaces == null) { ifcSpaces = Model.Instances.OfType <IfcSpace>().ToList(); } //get Geometry for spaces SpaceBoundingBoxInfo = Model.GetGeometryData(XbimGeometryType.BoundingBox) .Where(bb => bb.IfcTypeId == IfcMetaData.IfcTypeId(typeof(IfcSpace))) .Select(bb => new SpaceInfo { Rectangle = XbimRect3D.FromArray(bb.ShapeData), Matrix = XbimMatrix3D.FromArray(bb.DataArray2), Name = ifcSpaces.Where(sp => (sp.EntityLabel == bb.IfcProductLabel)).Select(sp => sp.Name.ToString()).FirstOrDefault() }).ToList(); } string spaceName = string.Empty; //only if we have any space information if (SpaceBoundingBoxInfo.Any()) { //find the IfcElement Bounding Box and To WCS Matrix XbimGeometryData elGeoData = Model.GetGeometryData(el, XbimGeometryType.BoundingBox).FirstOrDefault(); //check to see if we have any geometry within the file if (elGeoData == null) { return(string.Empty); //No geometry } XbimRect3D elBoundBox = XbimRect3D.FromArray(elGeoData.ShapeData); XbimMatrix3D elWorldMatrix = XbimMatrix3D.FromArray(elGeoData.DataArray2); //Get object space top and bottom points of the bounding box List <XbimPoint3D> elBoxPts = new List <XbimPoint3D>(); elBoxPts.Add(new XbimPoint3D(elBoundBox.X, elBoundBox.Y, elBoundBox.Z)); elBoxPts.Add(new XbimPoint3D(elBoundBox.X + elBoundBox.SizeX, elBoundBox.Y + elBoundBox.SizeY, elBoundBox.Z + elBoundBox.SizeZ)); elBoxPts.Add(elBoundBox.Centroid()); //convert points of the bounding box to WCS IEnumerable <XbimPoint3D> elBoxPtsWCS = elBoxPts.Select(pt => elWorldMatrix.Transform(pt)); //see if we hit any spaces spaceName = GetSpaceFromPoints(elBoxPtsWCS); //if we failed to get space on min points then use the remaining corner points if (string.IsNullOrEmpty(spaceName)) { XbimPoint3D elMinPt = elBoxPts[0]; XbimPoint3D elMaxPt = elBoxPts[1]; //elBoxPts.Clear(); //already tested points in list so clear them //Extra testing on remaining corner points on the top and bottom plains elBoxPts.Add(new XbimPoint3D(elMaxPt.X, elMaxPt.Y, elMinPt.Z)); elBoxPts.Add(new XbimPoint3D(elMaxPt.X, elMinPt.Y, elMinPt.Z)); elBoxPts.Add(new XbimPoint3D(elMinPt.X, elMaxPt.Y, elMinPt.Z)); elBoxPts.Add(new XbimPoint3D((elMaxPt.X - elMinPt.X) / 2.0, (elMaxPt.Y - elMinPt.Y) / 2.0, elMinPt.Z)); //centre face point elBoxPts.Add(new XbimPoint3D(elMinPt.X, elMinPt.Y, elMaxPt.Z)); elBoxPts.Add(new XbimPoint3D(elMaxPt.X, elMinPt.Y, elMaxPt.Z)); elBoxPts.Add(new XbimPoint3D(elMinPt.X, elMaxPt.Y, elMaxPt.Z)); elBoxPts.Add(new XbimPoint3D((elMaxPt.X - elMinPt.X) / 2.0, (elMaxPt.Y - elMinPt.Y) / 2.0, elMaxPt.Z)); //centre face point //convert points of the bounding box to WCS elBoxPtsWCS = elBoxPts.Select(pt => elWorldMatrix.Transform(pt)); //see if we hit any spaces spaceName = GetSpaceFromPoints(elBoxPtsWCS); } if (string.IsNullOrEmpty(spaceName)) { //Get tolerance size from element, 1% of smallest side size double tol = elBoundBox.SizeX * 0.001; if ((elBoundBox.SizeY * 0.001) < tol) { tol = elBoundBox.SizeY * 0.001; } if ((elBoundBox.SizeZ * 0.001) < tol) { tol = elBoundBox.SizeZ * 0.001; } if ((tol == 0.0) && //if tol 0.0 ((Context.WorkBookUnits.LengthUnit.Equals("meters", StringComparison.OrdinalIgnoreCase)) || (Context.WorkBookUnits.LengthUnit.Equals("metres", StringComparison.OrdinalIgnoreCase)) ) ) { tol = 0.001; } spaceName = GetSpaceFromClosestPoints(elBoxPtsWCS, tol); } } return(spaceName); }
/// <summary> /// This version uses the new Geometry representation /// </summary> /// <param name="model"></param> /// <param name="context"></param> /// <param name="exclude">List of type to exclude, by default excplict openings and spaces are excluded if exclude = null</param> /// <returns></returns> public XbimScene <WpfMeshGeometry3D, WpfMaterial> BuildScene(XbimModel model, Xbim3DModelContext context, List <Type> exclude = null) { var excludedTypes = new HashSet <short>(); if (exclude == null) { exclude = new List <Type>() { typeof(IfcSpace) // , typeof(IfcFeatureElement) } } ; foreach (var excludedT in exclude) { var ifcT = IfcMetaData.IfcType(excludedT); foreach (var exIfcType in ifcT.NonAbstractSubTypes.Select(IfcMetaData.IfcType)) { excludedTypes.Add(exIfcType.TypeId); } } var scene = new XbimScene <WpfMeshGeometry3D, WpfMaterial>(model); if (context == null) { return(scene); } //get a list of all the unique styles var styles = new Dictionary <int, WpfMaterial>(); var repeatedShapeGeometries = new Dictionary <int, MeshGeometry3D>(); var styleMeshSets = new Dictionary <int, WpfMeshGeometry3D>(); var tmpOpaquesGroup = new Model3DGroup(); var tmpTransparentsGroup = new Model3DGroup(); var sstyles = context.SurfaceStyles(); foreach (var style in sstyles) { var wpfMaterial = new WpfMaterial(); wpfMaterial.CreateMaterial(style); styles.Add(style.DefinedObjectId, wpfMaterial); var mg = new WpfMeshGeometry3D(wpfMaterial, wpfMaterial); mg.WpfModel.SetValue(FrameworkElement.TagProperty, mg); styleMeshSets.Add(style.DefinedObjectId, mg); mg.BeginUpdate(); if (style.IsTransparent) { tmpTransparentsGroup.Children.Add(mg); } else { tmpOpaquesGroup.Children.Add(mg); } } if (!styles.Any()) { return(scene); //this should always return something } var shapeInstances = context.ShapeInstances() .Where(s => s.RepresentationType == XbimGeometryRepresentationType.OpeningsAndAdditionsIncluded && !excludedTypes.Contains(s.IfcTypeId)); // !typeof (IfcFeatureElement).IsAssignableFrom(IfcMetaData.GetType(s.IfcTypeId)) /*&& // !typeof(IfcSpace).IsAssignableFrom(IfcMetaData.GetType(s.IfcTypeId))*/); foreach (var shapeInstance in shapeInstances) { var styleId = shapeInstance.StyleLabel > 0 ? shapeInstance.StyleLabel : shapeInstance.IfcTypeId * -1; //GET THE ACTUAL GEOMETRY MeshGeometry3D wpfMesh; //see if we have already read it if (repeatedShapeGeometries.TryGetValue(shapeInstance.ShapeGeometryLabel, out wpfMesh)) { var mg = new GeometryModel3D(wpfMesh, styles[styleId]); mg.SetValue(FrameworkElement.TagProperty, new XbimInstanceHandle(model, shapeInstance.IfcProductLabel, shapeInstance.IfcTypeId)); mg.BackMaterial = mg.Material; mg.Transform = XbimMatrix3D.Multiply(shapeInstance.Transformation, Control.ModelPositions[model].Transfrom).ToMatrixTransform3D(); if (styles[styleId].IsTransparent) { tmpTransparentsGroup.Children.Add(mg); } else { tmpOpaquesGroup.Children.Add(mg); } } else //we need to get the shape geometry { IXbimShapeGeometryData shapeGeom = context.ShapeGeometry(shapeInstance.ShapeGeometryLabel); if (shapeGeom.ReferenceCount > 1) //only store if we are going to use again { wpfMesh = new MeshGeometry3D(); switch ((XbimGeometryType)shapeGeom.Format) { case XbimGeometryType.PolyhedronBinary: wpfMesh.Read(shapeGeom.ShapeData); break; case XbimGeometryType.Polyhedron: wpfMesh.Read(((XbimShapeGeometry)shapeGeom).ShapeData); break; } repeatedShapeGeometries.Add(shapeInstance.ShapeGeometryLabel, wpfMesh); var mg = new GeometryModel3D(wpfMesh, styles[styleId]); mg.SetValue(FrameworkElement.TagProperty, new XbimInstanceHandle(model, shapeInstance.IfcProductLabel, shapeInstance.IfcTypeId)); mg.BackMaterial = mg.Material; mg.Transform = XbimMatrix3D.Multiply(shapeInstance.Transformation, Control.ModelPositions[model].Transfrom).ToMatrixTransform3D(); if (styles[styleId].IsTransparent) { tmpTransparentsGroup.Children.Add(mg); } else { tmpOpaquesGroup.Children.Add(mg); } } else //it is a one off, merge it with shapes of a similar material { var targetMergeMeshByStyle = styleMeshSets[styleId]; switch ((XbimGeometryType)shapeGeom.Format) { case XbimGeometryType.Polyhedron: // var shapePoly = (XbimShapeGeometry)shapeGeom; var asString = Encoding.UTF8.GetString(shapeGeom.ShapeData.ToArray()); targetMergeMeshByStyle.Add( asString, shapeInstance.IfcTypeId, shapeInstance.IfcProductLabel, shapeInstance.InstanceLabel, XbimMatrix3D.Multiply(shapeInstance.Transformation, Control.ModelPositions[model].Transfrom), model.UserDefinedId); break; case XbimGeometryType.PolyhedronBinary: var transform = XbimMatrix3D.Multiply(shapeInstance.Transformation, Control.ModelPositions[model].Transfrom); targetMergeMeshByStyle.Add( shapeGeom.ShapeData, shapeInstance.IfcTypeId, shapeInstance.IfcProductLabel, shapeInstance.InstanceLabel, transform, model.UserDefinedId); break; default: throw new ArgumentOutOfRangeException(); } } } } foreach (var wpfMeshGeometry3D in styleMeshSets.Values) { wpfMeshGeometry3D.EndUpdate(); } //} if (tmpOpaquesGroup.Children.Any()) { var mv = new ModelVisual3D(); mv.Content = tmpOpaquesGroup; Control.OpaquesVisual3D.Children.Add(mv); // Control.ModelBounds = mv.Content.Bounds.ToXbimRect3D(); } if (tmpTransparentsGroup.Children.Any()) { var mv = new ModelVisual3D(); mv.Content = tmpTransparentsGroup; Control.TransparentsVisual3D.Children.Add(mv); //if (Control.ModelBounds.IsEmpty) Control.ModelBounds = mv.Content.Bounds.ToXbimRect3D(); //else Control.ModelBounds.Union(mv.Content.Bounds.ToXbimRect3D()); } return(scene); }