void create_product_from_item(IfcHierarchyHelper& file, IfcSchema::IfcRepresentationItem* item, const std::string& s) {
	IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy(
		guid(), 0, S("product"), null, null, 0, 0, null, null);
	file.addBuildingProduct(product);
	product->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());

	product->setObjectPlacement(file.addLocalPlacement(120 * i++));

	IfcSchema::IfcRepresentation::list reps (new IfcTemplatedEntityList<IfcSchema::IfcRepresentation>());
	IfcSchema::IfcRepresentationItem::list items (new IfcTemplatedEntityList<IfcSchema::IfcRepresentationItem>());
	items->push(item);

	if (s == "GeometricSet") {
		IfcSchema::IfcGeometricSet* set = new IfcSchema::IfcGeometricSet(items->generalize());
		file.AddEntity(set);
		items = IfcSchema::IfcRepresentationItem::list(new IfcTemplatedEntityList<IfcSchema::IfcRepresentationItem>());
		items->push(set);
	}
		
	IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
		file.getSingle<IfcSchema::IfcRepresentationContext>(), S("Body"), s, items);
	reps->push(rep);

	IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
	file.AddEntity(rep);
	file.AddEntity(shape);
		
	product->setRepresentation(shape);
}
int main(int argc, char** argv) {
	IfcHierarchyHelper file;

	IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy(
		guid(), 0, S("Blender's Suzanne"), null, null, 0, 0, null, null);
	file.addBuildingProduct(product);
	product->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());

	product->setObjectPlacement(file.addLocalPlacement());

	IfcSchema::IfcRepresentation::list::ptr reps (new IfcSchema::IfcRepresentation::list);
	IfcSchema::IfcRepresentationItem::list::ptr items (new IfcSchema::IfcRepresentationItem::list);

	std::vector< std::vector< double > > vertices_vector = create_vector_from_array(vertices, sizeof(vertices) / sizeof(vertices[0]));
	std::vector< std::vector< int > > indices_vector = create_vector_from_array(indices, sizeof(indices) / sizeof(indices[0]));

	IfcSchema::IfcCartesianPointList3D* coordinates = new IfcSchema::IfcCartesianPointList3D(vertices_vector);	
	IfcSchema::IfcTriangulatedFaceSet* faceset = new IfcSchema::IfcTriangulatedFaceSet(coordinates, null, null, indices_vector, null);
		
	items->push(faceset);
	IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
		file.getRepresentationContext("Model"), S("Body"), S("SurfaceModel"), items);
	reps->push(rep);

	IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
	file.addEntity(shape);
		
	product->setRepresentation(shape);

	const std::string filename = "tesselated_faceset.ifc";
	file.header().file_name().name(filename);
	std::ofstream f(filename.c_str());
	f << file;
}
int main(int argc, char** argv) {
	const char filename[] = "IfcCompositeProfileDef.ifc";
	IfcHierarchyHelper file;
	file.filename(filename);

	double coords1[] = {100.0, 0.0};
	double coords2[] = {200.0, 0.0};
	double coords3[] = {300.0, 0.0};

	IfcSchema::IfcProfileDef::list profiles (new IfcTemplatedEntityList<IfcSchema::IfcProfileDef>());

	IfcSchema::IfcCartesianTransformationOperator2D* transform1 = new IfcSchema::IfcCartesianTransformationOperator2D(file.addDoublet<IfcSchema::IfcDirection>(1, 0), file.addDoublet<IfcSchema::IfcDirection>(0, -1), file.addDoublet<IfcSchema::IfcCartesianPoint>(40, 0), null);
	IfcSchema::IfcCartesianTransformationOperator2D* transform2 = new IfcSchema::IfcCartesianTransformationOperator2D(file.addDoublet<IfcSchema::IfcDirection>(0, -1), file.addDoublet<IfcSchema::IfcDirection>(1, 0), file.addDoublet<IfcSchema::IfcCartesianPoint>(40, 0), 0.3);
	
	IfcSchema::IfcProfileDef* p1 = new Ifc2x3::IfcIShapeProfileDef(
		IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
		null, file.addPlacement2d(),    25.0,    50.0,     5.0,     5.0,     2.0);

	IfcSchema::IfcProfileDef* p2 = new Ifc2x3::IfcLShapeProfileDef(
		IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
		null, file.addPlacement2d(),    50.0,    25.0,     5.0,      1.0,     2.0,     2.0,    null,    null);

	IfcSchema::IfcProfileDef* p3 = new Ifc2x3::IfcTShapeProfileDef(
		IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
		null, file.addPlacement2d(),    50.0,    40.0,    10.0,     10.0,     3.0,     2.0,     1.0,     2.0,     2.0,    null);

	IfcSchema::IfcProfileDef* p4 = new Ifc2x3::IfcCShapeProfileDef(
		IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA,
		null, file.addPlacement2d(80.),    50.0,    25.0,     5.0,    10.0,     2.0,    null);

	file.AddEntity(p2);
	file.AddEntity(p3);
	
	file.AddEntity(transform1);
	file.AddEntity(transform2);
	
	IfcSchema::IfcDerivedProfileDef* p5 = new IfcSchema::IfcDerivedProfileDef(IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, null, p2, transform1, null);
	IfcSchema::IfcDerivedProfileDef* p6 = new IfcSchema::IfcDerivedProfileDef(IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, null, p3, transform2, null);
	
	profiles->push(p1);
	profiles->push(p5);
	profiles->push(p6);
	profiles->push(p4);

	file.AddEntities(profiles->generalize());

	IfcSchema::IfcCompositeProfileDef* composite = new IfcSchema::IfcCompositeProfileDef(IfcSchema::IfcProfileTypeEnum::IfcProfileType_AREA, S("IFC"), profiles, null);

	IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy(
			guid(), 0, S("profile"), null, null, 0, 0, null, null);

	file.addBuildingProduct(product);

	product->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());

	product->setObjectPlacement(file.addLocalPlacement());

	IfcSchema::IfcExtrudedAreaSolid* solid = new IfcSchema::IfcExtrudedAreaSolid(composite,
		file.addPlacement3d(), file.addTriplet<IfcSchema::IfcDirection>(0, 0, 1), 20.0);

	file.AddEntity(composite);
	file.AddEntity(solid);
		
	IfcSchema::IfcRepresentation::list reps (new IfcTemplatedEntityList<IfcSchema::IfcRepresentation>());
	IfcSchema::IfcRepresentationItem::list items (new IfcTemplatedEntityList<IfcSchema::IfcRepresentationItem>());
		
	items->push(solid);
	IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
		file.getSingle<IfcSchema::IfcRepresentationContext>(), S("Body"), S("SweptSolid"), items);
	reps->push(rep);

	IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
	file.AddEntity(rep);
	file.AddEntity(shape);
		
	product->setRepresentation(shape);

	file.getSingle<IfcSchema::IfcProject>()->setName("IfcCompositeProfileDef");

	std::ofstream f(filename);
	f << file;
}
void create_testcase_for(IfcHierarchyHelper& file, const EllipsePie& pie, Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference pref) {
	const double deg = 1. / 180. * 3.141592653;
	double flt1[] = {0.                      , 0.                      };
	double flt2[] = {pie.r1 * cos(pie.t1*deg), pie.r2 * sin(pie.t1*deg)};
	double flt3[] = {pie.r1 * cos(pie.t2*deg), pie.r2 * sin(pie.t2*deg)};

	std::vector<double> coords1(flt1, flt1 + 2);
	std::vector<double> coords2(flt2, flt2 + 2);
	std::vector<double> coords3(flt3, flt3 + 2);
	
	Ifc2x3::IfcCartesianPoint* p1 = new Ifc2x3::IfcCartesianPoint(coords1);
	Ifc2x3::IfcCartesianPoint* p2 = new Ifc2x3::IfcCartesianPoint(coords2);
	Ifc2x3::IfcCartesianPoint* p3 = new Ifc2x3::IfcCartesianPoint(coords3);
	
	Ifc2x3::IfcCartesianPoint::list points(new IfcTemplatedEntityList<Ifc2x3::IfcCartesianPoint>());
	points->push(p3);
	points->push(p1);
	points->push(p2);
	file.AddEntities(points->generalize());

	
	Ifc2x3::IfcEllipse* ellipse = new Ifc2x3::IfcEllipse(file.addPlacement2d(), pie.r1, pie.r2);
	file.AddEntity(ellipse);
	IfcEntities trim1(new IfcEntityList());
	IfcEntities trim2(new IfcEntityList());
	if (pref == Ifc2x3::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER) {
		trim1->push(new IfcWrite::IfcSelectHelper(pie.t1, Ifc2x3::Type::IfcParameterValue));
		trim2->push(new IfcWrite::IfcSelectHelper(pie.t2, Ifc2x3::Type::IfcParameterValue));
	} else {
		trim1->push(p2);
		trim2->push(p3);
	}
	Ifc2x3::IfcTrimmedCurve* trim = new Ifc2x3::IfcTrimmedCurve(ellipse, trim1, trim2, true, pref);
	file.AddEntity(trim);
	
	Ifc2x3::IfcCompositeCurveSegment::list segments(new IfcTemplatedEntityList<Ifc2x3::IfcCompositeCurveSegment>());
	Ifc2x3::IfcCompositeCurveSegment* s2 = new Ifc2x3::IfcCompositeCurveSegment(Ifc2x3::IfcTransitionCode::IfcTransitionCode_CONTINUOUS, true, trim);
	
	Ifc2x3::IfcPolyline* poly = new Ifc2x3::IfcPolyline(points);	
	file.AddEntity(poly);
	Ifc2x3::IfcCompositeCurveSegment* s1 = new Ifc2x3::IfcCompositeCurveSegment(Ifc2x3::IfcTransitionCode::IfcTransitionCode_CONTINUOUS, true, poly);
	segments->push(s1);
	
	segments->push(s2);
	file.AddEntities(segments->generalize());
	
	Ifc2x3::IfcCompositeCurve* ccurve = new Ifc2x3::IfcCompositeCurve(segments, false);
	Ifc2x3::IfcArbitraryClosedProfileDef* profile = new Ifc2x3::IfcArbitraryClosedProfileDef(Ifc2x3::IfcProfileTypeEnum::IfcProfileType_AREA, null, ccurve);
	file.AddEntity(ccurve);
	file.AddEntity(profile);

	IfcSchema::IfcBuildingElementProxy* product = new IfcSchema::IfcBuildingElementProxy(
		guid(), 0, S("profile"), null, null, 0, 0, null, null);
	file.addBuildingProduct(product);
	product->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());

	product->setObjectPlacement(file.addLocalPlacement(200 * i++));

	IfcSchema::IfcExtrudedAreaSolid* solid = new IfcSchema::IfcExtrudedAreaSolid(profile,
		file.addPlacement3d(), file.addTriplet<IfcSchema::IfcDirection>(0, 0, 1), 20.0);

	file.AddEntity(solid);
		
	IfcSchema::IfcRepresentation::list reps (new IfcTemplatedEntityList<IfcSchema::IfcRepresentation>());
	IfcSchema::IfcRepresentationItem::list items (new IfcTemplatedEntityList<IfcSchema::IfcRepresentationItem>());
		
	items->push(solid);
	IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
		file.getSingle<IfcSchema::IfcRepresentationContext>(), S("Body"), S("SweptSolid"), items);
	reps->push(rep);

	IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(0, 0, reps);
	file.AddEntity(rep);
	file.AddEntity(shape);
		
	product->setRepresentation(shape);
}