/* $RCSfile: geometry.cxx,v $ * $Revision: 1.7 $ $Date: 2011/12/16 21:34:52 $ * Auth: Dave Loffredo (loffredo@steptools.com) * * Copyright (c) 1991-2012 by STEP Tools Inc. * All Rights Reserved. * * Permission to use, copy, modify, and distribute this software and * its documentation is hereby granted, provided that this copyright * notice and license appear on all copies of the software. * * STEP TOOLS MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE * SUITABILITY OF THE SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING * BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. STEP TOOLS * SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE AS A * RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS * DERIVATIVES. */ #include #include #include #include // BUILD GEOMETRY - This IFC "hello world" program creates a building // then attaches unit contexts and an empty shape representation. Use // this as the starting point for a more sophisticated program. // This program creates the data set and saves it as a STEP Part 21 // file called "output_file.stp". This is a text file, so you can // look at it with a text editor or the STEP Part 21 file browser to // see how the information is represented. IfcShapeRepresentation * create_building_with_geometry(); // Build some boilerplate data IfcOwnerHistory * make_owner_history(); IfcRepresentationContext * make_geometry_context(); IfcUnitAssignment * make_units(); int main(int argc, char* argv[]) { /* Force optimizing linkers to bring in all C++ classes */ ifc2x2_final_force_load(); rose_p28_init(); // support xml read/write /* Create a RoseDesign to hold the instance data */ const char * output_name = "output_file"; RoseDesign * design = new RoseDesign (output_name); /* Give the design some Part 21 header information */ design-> initialize_header(); design-> header_name()-> originating_system ("IFC Hello World"); design-> header_description()-> description ()-> add ("Empty Project Sample File"); /* Set as the current design. Objects created using the "pnew" * macro go here. We can create objects in a specific design * using "pnewIn(design)", but is less convenient to write. */ ROSE.useDesign(design); create_building_with_geometry(); // You can change the file extension from .stp to .ifc using the // following call if you would like // design-> fileExtension("ifc"); // Uncomment the following to write as zip compressed P28 XML // rather than Part 21 ASCII. Change the string "p28-raw" to // write uncompressed XML. The default is "p21". // // design-> format ("p28"); design-> save(); return 0; } IfcShapeRepresentation * create_building_with_geometry() { //---------------------------------------- // CREATE A PROJECT - // Create a project object, and fill it in with some sample // information // IfcProject * p = pnew IfcProject(); p-> GlobalId ("123456789012345678901a"); // 22 char unique uid p-> Name ("project"); // An owner history is required for most items IfcOwnerHistory * hist = make_owner_history(); p-> OwnerHistory (hist); // Create a representation context that gives us an origin, some // precision information, and the number of dimensions. See the // function below for the details. // IfcRepresentationContext * ctx = make_geometry_context(); p-> RepresentationContexts()-> add (ctx); // Geometry is unitless, so create a collection of units to // indicate what the numbers in the geometry correspond to. See // the function below for details. // IfcUnitAssignment * units = make_units(); p-> UnitsInContext (units); //---------------------------------------- // CREATE THE BUILDING - // Create a building object, and fill it in with some sample // information // IfcBuilding * b = pnew IfcBuilding(); b-> GlobalId ("123456789012345678901b"); // 22 char unique uid b-> Name ("fortress of solitude"); b-> Description ("secret lair"); b-> OwnerHistory (hist); //---------------------------------------- // CREATE THE SHAPE REPRESENTATION // // Create the shape representation. This is the container that // holds geometry items. // IfcShapeRepresentation * rep = pnew IfcShapeRepresentation; // The shape representation needs the representation context too. rep-> ContextOfItems (ctx); // Attach the shape rep to the building using a product definition // shape instance, which can refer to one or more representations. b-> Representation (pnew IfcProductDefinitionShape); b-> Representation()-> Representations()-> add (rep); //---------------------------------------- // POPULATE THE SHAPE REPRESENTATION // // Now we would add the geometry and topology items that define // the product shape. For an example, we just create a simple // bounding box with the corner at 0,0,0 // IfcCartesianPoint * loc = pnew IfcCartesianPoint; loc-> Coordinates()->add(0); loc-> Coordinates()->add(0); loc-> Coordinates()->add(0); IfcBoundingBox * box = pnew IfcBoundingBox; box-> Corner (loc); box-> XDim (20); box-> YDim (20); box-> ZDim (2000); // a mighty tower // add the bounding box to the representation rep-> Items()-> add (box); // Done return rep; } IfcOwnerHistory * make_owner_history() { IfcOwnerHistory * hist = pnew IfcOwnerHistory; IfcOrganization * org = pnew IfcOrganization; org-> Name ("Foo Bar, Inc."); IfcPerson * person = pnew IfcPerson; person-> GivenName ("John"); person-> FamilyName ("Doe"); IfcPersonAndOrganization * po = pnew IfcPersonAndOrganization; po-> ThePerson (person); po-> TheOrganization (org); IfcApplication * app = pnew IfcApplication; app-> ApplicationDeveloper (org); app-> Version ("1.0"); app-> ApplicationFullName ("sample program"); app-> ApplicationIdentifier ("program id"); hist-> OwningUser (po); hist-> OwningApplication (app); hist-> ChangeAction (IfcChangeActionEnum_ADDED); hist-> CreationDate (time(0)); return hist; } IfcRepresentationContext * make_geometry_context() { // Create a geometric context IfcGeometricRepresentationContext * ctx = pnew IfcGeometricRepresentationContext; ctx-> ContextIdentifier ("Plan"); ctx-> ContextType ("Design"); ctx-> CoordinateSpaceDimension (3); ctx-> Precision (1e-6); // Create a coordinate system origin for the context IfcCartesianPoint* p1 = pnew IfcCartesianPoint; p1-> Coordinates()->add(1.1); p1-> Coordinates()->add(2.2); p1-> Coordinates()->add(3.3); IfcAxis2Placement3D* ap3d = pnew IfcAxis2Placement3D (p1, 0, 0); // The placement is referenced through a select type ctx-> WorldCoordinateSystem (pnew IfcAxis2Placement); ctx-> WorldCoordinateSystem()-> _IfcAxis2Placement3D (ap3d); return ctx; } IfcUnitAssignment * make_units() { // The individual units are wrapped in a select type IfcUnitAssignment * units = pnew IfcUnitAssignment; IfcUnit * u; //---------------------------------------- // LENGTH UNITS //---------------------------------------- // SI unit for millimeters, we do not add this to the context, but // we use it to define the foot unit. IfcSIUnit * mm = pnew IfcSIUnit; mm-> UnitType (IfcUnitEnum_LENGTHUNIT); mm-> Prefix (IfcSIPrefix_MILLI); mm-> Name (IfcSIUnitName_METRE); // Foot is defined as a conversion-based unit in terms of an // underlying SI unit. Usually 25.4mm or 2.54cm times 12 // // Conversion based unit also needs dimensional exponents that // show which basic quantities (length, time, mass, etc) the unit // describes. // // IFC uses a nested select for the value, whereas STEP only has a // single level one. IfcMeasureWithUnit * mwu = pnew IfcMeasureWithUnit; IfcMeasureValue * val = pnew IfcMeasureValue; val-> _IfcLengthMeasure (25.4 * 12); mwu-> ValueComponent (pnew IfcValue); mwu-> ValueComponent ()-> _IfcMeasureValue (val); mwu-> UnitComponent (pnew IfcUnit); mwu-> UnitComponent ()-> _IfcNamedUnit (mm); IfcConversionBasedUnit * ft = pnew IfcConversionBasedUnit; ft-> Name ("FOOT"); ft-> UnitType (IfcUnitEnum_LENGTHUNIT); ft-> Dimensions (pnew IfcDimensionalExponents (1,0,0,0,0,0,0)); ft-> ConversionFactor (mwu); // Add foot to the unit context u = pnew IfcUnit; u-> _IfcNamedUnit (ft); units-> Units()-> add (u); //---------------------------------------- // ANGLE UNITS //---------------------------------------- // SI unit for radians, we do not add this to the context, but we // use it to define the degree unit. IfcSIUnit * rad = pnew IfcSIUnit; rad-> UnitType (IfcUnitEnum_PLANEANGLEUNIT); rad-> Prefix (IfcSIPrefix_NULL); rad-> Name (IfcSIUnitName_RADIAN); // Degree is defined as a conversion-based unit in terms of the // underlying radian SI unit. 1 Degree == PI/180 radians. Create // the measure with unit to indicate this. // // Conversion based unit also needs dimensional exponents but // these are all zero for angles. // mwu = pnew IfcMeasureWithUnit; val = pnew IfcMeasureValue; val-> _IfcPlaneAngleMeasure (0.01745329252); mwu-> ValueComponent (pnew IfcValue); mwu-> ValueComponent ()-> _IfcMeasureValue (val); mwu-> UnitComponent (pnew IfcUnit); mwu-> UnitComponent ()-> _IfcNamedUnit (rad); IfcConversionBasedUnit * deg = pnew IfcConversionBasedUnit; deg-> Name ("DEGREE"); deg-> UnitType (IfcUnitEnum_PLANEANGLEUNIT); deg-> Dimensions (pnew IfcDimensionalExponents (0,0,0,0,0,0,0)); deg-> ConversionFactor (mwu); // Add degree to the unit context u = pnew IfcUnit; u-> _IfcNamedUnit (deg); units-> Units()-> add (u); return units; }