UBC Theses and Dissertations

UBC Theses Logo

UBC Theses and Dissertations

Semantic spatial interoperability framework : a case study in the architecture, engineering and construction… Webster, April 2010

Your browser doesn't seem to have a PDF viewer, please download the PDF to view this item.

Item Metadata

Download

Media
24-ubc_2010_fall_webster_april.pdf [ 1.22MB ]
Metadata
JSON: 24-1.0051947.json
JSON-LD: 24-1.0051947-ld.json
RDF/XML (Pretty): 24-1.0051947-rdf.xml
RDF/JSON: 24-1.0051947-rdf.json
Turtle: 24-1.0051947-turtle.txt
N-Triples: 24-1.0051947-rdf-ntriples.txt
Original Record: 24-1.0051947-source.json
Full Text
24-1.0051947-fulltext.txt
Citation
24-1.0051947.ris

Full Text

Semantic Spatial Interoperability Framework: A Case Study in the Architecture, Engineering and Construction (AEC) Domain  by April Webster BSc Math and Biology, University of British Columbia, 2000 BSc Computer Science, University of British Columbia, 2007  A THESIS SUBMITTED IN PARTIAL FULFILLMENT OF THE REQUIREMENTS FOR THE DEGREE OF  Master of Science in THE FACULTY OF GRADUATE STUDIES (Computer Science)  The University Of British Columbia (Vancouver) August 2010 c April Webster, 2010  Abstract The volume of disseminated digital spatial data has exploded, generating demand for tools to support interoperability and the extraction of usable knowledge. Previous work on spatial interoperability has focused on semi-automatically generating the mappings to mediate multi-modal spatial data. We present a case study in the Architecture, Engineering and Construction (AEC) domain that demonstrates that even after this level of semantic interoperability has been achieved, mappings from the integrated spatial data to concepts desired by the domain experts must be articulated. We propose the Semantic Spatial Interoperability Framework to provide the next layer of semantic interoperability: GML provides the syntactic glue for spatial and non-spatial data integration, and an ontology provides the semantic glue for domain-specific knowledge extraction. Mappings between the two are created by extending XQuery with spatial query predicates.  ii  Table of Contents Abstract . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  ii  Table of Contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  iii  List of Figures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  vi  1  Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  1  1.1  AEC Case Study . . . . . . . . . . . . . . . . . . . . . . . . . .  2  1.2  Proposed Solution . . . . . . . . . . . . . . . . . . . . . . . . . .  3  Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  5  2.1  The ARTIFACT Project . . . . . . . . . . . . . . . . . . . . . . .  5  2.1.1  Architecture . . . . . . . . . . . . . . . . . . . . . . . . .  5  2.1.2  Current Status  . . . . . . . . . . . . . . . . . . . . . . .  7  Building Design Data . . . . . . . . . . . . . . . . . . . . . . . .  8  2.2.1  The Building Information Model (BIM) . . . . . . . . . .  8  2.2.2  Autodesk Revit Architecture: The Selected BIM Application 10  2.2.3  IFC/ifcXML: Exporting Building Design Data from Revit  2  2.2  2.3  3  10  Geography Markup Language (GML) . . . . . . . . . . . . . . .  11  2.3.1  Background . . . . . . . . . . . . . . . . . . . . . . . . .  11  2.3.2  The GML Model . . . . . . . . . . . . . . . . . . . . . .  12  2.3.3  Extending GML: Community-specific Application Schemas 13  Related Work . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  14  3.1  Ontologies . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  14  3.2  Semantic Spatial Interoperability . . . . . . . . . . . . . . . . . .  14  iii  3.3 4  XQuery-based Spatial Query Languages . . . . . . . . . . . . . .  15  Case Study in the Architecture, Engineering and Construction Domain (AEC) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1  19  Construction-Specific Spatial Relationships are Not Supported by BIMs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  19  4.1.1  What Spatial Data is Missing? . . . . . . . . . . . . . . .  20  Solution: Direct Extraction of Spatial Data Using the Revit API .  21  4.2.1  Spatial Data Representation of Building Objects in Revit .  22  4.2.2  The Revit API . . . . . . . . . . . . . . . . . . . . . . .  25  4.2.3  Spatial Data Extraction Application . . . . . . . . . . . .  26  4.2.4  Challenges . . . . . . . . . . . . . . . . . . . . . . . . .  26  Semantic Spatial Interoperability Framework (SSIF) . . . . . . . .  29  5.1  The Construction Ontology . . . . . . . . . . . . . . . . . . . . .  30  5.2  The ARTIFACT Application Schema (AAS) . . . . . . . . . . . .  31  5.2.1  Representing Location . . . . . . . . . . . . . . . . . . .  31  5.2.2  Features . . . . . . . . . . . . . . . . . . . . . . . . . . .  35  5.2.3  Feature Collections . . . . . . . . . . . . . . . . . . . . .  36  5.2.4  Feature Relationships . . . . . . . . . . . . . . . . . . . .  37  5.2.5  Units of Measure (UOMs) . . . . . . . . . . . . . . . . .  38  5.2.6  Schema and Instance Validation . . . . . . . . . . . . . .  40  5.2.7  Challenges . . . . . . . . . . . . . . . . . . . . . . . . .  40  Construction Query Predicates . . . . . . . . . . . . . . . . . . .  42  5.3.1  Overview . . . . . . . . . . . . . . . . . . . . . . . . . .  42  5.3.2  Assumptions . . . . . . . . . . . . . . . . . . . . . . . .  42  5.3.3  2D Topological Query Predicates . . . . . . . . . . . . .  43  5.3.4  Construction Query Predicates . . . . . . . . . . . . . . .  57  5.3.5  Challenges . . . . . . . . . . . . . . . . . . . . . . . . .  67  Conclusion and Future Work . . . . . . . . . . . . . . . . . . . . . .  69  Bibliography . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  71  4.2  5  5.3  6  iv  A Construction Ontology . . . . . . . . . . . . . . . . . . . . . . . . .  76  B ARTIFACT Application Schema . . . . . . . . . . . . . . . . . . . .  78  C Units of Measure Dictionary . . . . . . . . . . . . . . . . . . . . . .  88  D Spatial Query Predicates . . . . . . . . . . . . . . . . . . . . . . . .  90  E Revit API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127  v  List of Figures 2.1  The overall architecture of the ARTIFACT Project [34] . . . . . .  6  4.1  Spatial information stored by the Revit API for a Wall . . . . . . .  23  5.1  Semantic Spatial Interoperability Framework . . . . . . . . . . .  30  5.2  Application of the Separating Axis Theorem (SAT) to the AEC domain (i.e., with respect to two walls, Wall1 and Wall2). . . . . .  45  5.3  Cases in which two Walls will be disjoint. . . . . . . . . . . . . .  46  5.4  Layout of columns on the first level of a building. The proximate columns of column 80940 are highlighted in black.). . . . . . . .  5.5  The difference between interior on-grid, exterior on-grid and offgrid columns. . . . . . . . . . . . . . . . . . . . . . . . . . . . .  5.6  5.9  61  Example of a duct penetration on a wall. The location of the duct in relation to the sides of the wall is indicated. . . . . . . . . . . .  5.8  55  Example of a Wall-to-Wall Intersection and the details provided by the Intersection spatial query predicate . . . . . . . . . . . . . . .  5.7  50  63  Spacing of on-grid columns on the first level of a building design plan . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .  65  Face-to-face versus Center-to-center spacing. . . . . . . . . . . .  66  vi  Chapter 1  Introduction Spatial data is typically housed in specialized storage systems (e.g., CAD or GIS applications) rather than being stored in a relational or XML database. This makes it difficult to use spatial data to its full potential when the users’ needs veer from the application’s intended usage. For example, in the Architecture, Engineering, and Construction (AEC) domain, construction practitioners often want to analyze a building design plan to determine how best to adjust it in order to meet a change in specification, budget, or schedule. Consider Example1: Example 1 If a structural engineer reduces the floor-to-floor distance in a building by 6 inches, the clients can save $250,000. While this appears to be a simple design change, it has the potential to impact other downstream phases of the construction project; the expected savings may not be as great as first thought. For example, the planned ceiling space may no longer be deep enough to contain duct work, electrical conduits, and plumbing [46]. Gaging the true impact of any change requires access to data not easily accessible in a building design, e.g., how floor-to-floor distance in the structural design relates to and impacts other building components ✷  and downstream activities in the project.  The scenario in Example 1 is outside the intended usage of the AEC tools in which the building design plan was created making it difficult for users to perform the required calculation. This problem is often compounded by the fact that the information can be stored in several applications and in proprietary data formats. 1  Moreover, what is considered spatial data is really comprised of a spatial component — the location of a building object in space — and a non-spatial component which represents everything else — the building object’s attribute data such as its specific type, whether it is fire-rated, etc. Spatial and non-spatial data are also typically stored in incompatible formats, spatial data in a proprietary format and non-spatial data in a relational format. Once extracted, the spatial and non-spatial data must be integrated into a single, common representation which will provide schematic interoperability. Finally, the integrated spatial and non-spatial data must be filtered to extract the knowledge that is both relevant to and digestible by domain experts to provide semantic interoperability. Our proposed end-to-end semantic spatial interoperability system addresses both schematic and semantic interoperability to ensure usability of the rich spatial data available in the AEC domain and ensure that queries of a spatial nature, such as those exemplified by the problem presented in Example 1, can be answered. We present our case study in the AEC domain in the following section.  1.1  AEC Case Study  The AEC industry is a domain plagued by poor semantic interoperability as illustrated in Example 1. This problem has attracted considerable attention due to the economic toll it exacts on the industry. A report issued in 2004 by the US National Institute of Standards and Technology estimates that each year the AEC industry loses $15.8 billion due to inadequate interoperability [23]. From the perspective of domain experts, lack of interoperability manifests itself in an inability to extract knowledge, such as the design conditions that impact constructability of a building — how easy it is to construct a building [21]. For example, the spacing and variability in spacing among building elements such as columns will determine what formwork systems can be employed during construction to pour concrete. A ganged form can accommodate variation of the location and spacing of columns, a jump form can handle moderate variation, but a slip form cannot handle any variation at all [25]. Information such as this is not explicitly modeled in a building design plan. While both the spatial and non-spatial attribute data for a building design plan  2  are stored in the same application (e.g., Autodesk Revit Architecture) and can be extracted to a common syntax (i.e., XML), it must still be integrated into a common representation. However, the problem addressed in Example 1 still persists even after the spatial and non-spatial data has been integrated into a single schema. In particular the semantic interoperability problem that has been focused on to date (see Section 3.2) — extracting usable, domain-specific knowledge, the ultimate level of semantic interoperability — is not possible. Hence the focus of this research and our ongoing work is to address lack of a higher layer of semantic interoperability in the AEC domain.  1.2  Proposed Solution  A system that addresses semantic spatial interoperability must be capable of (1) storing both spatial and non-spatial attribute data using a common representation, (2) capturing the knowledge needed by domain practitioners in a machine- and human-readable manner, and (3) supporting domain expert specified queries on the underlying data to extract the desired concepts. Our proposed solution is the Semantic Spatial Interoperability Framework (SSIF). The SSIF combines (1) a GML application schema (see Section 5.2) to schematically integrate the data, (2) a Prot´eg´e ontology [41] (see Section 5.1) to formally capture domain-specific knowledge, and (3) custom XQuery predicates to articulate the mappings between the integrated raw data and the high level spatial concepts in the ontology to support automatic knowledge extraction (see Section 5.3). Hence the desired knowledge can be easily extracted for a specific construction project. The contributions of our work can be summarized as follows: Contribution 1: We created an application to extract spatial data from the Autodesk Revit API. Contribution 2: We extended GML for the Architecture, Engineering and Construction (AEC) domain. We created a GML application schema (XML vocabulary) that represents in a common syntax and schema the spatial data extracted from the underlying Revit model (API) and the non-spatial attribute 3  data exported from Revit in ifcXML. Contribution 3: We developed custom spatial query predicates specific to the AEC domain. XQuery does not natively support queries of a spatial nature. Also, we involved domain experts whose domain knowledge and experience could be utilized to identify the most relevant spatial queries for construction practitioners. Contribution 4: We created a complete end-to-end semantic spatial data interoperability system, the Semantic Spatial Interoperability Framework. Contribution 5: We described our experiences in developing a semantic spatial data interoperability system for the AEC domain. In particular, we identified and generalized some of the existing problems in extracting, integrating and querying spatial design data to uncover the most effective directions for improvement. Relevant background knowledge and related work are presented in Chapters 2 and 3 respectively. We then describe the AEC case study and the initial work done on the project in more detail in Chapter 4. The implementation details of the SSIF are presented in Chapter 5, qualitative results in Chapter 6 and we conclude with a summary of the work described herein as well as suggestions for future work in Chapter 6.  4  Chapter 2  Background 2.1  The ARTIFACT Project  The ARTIFACT (Advanced Research, Techniques, and Informatics for Future Advantages in Construction Technology) Project is a joint endeavor between civil engineers and computer scientists at the University of British Columbia and the University of Victoria. The goal of ARTIFACT is to address the need for more effective information management and collaboration in the Architecture, Engineering and Construction (AEC) domain and, in doing so, make it easier for practitioners to make critical decisions for large construction projects. The approach proposed by the ARTIFACT team is to develop technology for extracting, integrating, and managing the various types of information that are important to construction practitioners, and then abstract the knowledge they find important. This will enable more sophisticated analysis of construction information than is currently possible.  2.1.1  Architecture  The overall architecture of the proposed ARTIFACT system is shown in Figure 2.1. As demonstrated, each of the various types of data – scheduling information, building design plans, construction photos, and cost estimate data – are stored in different applications; each application provides several export options. The intent is to find a way to coordinate the data and provide a unified interface that supports 5  Figure 2.1: The overall architecture of the ARTIFACT Project [34] the user in browsing and querying all manners of construction data. XML: the Selected Data Coordination Mechanism XML is a data exchange format commonly used for information sharing in a wide variety of domains, many of which have developed standards based on XML to support information exchange. In the ARTIFACT Project, XML was chosen as the method for coordinating the various forms of construction data generated by a large building project as it is the only data storage format common to all relevant applications. Building design data stored in Revit can be exported to three different XML-based standards – ifcXML, gbXML and DWF-content XML (see Section 2.2.3 for details on these standards). Autodesk Building Systems (ABS), another application that is used for representing building design data, also supports export to gbXML. Project scheduling and cost estimate data as well as meeting notes are commonly stored in Microsoft Project, Excel and Word respectively, all of which export to XML. From the point of view of the ARTIFACT Project as a whole the most logical choice was to use XML as the underlying storage and exchange format. XML (eXtensible Markup Language) is a World Wide Web Consortium (W3C) 6  recommended language. It was initially designed to support information exchange over the Web, but today has become more commonly used for the purpose of exchanging data between applications, due to its expressiveness and extensibility. The basic structure of an XML file is quite simple. A file contains one or more elements, each of which can have zero or more sub-elements. Both elements and subelements can have attributes. The most important feature from a user’s perspective is that XML provides users with an unprecedented flexibility in describing and structuring their information in a manner that is most appropriate for their needs. Traditional data storage structures, such as relational databases, can be restrictive in their expressiveness because they enforce a relatively rigid organizational structure, a structure that may not be conducive for many types of information.  2.1.2  Current Status  The focus of the ARTIFACT Project to date has been on the building design data generated by large building projects. Making a change at this phase in the building project lifecycle typically has the biggest impact on a project: 75% of construction costs are decided at the design phase [43]. As well, many of the problems experienced in downstream phases and activities can be attributed to the design phase. For example, about 50% of the problems associated with productivity and quality in the construction phase are due to a poor building design [43]. Some initial research work on the ARTIFACT Project [52] was completed prior to the research work described in this document. The purpose of this initial work was to extract non-spatial building design data from Revit and to instantiate the concepts in the Construction Ontology (see Section 5.1) — an ontology of the building objects and relationships between them that are important to construction practitioners — based on this information. For example, attributes of a wall such as the wall’s thickness or length, what building storey it is located in (Contained in the storey), and the wall’s type — whether it is externally located (Is external), curved (Is curved) or clipped (Is clipped)) — are all considered non-spatial attributes. The final product of this work was a prototype application that allows construction practitioners to query the non-spatial concepts contained in the construction ontology. An example of such a query would be to determine the total length of all walls by  7  wall type (e.g., interior versus exterior) and wall shape (e.g., clipped and curved). One of the major difficulties encountered in extracting design data from Revit in [52] was the inability to determine the relative location of building objects (this challenge is described in more detail in Section 4.1.1). The motivation for the work described in this document stems directly from this shortcoming. It is important to point out that a few of the spatial queries articulated in the Construction Ontology were addressed in the initial work [52]; however, a number of assumptions about the spatial data had to be made. In particular, the semantics of the only locational information about building objects available through Revit’s export mechanisms — an object’s insertion point (4.1.1) — was assumed to have a certain position on the object. On walls, the insertion point was assumed to be in the middle of the lower-left edge of the wall; on columns, it was assumed to be in the center of the column’s bottom face [52]. However, this assumption cannot be guaranteed to always be accurate as Revit allows users to draw building objects in different manners and also allows them to manually change the placement of the insertion point. Moreover, there is also some ambiguity in the semantics of these assumed locations, for example, the definition of the lower-left edge of a wall. For these reasons, the initial work for Phase 1 focused on non-spatial building design data.  2.2  Building Design Data  Building design data includes any information related to the design of a building. Traditionally this would be the paper blueprints – the detailed set of plans used to guide construction. Today, in most large construction projects, building design plans are digital artifacts created and stored using 3D Computer-Aided Design (CAD) building modeling software. Most building modeling applications are now based on the building information model (BIM) and are referred to as objectoriented CAD.  2.2.1  The Building Information Model (BIM)  BIM is an object-oriented, semantic model of the elements that comprise a building [10]. Building components such as columns and walls are represented by objects that encapsulate the component’s attributes, its geometry, and its spatial relation8  ships to other building objects. For example, when a wall is added to a BIM, the object that represents the wall will describe not only the location and other physical information that is required to model the wall in 3D and situate it in relation to the other components (e.g., walls and columns) in the design, but also non-spatial information such as the wall’s type (e.g., masonry, exterior, interior, curved, clipped) and other properties such as its fire-rating, material composition and cost. This representation is aligned with the way in which construction practitioners think about a building design plan; model objects are meaningful representations of real world objects. The goal of BIM is to “assist in integrating the fragmented industry by eliminating inefficiencies and redundancies, improving collaboration and communication, and enhancing overall productivity” [13]. Inability of BIMs to Represent Higher Level Design Knowledge While BIMs provide a vehicle for representing richer and more varied design information, abstracting the construction-specific knowledge essential to the tasks required of a construction practitioner including cost estimation, method selection, scheduling, productivity analysis and project management is still very challenging. BIMs are created for designers, not construction practitioners, afterall. This limits the usability of BIMs for downstream activities, particularly for construction [36]. Examples of the design conditions that are important to the construction phase include the modularity, similarity, and layout of building components. This information is critical for constructing the walls, ducts, pipes, and columns in a building. For example, knowing if and where building components penetrate other building components is important because penetrations typically require special construction procedures such as fire stopping, weather resistance, and the application of penetration seals [36]. Currently construction design conditions must be explicitly derived through manual inspection, analysis and interpretation of a building design plan. For practitioners, this is a very inefficient, error-prone and frustrating exercise that limits the utility of BIMs for construction and other downstream activities [43]. In most cases, identifying all of the design conditions that impact construction is far too time-consuming; many constructability problems go undetected in the design  9  phase only to surface later during construction. The end result is in “rework, redesign, or decreased crew productivity” [43]. Substantially more computer support is needed to help practitioners be able to query a building model in a way that allows them to focus on the features that they deem important. While some efforts have been made on this front, progress has been limited. The proposed solutions are not entirely usable: they have either focused on a simple and narrow set of conditions, required an unacceptable level of user input, allowed the user to query only a subset of conditions, or have not supported customization [36].  2.2.2  Autodesk Revit Architecture: The Selected BIM Application  Designers of a building typically use software that is based on 3D Computer-Aided Design (CAD) technology to create a 3D model of a building and all of the components it contains such as columns and walls. Autodesk Revit Architecture (Revit), is a commercial CAD system and is commonly used in the AEC industry for large construction projects [3]. Revit is built on top of a building information model (BIM) (see Section 2.2.1). Revit is the application in which the building design information for the ARTIFACT Project is stored. Unfortunately, the data stored in Revit is effectively non-shareable in its native format due to its proprietary nature. The inability to exchange data between two different applications is a common barrier to data extraction efforts as many of the applications and data storage solutions available today have proprietary data storage formats.  2.2.3  IFC/ifcXML: Exporting Building Design Data from Revit  Revit provides several choices for exporting a native Revit file (RVT) including a handful of XML-based options: DWF-content XML, gbXML and ifcXML. DWF (DesignWeb Format) is an Autodesk file format for distributing design data created and stored in products such as Autodesk Revit [5]. The exported DWF file, which is really a package of files, is stored as a ZIP file [2]. Among the files contained in the DWF package is an XML file, content.xml (DWF-content XML), which contains the design information exported from the original RVT file. While containing most  10  of the components available in Revit as well as a majority of the properties of these components, much of the information related to component relationships that are derived from the relative location of components is not represented. gbXML (Green Building XML) is an object-oriented open source standard. It is a part of aecXML’s framework of XML standards for the AEC industry [30]. It addresses the data representation needs of the green building design movement [7]. Because it was created with a more focused purpose, the exported gbXML file contains only information pertaining to building energy analysis [7] such as the components related to spaces and surfaces: walls, windows, and doors are exported, but components such as columns, beams, slabs and ducts are not. IFC (Industry Foundation Classes) and its XML specification, ifcXML is also an object-oriented open source standard for the AEC industry. It was developed by buildingSMART (International Alliance for Interoperability) with the goal of making it easier to share and exchange the information used by AEC professionals during the “entire lifecycle of [a] building project including strategic planning, design and engineering, construction, and building operation” [22]. IFC represents not only the physical information that describes buildings, but also some of the information necessary for managing tasks that comprise a building project including planning, cost estimation, scheduling and operation [22]. Of the three XML export options available in Revit, ifcXML provides the representation that is closest to the BIM model – it provides the greatest coverage of attribute and geometric information is for construction components and several component relationships as well. For this reason, it was chosen as the XML export mechanism for the ARTIFACT Project [52].  2.3 2.3.1  Geography Markup Language (GML) Background  GML is an XML grammar defined by the Open Geospatial Consortium (OGC) to describe geographical features. It is by no means the first language developed to describe spatial data, but it is the first to gain widespread acceptance by the GIS community as demonstrated by its approval by the OGC [27]. The most recent 11  version, GML 3.2.1, was approved in July 2007 by the OGC and published later that year as an international standard (ISO 19136) [37]. GML provides a non-proprietary, open-source and standard representation of spatial data (up to three dimensions), units of measure, and coordinate reference systems. Although not required for the purposes of the ARTIFACT Project, GML also provides a grammar for describing spatio-temporal data [40]. Should there later be a need to track changes in building design plans over time, GML could be used to document and organize this information in a formal manner. The GML specification also specifies rules for extending the standard to create a domain-specific application schema. This means that construction practitioners can refer to the objects that make sense to them — walls, columns, and intersections for example — instead of points, lines and polygons.  2.3.2  The GML Model  The basic constructs of the GML data model are the feature and its properties. A GML feature represents a real world object such as a Column or Wall. A GML property is an attribute of a real world object or a relationship between objects. In a GML schema, features are encoded as direct elements of the root of the schema document, the <xs:schema> element. Properties are modeled as child elements of features with which they are associated. For example, the properties of a Column feature include its location (i.e., the centerpoint of the base of the Column), its height, the type of column it is, and so on. The following XML fragment provides an example of a GML instance demonstrating the relationship between an object (or feature) and a property of that object: <app:ObjectName gml:id=".."> <app:propertyName1>value1</app:propertyName1> . . . </app:ObjectName> The GML model differs from the traditional GIS model in what is modeled as first-class objects. Instead of representing geometric information such as a points, lines or areas as in the GIS model, objects in the GML model describe meaningful, 12  real-world objects such as a Column or a Building; these objects have some significance to the domain for which they are defined. Object properties may or may not be geometric. Specific features are not defined in the core GML schemas, but instead in application schemas that extend GML.  2.3.3  Extending GML: Community-specific Application Schemas  GML can be extended to provide data interoperability for a particular community through what are called application schemas. A GML application schema is a vocabulary that represents the spatial (and non-spatial) objects that are important to a specific target community. It is usually a smaller, more manageable subset of GML that is targeted for a particular set of uses within the domain [37]. For example, cityGML is an general-purpose application schema that models built structures and landscapes including water bodies, vegetation and elevation. cityGML provides constructs for describing buildings but does not support the level of detail for building components that is needed to support the type of analysis required by AEC practitioners [16]. Several application schemas, including cityGML, have been proposed. None exist for the AEC domain [38]. cityGML does provide some coverage of information for buildings, but not to the level of detail required to support the type of analysis desired by AEC practitioners.  13  Chapter 3  Related Work 3.1  Ontologies  An ontology describes the concepts in a domain and the relationships between those concepts [20]. Ontologies are particularly useful for representing domainspecific knowledge and developing knowledge-based technologies because they provide: (1) a common vocabulary, (2) explication of what has been often left implicit, (3) systematization of knowledge, (4) standardization, and (5) meta-model functionality, where the concepts and relations among them are used as building blocks for the model [31]. In AEC, ontologies provide a structured and consistent representation of building components.  3.2  Semantic Spatial Interoperability  Semantic interoperability refers to the ability of different systems to share information such that the semantics of the information stored in one system and transferred to another system will be interpreted correctly [9]. It is not a new concept within the database management research community. There has been substantial research on how to integrate multiple heterogeneous and incompatible storage formats to create a single, semantically integrated database; [18] surveys semantic integration in the database community. Recently, an extensive body of work has also addressed the problem of het-  14  erogeneity for spatial data. Most solutions have tackled semantic spatial interoperability by using an ontology to represent the semantics common to the spatial data sources to be integrated [12, 49]. A handful of solutions take the approach of standardization and champion GML as an XML-based standard that should be adopted by the geo-spatial community moving forward to ensure spatial interoperability [14]. This solution does not address how to integrate legacy multi-modal spatial data sources. We focus on creating the mappings from concepts in the final product of these previous works (i.e., an integrated spatial database) to the concepts that represent domain knowledge. In the AEC domain this is already done; in others it can be done using the previous work above. We also use an ontology, but we use it to provide an alternative view of the domain knowledge. Our aim is to transform the information represented by a building design plan from a designer-focused to a construction-specific view, but in a top-down manner driven by what the construction practitioner wants to see as anticipated by [9]. Finally, our work provides an end-to-end solution, one with which construction practitioners can actually work. Previous solutions provide only a base level of semantic interoperability through the integration of multimodal spatial data sources, and would require the additional work we provide to be able to directly support domain experts in extracting the knowledge they need.  3.3  XQuery-based Spatial Query Languages  XQuery [51] is the standard language for querying XML. XQuery was created as a general-purpose XML query language. While it provides substantial support for queries involving non-spatial attributes, it provides no native support for queries of a spatial nature [48]. It is therefore necessary to extend XQuery with custom spatial query predicates to support queries over GML [17]. A handful of XQuery-based spatial query languages for GML have been proposed in the research literature [8, 15, 24, 48]. While none of these languages are specifically created for the AEC domain, they all have been proposed within the context of Geographic Information Systems (GIS).  15  GML-QL The first of these, GML-QL [48], was developed when XQuery was in its infancy, several years before it became a W3C Recommendation. The purpose of the work in [48] was to evaluate the currently available XML query languages to determine which would be most suitable for the special challenges presented by spatial data and to extend the selected query language. They found that not only was XQuery the most powerful and flexible extant XML query language, but that it also had provisions for user-defined functions and was the W3C proposed standard [48]. Spatial queries can be categorized into unary and binary types [48]. A unary spatial query operates on spatial attributes for a single spatial object. Examples include operations on the boundary and interior of an object, or arithmetic operations such as Length and Area. A binary query operator is applied to two spatial objects. For example, the Distance between two objects is a binary operator. Most binary query operators can be classified as topological relationships which are “based on the set of intersections of the boundaries and interiors of [...] two spatial objects” [48] and include Disjoint, Meet, Overlap, Inside/Contains, Covers/CoveredBy and Equal. Examples of queries such as determining the area of a country (using an area function), conducting buffer analysis (using a buffer function) or performing spatial joins (e.g., overlap) are found in [17, 48]. However, the authors do not provide any concrete implementation details. CXQuery CXQuery was proposed around the same time as GML-QL. It is a rule- or constraintbased, Datalog-style query language. It provides support for both spatial and spatio-temporal queries through operators such as area and length. While it is a query language, the main focus of the work is to “provide schema information in the query result” [17] for the purpose of better manipulating spatial data (e.g., defining views and updating data). As was the case in [48], Chen et al. do not describe in any detail the operators they implement [15]. Moreover, no topological operators are described by the authors.  16  GQuery GQuery is an XML query language with extensions for spatial data whose goal is to facilitate the integration of spatial data and is used in the VirGIS mediation system. GQuery is the first spatial XQuery-based query language in the research literature that actually describes a functional implementation. A spatial data model with basic data types — point, line and polygon — that extends XQuery is given in [11]. It implements three different types of spatial operators: (1) those that are used for spatial analysis and return numeric data such as Area, Length and Distance, (2) those that are used for spatial analysis and return GML values such as Convexhull and Centroid and, (3) those that represent spatial relationships and return boolean values such as Equal, Within and Touches. In a later refinement to GQuery, Belussi et al. extend the breadth of topological relationship operators that fall into the last category to include the set of topological relationships defined in the 9-intersection model (9-IM) [8]. The 9-IM characterizes the “fundamental concepts necessary for the analysis of spatial spatial data in a [...] GIS” [19]. These relationships are “based on fundamental geometric principles and models” [19] and do not represent any specific application domain. In particular the 9-IM describes the possible binary topological relationships between two spatial objects (i.e., points, lines and regions) which are represented by their interior, exterior and boundary: Disjoint, Touch, In, Contains, Equal, Cross, Overlap, Covers, and CoveredBy [19]. GQL XQuery can be extended in four ways: data model, algebra, functions and formal semantics [24]. The data model extends XQuery with twelve new spatial data types in order to more adequately capture the semantics of GML data. These include Geometry, Coord, Coordinates, Point, LineString, LinearRing, Polygon, Box, GeometryCollection, MultiPoint, MultiLineString and MultiPolygon. GQuery also provides an algebra for XQuery to better support spatial analysis and queries: the authors define spatial relationship predicates based on the 9-IM as was done by [11]. The seven topological predicates implemented in GQuery are Disjoint, Touches, Crosses, Within, Overlaps, Contains and Intersects. GQuery, like GML-QL, also  17  defines a set of unary and binary functions. The unary functions implemented in GQL work either with Dimension, Boundary, Convexhull and the Interior of spatial objects or are arithmetic operations such as Length, Area and Volume. The binary functions provided in [24] include Distance, Buffer, Direction, Union, Difference and Symdifference. GQuery also provides a formal definition of semantics “to enhance the GQL specification by defining the meaning of GQL expressions, ensure that no corner case is left out, and provide a reference for implementation” [24]. Our Approach We base our work on the core topological relationships specified by the 9-IM and extend it for the AEC application domain. However, we do not, in our framework, implement all nine of the topological relationships identified by the 9-IM in our first implementation but only those that were necessary for creating the more complex spatial query predicates representing the spatial relationships important to construction practitioners: Intersects, Touches and Disjoint (see Section 5.3.3).  18  Chapter 4  Case Study in the Architecture, Engineering and Construction Domain (AEC) 4.1  Construction-Specific Spatial Relationships are Not Supported by BIMs  As has been suggested in Chapter 1, many of the interesting and more difficult to extract building design conditions for construction practitioners have some spatial component to them. This is not surprising as the location of and spatial relationships between building components are what essentially define a building. Unfortunately, there are no existing software applications that can support sophisticated spatial analysis of BIMs or BIM-based models such as IFC [10]. Queries on BIMs are limited to predefined spatial relationships targeted to designers, the population for which BIMs were created. Most of the spatial relationships supported by BIMs can be described as highlevel boolean relationships. For example, whether two components such as a column and a wall intersect. No further details about the spatial relationship such as the dimensions of the intersection or the location within the building project are encoded in the underlying model. Other potentially interesting and more useful  19  spatial relationships from a construction practitioner’s point of view, such as the alignment of columns to a building project’s gridlines, the uniformity of columns across the levels of a building, the spacing between columns, and the connections between architectural and building service components (e.g., a wall and a duct), are not represented by BIMs at all [44]. This is a major shortcoming. In today’s large multi-story construction projects, this is a very serious limitation. Construction-specific spatial queries typically span multiple floors making them difficult, if not infeasible, to answer through manual inspection of a digital building design plan or paper blueprint.  4.1.1  What Spatial Data is Missing?  Even though construction-specific spatial relationships are not explicitly available through Revit’s data model (i.e., a BIM), conceivably such relationships could be interpolated given the location of each building object in the building project plan. One of the options for exporting data from Revit is IFC. 2.2.3 In IFC the location of a building object is provided in the form of an insertion point — the location on the object where the user started to draw the building component using Revit’s interface. Unfortunately, the semantics of an object’s insertion point is not explicit: where the insertion point is on each object is variable and depends on how the object was drawn by the user using Revit’s graphical interface [52]. Therefore, one can only assume where the insertion point is on the object given its IFC representation. In previous work [52] on the ARTIFACT Project (see Section 2.1.2), the location of an object’s insertion point was assumed to be in a particular location to facilitate the computation of some of the construction-specific spatial queries as an initial proof of concept. For example, it was assumed that insertion points for walls are always in the middle of the wall’s lower-left edge and for columns are in the center of the column’s bottom face. However, this is not always true. Revit is flexible and allows designers to change the location of insertion points when they create their models. Moreover, the semantics of the assumed location of the insertion point for various objects is also ambiguous. Concepts such as “left” need to be clearly defined in order for the meaning to be interpreted correctly. An additional complication is that an insertion point alone is not sufficient to  20  locate a building object in 3D space. To determine where the boundary of an object’s surface is situated, additional data is required such as the object’s orientation, dimensions (e.g., length, height) and shape. However, this information is not exported by Revit to IFC for all building objects. For instance, the orientation of curved walls is not available, nor is height information for one of the column types, and only the insertion point and shape information is available for ducts [52]. In such cases, spatial queries involving these building objects cannot be supported.  4.2  Solution: Direct Extraction of Spatial Data Using the Revit API  The inability to export spatial information from Revit project files using IFC (or any of the other export mechanisms available for Revit) meant that we had to find an alternative method for extracting the relative location of building objects. We chose to use the Revit API which is described in Section 4.2.2. The Revit API provides a way to programmatically access the spatial data that is hidden within each building object in a building project. However, this method does incur significantly more overhead than simply using a built-in export mechanism in terms of the time required to learn how to use the Revit API and to determine how spatial data is represented in Revit’s BIM-based data model. In order to extract the spatial information needed to answer the spatial queries that are important to construction practitioners, we first had to determine what spatial data Revit stores for the building objects — walls, columns, and ducts — and how it is organized within its data model. We also required spatial information about the project’s grid in the xy-plane. The grid is composed of individual gridlines that are automatically lettered in the x-direction and numbered in the y-direction. Its primary use is to help practitioners more easily locate columns. Instead of referring to a column’s center as an xy-coordinate, practitioners instead typically refer to the intersection of labeled gridlines (e.g., a column located at grid intersection 3-A will have its center at the point where the x-gridline named 3 and the y-gridline named A intersect). The spatial queries identified by the domain experts on our team as being important to construction practitioners (Section 5.3 requires the use of gridlines; the output of some of these queries, particularly those 21  regarding columns, is specified in terms of gridlines. In Section 4.2.1, we address Revit’s representation of spatial data for building objects. This is followed by a description of the application that was developed to extract the spatial data for walls, columns and gridlines from Revit, the Spatial Data Extraction Application in Section 4.2.3.  4.2.1  Spatial Data Representation of Building Objects in Revit  The objects in a building project, such as columns, walls, ducts and gridlines, are represented as elements in Revit. All of the elements in a building project are stored in a single Elements list and are associated with a Document object — a Revit project file or building design plan [26]. Each building object stores its own spatial information. The most basic representation of a building object’s location in Revit is either as a point or a line which identifies the ‘center’ of the building object. If the object’s location is a point as is the case with columns, it will have an instance of the Revit LocationPoint class. If the location is a line, as is the case with walls, the object will have an instance of the LocationCurve class. The external surface of building objects, such as a wall’s faces, was not extracted for this initial implementation of the Semantic Spatial Interoperability Framework. We made this decision because of time constraints and the fact that this information is really only necessary for building objects that do not have a regular shape (e.g., curved or clipped (i.e., slanted) walls), which is generally not the case. Moreover, determining how this information is organized in the Revit API and how to extract it is significantly more complicated. A LocationPoint object has a single 3D coordinate in the project’s Cartesian coordinate system and a LocationCurve object has two or more 3D coordinates. If the object is not curved, the LocationCurve will store two points that represent the endpoints of the centerline that describes the object’s location in 3D space; otherwise it will store several points to approximate the line. The LocationCurve also contains a Function parameter that describes the object’s trajectory through 3D space as a mathematical expression. Because the location of each object — either in the form of a LocationPoint or a LocationCurve — is in the same coordinate system this information can be used to determine the relative locations of two  22  Figure 4.1: Spatial information stored by the Revit API for a Wall objects. Therefore, topological relationships between objects can be deduced [4]. However, the distances calculated between points in this coordinate system does not necessarily represent the actual distance between building object instances in the units specified by the user because Revit converts all location information into the internal units it uses [28]. Walls As demonstrated in Figure 4.1, the Revit API stores two pieces of spatial information about a Wall: the Wall’s centerline — a line that follows the trajectory of the Wall — and its height. The centerline describes the Wall’s location in the xy-plane which can be thought of as the plane that describes the floor of the building. The height describes the Wall’s location in the z-direction. The centerline of a Wall is represented in the Revit model as a Curve object which is a child of the LocationCurve object. The Curve object stores an array of 3-dimensional points which can be accessed using the object’s Tessellate function. The array representing the centerline of a straight Wall will contain two points which identify the two endpoints of the Wall’s centerline. The array representing a curved wall will contain multiple points — the greater the curvature of the wall, the greater the number of points that are required to adequately capture its location [32].  23  Columns Columns are children of the Category class in the Revit API. There are two types of Columns in Revit: Structural Columns (i.e., OST StructuralColumns) and Architectural Columns (i.e., OST Columns). Objects that are children of the Category class in Revit, such as Columns, are represented by an enumeration class called BuiltInCategory. The geometry of a column is defined by two spatial properties: a centerpoint and a height. The centerpoint represents the location of the center of the column in the xy-plane: the intersection of the midpoint of the column in the x-dimension with the midpoint of the column in the y-dimension. It is modeled as a LocationPoint object which contains an XYZ 3D coordinate point; the z-coordinate is the same as the z-value of the level (or floor) where the Column is located. The height represents the height of the column in the z-direction [32]. Gridlines As mentioned in Section 4.2, Gridlines are required for spatial queries because construction practitioners typically refer to a Column’s location not by its location in the xy-plane, but instead by the grid intersection to which the Column is aligned. Gridlines are modeled as instances of Revit’s Grid class. A Gridline’s location is represented in the same manner as the centerline of Wall: as an array of two (or more) points that are extracted from the LineCurve object using the Tesselate function. It is assumed that Gridlines are straight lines. The gridline’s axis property, gridAxis, is a derived value that is determined by comparing the two points representing the gridline: if the x-values of the two-points are equal, then the axis of the gridline is “x,” otherwise it is “y.” The gridline’s value, gridlineValue, is also derived and is the value of the x- or y-coordinate corresponding to the axis of the gridline. The name of the gridline is a property of the Grid class; it is an integer if the gridAxis of the Gridline is “x” and a letter if the gridAxis is “y.”  24  Ducts Due to time constraints, we did not explore how to extract the spatial information for Ducts from the Revit API. It was decided that our limited time be allocated to first extracting the spatial information for Columns, Walls and Gridlines as this information is used in a many of the spatial queries required by construction practitioners whereas Ducts are only involved in the Penetration spatial query (see Section 5.3.4). However, spatial information was determined for a single building project file that had a duct modeled to allow us to test the Penetration query. This information was ascertained using the RvtMgdDbg which is described in more detail in Section 4.2.2. In particular, the duct’s centerline, diameter, length, and its elevation at the bottom, center and top of the duct was determined.  4.2.2  The Revit API  The Autodesk Revit API is an application programming interface that gives programmers direct access to Revit’s BIM model — all BIM building element objects as well as their properties. This facilitates more sophisticated analysis of a building project and, for our purposes, the ability to answer custom spatial queries. The API is built into all Revit applications. To develop an application that uses the Revit API requires a .NET development environment. Any .NET-compliant language can be used to interface with the API. Applications that access the API must be deployed as a Microsoft dynamic-linked library (or DLL). After being compiled as a DLL the application gets deployed within the Revit application. The application can either be an external command which is added to the Revit submenu External Tools (in the Tools menu on the toolbar) or an external application which supports the creation of a customized interface that builds off of the elements in the Revit framework [4, 6]. Revit also provides an external application, the RvtMgdDbg, that allows users to explore the Revit API to discover the internal structure of the Revit model. It is comprised of five different commands, two of which were useful in determining the spatial information for building objects (see Section 4.2.1): Snoop Db and Snoop Current Selection. The first command allows the user to explore the properties of the elements in the Elements list for the open building project file. The  25  second command is a simply a more targeted version of the first command: it provides property information for elements that have been selected in the Revit interface. These two commands helped us find values for the spatial properties we were interested in, which allowed us to test the functions we created to extract spatial information from the Revit API. They also helped us navigate the hierarchy of element properties which helped us discover how to extract the information we wanted from the Revit API [29].  4.2.3  Spatial Data Extraction Application  The application that was created to extract spatial data for Walls, Columns and Gridlines from Revit’s BIM data model using the Revit API was developed in Microsoft Visual Studio using C#, a .NET-compliant language, a requirement for working with the Revit API [4]. The application is essentially organized as three different external tools — ColumnLocation, WallLocation, and GridLocation — that are available from the Tools menu item in the toolbar in Revit’s interface. Each Tool extracts the spatial information discussed in Section 4.2.1 for the building object it is named after (e.g., the WallLocation tool extracts the centerline and height, as well as length for all walls in a building project file); this information is output in an XML file.  4.2.4  Challenges  While directly extracting spatial data through the Revit API was the only solution available, it was not an easy nor quick one. There were a number of issues that surfaced during the data extraction process: • The Revit API is a large, very complicated and nested object model. This makes it difficult to find information. The Revit API class hierarchy is provided in Appendix E, and while somewhat difficult to read, it does provide an idea of the magnitude and nested nature of the model. For the past few years, the size of the API has doubled. In the 2008 release there were over 400 classes [47].  26  • The documentation for the Revit API does not provide much assistance. While help files are included, they only provide a basic listing of the Revit classes, methods and properties. However, in the Revit model, class information is not always sufficient to identify a particular building object in a Document’s Elements list, which even for small project files can contain upwards of 2000 elements [26]. Some building objects — such as columns, ducts, doors, beams and windows — can only be identified by their category, of which there were 598 in the 2008 release of Revit. Once a desired object has been located, extracting its spatial information is not necessarily straightforward either. For example, to get at the numerical values for the coordinates of the points that form the centerline of a wall, the Location property must first be extracted and cast as a Curve object. The Tesselate function must then be called on the Curve representing the wall’s centerline to produce an XYZArray which is an array of 3D coordinates. This array can be iterated through and the individual X, Y and Z values extracted. • Units of measurement also present some difficulties. The units associated with a measurement are not stored directly with the quantity. Moreover, the units for measurements used internally by the Revit database (i.e., the Revit internal units) may or may not correspond to the units specified by the user in the Revit application interface (i.e., the display units). This is because Revit has its own internal fixed set of database units for different types of numerical measurements. For example, the thickness of a 200mm wall (i.e., the value of the user-specified parameter ‘width’ is 200mm in the Revit interface) when queried from the Revit API will return a value of 0.6561. Without knowledge of the Revit API, it is unclear what this quantity means. Revit uses imperial units internally for length: feet for length measurements and square-feet for area measurements. These units are used by the Revit application for any calculations it needs to do and are also the units for numerical measurements returned when the Revit API is queried. Therefore, because ‘width’ can be categorized as a ‘length’ type of measurement, 0.6561 will be the width of the 200mm wall in feet. The display units specified by the user in the Revit application interface can be queried from the Revit API by  27  extracting the DisplayUnitSystem property from the Document object and appropriate conversions between the display unit and the Revit internal unit can be done. Alternatively, the display units used for an individual building object attribute can also be determined by extracting the DisplayUnitType property from the parameter [28].  28  Chapter 5  Semantic Spatial Interoperability Framework (SSIF) Designers of a building typically use software based on a Building Information Model (BIM). A BIM is an object-oriented model of a building from the designer’s perspective. Because it is tailored to the needs of designers, BIMs do not support the needs of those working on other phases of the building project life-cycle when their needs stray from that of the designer. For example, a designer sees the building primarily in terms of its aesthetics and functionality — their world is composed of rooms, individual walls, and columns. Designers are not concerned with higher level spatial topological relationships such as the horizontal layout of columns on a floor or the uniformity of the location and dimensions of columns from one floor to the next. This is the knowledge that concerns construction practitioners who choose which of multiple construction methods to use during building construction. The inability of building design applications to support different views of a building design plan is a serious impediment. There is a real and pressing need for applications that can provide these alternate views to support the type of analysis described here and in Example 1; it is simply too difficult and time-consuming to do manually. Our work is a necessary precursor to such future applications. Providing the sort of semantic interoperability we describe requires two key components: (1) a way to encode the user’s view of the data in a formal and 29  Figure 5.1: Semantic Spatial Interoperability Framework machine-readable way and, (2) a way to automatically transform or map the application’s internal model to the domain user’s view. The Semantic Spatial Interoperability Framework (SSIF) described in the following sections implements these two components for construction practitioners. Our construction-specific ontology describes the construction view of a building plan. The mappings from BIM objects to concepts in the construction-specific ontology are implemented as XQuery spatial query predicates. This section describes these components in greater detail.  5.1  The Construction Ontology  The Construction Ontology (see Appendix A) describes the important knowledge for construction practitioners in terms of concepts and relationships between concepts. It was developed jointly by the civil engineering and data management experts on our team. The ontology is comprised of features — objects in the design that have meaning to construction practitioners — and the relationships between them. This knowledge is described in an unambiguous and consistent way using Prot´eg´e [41] to ensure that data can be easily exchanged between applications [36]. As the purpose of our ontology is to represent the implicit design conditions embedded in a building design plan that are critical to building construction practitioners, only those features and relationships that can contribute to the representation of these conditions are described. Each of the conditions that we modeled were identified by the domain experts on our team.  30  The ontology is comprised of three basic elements: features, relationships between features, and properties of each. Both the features and the relationships are represented as classes: Component, Opening, Intersection, Penetration, Design Uniformity, Spacing, and Alignment [36]. These elements represent the data the designers and construction practitioners need to interoperate. The Component class represents features — the standard building elements — such as Walls, Columns, Openings and Ducts. The other five classes are relationships between features and represent the design conditions that impact a project’s constructibility. Knowledge about these relationships is important because they may require additional work during construction as described in more detail in Section 5.3. These relationships are some of the more common conditions that construction professionals look for in a building design plan. These higher level spatial topological relationships are the ones for which we implemented XQuery spatial query predicates; they encode the mappings from the designer-specific BIM to the construction ontology. The more complex construction-specific topological query predicates use some of the core spatial query predicates described in Section 5.3 — the topological relationships defined in 9-IM — as building blocks. We did not implement all nine of the 9-IM topological relationships. Instead we elected to implement only those relationships needed as building blocks for the construction-specific spatial query predicates, i.e., Intersects, Disjoint and Touches.  5.2  The ARTIFACT Application Schema (AAS)  This section describes how I extended GML to create an application schema tailored to the AEC domain. The most current version of the GML Schema, GML 3.2.1 [39], was used to create the ARTIFACT Application Schema (AAS). The complete AAS can be found in Appendix B.  5.2.1  Representing Location  Several geometric types are provided by GML including one-, two- and threedimensional types. In the initial version of the AAS, only two-dimensional spatial information is encoded for the features specified in the Construction Ontology 31  (Section 5.1). The location of a feature is therefore described in terms of points and/or lines. Points GML provides two geometric types to represent a single point: the PointType and the PointPropertyType. If the point is encoded as a first-class object, the PointType should be used. However, in most cases the location of a feature should be encoded as a property of the feature; in this case the PointPropertyType is required. In the ARTIFACT Project, a Column’s location is specified by the centerpoint of the base of the Column. We model the centerpoint as a property of the Column; it is represented as a PointPropertyType in the AAS. The location of an Intersection and the location of a Penetration are also represented using the PointPropertyType: each of the eight corners of the rectangular cuboid (or box) that represents the three-dimensional intersection of a Column and a Wall, a Wall and a Wall, or a Duct and a Wall (i.e., a Penetration) is a point. For example, the schema element for the centerpoint of a Column has the following structure: <element name="centerOf" type="gml:PointPropertyType" minOccurs="1" maxOccurs="1"/>  The minOccurs and maxOccurs attributes are optional. They specify the minimum and maximum number of occurrences of an element. Columns must have exactly one centerpoint; therefore, both the minOccurs and maxOccurs attributes in the schema fragment for the centerpoint of a Column have a value of 1. Lines The GML CurveType and CurvePropertyType represent a line; the former type is used for an object and the latter for a property. In the ARTIFACT Project, the location of Walls and Ducts are represented using the CurvePropertyType. For instance, the schema element for the centerline of a Wall or Duct is as follows: <element name="centerLineOf" type="gml:CurvePropertyType" 32  minOccurs="1" maxOccurs="1"/>  As was the case with a Column’s centerpoint, Walls and Ducts must have exactly one centerline specifying their location. Instances of Point and Line Schema Elements GML’s PointPropertyType and CurvePropertyType specify geometric types for the properties of features such as Walls, Columns and Intersections. However, when an application schema such as AAS is instantiated with the information from a particular building design plan, these types are replaced with specific geometry object types. In an instance of a GML application schema, GML’s PointPropertyType is replaced with GML’s Point type. The following excerpt is an instance of the centerOf property of a Column: <centerOf> <gml:Point srsName="gml:CartesianCS"> <gml:pos>-33.75 20.79 0.00</gml:pos> </gml:Point> </centerOf> The actual coordinate of the Point representing the centerpoint of the Column, (-33.75, 20.79, 0.00), is encoded as a subelement of the Point using the GML pos property as shown above. GML’s pos property is a direct position: Definition 1 A direct position is a location in space whose coordinates are specified relative to some coordinate reference system (CRS) — a system of coordinates that uniquely identifies a point in the space defined by that system. The srsName attribute is used to specify the CRS that should be used to interpret the coordinates encoded by a pos property [33]. Typically the srsName attribute is specified on the geometry object — in this case a Point — containing the pos property and not on the pos property itself as is demonstrated in the 33  instance of a centerOf schema element above [33]. In the ARTIFACT Project, the CRS is a three-dimensional Cartesian Coordinate system. It consists of three perpendicular axes — x, y and z — the intersection of which corresponds to the origin of the system. All points in the system are specified by three coordinates that identify the signed distances of that point from the origin. GML 3.2.1 provides a concrete CartesianCS type which is used in an instance of the AAS, as shown in the excerpt above. Similarly, GML’s CurvePropertyType can be replaced with several associated GML curve object types in an application schema instance including the LineString, Curve, OrientableCurve and CompositeCurve types [40]. A LineString is the GML type that represents a straight line. It is encoded as a set of coordinates referred to as control points each of which are a direct position (as defined in Definition 1); the LineString connects the control points [27]. In the ARTIFACT Project, the location of Walls and Ducts are described using their centerline and are represented in the AAS using a LineString object. An example of an instance of the AAS centerline element follows: <centerLineOf> <gml:LineString srsName="gml:CartesianCS"> <gml:posList dimension="3">-33.75 20.79 0.00 -33.75 50.79 0.00</gml:posList> </gml:LineString> </centerLineOf>  The control points of a LineString are represented as a single subelement of a LineString using the GML posList property, a list of double numbers. The posList property does not delineate individual points in the posList. To ensure that the points in the posList are interpreted properly, a dimension attribute is provided to specify the number of coordinate entries for each point. Because the CRS for the ARTIFACT Project is a three-dimensional Cartesian coordinate system, the dimension of posList is set to 3.  34  5.2.2  Features  Each real-world object identified in the Construction Ontology (Section 5.1) is modeled as a GML feature in the AAS. A GML feature is defined by creating a global element whose type is derived from the GML AbstractFeatureType. A global element is simply a child element of the schema element. For example, the following excerpt from the AAS shows the definition of the grid feature. It is a direct subelement of the <xs:schema> element and its type is an extension of the GML AbstractFeatureType: <xs:schema version="1.0" targetNamespace="artifact" elementFormDefault="qualified" xmlns:artifact="artifact" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.w3.org/2001/XMLSchema"> . . . <element name="grid"> <complexType> <complexContent> <extension base="gml:AbstractFeatureType"> <sequence> <element ref="artifact:Gridline" maxOccurs="unbounded"/> </sequence> </extension> </complexContent> </complexType> </element> . . . </xs:schema> In most cases, the types of features are defined implicitly and hidden within the feature definition as is shown in the schema excerpt for a grid feature: the grid’s 35  type is a complexType (i.e., it contains other elements, as opposed to a simpleType which do not). Named types — a simpleType or complexType that is defined as a subelement of the <xs:schema> element and is given is a name — are only used where the type needs to be reused [50].  5.2.3  Feature Collections  For each feature in the AAS — Wall, Column, Duct, Intersection, etc — a GML feature collection is also modeled in the AAS. For example, there is a feature collection called walls that acts as a container for all Wall features in a building: <element name="walls"> <complexType> <complexContent> <extension base="gml:AbstractFeatureType"> <sequence> <element ref="artifact:Wall" maxOccurs="unbounded"/> </sequence> </extension> </complexContent> </complexType> </element> The walls feature collection is itself a feature — it extends GML’s AbstractFeatureType — and it contains GML objects, each of which must be a GML feature. Each feature in the collection is modeled as a property (i.e., subelement) of the collection and its type must extend GML’s AbstractFeatureMemberType as shown in the following schema definition of a Wall. <element name="Wall"> <complexType> <complexContent> <extension base="gml:AbstractFeatureMemberType"> ... 36  </extension> </complexContent> </complexType> </element> The AbstractFeatureMemberType identifies the property as a member of a feature collection.  5.2.4  Feature Relationships  In GML, a Feature Relationship is not modeled as a Feature, but instead as a property on a Feature or the Features participating in the relationship. This is contrary to the model of a building as described by the Construction Ontology (Section 5.1) in which spatial relationships such as Penetrations and Intersections are modeled as first-class objects or features. Therefore, to maintain the semantic model of a building held by construction practitioners, spatial relationships are modeled as GML features in the AAS. For example, the Intersection spatial relationship is modeled as an element instead of as a property of an element or elements: <element name="Intersection"> <complexType> <complexContent> <extension base="gml:AbstractFeatureMemberType"> <sequence> <element ref="artifact:Wall"/> <choice minOccurs="1" maxOccurs="1"> <element ref="artifact:Wall"/> <element ref="artifact:Column"/> </choice> <element name="location" type="artifact:IntersectionLocationType"/> <element name="area" type="gml:MeasureType" minOccurs="0"/> <element name="volume" type="gml:MeasureType" 37  minOccurs="0"/> </sequence> </extension> </complexContent> </complexType> </element>  5.2.5  Units of Measure (UOMs)  It is important to qualify a numerical measurement with units. Failing to do so introduces ambiguity and can easily lead to the incorrect interpretation of numerical measurements. The GML schema, units.xsd, provides seven base unit of measure (UOM) types as defined by the International System of Units (SI) [33]. The only relevant base unit for the ARTIFACT Project is the one for length; the unit specified for length is the metric unit metre (m). However, in the Revit internal model, length measurements are specified using feet, and area and volume measurements with square-feet and cubic-feet respectively. The definition of a foot UOM is not provided in the GML model and must instead be explicitly defined. GML’s units.xsd provides constructs to support the creation of user-defined UOM. While UOMs can be specified within an instance of a GML application schema, they are more often specified in a units dictionary to enable reuse and to make their definition explicit. We took this latter approach in our project. A units dictionary is simply an XML file that contains a collection of GML Definitions for UOM. The ARTIFACT units dictionary, units.xml, contains entries for feet, square-feet and cubic-feet. It is provided in Appendix C. The definition of feet is provided below: <gml:dictionaryEntry> <gml:ConventionalUnit gml:id="ft"> <gml:name codeSpace="http://www.bipm.fr/en/3_SI"> feet </gml:name> </gml:ConventionalUnit> <gml:quantityType>length</gml:quantityType> <gml:catalogSymbol codeSpace="http://www.bipm.fr/en/3_SI"> 38  ft</gml:catalogSymbol> <gml:conversionToPreferredUnit uom="#m"> <gml:factor>0.3048</gml:factor> </gml:conversionToPreferredUnit> </gml:dictionaryEntry> The feet UOM is of type ConventionalUnit, the GML type for encoding UOM definitions that are not a base type or derived from the base types (e.g., the UOM of kg/m3 which is a unit used for mass density; it combines the base units of meter and kilogram). The GML dictionaryEntry type also has a built-in property, conversionToPreferredUnit which is used to specify the factor for converting the defined type to another UOM type. In the definition of feet, the conversion factor to meters, 0.3048, is provided. In an application schema such as AAS, it is possible to require that a UOM be specified on a property that is a numerical measurement. This can be done by including the uom attribute with a value of “required” in a user-defined type definition for the property. Alternatively, the property can be given the GML MeasureType, a built-in type that can be used for a measurement whose value is of type double and which requires a UOM: <complexType name="MeasureType"> <simpleContent> <extension base="double"> <attribute name="uom" type="gml:UomIdentifier" use="required"/> </extension> </simpleContent> </complexType> The following schema element for a length property of a building element such as a Wall demonstrates the use of the GML MeasureType <element name="length" type="gml:MeasureType" minOccurs="1" maxOccurs="1"/> 39  To specify concrete units for a numerical property in an instance of a GML application schema, the UOM attribute is used. In a GML instance, the UOM attribute must be a URI that either points to a local UOM definition (i.e., it is defined directly in the instance of the GML application) or to a UOM definition in an external unit dictionary. The latter approach was taken in the AAS. The instance fragment that follows shows the use of UOM with the length property: <artifact:length uom="http://cs.ubc.ca/˜awebster/artifact/ units.xml#ft">10</artifact:length>  5.2.6  Schema and Instance Validation  A GML application schema is valid if it conforms to the rules specified by XML Schema 1.0 as well as those specified by the version of GML that is extended, in our case version 3.2.1. An instance of a GML application schema is valid if it is a well-formed XML document — it meets the syntactic rules specified by the XML 1.0 Specification — and if it satisfies the requirements specified by the application schema. For example, a schema might require that certain elements, properties and attributes (e.g., the UOM attribute on the length property of a Wall) must be included. It also dictates the structure of elements such as the order of properties belonging to a feature. The Oxygen XML Editor, the application used to create the AAS, also provides functions to validate schemas and to ensure that a schema instance — an XML document — is well-formed and conforms to the appropriate schema [45].  5.2.7  Challenges  A number of challenges were encountered in developing the AAS: • Several application schemas, including cityGML, have been proposed for various domains [38]. Investigating, which, if any of these might be suitable to use or extend to create a new application domain requires the user to manually search through the GML Schema for each if there is any possibility of overlap. There was one potential application schema that we explored to see if it would be a suitable base for our application schema for the AEC 40  domain. cityGML is a general-purpose application schema that models built structures and landscapes including water bodies, vegetation and elevation. cityGML provides constructs for describing buildings but does not support the level of detail for building components that is needed to support the type of analysis required by AEC practitioners [16]. Moreover, it models a significant amount of information that is unnecessary for the AEC domain. • The documentation for the GML Schema is limited and not easy to understand making it difficult to figure out how to convert the domain model as specified by the Construction Ontology (Section 5.1) into the GML model. This is further complicated by a number of factors. First, the sheer size of the GML schema makes it difficult to navigate and determine how to model a concept. Second, some GML types get deprecated from one version to the next and schema validators (Section 5.2.6) do not identify these elements as errors. Third, the GML Schema provides multiple ways of encoding the same concept. It is often unclear which representation is the best for a particular situation. For instance, a list of coordinates that represent a line, as an example, can be represented either as a <gml:coordinates> element, as a <gml:posList> element, or as a series of individual <gml:pos> elements. There is no guidance provided for using one representation over the other and no justification as to why the different representations are provided. • There was a mismatch of the GML Schema model to the application domain model. In particular, feature relationships in the GML model are not firstclass objects but are instead encoded as properties of GML features. For example, in the following GML Schema excerpt that represents the intersection between a Road and a Creek, the spatial relationship is modeled as a property of a feature, the Road: <app:Road gml:id = "R1"> <app:intersects> <app:Creek gml:id = "C1"/> </app:intersects> </app:Road> 41  This is contrary to the way relationships are modeled by construction practitioners — as first class objects — as demonstrated in Section 5.2.4. In order for the AAS to accurately represent the way that construction practitioners view building design data, as articulated in the Construction Ontology (Section 5.1), it was necessary to veer from how the GML Schema models feature relationships.  5.3 5.3.1  Construction Query Predicates Overview  Many of the interesting and relevant construction-specific queries from the perspective of construction practitioners are prohibitively difficult to answer manually through the review of building design plans. These queries typically span multiple stories. However, design plans are presented on a per-level basis. Determining whether the columns are aligned on a single level is easy; determining whether the columns on each level of a 50-storey building is not. Doing comparisons across levels is significantly more cumbersome! This is precisely where practitioners need support. All of the construction query predicates desribed in this section can be found in Appendix D.  5.3.2  Assumptions  In a first pass at satisfying the spatial queries required by building practitioners our goal was to address the cross-section of queries that are commonly required by a building project practitioner and that have a serious impact on the constructibility of large building projects. Many of our assumptions were made in light of the target to contain the scope of the work. Our assumptions also took into account the available information and the trade-off between the difficulty of the query — which included the efforts required to extract the spatial data necessary to answer the query — and its significance to the AEC domain: • Building components are regularly shaped - their base is either square, rectangular or circular. The vast majority of building components meet 42  this criteria. The spatial representation of irregularly shaped components is much more complicated; the time and effort required to extract and interpret the spatial information needed to satisfy the construction-specific queries for this class of components was deemed to be too prohibitive for the initial prototype. • The b dimension of the base of rectangular columns is assumed to be aligned to the project plan’s horizontal or x-axis and the h dimension of the base is assumed to be aligned to the project plan’s vertical or y-axis. This is a necessary assumption as in the case of rectangular columns, there is semantic ambiguity with respect to the dimensions of the base, b and h: it is unclear which of b and h represents the x-dimension of the base and which represents the y-dimension. • Curved walls are excluded. Curved walls are not commonly used in a building project.  5.3.3  2D Topological Query Predicates  In the initial prototype of our proposed semantic spatial interoperability framework, we implement only those 2D topological query predicates required to implement the construction specific query predicates described in Section 5.3.4. In particular we implement the Intersects, Touches, and Disjoint query predicates that were defined in [19]. We also introduce two new 2D topological query predicates – Proximate and On-Grid – not specified by the 9-IM model described in Section 3.3. These predicates were needed to implement the Spacing (Section 5.3.4) and Alignment (Section 5.3.4) query predicates. Intersects, Touches, and Disjoint The Intersects, Touches and Disjoint query predicates are boolean functions; they take as input two building components. The Intersects query predicate is true if there is an intersection or overlap in the space occupied by the two building components. There are two ways in which building components could potentially overlap: (1) they touch (share a face) or (2) they overlap (share a space). We do not 43  distinguish between these two conditions for the Intersects query. However, the first condition represents the Touches query predicate. The Disjoint and Intersects predicates are converses of each other: two building components are disjoint if they do not intersect. Only two types of building components are considered — Walls and Columns. We focus, in particular, on the spatial relationships between two Walls or a Wall and a Column, e.g., Wall-to-Wall intersections and Wall-to-Column intersections. Column-to-Column spatial relationships are not addressed as this type of relationship rarely, if ever, occurs in building design and construction [44]. Moreover, we make the simplifying assumption that Columns are non-circular; this means that both the Walls and Columns that will serve as input to the Intersects, Disjoint and Touches query predicates will be either rectangular or square. A standard algorithm used to determine if two objects intersect, touch or are disjoint is the Separating Axis Theorem (SAT). The SAT states that two 2D objects are disjoint (i.e., do not intersect) if there exists some line — the ‘separating line’ — onto which their projections are disjoint [1]. In other words, if there is some line that can be placed between the two objects, they won’t intersect. The separating line is perpendicular to the ‘separating axis’ of the two objects as illustrated in Figure 5.2. A simplifying assumption that can be made for the SAT theorem is that the objects are axis-aligned. In this case, the theorem is known as the Axis-Aligned Rectangle Test [42]. As the majority of Walls and Columns in a building are axis-aligned (i.e., their centerline is parallel to the x- or y-axis), we make this assumption. Determining if a Wall is aligned to the x-axis (i.e., is horizontal) can be accomplished by testing whether the x-value of the points defining a Wall’s centerline are the same (i.e., y varies and x is constant); alignment to the y-axis can be determined in the same manner. The query to determine if a Wall is aligned to the x-axis is presented below. declare function artifact:isWallXAligned($wall) { let $x1 := $wall/centerline[@size="2"]/point[@position="1" 44  Figure 5.2: Application of the Separating Axis Theorem (SAT) to the AEC domain (i.e., with respect to two walls, Wall1 and Wall2). and @axis="x"], $x2 := $wall/centerline[@size="2"]/point[@position="2" and @axis="x"] return  if($x1 = $x2) then true() else false()  }; A non-curved Wall in the input data will have a centerline that is defined by two points; this is represented by a centerline that has a size of 2 (i.e., $wall/centerline/[@size="2"] ). As shown in the isWallXAligned query, the x-values of the Wall’s defining 45  Figure 5.3: Cases in which two Walls will be disjoint. points are extracted and compared for equality to determine alignment to the xaxis. Determining if a Column is axis-aligned can be similarly ascertained. We begin with the implementation of the Disjoint query predicate as the Intersects query predicate is defined using the Disjoint predicate. There are four cases in which two Walls will be disjoint as shown in Figure 5.3: (1) Wall 1 is completely to the left of Wall 2, (2) Wall 1 is completely to the right of Wall 2, (3) Wall 1 is completely above Wall 2 or (4) Wall 1 is completely below Wall 2. Because we assume that the building components are axis-aligned and are rectangular, determining if they are disjoint (or intersect or touch) means that we only need to store/compute the maximum and minimum x- and y-values of each of the  46  two components. The Disjoint query predicate, for the four cases shown in Figure 5.3 is as follows: declare function artifact:disjoint($wall1, $wall2) { let $wall1.left := artifact:getWallMinX($wall1), $wall1.right := artifact:getWallMaxX($wall1), $wall1.top := artifact:getWallMaxY($wall1), $wall1.bottom := artifact:getWallMinY($wall1), $wall2.left := artifact:getWallMinX($wall2), $wall2.right := artifact:getWallMaxX($wall2), $wall2.top := artifact:getWallMaxY($wall2), $wall2.bottom := artifact:getWallMinY($wall2), $isWall1AxisAligned := artifact:isWallXAligned($wall1) or artifact:isWallYAligned($wall1), $isWall2AxisAligned := artifact:isWallXAligned($wall2) or artifact:isWallYAligned($wall2) where $wall1/centerline[@size="2"] and $wall2/centerline[@size="2"] and $isWall1AxisAligned and $isWall2AxisAligned  (:$wall1 is non-curved :)  (:$wall2 is non-curved :)  (:$wall1 is axis-aligned :)  (:$wall2 is axis-aligned :)  return if ($wall1.right < $wall2.left or $wall1.left > $wall2.right or $wall1.bottom > $wall2.top or $wall1.top < $wall2.bottom ) then true() else false() 47  }; Because the Intersects and Disjoint query predicates represent inverse spatial relationships — two building components are disjoint if they do not intersect — the Disjoint query predicate can be used in defining the Intersects query predicate as follows: declare function artifact:intersects($wall1, $wall2) { let $isWall1Aligned := artifact:isWallXAligned($wall1) or artifact:isWallYAligned($wall1), $isWall2Aligned := artifact:isWallXAligned($wall2) or artifact:isWallYAligned($wall2) where  $wall1/centerline[@size="2"] and (: wall1 is non-curved :) $wall2/centerline[@size="2"] and $wall1/centerline[@size="2"] and (: wall1 is non-curved :) $wall2/centerline[@size="2"]  return not(artifact:disjoint($wall1, $wall2)) }; In particular, the Intersects query predicate returns the logical negation of the Disjoint query predicate as demonstrated in the return statement of the Intersects predicate: “return not (artifact:disjoint($wall1, $wall2)).” The Touches query predicate can be implemented by slightly changing the Disjoint query predicate. In particular, the greater-than and lesser-than signs in the four test conditions in the return statement of the Disjoint predicate can be replaced with equals signs; this change creates a predicate that tests if two rectangular axis-aligned building components touch at one of their faces. The resulting return statement for the Touches query predicate is as follows: return if ($wall1.right = $wall2.left or $wall1.left = $wall2.right or $wall1.bottom = $wall2.top or 48  $wall1.top = $wall2.bottom ) then true() else false()  Proximate The Proximate query predicate is used to answer the Spacing query (Section 5.3.4), which is only considered between columns. Two columns are proximate if they are adjacent to each other and if they meet two other conditions which are described in the next paragraph. It is assumed for the Proximate predicate that the columns are on-grid (see Section 5.3.3) and that they are square, circular or rectangular in shape. A target column is proximate to a source column (an input column) if it satisfies two criteria: (1) the column is aligned to one of the gridlines that the source column is aligned to and (2) it is the closest such column along that gridline in a given direction (i.e., the positive or negative x- or y-direction from the input column). For example, in Figure 5.4, column 81936 is the northern (i.e., in the positive x-direction) proximate column of column 80940 along x-gridline 5. Similarly, columns 80376, 80871, and 80794 are the southern, western, and eastern proximate columns. A column will have at least two and at most four proximate columns. For example, column 80034, an exterior column at the corner of the building, only has two proximate columns. An algorithm called ray tracing is employed to identify proximate column candidates. Ray tracing is a common technique used in graphics to render an object. The path of a ray of light is followed from a source and the interaction of the ray with objects in the space is used to generate an image. This technique can also be used to detect ray-object intersections and locate the closest object in a particular direction from the source. Ray tracing was used to determine the proximate columns for each on-grid column. In the context of the Proximate query predicate, the ray represents the gridline extending from the center of a source column in either the north, south, east or west direction. The ray is defined by its origin and direction. Its origin 49  Figure 5.4: Layout of columns on the first level of a building. The proximate columns of column 80940 are highlighted in black.). is the centerpoint of the source column in the xy-plane, (x0, y0), and its direction is a two-dimensional unit vector, (xd, yd). The unit vector in the north direction is represented as (1, 0); a value of 1 for xd and 0 for yd indicates that the ray’s direction is in the positive x-direction. A candidate proximate column is represented by its centerpoint, (xT, yT) and its radius, rT. We represent all columns (circular, square and rectangular) as circles in the xy-plane because it simplifies the intersection test. A box-ray intersection test could be used instead of a a circle-ray intersection test. However, the circleray intersection test involves only one comparison — the circle is represented as a single equation — whereas a box-ray intersection would involve four comparisons. 50  A box would be represented as four line equations and it would be necessary to check for an intersection of the ray with each of these lines. Our choice to represent all columns as circles is acceptable because all columns are on-grid and we are following a ray along a gridline; therefore, the point at which the column’s face and the circle representing the column intersects that gridline will be the same point. Given the equation for a ray and the equation for a the circle that represents a column, the ray will intersect the ‘target’ column if the quadratic equation formed by substituting the equation for the ray (a linear equation) into the equation for the circle representing the column has a solution. The xquery provided below determines if a gridline (represented as a ray) that a source column is aligned to intersects a column in direction d, where d is north, south, east or west from the source column; the query is a boolean one and thus outputs either a value of true or false. declare function artifact:isRayCircleIntersection($x0, $y0, $xT, $yT, $rT, $xd, $yd) { let $B := 2 * ( $xd * ($x0-$xT) + $yd * ($y0-$yT)), $C := ($x0-$xT)*($x0-$xT) + ($y0-$yT)*($y0-$yT) - $rT*$rT, $discriminant := $B * $B - 4 * $C, $t0 := (-1 * $B - math:sqrt($B * $B - 4 * $C)) div 2, $t1 := (-1 * $B + math:sqrt($B * $B - 4 * $C)) div 2 return if ($discriminant > 0 and $t0 > 0 and $t1 > 0) then true() else false() }; If there is a real solution to the resulting system of equations, an intersection exists. This technique can be used to determine the proximate column of an on-grid column along the two gridlines to which the column is aligned in each of the four grid directions extending from the on-grid column’s centerpoint. As shown below, the proximateColumn query predicate calls the proximateColumnCandidates query 51  predicate which, for a given direction (xd, yd), returns all on-grid columns in the given direction. The proximateColumn query predicate determines the distance to each of these candidates and returns the closest one. The distance from a column to its proximate column will either be the clear distance or the center-to-center distance as specified by the user. Manhattan distance and Euclidean distance are equivalent in this case as the distance is being calculated in a straight line along an x- or y-gridline. declare function artifact:proximateColumn($sourceColumn, $xd, $yd) { let $proximateColumnCandidates := artifact:proximateColumnCandidates($sourceColumn/id/text(), $xd, $yd), $minDistance := artifact:minDistance($sourceColumn, $proximateColumnCandidates) for $col in $proximateColumnCandidates let $distanceToSource := round(number (math:manhattanDistance($sourceColumn,$col/column)) * 100) div 100 where $distanceToSource = $minDistance return $col/column }; declare function artifact:proximateColumnCandidates($columnId, $xd, $yd) { let $sourceColumn := (for $col in doc($columnsXMLFile)/columns/column where $col/id = $columnId return $col), $sourceCenterX := round(number( $sourceColumn/centerpoint[@axis="x"])*10000) div 10000, 52  $sourceCenterY := round(number( $sourceColumn/centerpoint[@axis="y"])*10000) div 10000, $sourceRadius := round(number($sourceColumn/base_b)*10000) div 10000, $x0_N := $sourceCenterX, $y0_N := $sourceCenterY + $sourceRadius for $targetColumn in doc($columnsXMLFile)/columns/column where artifact:ongrid($targetColumn) and round(number($targetColumn/level)*10000) div 10000 = round(number($sourceColumn/level)*10000) div 10000 and $targetColumn/id != $sourceColumn/id and artifact:isRayCircleIntersection($sourceCenterX, $sourceCenterY, round(number($targetColumn/centerpoint[@axis="x"]) *10000) div 10000, round(number($targetColumn/centerpoint[@axis="y"]) *10000) div 10000, round(number($targetColumn/base_b div 2)*10000) div 10000, $xd, $yd) return <proximateColumns>{$targetColumn}</proximateColumns> };  On-Grid A column is On-grid (or horizontally aligned) if it is aligned to both an x-gridline and a y-gridline. The on-grid query is given below: declare function artifact:ongrid($column) { 53  let $isXAligned := artifact:isAlignedToGridlineInterior($column,"x") or artifact:isAlignedToGridlineExterior($column,"x") $isYAligned := artifact:isAlignedToGridlineInterior($column,"y") or artifact:isAlignedToGridlineExterior($column,"y") $ongrid := $isXAligned and $isYAligned return $ongrid }; The definition of alignment, however, depends on whether a column is an interior or an exterior one. In the floorplan shown in Figure 5.5, the difference between interior on-grid columns, exterior on-grid columns and off-grid columns is demonstrated. An interior column is on-grid if its centerpoint is at the intersection of two perpendicular gridlines (i.e., an x- and y- gridline) as is the case for columns 80871 and 80940 in Figure 5.5. There are two cases in which an exterior column is ongrid. First, one its faces touches an exterior gridline and its centerpoint is on an interior gridline that is perpendicular to the exterior gridline as is the case with column 80671 in Figure 5.5; columns that fall into this category are located at the sides of buildings. Second, two adjacent faces touch perpendicular exterior gridlines as with column 80034 in Figure 5.5; columns that meet this criteria will be found at the corner of a building. The query that determines if a column is aligned to either an interior x- or y-gridline is as follows: declare function artifact:isAlignedToGridlineInterior($column, $axis) { for $g in doc($gridsXMLFile)/grids/ gridline[gridlineAxis=$axis] where round(number($column/centerpoint[@axis=$axis])*10000) div 10000 = round(number($g/gridlineValue)*10000) 54  Figure 5.5: The difference between interior on-grid, exterior on-grid and offgrid columns. div 10000 return true() };  The $axis input variable in the isAlignedToGridlineInterior function identifies the type of gridline, either an x- or y-gridline. The location data that is extracted from Revit is given to thirteen decimal places; however, the precision of the data is not at the same level. For example, in Figure 5.3.3, column 80871 is obviously aligned to the grid intersection 3-B. The yvalue of column 80871’s centerpoint as extracted from Revit is 9.08742107017389, 55  but the y-value for the y-gridline it is aligned to, gridline B, is 9.08742107017328. The two values should be the same, but instead disagree at the 12th decimal place. To ensure that spatial data is accurately compared it is necessary to round values to a lower level of precision as shown in the isOnGridInterior query above: values are rounded to five decimal places to prevent incorrect output from comparisons. The query that determines if a column is aligned to either an exterior x- or y-gridline is presented below: declare function artifact:isAlignedToGridlineExterior($column, $axis) { let $g := doc($gridsXMLFile)/grids/ gridline[gridlineAxis=$axis], $min_g := min($g/gridlineValue), $max_g := max($g/gridlineValue) where (artifact:isSquare($column) or artifact:isRound($column)) and (round(number($column/centerpoint[@axis=$axis] + $column/base_b div 2) * 10000) div 10000 = round(number($min_g) * 10000) div 10000 or round(number($column/centerpoint[@axis=$axis] $column/base_b div 2) * 10000) div 10000 = round(number($min_g) * 10000) div 10000 or round(number($column/centerpoint[@axis=$axis] + $column/base_b div 2) * 10000) div 10000 = round(number($max_g) * 10000) div 10000 or round(number($column/centerpoint[@axis=$axis] 56  $column/base_b div 2) * 10000) div 10000 = round(number($max_g) * 10000) div 10000 ) return true() }; There are four exterior gridlines — the minimum x-gridline (i.e., the x gridline that has the smallest value), the maximum x-gridline, the minimum y-gridline and the maximum y-gridline. The query presented above, isAlignedToGridlineExterior, will determine if the face of an input column is aligned to either an exterior x-gridline or an exterior y-gridline.  5.3.4  Construction Query Predicates  Alignment Horizontal alignment of a building component is defined based on its location in the xy-plane (i.e., the floor) in a building and in relation to the project gridlines. Column alignment is generally what is considered as it helps construction practitioners determine what formwork system to use. The alignment query makes use of the On-grid query predicate to determine if columns are on- or off-grid. The alignment query provides additional information depending on which category a column matches. If a column is on-grid, the grid intersection to which it is aligned is returned. The query predicate alignedToGridIntersection, which is shown below, provides this information. alignedToGridIntersection is very similar to the on-grid query predicate (see Section 5.3.3). It also makes use of helper query predicates to determine the x- and y-gridlines to which an on-grid column is aligned. Because the helper functions are so similar to those for the On-grid query predicate, only the alignedToGridIntersection predicate is provided here. declare function artifact:alignedToGridIntersection($column) { 57  let $alignedToGridIntersection := ( if (artifact:ongrid($column)) then concat(artifact:alignedToGridline($column,"x"), "-", artifact:alignedToGridline($column,"y")) else "null" ) return $alignedToGridIntersection };  The output of the alignedToGridIntersection query predicate is the grid intersection that a column is horizontally aligned to in the format ’x-gridline - ygridline’ (e.g., 3-C). If a column is not on-grid it is described as off-grid and the x- and y-gridline that it is closest to are returned as well as the distance of the column to each. The closestGridline query predicate takes as input both the column and the axis (i.e., x or y) for which the closest gridline is desired. declare function artifact:closestGridline($column,$axis) { let $distToGridlines := ( (: for all gridlines, find distance from column to the gridline :) for $gl in doc($gridsXMLFile)/grids/ gridline[gridlineAxis=$axis] return <closestGridline> <gridline>{$gl/name/text()}</gridline> <distance uom="#ft"> {artifact:distanceToClosestGridline ($column,$gl,$axis)} </distance> </closestGridline> ), 58  $minDistance := min(($distToGridlines/dist)), $closestGridlines := (for $g in $distToGridlines where $g/dist = $minDistance return $g/gridline/text()) return $closestGridlines };  The distanceToClosestGridline is used in the closestGridline query predicate to help determine which gridline is closest to the off-grid column. This distance is also reported for the gridline that is returned by the closestGridline predicate. declare function artifact:distanceToClosestGridline($column, $gl, $axis) { let $distance := round(fn:abs(round(number($column/ centerpoint[@axis=$axis])*10000) div 10000 - round(number($gl/gridlineValue)*10000) div 10000)*100) div 100 return $distance }; An example of the output of the alignment query for an off-grid column is as follows: <closestXGridline> <gridline>1</gridline> <distance uom="#ft">1.23</distance> </closestXGridline>  Uniformity The uniformity of a building design or the lack thereof affects constructibility. Non-uniformity or variability of column location “can prevent the use of most economical construction methods, reduce labor productivity that ultimately increases 59  cost” [35]. For example, column location variability affects what formwork systems can be used to pour concrete: a ganged form can accommodate some variation, a jump form can handle moderate variation, but a slip form cannot handle any variation at all [25]. It is therefore important for construction practitioners to have some idea of where variability in design exists and some measure of the degree of this variability. In the initial implementation of the SSIF, we use vertical alignment of columns as a representative uniformity query. In most cases there will be uniformity in the vertical alignment of columns; it is more important to point out to practitioners where there is variation in the building design, in this case the location of columns vertically. Therefore, the uniformity query actually identifies non-uniform columns, i.e., those columns in the base floor (level 1) whose location changes in the floor(s) about it. In the initial version of the SSIF, uniformity is considered only for on-grid columns. The nonUniformColumns query predicate is presented below. declare function artifact:nonUniformColumns($referenceLevel) { let $columns := artifact:onGridColumns($referenceLevel), $levels := artifact:getBuildingLevels($columnsXMLFile) for $column in $columns for $level in $levels order by $level, $column/id/text() return if(empty(index-of(artifact:onGridColumns($level), $column/text()))) then <nonUniformColumn level= "{artifact:getComponentLevel($level)}"> {$column}</nonUniformColumn> else () };  60  Figure 5.6: Example of a Wall-to-Wall Intersection and the details provided by the Intersection spatial query predicate Intersection An intersection occurs when two building components intersect as shown in Figure 5.6. The Intersection query predicate makes use of the Intersects query predicate introduced in Section 5.3.3 to first determine if an intersection occurs. Where an intersection exists, the Intersection query predicate will return more detailed information about the intersecting region: its location (i.e., the corner points of the region), dimensions (i.e., width, length, height), area and volume. Sample output from the Intersection query is provided below: <Intersection> <Wall gml:id="137269"/> <Wall gml:id="133152"/> <location> <gml:Point srsName="gml:CartesianCS"> <gml:pos>-33.75 50.79 0.00</gml:pos> </gml:Point> <gml:Point srsName="gml:CartesianCS"> 61  <gml:pos>-33.75 49.98 0.00</gml:pos> </gml:Point> <gml:Point srsName="gml:CartesianCS"> <gml:pos>-33.27 50.79 0.00</gml:pos> </gml:Point> <gml:Point srsName="gml:CartesianCS"> <gml:pos>-33.27 49.98 0.00</gml:pos> </gml:Point> </location> <area uom=#sq-ft>0.39</area> <volume uom=#cu-ft>3.95</volume> </Intersection> Construction practitioners use this information in a number of different ways. For example, Wall-to-Column Intersections can require additional framing for movement joints and, Wall-to-Wall Intersections impact drywall construction costs [36]. Both examples require information above and beyond whether building components simply intersect or not. Penetration A penetration is a special case of the intersection query. In particular it is an intersection in which one of the two intersecting components is a building service component such as a duct. Ducts are considered to be part of the mechanical system that supplies heating, ventilation and air-conditioning for a building [46]. Additional information above and beyond what is reported for a standard intersection is needed. The size and location of the penetration of a building service on the wall (i.e., its distance from each side of the wall, the ceiling and floor) is important as minimum clearances of building services from walls and ceilings must be met and additional work may be needed to prevent moisture penetration or heat exchange [46]. Knowing where these penetrations occur will result in a more accurate cost estimate of work. Figure 5.7 demonstrates the penetration of a wall by a circular duct. While there are other types of building services such as plumbing or electrical system 62  Figure 5.7: Example of a duct penetration on a wall. The location of the duct in relation to the sides of the wall is indicated. components, we consider only duct penetrations as a representative example of this type of intersection. The location of the duct on the wall with respect to the wall’s four edges is also indicated in the diagram. Like the Intersection query, the Penetration query employs the Intersects query predicate (see Section 5.3.3) to first determine if a penetration occurs; as indicated above, a penetration is essentially an intersection where one of the intersecting components is a duct and the other is a wall. Where a penetration exists, the Penetration query predicate provides additional information about the penetration: its location (i.e., the corner points of the penetration region in the xy-plane as well as its location on the wall) and its area and volume. Sample output from the Penetration query is provided below: <Penetration> <Wall gml:id="133152"/> <Duct gml:id="149164"/> <area uom=#sq-ft>0.39</area> <volume uom=#cu-ft>3.95</volume> <location> <gml:Point srsName="gml:CartesianCS"> 63  <gml:pos>-34.24 42.04</gml:pos> </gml:Point> <gml:Point srsName="gml:CartesianCS"> <gml:pos>-34.24 40.54</gml:pos> </gml:Point> <gml:Point srsName="gml:CartesianCS"> <gml:pos>-33.27 42.04</gml:pos> </gml:Point> <gml:Point srsName="gml:CartesianCS"> <gml:pos>-33.27 40.54</gml:pos> </gml:Point> </location> <locationOnWall> <distanceFromWallTop uom="#ft">2.25 </distanceFromWallTop> <distanceFromWallBottom uom="#ft">6.25 </distanceFromWallBottom> <distanceFromWallLeft uom="#ft">8.75 </distanceFromWallLeft> <distanceFromWallRight uom="#ft">19.75 </distanceFromWallRight> </locationOnWall> </Penetration>  Spacing The Spacing between features is important to construction practitioners because it directly impacts the construction and/or installation of components. For example, practitioners will commonly analyze a building design plan to ensure that the spacing between components is less than the maximum constraint specified by a desired construction method. Spacing between columns is important because it it determines the column/bay size and impacts the formwork selection for column construction. 64  Figure 5.8: Spacing of on-grid columns on the first level of a building design plan The Spacing query identifies the minimum or maximum spacing (or distance) between proximate columns on a level-by-level basis. The definition of proximate as well as the Proximate query predicate is presented in Section 5.3.3. This predicate is used to identify the proximate columns for each column on each level of a building. The Spacing query uses the output of the Proximate query predicate and calculates both the face-to-face (or clear) and center-to-center distance between a column and its proximate columns. The difference between the two types of spacings is shown in Figure 5.9. As can be observed, face-to-face spacing is the distance between the closest faces of proximate (or adjacent) columns. Center-to-center spacing is the distance between the centerpoints of two proximate columns. Figure 5.3.4 presents the faceto-face spacings for all columns (to their respective proximate columns) on the first 65  Figure 5.9: Face-to-face versus Center-to-center spacing. level of a building design plan. The maximum and minimum face-to-face spacings — 22.97 feet and 16.4 feet respectively — are also indicated. In the XML excerpt presented below, output from the Spacing query is provided. The query returns, for each level in the building, the minimum and maximum face-to-face and center-to-center spacings. <spacings> <Spacing> <level>1</level> <faceToFace> <minimum uom="#ft">11.48</minimum>  66  <maximum uom="#ft">18.04</maximum> </faceToFace> <centerToCenter> <minimum uom="#ft">16.40</minimum> <maximum uom="#ft">22.97</maximum> </centerToCenter> </Spacing> <Spacing> <level>2</level> <faceToFace> <minimum uom="#ft">11.98</minimum> <maximum uom="#ft">37.73</maximum> </faceToFace> <centerToCenter> <minimum uom="#ft">16.40</minimum> <maximum uom="#ft">41.67</maximum> </centerToCenter> </Spacing> </spacings>  5.3.5  Challenges  As was the case with the other components of the Semantic Spatial Interoperability Framework, we were confronted with several problems in developing the spatial query predicates. A number of simplifying assumptions had to be made (see Section 5.3.2), assumptions that introduce limitations to our work. • Because we did not extract the location of the external surfaces of building objects from Revit as described in Section 4.2.1, the types of building objects we could consider in our spatial queries were limited. In particular we had to restrict our queries to non-curved, non-clipped (i.e., an object with consistent height), regularly-shaped (i.e., rectangular, square or circular) building objects. This is due to the fact that we cannot determine the location of the external faces of building objects that do not meet these requirements. Without 67  this information, the relative location of an object’s exterior is unknown and spatial topology cannot be inferred. In the case of regularly shaped objects, it is a simple exercise to interpolate this information with the information we extracted — an object’s centerpoint or centerline, the dimensions of its base in the xy-plane (e.g., the radius of a circular column or the length and width of a rectangular/square column of wall). The exterior of the object can be determined by extruding the object’s shape in the xy-plane through the z-direction. • The semantics of Revit building objects, their attributes and what they represent are not explicit in the Revit model. For example, the dimensions of the base of a rectangular column are not distinguished: it is unclear as to which of the two dimensions — b and h  1  — is in the x-direction and which is  in the y-direction. This makes it impossible to determine the exact location of the boundary of a rectangular column. Some way of programmatically determining how to differentiate the two dimensions is required. • Determining how to represent the results of spatial queries and communicate the semantics to users is also problematic and was not addressed in this initial implementation of the Semantic Spatial Interoperability Framework. For example, describing the location of a penetration as a distance from the sides of a wall (see Section 5.3.4) can be ambiguous without visual cues. The semantics of the left or right side of the wall can be unclear to the user. Another example is how to describe the intersection of a wall and a circular column. It is not apparent how to consistently and unambiguously encode the location of irregularly shaped regions such as circle segments that are formed by the intersection of a rectangular wall and circular column. The intersection region of two rectangular objects is much easier to describe — it will either be a line in the case that the two objects touch or it will be a rectangle if there is some overlap. In the case of a line, the two endpoints can be used to describe the intersecting region and in the case of a rectangle, corner points are used. 1 In  this context, h is just one of the dimensions of the base of a column. It does not represent the height of the column.  68  Chapter 6  Conclusion and Future Work Preliminary feedback from domain experts has been positive and speaks to the utility and usability of our initial efforts. The end-to-end solution presented in Chapter 5 demonstrates that domain-specific ontologies can be applied to integrated spatial data to support greater semantic interoperability, including the more sophisticated analyses described in Example 1. In particular, our semantic spatial interoperability framework can support alternate views of the building design plan. It is important to point out that the work described in this thesis is part of a much larger project, the ARTIFACT Project. The potential benefit of the ARTIFACT Project is substantial: in the US construction industry alone if, through our efforts, interoperability can be improved by a mere 5%, the savings that could be reaped numbers in the hundreds of millions of dollars. Our work allows users of spatial data to better interoperate by building layers upon the existing basic definitions. This work is in the context of AEC data, but is necessary for interoperability of all spatial data as well. Specifically, we provide the following contributions: • We created an application to extract spatial data from the Autodesk Revit API. • We extended GML to create an AEC-specific GML application schema based on our construction ontology. • We extended XQuery for spatial data and AEC-specific spatial queries — 69  mappings from the source data to the concepts described in the ontology. • We created a complete end-to-end semantic spatial data interoperability system, the Semantic Spatial Interoperability Framework. • We described our experiences in developing the Semantic Spatial Interoperability Framework in the Challenges sections of each component of the Semantic Spatial Interoperability Framework. In the future, we envision adding other 2D topological query predicates and generalizing spatial query predicates to both convex and 3D polygons to improve expressibility. We intend to implement spatial indexes to improve performance, and facilitate a more automated mapping between base spatial relationships and building objects. Finally, we plan to auto-generate the GML application schema.  70  Bibliography [1] T. Akenine-Moller, E. Haines, and N. Hoffman. Real-Time Rendering. A. K. Peters, 2008. → pages 44 [2] Autodesk. DWF 6 Specification, 2003. → pages 10 [3] Autodesk. Revit Structure and BIM. http://images.autodesk.com/adsk/files/revit architecture 2010 brochure.pdf,  2007. → pages 10 [4] Autodesk. Revit 2009 API Developer’s Guide Version 1.0, 2009. → pages 23, 25, 26 [5] Autodesk. White Paper, DWF: The Best File Format for Published Design Information. http://www.calcad.com/public/products/docs/Autodesk% 20DWF%20WhitePaper.pdf, 2010. → pages 10 [6] Autodesk Inc. Autodesk Revit 2009 API - Getting Started. Technical report, Autodesk Inc., 2009. → pages 25 [7] W. Behrman. Best Practices for the Development and Use of XML Data Interchange Standards. Technical report, Center for Integrated Facilities Engineering, Stanford University, USA, 2002. → pages 11 [8] A. Belussi, O. Boucelma, B. Catania, Y. Lassoued, and P. Podest`a. Towards Similarity-Based Topological Query Languages. In EDBT, pages 675–686, 2006. → pages 15, 17 [9] Y. Bishr. Overcoming the Semantic and Other Barriers to GIS Interoperability. In International Journal of Geographical Information Science, pages 299–314, 1998. → pages 14, 15 [10] A. Borrmann and E. Rank. Topological Analysis of 3D Building Models Using a Spatial Query Language. In Advanced Engineering Informatics, volume 23, pages 370–385, 2009. → pages 8, 19 71  [11] O. Boucelma and F.-M. Colonna. GQuery: a Query Language for GML. In Urban Data Management Symposium, pages 23–32, 2004. → pages 17 [12] S. Boucher and E. Zim´anyi. Leveraging OWL for GIS Interoperability: Rewards and Pitfalls. In SAC, March 2009. → pages 15 [13] D. A. Campbell. Building Information Modeling: the Web3D Application for AEC. In ACM, 2007. → pages 9 [14] C. Chang, Y. Chang, M. Chiang, T. Chuang, D. Deng, S. Ho, and F. Lin. Experience in Building GML-based Interoperable Geo-spatial Systems. In GML and Geo-Spatial Web Services Conference, July 2005. → pages 15 [15] Chen and Revesz. CXQuery: A Novel XML Query Language. In SSGRR, 2002. → pages 15, 16 [16] CityGML. CityGML Exchange and Storage of Virtual 3D City Models. http://www.citygml.org, 2010. → pages 13, 41 [17] J. E. C´orcoles and P. Gonz´alez. Handbook of Research on Geoinformatics, chapter Querying GML: A Pressing Need, pages 11–19. Information Science Publishing, 2009. → pages 15, 16 [18] A. Doan and A. Y. Halevy. Semantic-Integration Research in the Database Community: A Brief Survey. In American Association for Artificial Intelligence, pages 83–94, 2005. → pages 14 [19] M. J. Egenhofer and J. R. Herring. Categorizing Binary Topological Relations Between Regions, Lines, and Points in Geographic Databases. In Tech. Rep., Dep. of Surveying Engineering, University of Maine, 1990. → pages 17, 43 [20] R. Fikes. Ontologies: What Are They, and Where’s the Research? In Principles of Knowledge Representation and Reasoning (KR), pages 652–653, 1996. → pages 14 [21] M. Fischer and C.B.Tatum. Characteristics of Design-Relevant Constructability Knowledge. In Journal of Construction Engineering and Management, volume 123, pages 253–260, 1997. → pages 2 [22] T. Froese, M. Fischer, F. Grobler, J. Ritzenthaler, K. Yu, S. Sutherland, S. Staub, B. Akinci, R. Akbas, B. Koo, A. Barron, and J. Kunz. Industry Foundation Classes for Project Management - A Trial Implementation. In ITCon, 1999. → pages 11 72  [23] M. P. Gallaher, A. C. O’Connor, J. L. D. Jr., and L. T. Gilday. Cost Analysis of Inadequate Interoperability in the U.S. Capital Facilities Industry. Technical Report NIST GCR 04-867, U.S. Department of Commerce Technology Administration National Institute of Standards and Technology, August 2004. → pages 2 [24] J. Guan, F. Zhu, J. Zhou, and L. Niu. GQL: Extending XQuery to Query GML Documents. In Geo-spatial Information Science (Quarterly), volume 9(2), June 2006. → pages 15, 17, 18 [25] A. S. Hanna, J. H. Willenbrock, and V. E. Sanvido. Knowledge Acquisition and Development for Formwork Selection System. In Journal of Construction Engineering and Management, volume 118, pages 179–198, 1992. → pages 2, 60 [26] M. Harada. A Closer Look at the Revit Database with the Revit API. Technical report, Autodesk Inc., 2007. → pages 22, 27 [27] G. S. Inc. GML Foundation Project: Developing and Managing Application Schemas (TR2003-232-01). Technical report, Galdos Systems Inc., May 2003. → pages 11, 34 [28] Jeremy Tammik. Units. http://thebuildingcoder.typepad.com/blog/2008/09/units.html, 2008. →  pages 23, 28 [29] Jeremy Tammik. RvtMgdDbg. http://thebuildingcoder.typepad.com/blog/2009/02/rvtmgddbg.html, 2009.  → pages 26 [30] John Kennedy. About gbXML. http://www.gbxml.org/about.html, 2010. → pages 11 [31] K.-Y. Kim, D. G. Manley, and H. Yang. Ontology-based Assembly Design and Information Sharing for Collaborative Product Development. In Computer-Aided Design, volume 38, pages 1233–1250, 2006. → pages 14 [32] C. Kwan. Data Management Concepts for Spatial Data Projects: A Case Study of the ARTIFACT Project. Technical report, University of British Columbia, 2008. → pages 23, 24 [33] R. Lake, D. S. Burggraf, M. Trninic, and L. Rae. GML. John Wiley and Sons Ltd., 2004. → pages 33, 34, 38 73  [34] M. Lawrence. Data Management in Architecture, Engineering and Construction: The ARTIFACT Project. Technical report, Department of Computer Science, University of British Columbia, April 2008. → pages vi, 6 [35] M. Nepal. Update on the Feature Ontology and Query Specifications. Technical report, University of British Columbia, December 2009. → pages 60 [36] M. P. Nepal, S. Staub-French, J. Zhang, M. Lawrence, and R. Pottinger. Deriving Construction Features from an IFC Model. In Canadian Society for Civil Engineering (CSCE) annual conference, June 2008. → pages 9, 10, 30, 31, 62 [37] Open Geospatial Consortium. Geography Markup Language (GML). http://www.ogcnetwork.net/gml, 2010. → pages 12, 13 [38] Open Geospatial Consortium. GML Application Schemas and Profiles. http://www.ogcnetwork.net/node/210, 2010. → pages 13, 40 [39] Open Geospatial Consortium Inc. GML Schema Version 3.2.1. http://schemas.opengis.net/gml/3.2.1/, 2007. → pages 31 [40] C. Portele. OpenGIS Geography Markup Language (GML) Encoding Standard, Version 3.2.1 (OGC 07-036). Technical report, Open Geospatial Consortium Inc., August 2007. → pages 12, 34 [41] Prot´eg´e. Prot´eg´e. http://protege.stanford.edu, 2010. → pages 3, 30 [42] P. J. Schneider and D. H. Eberly. Geometric Tools for Computer Graphics. Morgan Kaufmann Publishers, 2003. → pages 44 [43] S. Staub-French. Feature-based Product Models for Building Construction. In Xth International Conference on Computing in Civil and Building Engineering (ICCCBE-X), June 2004. → pages 7, 9, 10 [44] S. Staub-French, M. Fischer, J. Kunz, K. Ishii, and B. Paulson. A Feature Ontology to Support Construction Cost Estimating. In Artificial Intelligence for Engineering Design, Analysis and Manufacturing, 2003. → pages 20, 44 [45] SyncRO Soft Ltd. Oxygen XML Editor Version 11.2. http://www.oxygenxml.com/, 2010. → pages 40  74  [46] A. R. Tabesh and S. Staub-French. Modeling and Coordinating Building Systems in Three Dimensions: a Case Study. In Canadian Journal of Civil Engineering, volume 33, pages 1490–1504, 2006. → pages 1, 62 [47] J. Tammik. The ABCs of Programming in Revit Architecture, Revit Structure, and Revit MEP. Technical report, Autodesk Inc., 2007. → pages 26 [48] Vatsavai. GML-QL: A Spatial Query Language Specification for GML. http://www.cobblestoneconcepts.com/ucgis2summer2002/vatsavai/ vatsavai.htm, 2002. → pages 15, 16  [49] V. M. Vidal, E. R. Sacramento, J. A. F. de Macˆedo, and M. A. Casanova. An Ontology-Based Framework for Geographic Data Integration. In ER, pages 337–346, 2009. → pages 15 [50] W3 Schools. XML Schema Tutorial. http://www.w3schools.com/Schema/default.asp, 2010. → pages 36  [51] World Wide Web Consortium (W3C). XQuery 1.0: An XML Query Language. http://www.w3.org/TR/xquery, 2007. → pages 15 [52] J. Zhang. Evaluations on XML Standards for Actual Applications. Master’s thesis, Department of Computer Science, University of British Columbia, 2008. → pages 7, 8, 11, 20, 21  75  Appendix A  Construction Ontology  76  Appendix B  ARTIFACT Application Schema  78  1/9 file:/C:/Users/webster/Documents/thesis/XQueries/Schemas/aas.xsd  <?xml version="1.0" encoding="UTF-8"?> <!-- References: Lake, Ron. Geography mark-up language (GML). Wiley and Sons, 2004.--> <xs:schema version="1.0" targetNamespace="http://cs.ubc.ca/~awebster/artifact" elementFormDefault="qualified" xmlns:artifact="http://cs.ubc.ca/~awebster/artifact" xmlns:gml="http://www.opengis.net/gml/3.2" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns="http://www.w3.org/2001/XMLSchema" > <import namespace="http://www.opengis.net/gml/3.2" schemaLocation="http://schemas.opengis.net/gml/3.2.1/gml.xsd" /> <!-- **************************** FEATURE COLLECTION DEFINITIONS **********************--> <element name="building"> <complexType> <complexContent> <extension base="gml:AbstractFeatureType"> <sequence> <element ref="artifact:columns" maxOccurs="1"/> <element ref="artifact:walls" maxOccurs="1"/> <element ref="artifact:ducts" maxOccurs="1"/> <element ref="artifact:grid" maxOccurs="1"/> <element ref="artifact:intersections" maxOccurs="1"/> <element ref="artifact:penetrations" maxOccurs="1"/> <element ref="artifact:ongridColumns" maxOccurs="1"/> <element ref="artifact:offgridColumns"maxOccurs="1"/> <element ref="artifact:nonuniformColumns"maxOccurs="1"/> <element ref="artifact:spacings" maxOccurs="1"/> </sequence> </extension> </complexContent> </complexType> </element> <element name="columns"> <complexType> <complexContent> <extension base="gml:AbstractFeatureType"> <sequence> <element ref="artifact:Column" maxOccurs="unbounded"/> </sequence> </extension> </complexContent> </complexType> </element>  <element name="walls"> <complexType>  2/9 file:/C:/Users/webster/Documents/thesis/XQueries/Schemas/aas.xsd  <complexContent> <extension base="gml:AbstractFeatureType"> <sequence> <element ref="artifact:Wall" maxOccurs="unbounded"/> </sequence> </extension> </complexContent> </complexType> </element> <element name="ducts"> <complexType> <complexContent> <extension base="gml:AbstractFeatureType"> <sequence> <element ref="artifact:Duct" maxOccurs="unbounded"/> </sequence> </extension> </complexContent> </complexType> </element> <element name="grid"> <complexType> <complexContent> <extension base="gml:AbstractFeatureType"> <sequence> <element ref="artifact:Gridline" maxOccurs="unbounded"/> </sequence> </extension> </complexContent> </complexType> </element>  <element name="intersections"> <complexType> <complexContent> <extension base="gml:AbstractFeatureType"> <sequence> <element ref="artifact:Intersection" maxOccurs="unbounded"/> </sequence> </extension> </complexContent> </complexType> </element> <element name="penetrations"> <complexType> <complexContent> <extension base="gml:AbstractFeatureType">  3/9 file:/C:/Users/webster/Documents/thesis/XQueries/Schemas/aas.xsd  <sequence> <element ref="artifact:Penetration" maxOccurs="unbounded"/> </sequence> </extension> </complexContent> </complexType> </element> <element name="ongridColumns"> <complexType> <complexContent> <extension base="gml:AbstractFeatureType"> <sequence> <element ref="artifact:Column" maxOccurs="unbounded"/> </sequence> </extension> </complexContent> </complexType> </element> <element name="offgridColumns"> <complexType> <complexContent> <extension base="gml:AbstractFeatureType"> <sequence> <element ref="artifact:Column" maxOccurs="unbounded"/> </sequence> </extension> </complexContent> </complexType> </element> <element name="nonuniformColumns"> <complexType> <complexContent> <extension base="gml:AbstractFeatureType"> <sequence> <element ref="artifact:Column" maxOccurs="unbounded"/> </sequence> </extension> </complexContent> </complexType> </element> <element name="spacings"> <complexType> <complexContent> <extension base="gml:AbstractFeatureType"> <sequence> <element ref="artifact:Spacing" maxOccurs="unbounded"/> </sequence>  4/9 file:/C:/Users/webster/Documents/thesis/XQueries/Schemas/aas.xsd  </extension> </complexContent> </complexType> </element>  <!-- ****************************** FEATURE DEFINITIONS ***************************--> <element name="Wall"> <complexType> <complexContent> <extension base="gml:AbstractFeatureMemberType" > <sequence> <element name="id" type="integer" minOccurs="1" maxOccurs="1"/> <element name="category" type="string" minOccurs="0" maxOccurs="1"/> <element name="type" type="string" minOccurs="1" maxOccurs="1"/> <!-- e.g., Interior - 6 1/8" Partition (2-hr)--> <element name="thickness" type="gml:MeasureType" minOccurs="1" maxOccurs="1"/> <element name="length" type="gml:MeasureType" minOccurs="1" maxOccurs="1"/> <element name="height" type="gml:MeasureType" minOccurs="1" maxOccurs="1"/> <element name="centerLineOf" type="gml:CurvePropertyType" minOccurs="1" maxOccurs="1"/> </sequence> </extension> </complexContent> </complexType> </element> <element name="Column"> <complexType> <complexContent> <extension base="gml:AbstractFeatureMemberType" > <sequence> <element name="id" type="integer" minOccurs="1" maxOccurs="1"/> <element name="category" type="string" minOccurs="0" maxOccurs="1"/> <!-- e.g., M_Concrete-Rectangular-Column--> <element name="type" type="string" minOccurs="1" maxOccurs="1"/> <!-- e.g., 600 x 750mm--> <element name="height" type="gml:MeasureType" minOccurs="1" maxOccurs="1"/> <element name="level" type="integer" minOccurs="1" maxOccurs="1"/> <element name="centerPointOf" type="gml:PointPropertyType" minOccurs="1" maxOccurs="1"/> <element name="base_b" type="gml:MeasureType" minOccurs="1" maxOccurs="1"/> <element name="base_h" type="gml:MeasureType" minOccurs="1" maxOccurs="1"/> <choice minOccurs="1" maxOccurs="1">  5/9 file:/C:/Users/webster/Documents/thesis/XQueries/Schemas/aas.xsd  <element name="onGrid"> <complexType> <complexContent> <extension base="gml:AbstractFeatureType"> <sequence> <element name="gridIntersection" type="string"/> </sequence> </extension> </complexContent> </complexType> </element> <element name="offGrid"> <complexType> <complexContent> <extension base="gml:AbstractFeatureType"> <sequence> <element name="closestXGridline" type="artifact:ClosestGridlineType" /> <element name="closestYGridline" type="artifact:ClosestGridlineType" /> </sequence> </extension> </complexContent> </complexType> </element> </choice> <element name="proximateColumns"> <complexType> <complexContent> <extension base="gml:AbstractFeatureType"> <sequence> <element name="proximateColumn" type="artifact:ProximateColumnType" maxOccurs="4"/> </sequence> </extension> </complexContent> </complexType> </element> </sequence> </extension> </complexContent> </complexType> </element> <element name="Duct"> <complexType>  6/9 file:/C:/Users/webster/Documents/thesis/XQueries/Schemas/aas.xsd  <complexContent> <extension base="gml:AbstractFeatureMemberType" > <sequence> <element name="id" type="integer" minOccurs="1" maxOccurs="1"/> <element name="diameter" type="gml:MeasureType" minOccurs="1" maxOccurs="1"/> <element name="length" type="gml:MeasureType" minOccurs="1" maxOccurs="1"/> <element name="centerElevation" type="gml:MeasureType" minOccurs="1" maxOccurs="1"/> <element name="topElevation" type="gml:MeasureType" minOccurs="1" maxOccurs="1"/> <element name="bottomElevation" type="gml:MeasureType" minOccurs="1" maxOccurs="1"/> <element name="centerLineOf" type="gml:CurvePropertyType" minOccurs="1" maxOccurs="1"/> </sequence> </extension> </complexContent> </complexType> </element> <element name="Gridline"> <complexType> <complexContent> <extension base="gml:AbstractFeatureMemberType" > <sequence> <element name="id" type="integer" minOccurs="1" maxOccurs="1"/> <element name="name" type="string" minOccurs="1" maxOccurs="1"/> <element name="axis" type="string" minOccurs="1" maxOccurs="1"/> <element name="value" type="double" minOccurs="1" maxOccurs="1"/> </sequence> </extension> </complexContent> </complexType> </element> <element name="Intersection"> <annotation> <documentation>An Intersection is the physical interaction between two building components: the components either touch each other or overlap in space. In the version 1.0 of the ARTIFACT Application Schema, an Intersection is assumed to occur between a Wall and either another Wall or a Column, i.e., we consider only Wall-to-Wall and Wall-to-Column Intersections. </documentation> </annotation> <complexType> <complexContent> <extension base="gml:AbstractFeatureMemberType" > <sequence> <element ref="artifact:Wall"/>  7/9 file:/C:/Users/webster/Documents/thesis/XQueries/Schemas/aas.xsd  <choice minOccurs="1" maxOccurs="1"> <element ref="artifact:Wall"/> <element ref="artifact:Column"/> </choice> <element name="location" type="artifact:IntersectionLocationType" /> <element name="area" type="gml:MeasureType" minOccurs="0"/> <element name="volume" type="gml:MeasureType" minOccurs="0"/> </sequence> </extension> </complexContent> </complexType> </element> <element name="Penetration"> <complexType> <complexContent> <extension base="gml:AbstractFeatureMemberType" > <sequence> <element ref="artifact:Wall" minOccurs="1" maxOccurs="1"/> <element ref="artifact:Duct" minOccurs="1" maxOccurs="1"/> <element name="area" type="gml:MeasureType" minOccurs="1" maxOccurs="1"/> <element name="volume" type="gml:MeasureType" minOccurs="1" maxOccurs="1"/> <element name="location" type="artifact:IntersectionLocationType" minOccurs="1" maxOccurs="1"/> <element name="locationOnWall" minOccurs="1" maxOccurs="1"> <complexType> <sequence> <element name="distanceFromWallTop" type="gml:MeasureType" minOccurs="1" maxOccurs="1"/> <element name="distanceFromWallBottom" type="gml:MeasureType" minOccurs="1" maxOccurs="1"/> <element name="distanceFromWallLeft" type="gml:MeasureType" minOccurs="1" maxOccurs="1"/> <element name="distanceFromWallRight" type="gml:MeasureType" minOccurs="1" maxOccurs="1"/> </sequence> </complexType> </element> </sequence> </extension> </complexContent> </complexType> </element> <!--gml:id in the instance should be the level!--> <element name="Spacing">  8/9 file:/C:/Users/webster/Documents/thesis/XQueries/Schemas/aas.xsd  <annotation> <documentation>The Spacing element describes the maximum and minimum Spacing between on-grid columns only. </documentation> </annotation> <complexType> <complexContent> <extension base="gml:AbstractFeatureMemberType" > <sequence> <element name="level" type="integer"/> <element name="faceToFace" type="artifact:SpacingType"/> <element name="centerToCenter" type="artifact:SpacingType"/> </sequence> </extension> </complexContent> </complexType> </element> <!-- *********************** FEATURE TYPE DEFINITIONS *********************--> <complexType name="IntersectionLocationType"> <complexContent> <extension base="gml:AbstractFeatureType"> <sequence> <!-- 8 points representing the corners of the box that comprises the intersecting region--> <element maxOccurs="8" minOccurs="4" name="Point" type="gml:PointPropertyType"/> </sequence> </extension> </complexContent> </complexType> <complexType name="ClosestGridlineType"> <complexContent> <extension base="gml:AbstractFeatureType"> <sequence> <element name="gridline" type="string"/> <element name="distance" type="gml:MeasureType"/> </sequence> </extension> </complexContent> </complexType> <complexType name="SpacingType"> <complexContent> <extension base="gml:AbstractFeatureType"> <sequence> <element name="maximum" type="gml:MeasureType"/> <element name="minimum" type="gml:MeasureType"/> </sequence>  9/9 file:/C:/Users/webster/Documents/thesis/XQueries/Schemas/aas.xsd  </extension> </complexContent> </complexType> <complexType name="ProximateColumnType"> <complexContent> <extension base="gml:AbstractFeatureType"> <sequence> <element ref="artifact:Column"/> <element name="faceToFaceDistance" type="gml:MeasureType"/> <element name="centerToCenterDistance" type="gml:MeasureType"/> </sequence> </extension> </complexContent> </complexType>  </xs:schema>  Appendix C  Units of Measure Dictionary  88  1/1 file:/C:/Users/webster/Documents/thesis/XQueries/artifactUOMDictionary.xml  <?xml version="1.0" encoding="UTF-8"?> <gml:Dictionary gml:id="artifactUOMDictionary" xmlns:gml="http://www.opengis.net/gml"> <gml:dictionaryEntry> <gml:ConventionalUnit gml:id="ft"> <gml:name codeSpace="http://www.bipm.fr/en/3_SI">foot</gml:name> </gml:ConventionalUnit> <gml:quantityType>length</gml:quantityType> <gml:catalogSymbol codeSpace="http://www.bipm.fr/en/3_SI">ft</gml:catalogSymbol> <gml:conversionToPreferredUnit uom="#m"> <gml:factor>0.3048</gml:factor> </gml:conversionToPreferredUnit> </gml:dictionaryEntry> <gml:dictionaryEntry> <gml:ConventionalUnit gml:id="sqft"> <gml:name codeSpace="http://www.bipm.fr/en/3_SI">square-feet</gml:name> </gml:ConventionalUnit> <gml:quantityType>area</gml:quantityType> <gml:catalogSymbol codeSpace="http://www.bipm.fr/en/3_SI">sqft</gml:catalogSymbol> <!--<gml:conversionToPreferredUnit uom="#m"> <gml:factor>0.3048</gml:factor> </gml:conversionToPreferredUnit>--> </gml:dictionaryEntry> <gml:dictionaryEntry> <gml:ConventionalUnit gml:id="cuft"> <gml:name codeSpace="http://www.bipm.fr/en/3_SI">cubic-feet</gml:name> </gml:ConventionalUnit> <gml:quantityType>volume</gml:quantityType> <gml:catalogSymbol codeSpace="http://www.bipm.fr/en/3_SI">cuft</gml:catalogSymbol> <!--<gml:conversionToPreferredUnit uom="#m"> <gml:factor>0.3048</gml:factor> </gml:conversionToPreferredUnit>--> </gml:dictionaryEntry> </gml:Dictionary>  Appendix D  Spatial Query Predicates  90  1/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  (: ********************************************************************************************** NAMESPACE DECLARATIONS *********************************************************************************************** *:) declare namespace artifact="http://www.cs.ubc.ca/labs/db/artifact" ; declare namespace math="http://www.cs.ubc.ca/labs/db/artifact/math" ; declare namespace gml="http://www.opengix.net/gml"; (: ********************************************************************************************** VARIABLE DECLARATIONS *********************************************************************************************** *:) declare variable $xd_N := 0; declare variable $yd_N := 1; declare variable $xd_S := 0; declare variable $yd_S := -1; declare variable $xd_E := 1; declare variable $yd_E := 0; declare variable $xd_W := -1; declare variable $yd_W := 0; (: ********************************************************************************************** FILE DECLARATIONS *********************************************************************************************** *:) declare variable $columnsXMLFile := "columns4.xml"; declare variable $gridsXMLFile := "grids2.xml"; declare variable $ductsXMLFile := "ducts.xml"; declare variable $wallsForPenetrationXML := "wallsForPenetration.xml"; declare variable $wallsForIntersectionXML := "nov6Walls.xml"; declare variable $columnsForPenetrationXML := "columnsForPenetrationSquare.xml" ; (: ********************************************************************************************** MATH FUNCTIONS *********************************************************************************************** *:) (: Source: http://www.xqsharp.com/xqsharp/samples/raytracer/part6.htm :) declare function math:sqrt($x as xs:double?) as xs:double? { math:sqrt2($x, 0.5 + $x div 2, 100) };  2/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  (: Source: http://www.xqsharp.com/xqsharp/samples/raytracer/part6.htm :) declare function math:sqrt2($x as xs:double?, $guess as xs:double?, $n as xs:integer) as xs:double? { if ($n <= 0) then $guess else let $next := ($x + $guess * $guess) div (2 * $guess) return math:sqrt2($x, $next, $n - 1) }; (: math:euclideanDistance returns the center-to-center euclidean :) declare function math:euclideanDistance($col1, $col2) { for $c1 in doc($columnsXMLFile)/columns/column, $c2 in doc($columnsXMLFile)/columns/column where $c1/id = $col1 and $c2/id = $col2 return math:sqrt( (data($c1/centerpoint[@axis="x"]/text()) data($c2/centerpoint[@axis="x"]/text()) ) * (data($c1/centerpoint[@axis="x"]/text()) data($c2/centerpoint[@axis="x"]/text()) ) + (data($c1/centerpoint[@axis="y"]/text()) data($c2/centerpoint[@axis="y"]/text()) ) * (data($c1/centerpoint[@axis="y"]/text()) data($c2/centerpoint[@axis="y"]/text()) ) ) };  distance between two columns  -  (: math:euclideanDistance returns the center-to-center euclidean distance between two columns :) declare function math:faceToFaceEuclideanDistance ($col1, $col2) { let $column1.centerX := data($col1/centerpoint[@axis="x"]/text()), $column1.centerY := data($col1/centerpoint[@axis="y"]/text()), $column1.baseB := data($col1/base_b/text()), $column2.centerX := data($col2/centerpoint[@axis="x"]/text()), $column2.centerY := data($col2/centerpoint[@axis="y"]/text()), $column2.baseB := data($col2/base_b/text()) return math:sqrt( ($column1.centerX - $column2.centerX ) * ($column1.centerX $column2.centerX ) + ($column1.centerY - $column2.centerY ) * ($column1.centerY $column2.centerY ) ) - $column1.baseB - $column2.baseB };  (: math:manhattanDistance returns the center-to-center manhattan distance between two columns :) declare function math:manhattanDistance($col1, $col2) {  3/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  let $manhattanDistance := fn:abs(data($col1/centerpoint[@axis="x"]/text()) data($col2/centerpoint[@axis="x"]/text())) + fn:abs(data($col1/centerpoint[@axis="y"]/text()) data($col2/centerpoint[@axis="y"]/text())) return $manhattanDistance }; declare function math:faceToFaceManhattanDistance ($col1, $col2) { let $column1.centerX := data($col1/centerpoint[@axis="x"]/text()), $column1.centerY := data($col1/centerpoint[@axis="y"]/text()), $column1.baseB := data($col1/base_b/text()), $column2.centerX := data($col2/centerpoint[@axis="x"]/text()), $column2.centerY := data($col2/centerpoint[@axis="y"]/text()), $column2.baseB := data($col2/base_b/text()), $manhattanDistance := fn:abs($column1.centerX - $column2.centerX) + fn:abs($column1.centerY - $column2.centerY) - $column1.baseB - $column2.baseB return $manhattanDistance }; declare function math:areaRectangle($left, $right, $top, $bottom) { let $side1_length := fn:abs($right - $left), $side2_length := fn:abs($top - $bottom) return $side1_length * $side2_length }; declare function math:volumeRectangle($left, $right, $top, $bottom, $height) { let $side1_length := fn:abs($right - $left), $side2_length := fn:abs($top - $bottom) return $side1_length * $side2_length * $height }; (: ********************************************************************************************** ARTIFACT HELPER FUNCTIONS *********************************************************************************************** *:)  declare function artifact:isRound($column) { let $column.type := $column/category return if(contains($column.type,'Round')) then true() else false() };  4/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  declare function artifact:isSquare($column) { let $column.type := $column/category return if(contains($column.type,'Square')) then true() else false() }; (: Reasoning: A wall is aligned along the x-axis if the x-value of the points defining the wall's centerline are the same (i.e., y varies, x is constant); this condition will always be true for a line that is parallel to the x-axis. :) declare function artifact:isWallXAligned($wall) { let $x1 := round((($wall/centerline[@size="2"]/point[@position="1" and @axis="x"]) * 100) div 100), $x2 := round((($wall/centerline[@size="2"]/point[@position="2" and @axis="x"]) * 100) div 100) return if($x1 = $x2) then true() else false() }; declare function artifact:isWallYAligned($wall) { let $y1 := round((($wall/centerline[@size="2"]/point[@position="1" and @axis="y"])*100) div 100), $y2 := round((($wall/centerline[@size="2"]/point[@position="2" and @axis="y"])*100) div 100) return if($y1 = $y2) then true() else false() };  declare function artifact:getWallMinX($wall) { let $x1 := round(number($wall/centerline[@size="2"]/point[@position="1" and @axis="x"]) * 100) div 100, $x2 := round(number($wall/centerline[@size="2"]/point[@position="2" and @axis="x"]) * 100) div 100, $isWallXAligned := artifact:isWallXAligned($wall), $thickness := round(number($wall/thickness) * 100) div 100, $minX := if($isWallXAligned) then (min(($x1,$x2)) - $thickness div 2) else (min(($x1,$x2))) return $minX };  5/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  declare function artifact:getWallMaxX($wall) { let $x1 := round(number($wall/centerline[@size="2"]/point[@position="1" and @axis="x"]) * 100) div 100, $x2 := round(number($wall/centerline[@size="2"]/point[@position="2" and @axis="x"]) * 100) div 100, $isWallXAligned := artifact:isWallXAligned($wall), $thickness := round(number($wall/thickness) * 100) div 100, $maxX := if($isWallXAligned) then (max(($x1,$x2)) + $thickness div 2) else (max(($x1,$x2))) return $maxX }; declare function artifact:getWallMinY($wall) { let $y1 := round(number($wall/centerline[@size="2"]/point[@position="1" and @axis="y"]) * 100) div 100, $y2 := round(number($wall/centerline[@size="2"]/point[@position="2" and @axis="y"]) * 100) div 100, $isWallXAligned := artifact:isWallXAligned($wall), $thickness := round(number($wall/thickness) * 100) div 100, $minY := if(not($isWallXAligned)) then (min(($y1,$y2)) - $thickness div 2) else (min(($y1,$y2))) return $minY }; declare function artifact:getWallMaxY($wall) { let $y1 := round(number($wall/centerline[@size="2"]/point[@position="1" and @axis="y"]) * 100) div 100, $y2 := round(number($wall/centerline[@size="2"]/point[@position="2" and @axis="y"]) * 100) div 100, $isWallXAligned := artifact:isWallXAligned($wall), $thickness := round(number($wall/thickness) * 100) div 100, $maxY := if(not($isWallXAligned)) then (max(($y1,$y2)) + $thickness div 2) else (max(($y1,$y2))) return $maxY };  (: ********************************************************************************************** ARTIFACT PENETRATION FUNCTIONS *********************************************************************************************** *:) declare function artifact:getDuctMinX($duct) { let $x1 := round(number($duct/centerline[@size="2"]/point[@position="1" and @axis="x"]) * 100) div 100,  6/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  $x2 := round(number($duct/centerline[@size="2"]/point[@position="2" and @axis="x"]) * 100) div 100, $isWallXAligned := artifact:isDuctXAligned($duct), $diameter := round(number($duct/diameter) * 100) div 100, $minX := if($isWallXAligned) then (min(($x1,$x2)) - $diameter div 2) else (min(($x1,$x2))) return $minX }; declare function artifact:getDuctMaxX($duct) { let $x1 := round(number($duct/centerline[@size="2"]/point[@position="1" and @axis="x"]) * 100) div 100, $x2 := round(number($duct/centerline[@size="2"]/point[@position="2" and @axis="x"]) * 100) div 100, $isWallXAligned := artifact:isDuctXAligned($duct), $diameter := round(number($duct/diameter) * 100) div 100, $maxX := if($isWallXAligned) then (max(($x1,$x2)) + $diameter div 2) else (max(($x1,$x2))) return $maxX }; declare function artifact:getDuctMinY($duct) { let $y1 := round(number($duct/centerline[@size="2"]/point[@position="1" and @axis="y"]) * 100) div 100, $y2 := round(number($duct/centerline[@size="2"]/point[@position="2" and @axis="y"]) * 100) div 100, $isWallXAligned := artifact:isDuctXAligned($duct), $diameter := round(number($duct/diameter) * 100) div 100, $minY := if(not($isWallXAligned)) then (min(($y1,$y2)) - $diameter div 2) else (min(($y1,$y2))) return $minY }; declare function artifact:getDuctMaxY($duct) { let $y1 := round(number($duct/centerline[@size="2"]/point[@position="1" and @axis="y"]) * 100) div 100, $y2 := round(number($duct/centerline[@size="2"]/point[@position="2" and @axis="y"]) * 100) div 100, $isWallXAligned := artifact:isDuctXAligned($duct), $diameter := round(number($duct/diameter) * 100) div 100, $maxY := if(not($isWallXAligned)) then (max(($y1,$y2)) + $diameter div 2) else (max(($y1,$y2))) return $maxY }; declare function artifact:isDuctXAligned($duct) { let $x1 := $duct/centerline[@size="2"]/point[@position="1" and @axis="x"],  7/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  $x2 := $duct/centerline[@size="2"]/point[@position="2" and @axis="x"] return if($x1 = $x2) then true() else false() }; (: FUNCTIONS FOR PENETRATION :) (: ********************************************************************************************** :)  declare function artifact:minDistance($sourceColumn, $columns) { let $minDistance := round( min(( for $col in $columns return (math:manhattanDistance($sourceColumn, $col/column)) )) * 100) div 100 return $minDistance }; declare function artifact:maxDistance($sourceColumn, $columns) { let $minDistance := round( max(( for $col in $columns return (math:manhattanDistance($sourceColumn, $col/column)) )) * 100) div 100 return $minDistance }; declare function artifact:avgDistance($sourceColumn, $columns) { let $minDistance := round( avg(( for $col in $columns return (math:manhattanDistance($sourceColumn, $col/column)) )) * 100) div 100 return $minDistance };  declare function artifact:exteriorGridlines() { let $gx := doc($gridsXMLFile)/grids/gridline[gridlineAxis="x"], $gy := doc($gridsXMLFile)/grids/gridline[gridlineAxis="y"], $min_gx := min($gx/gridlineValue), $max_gx := max($gx/gridlineValue), $min_gy := min($gy/gridlineValue), $max_gy := max($gy/gridlineValue) return <exteriorGridlines> <minX>{$min_gx}</minX> <maxX>{$max_gx}</maxX> <minY>{$min_gy}</minY> <maxY>{$max_gy}</maxY> </exteriorGridlines> };  8/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  declare function artifact:minExteriorGridline($axis) { let $g := doc($gridsXMLFile)/grids/gridline[gridlineAxis=$axis], $min_g := min($g/gridlineValue) for $grid in $g where $grid/gridlineValue = $min_g return $grid/name/text() }; declare function artifact:maxExteriorGridline($axis) { let $g := doc($gridsXMLFile)/grids/gridline[gridlineAxis=$axis], $max_g := max($g/gridlineValue) for $grid in $g where $grid/gridlineValue = $max_g return $grid/name/text() };  declare function artifact:getBuildingLevels($columnsXMLFile) { let $columnLevels := doc($columnsXMLFile)/columns/column/level return distinct-values(($columnLevels)) }; declare function artifact:getComponentLevel($componentZValue) { let $buildingLevels:= artifact:getBuildingLevels($columnsXMLFile) return index-of($buildingLevels, $componentZValue) }; declare function artifact:getColumn($columnId) { for $c in doc($columnsXMLFile)/columns/column where $c/id/text() = $columnId return $c }; (: ********************************************************************************************** ARTIFACT QUERY PREDICATES *********************************************************************************************** *:) (: *************************************** ALIGNMENT PREDICATES ********************************************:) declare function artifact:ongrid($column)  9/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  { let $ongrid := artifact:isAligned($column,"x") and artifact:isAligned($column,"y") return $ongrid }; declare function artifact:isAligned($column,$axis) {  let $isYAligned := artifact:isAlignedInterior($column,$axis) or artifact:isAlignedExterior($column,$axis) return $isYAligned }; declare function artifact:isAlignedInterior($column, $axis) { for $g in doc($gridsXMLFile)/grids/gridline[gridlineAxis=$axis] where round(number($column/centerpoint[@axis=$axis]) * 10000) div 10000 = round(number($g/gridlineValue) * 10000) div 10000 return true() }; declare function artifact:isAlignedExterior($column,$axis) { let $g := doc($gridsXMLFile)/grids/gridline[gridlineAxis=$axis], $min_g := min($g/gridlineValue), $max_g := max($g/gridlineValue) where (artifact:isSquare($column) or artifact:isRound($column)) and (: one of the x-axis aligned edges is along the minimum x-aligned (exterior) gridline :) (round(number($column/centerpoint[@axis=$axis] + $column/base_b div 2) * 10000) div 10000 = round(number($min_g) * 10000) div 10000 or round(number($column/centerpoint[@axis=$axis] - $column/base_b div 2) * 10000) div 10000 = round(number($min_g) * 10000) div 10000 or round(number($column/centerpoint[@axis=$axis] + $column/base_b div 2) * 10000) div 10000 = round(number($max_g) * 10000) div 10000 or round(number($column/centerpoint[@axis=$axis] - $column/base_b div 2) * 10000) div 10000 = round(number($max_g) * 10000) div 10000 ) return true() };  10/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  (: Purpose: alignedToGridIntersection is a function that returns the grid intersection that a column (identified by columnId) is aligned to Input: $column = a column element Pre: $column must be XYAligned (i.e., it must be aligned to both an X-gridline and a Y-gridline) Output: the grid intersection in the format xGridline-yGridline (e.g., 3-C) that a column is aligned to; for interior columns this means that the column's centerpoint will be at the grid intersection and for exterior columns the one or both of its edges will be aligned to an exterior gridline. :) declare function artifact:alignedToGridIntersection ($column) { let $alignedToGridIntersection := ( if (artifact:ongrid($column)) then concat(artifact:alignedToGridline($column,"x"),"-",artifact:alignedToGridline($column,"y")) else "null" ) return $alignedToGridIntersection };  declare function artifact:alignedToGridline($column,$axis) { let $alignedToGridline := ( if(artifact:isAlignedInterior($column,$axis)) then artifact:alignedToGridlineInterior ($column,$axis) else if(artifact:isAlignedExterior($column,$axis)) then artifact:alignedToGridlineExterior ($column, $axis) else "null" ) return $alignedToGridline };  declare function artifact:alignedToGridlineInterior ($column,$axis) { for $g in doc($gridsXMLFile)/grids/gridline[gridlineAxis=$axis] where round(number($column/centerpoint[@axis=$axis]) * 10000) div 10000 = round(number($g/gridlineValue) * 10000) div 10000 return $g/name/text() };  declare function artifact:alignedToGridlineExterior ($column,$axis)  11/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  { let $g := doc($gridsXMLFile)/grids/gridline[gridlineAxis=$axis], $min_g := min($g/gridlineValue), $max_g := max($g/gridlineValue) where artifact:isSquare($column) or artifact:isRound($column) return if( (round(number($column/centerpoint[@axis="x"] + $column/base_b div 2) * 10000 = round(number($min_g) * 10000) div 10000) or (round(number($column/centerpoint[@axis=$axis] - $column/base_b div 2) 10000 = round(number($min_g) * 10000) div 10000) ) then artifact:minExteriorGridline($axis) else if ( (round(number($column/centerpoint[@axis=$axis] + $column/base_b div 2) 10000 = round(number($max_g) * 10000) div 10000) or (round(number($column/centerpoint[@axis=$axis] - $column/base_b div 2) 10000 = round(number($max_g) * 10000) div 10000) ) then artifact:maxExteriorGridline($axis) else "null" };  10000) div  * 10000) div  * 10000) div  * 10000) div  (: returns all columns that are on-grid, both interior and exterior columns :) declare function artifact:onGridColumns() { for $c in doc($columnsXMLFile)/columns/column where artifact:ongrid($c) return $c }; (: returns for each onGrid column on $level the gridIntersection it is aligned to :) (: here $level is the height of the floor; could change to be the numerical level, in which case would replace artiface:getComponent($level) with $level :) declare function artifact:onGridColumns($level) { let $onGridColumns := artifact:onGridColumns() for $column in $onGridColumns where artifact:getComponentLevel($column/centerpoint[@axis="z"]) = artifact:getComponentLevel($level) return <column id = "{$column/id/text()}">{artifact:alignedToGridIntersection ($column)}</column> };  12/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  declare function artifact:onGridColumnsByLevel() { let $levels := artifact:getBuildingLevels($columnsXMLFile) for $level in $levels return <level value = "{artifact:getComponentLevel($level)}" >{artifact:onGridColumns($level)}</level> }; declare function artifact:closestGridline($column,$axis) { let $distToGridlines := ( (: for all gridlines, find distance from $column $axis-value to $axis gridline :) for $gl in doc($gridsXMLFile)/grids/gridline[gridlineAxis=$axis] return <closestGridline> <gridline>{$gl/name/text()}</gridline> <distance uom="#ft">{artifact:distanceToClosestGridline ($column,$gl,$axis)}</distance> </closestGridline> ), $minDistance := min(($distToGridlines/dist)), $closestGridlines := (for $g in $distToGridlines where $g/dist = $minDistance return $g/gridline/text()) return $closestGridlines }; declare function artifact:distanceToClosestGridline ($column,$gl,$axis) { let $distance := round(fn:abs(round(number($column/centerpoint[@axis=$axis]) * 10000) div 10000 round(number($gl/gridlineValue) * 10000) div 10000) * 10000) div 10000 return $distance };  (: ********************************** END OF ALIGNMENT PREDICATES *********************************:)  (: *************************************** SPACING PREDICATES *************************************:) (: Includes the proximate column predicate - spacing is determined between proximate columns :)  (: Purpose: determines if a gridline (represented as a ray) that a source column is aligned to intersects a target column in direction "d" (north, south, east or west) Input: ($x0, $y0) = centerpoint of source column  13/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  ($xT, $yT) = centerpoint of target column $rT = radius of the target column ($xd, $yd) = direction of the ray (a unit vector) - north, south, east or west; defined in the "Variable Declarations" section Output: true if there is an intersection; false otherwise :) declare function artifact:isRayCircleIntersection ($x0, $y0, $xT, $yT, $rT, $xd, $yd) { let $B := 2 * ( $xd * ($x0 - $xT) + $yd * ($y0 - $yT)), $C := ($x0 - $xT)*($x0 - $xT) + ($y0 - $yT)*($y0 - $yT) - $rT*$rT, $discriminant := $B * $B - 4 * $C, $t0 := (-1 * $B - math:sqrt($B * $B - 4 * $C)) div 2, $t1 := (-1 * $B + math:sqrt($B * $B - 4 * $C)) div 2 return if ($discriminant > 0 and $t0 > 0 and $t1 > 0) then true() else false() };  (: March 18, 2010 :) (: Added this so could rename what returning to be by column element; didn't want to cause a bug in other functions depending on artifact:proximateColumns() :) declare function artifact:proximateColumns($sourceColumn) { let $northProximateColumn := artifact:proximateColumn($sourceColumn, $xd_N, $yd_N), $southProximateColumn := artifact:proximateColumn($sourceColumn, $xd_S, $yd_S), $eastProximateColumn := artifact:proximateColumn($sourceColumn, $xd_E, $yd_E), $westProximateColumn := artifact:proximateColumn($sourceColumn, $xd_W, $yd_W), $northProximateDistance := ( if(string(round(number(math:manhattanDistance($sourceColumn, $northProximateColumn)*100)) div 100) = "NaN") then 1000000 else round(number(math:manhattanDistance($sourceColumn, $northProximateColumn)*100)) div 100 ), $southProximateDistance := ( if(string(round(number(math:manhattanDistance($sourceColumn, $southProximateColumn)*100)) div 100) = "NaN") then 1000000 else round(number(math:manhattanDistance($sourceColumn, $southProximateColumn)*100)) div 100 ), $eastProximateDistance := ( if(string(round(number(math:manhattanDistance($sourceColumn, $eastProximateColumn)*100)) div 100) = "NaN") then 1000000 else round(number(math:manhattanDistance($sourceColumn, $eastProximateColumn)*100)) div 100 ),  14/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  $westProximateDistance := ( if(string(round(number(math:manhattanDistance($sourceColumn, $westProximateColumn)*100)) div 100) = "NaN") then 1000000 else round(number(math:manhattanDistance($sourceColumn, $westProximateColumn)*100)) div 100 ) return <column> <id>{$sourceColumn/id/text()}</id> <levelHeight>{$sourceColumn/level/text()}</levelHeight> <level>{artifact:getComponentLevel($sourceColumn/level/text())}</level> <proximateColumns> <minDistance>{round(number(min((math:manhattanDistance($sourceColumn, $northProximateColumn), math:manhattanDistance($sourceColumn, $southProximateColumn), math:manhattanDistance($sourceColumn, $eastProximateColumn), math:manhattanDistance($sourceColumn, $westProximateColumn) )) * 100)) div 100}</minDistance> <column> <id>{$northProximateColumn/id/text()}</id> <distance>{$northProximateDistance}</distance> </column> <column> <id>{$southProximateColumn/id/text()}</id> <distance>{$southProximateDistance}</distance> </column> <column> <id>{$eastProximateColumn/id/text()}</id> <distance>{$eastProximateDistance}</distance> </column> <column> <id>{$westProximateColumn/id/text()}</id> <distance>{$westProximateDistance}</distance> </column> </proximateColumns> </column> }; declare function artifact:proximateColumn($sourceColumn, $xd, $yd) { let $proximateColumns := artifact:proximateColumnCandidates ($sourceColumn/id/text(), $xd, $yd), $minDistance := artifact:minDistance($sourceColumn, $proximateColumns) for $col in $proximateColumns let $distanceToSource := round(number(math:manhattanDistance($sourceColumn, $col/column)) * 100) div 100 where $distanceToSource = $minDistance  15/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  return $col/column }; (: Purpose: $xd, $yd gives the direction that want to find proximate column in...N, S, E or W - see above in constants as to how to specify this proximateColumnCandidates :) declare function artifact:proximateColumnCandidates ($columnId, $xd, $yd) { let $sourceColumn := (for $col in doc($columnsXMLFile)/columns/column where $col/id = $columnId return $col), $sourceCenterX := round(number($sourceColumn/centerpoint[@axis="x"]) * 10000) div 10000, $sourceCenterY := round(number($sourceColumn/centerpoint[@axis="y"]) * 10000) div 10000, $sourceRadius := round(number($sourceColumn/base_b) * 10000) div 10000, $x0_N := $sourceCenterX, $y0_N := $sourceCenterY + $sourceRadius for $targetColumn in doc($columnsXMLFile)/columns/column where artifact:ongrid($targetColumn) and round(number($targetColumn/level) * 10000) div 10000 = round(number($sourceColumn/level) * 10000) div 10000 and $targetColumn/id != $sourceColumn/id and artifact:isRayCircleIntersection ($sourceCenterX, $sourceCenterY, round(number($targetColumn/centerpoint[@axis="x"])*10000) div 10000, round(number($targetColumn/centerpoint[@axis="y"])*10000) div 10000, round(number($targetColumn/base_b div 2)*10000) div 10000, $xd, $yd) order by round(math:manhattanDistance($sourceColumn,$targetColumn) * 100) div 100 return <proximateColumns>{$targetColumn}</proximateColumns> };  (:******************************************MIN SPACING **************************************************:) declare function artifact:minSpacings($level) { for $column in doc($columnsXMLFile)/columns/column let $column_alignedTo := artifact:alignedToGridIntersection ($column) where artifact:getComponentLevel($column/centerpoint[@axis="z"]) = artifact:getComponentLevel($level) return <columnPair> <column id = "{$column/id/text()}">{$column_alignedTo}</column> <column id =  16/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  "{artifact:closestColumn($column)}" >{artifact:alignedToGridIntersection (artifact:getColumn(arti fact:closestColumn($column)))}</column> <distance>{round(math:manhattanDistance($column,artifact:getColumn(artifact:closestColumn($colu mn))) * 100) div 100}</distance> </columnPair> }; declare function artifact:closestColumn($sourceColumn) { let $proximateColumns := artifact:proximateColumns($sourceColumn)/proximateColumns/column, $distances := $proximateColumns/distance/text(), $minDistance := min(($distances)) for $c in $proximateColumns where number($c/distance/text()) = $minDistance return $c/id/text() };  declare function artifact:distinctMinSpacings($level) { let $minSpacings := artifact:minSpacings($level)/columnPair/distance return distinct-values(($minSpacings)) }; declare function artifact:minSpacing() { for $level in artifact:getBuildingLevels($columnsXMLFile) let $min := ( for $column in doc($columnsXMLFile)/columns/column let $column.minSpacing := round(number(min((math:manhattanDistance($column, artifact:proximateColumn($column, $xd_N, $yd_N)), math:manhattanDistance($column, artifact:proximateColumn($column, $xd_S, $yd_S)), math:manhattanDistance($column, artifact:proximateColumn($column, $xd_E, $yd_E)), math:manhattanDistance($column, artifact:proximateColumn($column, $xd_W, $yd_W)) )) * 100)) div 100 where (artifact:ongrid($column)) and artifact:getComponentLevel($column/centerpoint[@axis="z"]) = artifact:getComponentLevel($level) return if (string($column.minSpacing) = "NaN") then 1000000 else ($column.minSpacing) ) return <level value = "{artifact:getComponentLevel($level)}" > <minSpacing>{min(($min))}</minSpacing> </level> };  17/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  declare function artifact:minXSpacing() { for $level in artifact:getBuildingLevels($columnsXMLFile) let $min := ( for $column in doc($columnsXMLFile)/columns/column let $column.minSpacing := round(number(min((math:manhattanDistance($column, artifact:proximateColumn($column, $xd_E, $yd_E)), math:manhattanDistance($column, artifact:proximateColumn($column, $xd_W, $yd_W)) )) * 100)) div 100 where (artifact:ongrid($column)) and artifact:getComponentLevel($column/centerpoint[@axis="z"]) = artifact:getComponentLevel($level) return if (string($column.minSpacing) = "NaN") then 1000000 else ($column.minSpacing) ) return <level value = "{artifact:getComponentLevel($level)}" > <minXSpacing>{min(($min))}</minXSpacing> </level> }; declare function artifact:minYSpacing() { for $level in artifact:getBuildingLevels($columnsXMLFile) let $min := ( for $column in doc($columnsXMLFile)/columns/column let $column.minSpacing := round(number(min((math:manhattanDistance($column, artifact:proximateColumn($column, $xd_N, $yd_N)), math:manhattanDistance($column, artifact:proximateColumn($column, $xd_S, $yd_S)) )) * 100)) div 100 where (artifact:ongrid($column)) and artifact:getComponentLevel($column/centerpoint[@axis="z"]) = artifact:getComponentLevel($level) return if (string($column.minSpacing) = "NaN") then 1000000 else ($column.minSpacing) ) return <level value = "{artifact:getComponentLevel($level)}" > <minYSpacing>{min(($min))}</minYSpacing> </level> };  declare function artifact:faceToFaceMinSpacing() { for $level in artifact:getBuildingLevels($columnsXMLFile)  18/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  let $min := ( for $column in doc($columnsXMLFile)/columns/column let $column.minSpacing := round(number(min((math:faceToFaceManhattanDistance ($column, artifact:proximateColumn($column, $xd_N, $yd_N)), math:faceToFaceManhattanDistance ($column, artifact:proximateColumn($column, $xd_S, $yd_S)), math:faceToFaceManhattanDistance ($column, artifact:proximateColumn($column, $xd_E, $yd_E)), math:faceToFaceManhattanDistance ($column, artifact:proximateColumn($column, $xd_W, $yd_W)) )) * 100)) div 100 where (artifact:ongrid($column)) and artifact:getComponentLevel($column/centerpoint[@axis="z"]) = artifact:getComponentLevel($level) return if (string($column.minSpacing) = "NaN") then 1000000 else ($column.minSpacing)) return <level value = "{artifact:getComponentLevel($level)}" > <minSpacing>{min(($min))}</minSpacing> </level> }; declare function artifact:faceToFaceMinXSpacing () { for $level in artifact:getBuildingLevels($columnsXMLFile) let $min := ( for $column in doc($columnsXMLFile)/columns/column ($column, let $column.minSpacing := round(number(min((math:faceToFaceManhattanDistance artifact:proximateColumn($column, $xd_E, $yd_E)), math:faceToFaceManhattanDistance ($column, artifact:proximateColumn($column, $xd_W, $yd_W)) )) * 100)) div 100 where (artifact:ongrid($column)) and artifact:getComponentLevel($column/centerpoint[@axis="z"]) = artifact:getComponentLevel($level) return if (string($column.minSpacing) = "NaN") then 1000000 else ($column.minSpacing) ) return <level value = "{artifact:getComponentLevel($level)}" > <minFaceToFaceXSpacing>{min(($min))}</minFaceToFaceXSpacing> </level> }; declare function artifact:faceToFaceMinYSpacing () { for $level in artifact:getBuildingLevels($columnsXMLFile) let $min := (  19/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  for $column in doc($columnsXMLFile)/columns/column let $column.minSpacing := round(number(min((math:faceToFaceManhattanDistance ($column, artifact:proximateColumn($column, $xd_N, $yd_N)), math:faceToFaceManhattanDistance ($column, artifact:proximateColumn($column, $xd_S, $yd_S)) )) * 100)) div 100 where (artifact:ongrid($column)) and artifact:getComponentLevel($column/centerpoint[@axis="z"]) = artifact:getComponentLevel($level) return if (string($column.minSpacing) = "NaN") then 1000000 else ($column.minSpacing)) return <level value = "{artifact:getComponentLevel($level)}" > <minFaceToFaceYSpacing>{min(($min))}</minFaceToFaceYSpacing> </level> }; declare function artifact:maxSpacing() { for $level in artifact:getBuildingLevels($columnsXMLFile) let $max := ( for $column in doc($columnsXMLFile)/columns/column let $column.maxSpacing := round(number(max((math:manhattanDistance($column, artifact:proximateColumn($column, $xd_N, $yd_N)), math:manhattanDistance($column, artifact:proximateColumn($column, $xd_S, $yd_S)), math:manhattanDistance($column, artifact:proximateColumn($column, $xd_E, $yd_E)), math:manhattanDistance($column, artifact:proximateColumn($column, $xd_W, $yd_W)) )) * 100)) div 100 where (artifact:ongrid($column)) and artifact:getComponentLevel($column/centerpoint[@axis="z"]) = artifact:getComponentLevel($level) return if (string($column.maxSpacing) = "NaN") then 1000000 else ($column.maxSpacing)) return <level value = "{artifact:getComponentLevel($level)}" > <maxSpacing>{max(($max))}</maxSpacing> </level> }; declare { for let for  function artifact:faceToFaceMaxSpacing() $level in artifact:getBuildingLevels($columnsXMLFile) $max := ( $column in doc($columnsXMLFile)/columns/column  20/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  let $column.maxSpacing := round(number(max((math:faceToFaceManhattanDistance ($column, artifact:proximateColumn($column, $xd_N, $yd_N)), math:faceToFaceManhattanDistance ($column, artifact:proximateColumn($column, $xd_S, $yd_S)), math:faceToFaceManhattanDistance ($column, artifact:proximateColumn($column, $xd_E, $yd_E)), math:faceToFaceManhattanDistance ($column, artifact:proximateColumn($column, $xd_W, $yd_W)) )) * 100)) div 100 where (artifact:ongrid($column)) and artifact:getComponentLevel($column/centerpoint[@axis="z"]) = artifact:getComponentLevel($level) return if (string($column.maxSpacing) = "NaN") then 1000000 else ($column.maxSpacing)) return <level value = "{artifact:getComponentLevel($level)}" > <maxSpacing>{max(($max))}</maxSpacing> </level> }; (:******************************************MIN SPACING **************************************************:) declare function artifact:intersects($wall1, $wall2) { let $isWall1Aligned := artifact:isWallXAligned($wall1) or artifact:isWallYAligned($wall1), $isWall2Aligned := artifact:isWallXAligned($wall2) or artifact:isWallYAligned($wall2) where $wall1/centerline[@size="2"] and (: wall1 is non-curved :) $wall2/centerline[@size="2"] and $wall1/centerline[@size="2"] and (: wall1 is non-curved :) $wall2/centerline[@size="2"] return not(artifact:disjoint($wall1, $wall2)) }; declare function artifact:disjoint($wall1, $wall2) { let $wall1.left := artifact:getWallMinX($wall1), $wall1.right := artifact:getWallMaxX($wall1), $wall1.top := artifact:getWallMaxY($wall1), $wall1.bottom := artifact:getWallMinY($wall1), $wall2.left := artifact:getWallMinX($wall2), $wall2.right := artifact:getWallMaxX($wall2), $wall2.top := artifact:getWallMaxY($wall2), $wall2.bottom := artifact:getWallMinY($wall2), $isWall1Aligned := artifact:isWallXAligned($wall1) or artifact:isWallYAligned($wall1), $isWall2Aligned := artifact:isWallXAligned($wall2) or artifact:isWallYAligned($wall2) where $wall1/centerline[@size="2"] and (: wall1 is non-curved :) $wall2/centerline[@size="2"] and $isWall1Aligned and  21/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  $isWall2Aligned return if ($wall1.right <= $wall2.left or (: w1 is completely to the left of w2 :) $wall1.left >= $wall2.right or (: w1 is completely to the right of w2 :) $wall1.top <= $wall2.bottom or (: w1 is completely below w2 :) $wall1.bottom >=$wall2.top (: w1 is completely above w2 :) ) then true() else false() };  declare function artifact:containsVertex($x, $y, $wall) { let $wall.left := artifact:getWallMinX($wall), $wall.right := artifact:getWallMaxX($wall), $wall.top := artifact:getWallMaxY($wall), $wall.bottom := artifact:getWallMinY($wall) return if($wall.left <= $x and $x <= $wall.right and $wall.bottom <= $y and $y <= $wall.top) then true() else false() }; declare function artifact:columnContainsVertex($x, $y, $column) { let $column.left := artifact:getColumnMinX($column), $column.right := artifact:getColumnMaxX($column), $column.top := artifact:getColumnMaxY($column), $column.bottom := artifact:getColumnMinY($column) return if($column.left <= $x and $x <= $column.right and $column.bottom <= $y and $y <= $column.top) then true() else false() }; (: ********************************** END OF SPACING PREDICATES *********************************:)  (: ****************************** WALL-TO-WALL INTERSECTION PREDICATES **************************:) declare function artifact:intersectingRegion($wall, $wall2) { let $wall.left := artifact:getWallMinX($wall), $wall.right := artifact:getWallMaxX($wall), $wall.top := artifact:getWallMaxY($wall), $wall.bottom := artifact:getWallMinY($wall),  22/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  $wall2.left := artifact:getWallMinX($wall2), $wall2.right := artifact:getWallMaxX($wall2), $wall2.top := artifact:getWallMaxY($wall2), $wall2.bottom := artifact:getWallMinY($wall2) return <intersectingRegion> {if($wall2.left <= $wall.left and $wall.left <= $wall2.right and $wall.bottom <= $wall2.top and $wall2.top <= $wall.top) then <point><x>{$wall.left}</x><y>{$wall2.top}</y></point> (: (1l, 2t) :) else()} {if($wall2.left <= $wall.left and $wall.left <= $wall2.right and $wall.bottom <= $wall2.bottom and $wall2.bottom <= $wall.top) then <point><x>{$wall.left}</x> <y>{$wall2.bottom}</y></point> (: (1l, 2b) :) else()} {if($wall2.left <= $wall.right and $wall.right <= $wall2.right and $wall.bottom <= $wall2.top and $wall2.top <= $wall.top) then <point><x>{$wall.right}</x><y>{$wall2.top}</y></point> (: (1r, 2t) :) else()} {if($wall2.left <= $wall.right and $wall.right <= $wall2.right and $wall.bottom <= $wall2.bottom and $wall2.bottom <= $wall.top) then <point><x>{$wall.right}</x><y>{$wall2.bottom}</y></point> (: (1r, 2b) :) else()} {if($wall2.bottom <= $wall.top and $wall.top <= $wall2.top and $wall.left <= $wall2.left and $wall2.left <= $wall.right) then <point><x>{$wall2.left}</x><y>{$wall.top}</y></point> (: (2l, 1t) :) else()} {if($wall2.bottom <= $wall.bottom and $wall.bottom <= $wall2.top and $wall.left <= $wall2.left and $wall2.left <= $wall.right) then <point><x>{$wall2.left}</x><y>{$wall.bottom}</y></point> (: (2l, 1b) :) else()} {if($wall2.bottom <= $wall.top and $wall.top <= $wall2.top and $wall.left <= $wall2.right and $wall2.right <= $wall.right) then <point><x>{$wall2.right}</x><y>{$wall.top}</y></point> (: (2r, 1t) :) else()} {if($wall2.bottom <= $wall.bottom and $wall.bottom <= $wall2.top and $wall.left <= $wall2.right and $wall2.right <= $wall.right) then <point><x>{$wall2.right}</x><y>{$wall.bottom}</y></point> (: (2r, 1b) :) else()} {if(artifact:containsVertex($wall.left, $wall.top, $wall2)) then <point><x>{$wall.left}</x><y>{$wall.top}</y></point> else()} {if(artifact:containsVertex($wall.right, $wall.top, $wall2))  (: (1l,1t)  :)  23/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  then <point><x>{$wall.right}</x><y>{$wall.top}</y></point> else()}  (: (1r,1t)  :)  {if(artifact:containsVertex($wall.left, $wall.bottom, $wall2)) then <point><x>{$wall.left}</x><y>{$wall.bottom}</y></point> (: (1l, 1b) else()}  :)  {if(artifact:containsVertex($wall.right, $wall.bottom, $wall2)) (: (1r, 1b) then <point><x>{$wall.right}</x><y>{$wall.bottom}</y></point> else()}  :)  {if(artifact:containsVertex($wall2.left, $wall2.top, $wall)) then <point><x>{$wall2.left}</x><y>{$wall2.top}</y></point> else()}  (: (2l, 2t)  :)  {if(artifact:containsVertex($wall2.right, $wall2.top, $wall)) then <point><x>{$wall2.right}</x><y>{$wall2.top}</y></point> else()}  (: (2r, 2t)  :)  {if(artifact:containsVertex($wall2.left, $wall2.bottom, $wall)) then <point><x>{$wall2.left}</x><y>{$wall2.bottom}</y></point>  (: (2l, 2b)  :) else()} {if(artifact:containsVertex($wall2.right, $wall2.bottom, $wall)) :) then <point><x>{$wall2.right}</x><y>{$wall2.bottom}</y></point> else()} </intersectingRegion> };  declare function artifact:getIntersectingRegionLeft ($wall, $wall2) { let $intersectionPoints := artifact:intersectingRegion($wall, $wall2) return min(for $x in $intersectionPoints/point/x return data($x)) };  declare function artifact:getIntersectingRegionRight ($wall, $wall2) { let $intersectionPoints := artifact:intersectingRegion($wall, $wall2) return max(for $x in $intersectionPoints/point/x return data($x)) }; declare function artifact:getIntersectingRegionTop ($wall, $wall2) { let $intersectionPoints := artifact:intersectingRegion($wall, $wall2) return max(for $y in $intersectionPoints/point/y return data($y)) };  (: (2r, 2b)  24/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  declare function artifact:getIntersectingRegionBottom ($wall, $wall2) { let $intersectionPoints := artifact:intersectingRegion($wall, $wall2) return min(for $y in $intersectionPoints/point/y return data($y)) };  (: *************************** END OF WALL-TO-WALL INTERSECTION PREDICATES ************************:)  (: ************************************** PENETRATION PREDICATES **********************************:)  (: Note: can the getMinX, etc be adjusted so that they can be used with a wall or duct, each of which have a centerline... could the xpath be specified in not such a specific/absoluted way...starting from the duct or wall...but with centerline? :) declare function artifact:penetrates($wall, $duct) { let $wall.left := artifact:getWallMinX($wall), $wall.right := artifact:getWallMaxX($wall), $wall.top := artifact:getWallMaxY($wall), $wall.bottom := artifact:getWallMinY($wall), $duct.left := artifact:getDuctMinX($duct), $duct.right := artifact:getDuctMaxX($duct), $duct.top := artifact:getDuctMaxY($duct), $duct.bottom := artifact:getDuctMinY($duct) where $wall/centerline[@size="2"] return if (not($wall.right <= $duct.left or (: w1 is completely to the left of w2 :) $wall.left >= $duct.right or (: w1 is completely to the right of w2 :) $wall.top <= $duct.bottom or (: w1 is completely below w2 :) $wall.bottom >=$duct.top) (: w1 is completely above w2 :) ) then true() else false() };  declare function artifact:intersectingRegionDuct ($wall, $duct) { let $wall.left := artifact:getWallMinX($wall), $wall.right := artifact:getWallMaxX($wall), $wall.top := artifact:getWallMaxY($wall), $wall.bottom := artifact:getWallMinY($wall), $duct.left := artifact:getDuctMinX($duct), $duct.right := artifact:getDuctMaxX($duct), $duct.top := artifact:getDuctMaxY($duct),  25/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  $duct.bottom := artifact:getDuctMinY($duct) return <penetratingRegion> {if($duct.left <= $wall.left and $wall.left <= $duct.right and $wall.bottom <= $duct.top and $duct.top <= $wall.top) then <point><x>{$wall.left}</x><y>{$duct.top}</y></point> else()} {if($duct.left <= $wall.left and $wall.left <= $duct.right and $wall.bottom <= $duct.bottom and $duct.bottom <= $wall.top) then <point><x>{$wall.left}</x> <y>{$duct.bottom}</y></point> else()} {if($duct.left <= $wall.right and $wall.right <= $duct.right and $wall.bottom <= $duct.top and $duct.top <= $wall.top) then <point><x>{$wall.right}</x><y>{$duct.top}</y></point> else()} {if($duct.left <= $wall.right and $wall.right <= $duct.right and $wall.bottom <= $duct.bottom and $duct.bottom <= $wall.top) then <point><x>{$wall.right}</x><y>{$duct.bottom}</y></point> else()} {if($duct.bottom <= $wall.top and $wall.top <= $duct.top and $wall.left <= $duct.right and $duct.right <= $wall.right) then <point><x>{$duct.right}</x><y>{$wall.top}</y></point> else()} {if($duct.bottom <= $wall.top and $wall.top <= $duct.top and $wall.left <= $duct.left and $duct.left <= $wall.right) then <point><x>{$duct.left}</x><y>{$wall.top}</y></point> else()} {if($duct.bottom <= $wall.bottom and $wall.bottom <= $duct.top and $wall.left <= $duct.left and $duct.left <= $wall.right) then <point><x>{$duct.left}</x><y>{$wall.bottom}</y></point> else()} {if($duct.bottom <= $wall.bottom and $wall.bottom <= $duct.top and $wall.left <= $duct.right and $duct.right <= $wall.right) then <point><x>{$duct.right}</x><y>{$wall.bottom}</y></point> else()} {if(artifact:containsVertex($wall.left, $wall.top, $duct)) then <point><x>{$wall.left}</x><y>{$wall.top}</y></point> else()} {if(artifact:containsVertex($wall.right, $wall.top, $duct)) then <point><x>{$wall.right}</x><y>{$wall.top}</y></point> else()}  26/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  {if(artifact:containsVertex($wall.left, $wall.bottom, $duct)) then <point><x>{$wall.left}</x><y>{$wall.bottom}</y></point> else()} {if(artifact:containsVertex($wall.right, $wall.bottom, $duct)) then <point><x>{$wall.right}</x><y>{$wall.bottom}</y></point> else()} {if(artifact:containsVertex($duct.left, $duct.top, $wall)) then <point><x>{$duct.left}</x><y>{$duct.top}</y></point> else()} {if(artifact:containsVertex($duct.right, $duct.top, $wall)) then <point><x>{$duct.right}</x><y>{$duct.top}</y></point> else()} {if(artifact:containsVertex($duct.left, $duct.bottom, $wall)) then <point><x>{$duct.left}</x><y>{$duct.bottom}</y></point> else()} {if(artifact:containsVertex($duct.right, $duct.bottom, $wall)) then <point><x>{$duct.right}</x><y>{$duct.bottom}</y></point> else()} </penetratingRegion> };  declare function artifact:penetrationLocation($wall, $duct) { let $duct.centerElevation := $duct/centerline/point[@position="1" and @axis="z"], $duct.diameter := $duct/diameter, $duct.topElevation := $duct/topElevation, $duct.bottomElevation := $duct/bottomElevation, $wall.bottomElevation := $wall/centerline/point[@position="1" and @axis="z"], $wall.height := $wall/height, $wall.isWallXAligned := artifact:isWallXAligned($wall), $duct.distanceFromWallTop := (($wall.bottomElevation + $wall.height) ($duct.centerElevation + $duct.diameter div 2)), $duct.distanceFromWallBottom := ($duct.centerElevation - $duct.diameter div 2) $wall.bottomElevation, $wall.left := artifact:getWallMinX($wall), $wall.right := artifact:getWallMaxX($wall), $wall.top := artifact:getWallMaxY($wall), $wall.bottom := artifact:getWallMinY($wall), $duct.left := artifact:getDuctMinX($duct), $duct.right := artifact:getDuctMaxX($duct), $duct.top := artifact:getDuctMaxY($duct), $duct.bottom := artifact:getDuctMinY($duct)  27/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  return if ($wall.isWallXAligned) then( <penetrationLocation> <distanceFromWallTop>{$duct.distanceFromWallTop}</distanceFromWallTop> <distanceFromWallBottom>{$duct.distanceFromWallBottom}</distanceFromWallBottom> <distanceFromWallNorthSide>{$wall.top - $duct.top}</distanceFromWallNorthSide> <distanceFromWallSouthSide>{$duct.bottom $wall.bottom}</distanceFromWallSouthSide> </penetrationLocation> ) else( <penetrationLocation> <distanceFromWallTop>{$duct.distanceFromWallTop}</distanceFromWallTop> <distanceFromWallBottom>{$duct.distanceFromWallBottom}</distanceFromWallBottom> <distanceFromWallEastSide>{$duct.right - $wall.right}</distanceFromWallEastSide> <distanceFromWallWestSide>{$wall.left - $duct.left}</distanceFromWallWestSide> </penetrationLocation> ) };  (: *********************************** END OF PENETRATION PREDICATES ******************************:)  (: ******************************* WALL-TO-COLUMN INTERSECTION PREDICATES *************************:) declare function artifact:getColumnMinX($column) { let $x := round(number($column/centerpoint[@axis="x"]) * 100) div 100, $b := round(number($column/base_b) * 100) div 100 return $x - $b div 2 }; declare function artifact:getColumnMaxX($column) { let $x := round(number($column/centerpoint[@axis="x"]) * 100) div 100, $b := round(number($column/base_b) * 100) div 100 return $x + $b div 2 }; declare function artifact:getColumnMinY($column) { let $y := round(number($column/centerpoint[@axis="y"]) * 100) div 100, $b := round(number($column/base_b) * 100) div 100 return $y - $b div 2 }; declare function artifact:getColumnMaxY($column)  28/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  { let $y := round(number($column/centerpoint[@axis="y"]) * 100) div 100, $b := round(number($column/base_b) * 100) div 100 return $y + $b div 2 };  (: Purpose: proximateColumns is a function that :) declare function artifact:columnIntersectsWall($wall, $column) { let $wall.left := artifact:getWallMinX($wall), $wall.right := artifact:getWallMaxX($wall), $wall.top := artifact:getWallMaxY($wall), $wall.bottom := artifact:getWallMinY($wall), $column.left := artifact:getColumnMinX($column), $column.right := artifact:getColumnMaxX($column), $column.top := artifact:getColumnMaxY($column), $column.bottom := artifact:getColumnMinY($column) where $wall/centerline[@size="2"] return if (not($wall.right <= $column.left or (: w1 is completely to the left of w2 :) $wall.left >= $column.right or (: w1 is completely to the right of w2 :) $wall.top <= $column.bottom or (: w1 is completely below w2 :) $wall.bottom >=$column.top) (: w1 is completely above w2 :) ) then true() else false() };  declare function artifact:wallColumnIntersectingRegion ($wall, $column) { let $wall.left := artifact:getWallMinX($wall), $wall.right := artifact:getWallMaxX($wall), $wall.top := artifact:getWallMaxY($wall), $wall.bottom := artifact:getWallMinY($wall), $column.left := artifact:getColumnMinX($column), $column.right := artifact:getColumnMaxX($column), $column.top := artifact:getColumnMaxY($column), $column.bottom := artifact:getColumnMinY($column) return <intersectingRegion> {if($column.left <= $wall.left and $wall.left <= $column.right and $wall.bottom <= $column.top and $column.top <= $wall.top) then <point><x>{$wall.left}</x><y>{$column.top}</y></point> else()} {if($column.left <= $wall.left and $wall.left <= $column.right and $wall.bottom <= $column.bottom and $column.bottom <= $wall.top) then <point><x>{$wall.left}</x> <y>{$column.bottom}</y></point> else()}  29/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  {if($column.left <= $wall.right and $wall.right <= $column.right and $wall.bottom <= $column.top and $column.top <= $wall.top) then <point><x>{$wall.right}</x><y>{$column.top}</y></point> else()} {if($column.left <= $wall.right and $wall.right <= $column.right and $wall.bottom <= $column.bottom and $column.bottom <= $wall.top) then <point><x>{$wall.right}</x><y>{$column.bottom}</y></point> else()} {if($column.bottom <= $wall.top and $wall.top <= $column.top and $wall.left <= $column.right and $column.right <= $wall.right) then <point><x>{$column.right}</x><y>{$wall.top}</y></point> else()} {if($column.bottom <= $wall.top and $wall.top <= $column.top and $wall.left <= $column.left and $column.left <= $wall.right) then <point><x>{$column.left}</x><y>{$wall.top}</y></point> else()} {if($column.bottom <= $wall.bottom and $wall.bottom <= $column.top and $wall.left <= $column.left and $column.left <= $wall.right) then <point><x>{$column.left}</x><y>{$wall.bottom}</y></point> else()} {if($column.bottom <= $wall.bottom and $wall.bottom <= $column.top and $wall.left <= $column.right and $column.right <= $wall.right) then <point><x>{$column.right}</x><y>{$wall.bottom}</y></point> else()} {if(artifact:columnContainsVertex($wall.left, $wall.top, $column)) then <point><x>{$wall.left}</x><y>{$wall.top}</y></point> else()} {if(artifact:columnContainsVertex($wall.right, $wall.top, $column)) then <point><x>{$wall.right}</x><y>{$wall.top}</y></point> else()} {if(artifact:columnContainsVertex($wall.left, $wall.bottom, $column)) then <point><x>{$wall.left}</x><y>{$wall.bottom}</y></point> else()} {if(artifact:columnContainsVertex($wall.right, $wall.bottom, $column)) then <point><x>{$wall.right}</x><y>{$wall.bottom}</y></point> else()} {if(artifact:columnContainsVertex($column.left, $column.top, $wall)) then <point><x>{$column.left}</x><y>{$column.top}</y></point> else()}  30/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  {if(artifact:columnContainsVertex($column.right, $column.top, $wall)) then <point><x>{$column.right}</x><y>{$column.top}</y></point> else()} {if(artifact:columnContainsVertex($column.left, $column.bottom, $wall)) then <point><x>{$column.left}</x><y>{$column.bottom}</y></point> else()} {if(artifact:columnContainsVertex($column.right, $column.bottom, $wall)) then <point><x>{$column.right}</x><y>{$column.bottom}</y></point> else()} </intersectingRegion> };  declare function artifact:wallColumnIntersectingRegionLeft ($wall, $column) { let $intersectionPoints := artifact:wallColumnIntersectingRegion ($wall, $column) return min(for $x in $intersectionPoints/point/x return data($x)) };  declare function artifact:wallColumnIntersectingRegionRight ($wall, $column) { let $intersectionPoints := artifact:wallColumnIntersectingRegion ($wall, $column) return max(for $x in $intersectionPoints/point/x return data($x)) }; declare function artifact:wallColumnIntersectingRegionTop ($wall, $column) { let $intersectionPoints := artifact:wallColumnIntersectingRegion ($wall, $column) return max(for $y in $intersectionPoints/point/y return data($y)) }; declare function artifact:wallColumnIntersectingRegionBottom ($wall, $wall2) { let $intersectionPoints := artifact:wallColumnIntersectingRegion ($wall, $wall2) return min(for $y in $intersectionPoints/point/y return data($y)) }; (: **************************** END OF WALL-COLUMN INTERSECTION PREDICATES ***********************:)  (: **************************** UNIFORMITY PREDICATES ***********************:) declare function artifact:nonUniformColumns($referenceLevel) { let $columns := artifact:onGridColumns($referenceLevel), $levels := artifact:getBuildingLevels($columnsXMLFile) for $column in $columns  31/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  for $level in $levels order by $level, $column/id/text() return if(empty(index-of(artifact:onGridColumns($level), $column/text()))) then <nonUniformColumn level="{artifact:getComponentLevel($level)}" >{$column}</nonUniformColumn> else () }; (: **************************** END OF UNIFORMITY PREDICATES ***********************:)  (: ********************************************************************************************** TEST QUERIES *********************************************************************************************** *:) (: ONGRID COLUMNS TEST QUERY :) (: onGridColumns($level) expects $level to be a STRING!!! :) ( let $columns := artifact:onGridColumnsByLevel() return $columns ), (: UNIFORMITY TEST QUERY :) ( let $nonUniformColumns := artifact:nonUniformColumns("0") return $nonUniformColumns ), ( for $level in artifact:getBuildingLevels($columnsXMLFile) for $spacing in artifact:distinctMinSpacings($level) for $minSpacing in artifact:minSpacings($level)/columnPair where $minSpacing/distance = $spacing return <level value = "{artifact:getComponentLevel($level)}" > <spacing value="{$spacing/text()}"> {$minSpacing} </spacing> </level> ),  ( for $level in artifact:getBuildingLevels($columnsXMLFile) return <level value = "{artifact:getComponentLevel($level)}" >  32/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  {artifact:minSpacings($level)} </level> ),  ( for $sourceColumn in doc($columnsXMLFile)/columns/column let $proximateColumns := artifact:proximateColumns($sourceColumn)/proximateColumns/column, $distances := $proximateColumns/distance/text(), $minDistance := min(($distances)) for $c in $proximateColumns where number($c/distance/text()) = $minDistance return <column id = "{$sourceColumn/id/text()}"> <closestColumn>{$c/id/text()}</closestColumn> </column> ),  ( for $sourceColumn in doc($columnsXMLFile)/columns/column let $proximateColumns := artifact:proximateColumns($sourceColumn)/proximateColumns/column, $distances := $proximateColumns/distance/text(), $minDistance := min(($distances)) return $minDistance ), (: March 18, 2010 :) (: TEST artifact:onGridColumnsByLevel() :) ( artifact:onGridColumnsByLevel() ),  (: CLOSEST GRIDLINE TEST :) ( for $c in doc($columnsXMLFile)/columns/column let $closestXGridlineName := artifact:closestGridline($c,"x"), $closestXGridlineValue := ( for $gx in doc($gridsXMLFile)/grids/gridline[gridlineAxis="x"] where $gx/name/text() = $closestXGridlineName return $gx/gridlineValue ), $closestYGridlineName := artifact:closestGridline($c,"y"), $closestYGridlineValue := ( for $gy in doc($gridsXMLFile)/grids/gridline[gridlineAxis="y"] where $gy/name/text() = $closestYGridlineName return $gy/gridlineValue ) return <column id = "{$c/id/text()}">  33/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  <closestXGridline> <gridline>{$closestXGridlineName}</gridline> <distance>{fn:abs(round(number($c/centerpoint[@axis="x"]) * 100) div 100 - round(number($closestXGridlineValue) * 100) div 100)}</distance> </closestXGridline> <closestYGridline>{$closestYGridlineName}</closestYGridline> </column> ), (: Feb 7, 2010 :) (: ONGRID TEST QUERY :) ( for $level in artifact:getBuildingLevels($columnsXMLFile) for $c in doc($columnsXMLFile)/columns/column let $onGrid := artifact:ongrid($c) return <level value = "{artifact:getComponentLevel($level)}" > <column id = "{$c/id/text()}"> <isOnGrid>{$onGrid}</isOnGrid> </column> </level> ), (: March 17, 2010 :) (: ALIGNMENT TEST QUERY :) ( for $c in doc($columnsXMLFile)/columns/column let $onGrid := artifact:ongrid($c) return if ($onGrid) then( <column> <level></level> <alignedTo>{artifact:alignedToGridIntersection ($c)}</alignedTo> </column> ) else( <column>test</column> ) ),  (: Jan 31, 2010 :) (: SPACING TEST QUERY :) ( let $min := artifact:minSpacing(), $max := artifact:maxSpacing(), $faceToFaceMin := artifact:faceToFaceMinSpacing(), $faceToFaceMax := artifact:faceToFaceMaxSpacing() return $min ),  34/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  (: March 17, 2010 :) (: SPACING TEST QUERY :) ( for $level in artifact:getBuildingLevels($columnsXMLFile) let $faceToFaceMinX := artifact:faceToFaceMinXSpacing () for $column in doc($columnsXMLFile)/columns/column let $column.minSpacing := round(number(min((math:faceToFaceManhattanDistance ($column, artifact:proximateColumn($column, $xd_E, $yd_E)), math:faceToFaceManhattanDistance ($column, artifact:proximateColumn($column, $xd_W, $yd_W)) )) * 100)) div 100 where (artifact:ongrid($column)) and artifact:getComponentLevel($column/centerpoint[@axis="z"]) = artifact:getComponentLevel($level) return if (string($column.minSpacing) = "NaN") then 1000000 else ($column.minSpacing) ),  (: Jan 31, 2010 :) (: WALL-COLUMN INTERSECTION TEST QUERY :) ( for $column in doc($columnsForPenetrationXML)/columns/column for $wall in doc($wallsForPenetrationXML)/walls/wall let $wall.height := $wall/height, $column.height := $column/height where artifact:isSquare($column) return if(artifact:columnIntersectsWall($wall, $column)) then( <wallColumnIntersection> <column id = "{$column/id}"/> <wall id = "{$wall/@id}"/> <intersectingRegion> <left>{artifact:wallColumnIntersectingRegionLeft ($wall,$column)}</left> <right>{artifact:wallColumnIntersectingRegionRight ($wall,$column)}</right> <top>{artifact:wallColumnIntersectingRegionTop ($wall,$column)}</top> <bottom>{artifact:wallColumnIntersectingRegionBottom ($wall,$column)}</bottom> <area>{round(math:areaRectangle(artifact:wallColumnIntersectingRegionLeft ($wall,$column), artifact:wallColumnIntersectingRegionRight ($wall,$column), artifact:wallColumnIntersectingRegionTop ($wall,$column), artifact:wallColumnIntersectingRegionBottom ($wall,$column)) *100) div 100}</area> <height>{round(min(($wall.height, $column.height))*100)div 100}</height> <volume>{round(math:volumeRectangle(artifact:wallColumnIntersectingRegionLeft ($wall,$column), artifact:wallColumnIntersectingRegionRight ($wall,$column),  35/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  artifact:wallColumnIntersectingRegionTop ($wall,$column), artifact:wallColumnIntersectingRegionBottom ($wall,$column), min(($wall.height, $column.height))) * 100) div 100}</volume> </intersectingRegion> </wallColumnIntersection> ) else() ), (: WALL-WALL INTERSECTION TEST QUERY :) ( for $wall in doc($wallsForIntersectionXML)/walls/feature let $wall.left := artifact:getWallMinX($wall), $wall.right := artifact:getWallMaxX($wall), $wall.top := artifact:getWallMaxY($wall), $wall.bottom := artifact:getWallMinY($wall), $wall.thickness := $wall/thickness, $wall.height := $wall/height return (for $wall2 in doc($wallsForIntersectionXML)/walls/feature let $wall2.left := artifact:getWallMinX($wall2), $wall2.right := artifact:getWallMaxX($wall2), $wall2.top := artifact:getWallMaxY($wall2), $wall2.bottom := artifact:getWallMinY($wall2), $wall2.thickness := $wall2/thickness, $wall2.height := $wall2/height where not($wall/@id = $wall2/@id) return if(artifact:intersects($wall, $wall2)) then( <wallWallIntersection> <wall id = "{$wall/@id}"/> <wall id = "{$wall2/@id}"/> <intersectingRegion> <left>{artifact:getIntersectingRegionLeft ($wall,$wall2)}</left> <right>{artifact:getIntersectingRegionRight ($wall,$wall2)}</right> <top>{artifact:getIntersectingRegionTop ($wall,$wall2)}</top> <bottom>{artifact:getIntersectingRegionBottom ($wall,$wall2)}</bottom> ($wall,$wall2), <area>{math:areaRectangle(artifact:getIntersectingRegionLeft artifact:getIntersectingRegionRight ($wall,$wall2), artifact:getIntersectingRegionTop ($wall,$wall2), artifact:getIntersectingRegionBottom ($wall,$wall2))}</area> <volume>{math:volumeRectangle(artifact:getIntersectingRegionLeft ($wall,$wall2), artifact:getIntersectingRegionRight ($wall,$wall2), artifact:getIntersectingRegionTop ($wall,$wall2), artifact:getIntersectingRegionBottom ($wall,$wall2), min(($wall.height, $wall2.height)))}</volume>  36/37 file:/C:/Users/webster/Documents/thesis/XQueries/spatialQueryPredicates.xq  </intersectingRegion> </wallWallIntersection> ) else()) ),  (: PENETRATION TEST QUERY :) (: Jan 25, 2010: Test query for testing the penetrates query predicate :) (: Result: this query accurately detects the penetration between wall (id 133152) and the duct (id 149164) :) ( for $duct in doc($ductsXMLFile)/ducts/duct for $wall in doc($wallsForPenetrationXML)/walls/wall return if(artifact:penetrates($wall, $duct)) then <penetration> <duct id = "{$duct/@id}"/> <wall id = "{$wall/@id}"/> {artifact:intersectingRegionDuct ($wall, $duct)} {artifact:penetrationLocation($wall, $duct)} </penetration> else() ), (: WALL-WALL INTERSECTION TEST QUERY :) ( for $wall in doc($wallsForIntersectionXML)/walls/feature return <wall id = "{$wall/@id}"> <isXAligned>{artifact:isWallXAligned($wall)}</isXAligned> <isYAligned>{artifact:isWallYAligned($wall)}</isYAligned> </wall> )  Appendix E  Revit API  127  Autodesk Revit 2009 API Object Model  Options  Rooms Collections  Editor  Utility Areas Spaces  Events  Symbols  Parameters  Elements  Site  Creation  MEP  Structural  Enums  MEP.Enums  Structural.Enums  Geometry  

Cite

Citation Scheme:

        

Citations by CSL (citeproc-js)

Usage Statistics

Share

Embed

Customize your widget with the following options, then copy and paste the code below into the HTML of your page to embed this item in your website.
                        
                            <div id="ubcOpenCollectionsWidgetDisplay">
                            <script id="ubcOpenCollectionsWidget"
                            src="{[{embed.src}]}"
                            data-item="{[{embed.item}]}"
                            data-collection="{[{embed.collection}]}"
                            data-metadata="{[{embed.showMetadata}]}"
                            data-width="{[{embed.width}]}"
                            async >
                            </script>
                            </div>
                        
                    
IIIF logo Our image viewer uses the IIIF 2.0 standard. To load this item in other compatible viewers, use this url:
http://iiif.library.ubc.ca/presentation/dsp.24.1-0051947/manifest

Comment

Related Items