Пример #1
0
int
brep_build_bvh(struct brep_specific* bs, struct rt_brep_internal* bi)
{
    ON_TextLog tl(stderr);
    ON_Brep* brep = bs->brep;
    if (brep == NULL || !brep->IsValid(&tl)) {
	bu_log("brep is NOT valid");
	return -1;
    }

    bs->bvh = new BBNode(brep->BoundingBox());

    // need to extract faces, and build bounding boxes for each face,
    // then combine the face BBs back up, combining them together to
    // better split the hierarchy
    std::list<SurfaceTree*> surface_trees;
    ON_BrepFaceArray& faces = brep->m_F;
    for (int i = 0; i < faces.Count(); i++) {
        TRACE1("Face: " << i);
	ON_BrepFace& face = faces[i];

	SurfaceTree* st = new SurfaceTree(&face);
	face.m_face_user.p = st;
	brep_preprocess_trims(face, st);

	// add the surface bounding volumes to a list, so we can build
	// down a hierarchy from the brep bounding volume
	surface_trees.push_back(st);
    }

    brep_bvh_subdivide(bs->bvh, surface_trees);

    return 0;
}
Пример #2
0
bool STEPWrapper::convert(BRLCADWrapper *dot_g)
{
    MAP_OF_PRODUCT_NAME_TO_ENTITY_ID name2id_map;
    MAP_OF_ENTITY_ID_TO_PRODUCT_NAME id2name_map;
    MAP_OF_ENTITY_ID_TO_PRODUCT_ID id2productid_map;
    MAP_OF_PRODUCT_NAME_TO_ENTITY_ID::iterator niter = name2id_map.end();

    if (!dot_g) {
	return false;
    }

    this->dotg = dot_g;

    int num_ents = instance_list->InstanceCount();
    for (int i = 0; i < num_ents; i++) {
	SDAI_Application_instance *sse = instance_list->GetSTEPentity(i);
	if (sse == NULL) {
	    continue;
	}
	std::string name = sse->EntityName();
	std::transform(name.begin(), name.end(), name.begin(), (int(*)(int))std::tolower);

	if ((sse->STEPfile_id > 0) && (sse->IsA(SCHEMA_NAMESPACE::e_shape_definition_representation))) {
	    ShapeDefinitionRepresentation *sdr = dynamic_cast<ShapeDefinitionRepresentation *>(Factory::CreateObject(this, (SDAI_Application_instance *)sse));

	    if (!sdr) {
		bu_exit(1, "ERROR: unable to allocate a 'ShapeDefinitionRepresentation' entity\n");
	    } else {
		int sdr_id = sdr->GetId();
		std::string pname  = sdr->GetProductName();
		int product_id = sdr->GetProductId();

		id2productid_map[sdr_id] = product_id;

		if (pname.empty()) {
		    std::string str = "ShapeDefinitionRepresentation@";
		    str = dotg->GetBRLCADName(str);
		    id2name_map[sdr_id] = pname;
		} else {
		    std::string temp = pname;
		    int index = 2;
		    while ((niter=name2id_map.find(temp)) != name2id_map.end()) {
			temp = pname + "_" + static_cast<ostringstream*>( &(ostringstream() << (index++)) )->str();
		    }
		    pname = temp;
		    if ((niter=name2id_map.find(pname)) == name2id_map.end()) {
			id2name_map[sdr_id] = pname;
			name2id_map[pname] = product_id;
			id2name_map[product_id] = pname;
		    }
		}

		AdvancedBrepShapeRepresentation *aBrep = sdr->GetAdvancedBrepShapeRepresentation();
		if (aBrep) {
		    if (pname.empty()) {
			std::string str = "product@";
			pname = dotg->GetBRLCADName(str);
			id2name_map[aBrep->GetId()] = pname;
			id2name_map[product_id] = pname;
		    } else {
			id2name_map[aBrep->GetId()] = pname;
			id2name_map[product_id] = pname;
		    }
		    id2productid_map[aBrep->GetId()] = product_id;

		    if (Verbose()) {
			if (!pname.empty()) {
			    std::cerr << std::endl << "     Generating Product -" << pname ;
			} else {
			    std::cerr << std::endl << "     Generating Product";
			}
		    }

		    LocalUnits::length = aBrep->GetLengthConversionFactor();
		    LocalUnits::planeangle = aBrep->GetPlaneAngleConversionFactor();
		    LocalUnits::solidangle = aBrep->GetSolidAngleConversionFactor();
		    ON_Brep *onBrep = aBrep->GetONBrep();
		    if (!onBrep) {
			delete sdr;
			bu_exit(1, "ERROR: failure creating advanced boundary representation from %s\n", stepfile.c_str());
		    } else {
			ON_TextLog tl;

			if (!onBrep->IsValid(&tl)) {
			    bu_log("WARNING: %s is not valid\n", name.c_str());
			}

			//onBrep->SpSplitClosedFaces();
			//ON_Brep *tbrep = TightenBrep(onBrep);

			mat_t mat;
			MAT_IDN(mat);

			Axis2Placement3D *axis = aBrep->GetAxis2Placement3d();
			if (axis != NULL) {
			    //assign matrix values
			    double translate_to[3];
			    const double *toXaxis = axis->GetXAxis();
			    const double *toYaxis = axis->GetYAxis();
			    const double *toZaxis = axis->GetZAxis();
			    mat_t rot_mat;

			    VMOVE(translate_to,axis->GetOrigin());
			    VSCALE(translate_to,translate_to,LocalUnits::length);

			    MAT_IDN(rot_mat);
			    VMOVE(&rot_mat[0], toXaxis);
			    VMOVE(&rot_mat[4], toYaxis);
			    VMOVE(&rot_mat[8], toZaxis);
			    bn_mat_inv(mat, rot_mat);
			    MAT_DELTAS_VEC(mat, translate_to);
			}

			dotg->WriteBrep(pname, onBrep,mat);

			delete onBrep;
		    }
		} else { // must be an assembly
		    if (pname.empty()) {
			std::string str = "assembly@";
			pname = dotg->GetBRLCADName(str);
		    }
		    ShapeRepresentation *aSR = sdr->GetShapeRepresentation();
		    if (aSR) {
			int sr_id = aSR->GetId();
			id2name_map[sr_id] = pname;
			id2name_map[product_id] = pname;
			id2productid_map[sr_id] = product_id;
		    }
		}
		Factory::DeleteObjects();
	    }
	}
    }
    /*
     * Pickup BREP related to SHAPE_REPRESENTATION through SHAPE_REPRESENTATION_RELATIONSHIP
     *
     * like the following found in OpenBook Part 'C':
     *    #21281=SHAPE_DEFINITION_REPRESENTATION(#21280,#21270);
     *        #21280=PRODUCT_DEFINITION_SHAPE('','SHAPE FOR C.',#21279);
     *            #21279=PRODUCT_DEFINITION('design','',#21278,#21275);
     *                #21278=PRODUCT_DEFINITION_FORMATION_WITH_SPECIFIED_SOURCE('1','LAST_VERSION',#21277,.MADE.);
     *                    #21277=PRODUCT('C','C','NOT SPECIFIED',(#21276));
     *        #21270=SHAPE_REPRESENTATION('',(#21259),#21267);
     *            #21259=AXIS2_PLACEMENT_3D('DANTE_BX_CPU_TOP_1',#21256,#21257,#21258);
     *            #21267=(GEOMETRIC_REPRESENTATION_CONTEXT(3)GLOBAL_UNCERTAINTY_ASSIGNED_CONTEXT((#21266))
     *                GLOBAL_UNIT_ASSIGNED_CONTEXT((#21260,#21264,#21265))REPRESENTATION_CONTEXT('ID1','3'));
     *
     *    #21271=SHAPE_REPRESENTATION_RELATIONSHIP('','',#21270,#21268);
     *        #21268=ADVANCED_BREP_SHAPE_REPRESENTATION('',(#21254),#21267);
     *    #21272=SHAPE_REPRESENTATION_RELATIONSHIP('','',#21270,#21269);
     *        #21269=MANIFOLD_SURFACE_SHAPE_REPRESENTATION('',(#21255),#21267);
     *
     */
    for (int i = 0; i < num_ents; i++) {
	SDAI_Application_instance *sse = instance_list->GetSTEPentity(i);
	if (sse == NULL) {
	    continue;
	}
	std::string name = sse->EntityName();
	std::transform(name.begin(), name.end(), name.begin(), (int(*)(int))std::tolower);

	if ((sse->STEPfile_id > 0) && (sse->IsA(SCHEMA_NAMESPACE::e_shape_representation_relationship))) {
	    ShapeRepresentationRelationship *srr = dynamic_cast<ShapeRepresentationRelationship *>(Factory::CreateObject(this, (SDAI_Application_instance *)sse));

	    if (srr) {
		ShapeRepresentation *aSR = dynamic_cast<ShapeRepresentation *>(srr->GetRepresentationRelationshipRep_1());
		AdvancedBrepShapeRepresentation *aBrep = dynamic_cast<AdvancedBrepShapeRepresentation *>(srr->GetRepresentationRelationshipRep_2());
		if (!aBrep) { //try rep_1
		    aBrep = dynamic_cast<AdvancedBrepShapeRepresentation *>(srr->GetRepresentationRelationshipRep_1());
		    aSR = dynamic_cast<ShapeRepresentation *>(srr->GetRepresentationRelationshipRep_2());
		}
		if ((aSR) && (aBrep)) {
		    int sr_id = aSR->GetId();
		    MAP_OF_ENTITY_ID_TO_PRODUCT_ID::iterator it = id2productid_map.find(sr_id);
		    if (it != id2productid_map.end()) { // product found
			int product_id = (*it).second;
			int brep_id = aBrep->GetId();

			it = id2productid_map.find(brep_id);
			if (it == id2productid_map.end()) { // brep not loaded yet so lets do that here.
			    string pname = id2name_map[product_id];
			    id2productid_map[brep_id] = product_id;

			    if (Verbose()) {
				if (!pname.empty()) {
				    std::cerr << std::endl << "     Generating Product -" << pname ;
				} else {
				    std::cerr << std::endl << "     Generating Product";
				}
			    }

			    LocalUnits::length = aBrep->GetLengthConversionFactor();
			    LocalUnits::planeangle = aBrep->GetPlaneAngleConversionFactor();
			    LocalUnits::solidangle = aBrep->GetSolidAngleConversionFactor();
			    ON_Brep *onBrep = aBrep->GetONBrep();
			    if (!onBrep) {
				bu_exit(1, "ERROR: failure creating advanced boundary representation from %s\n", stepfile.c_str());
			    } else {
				ON_TextLog tl;

				if (!onBrep->IsValid(&tl)) {
				    bu_log("WARNING: %s is not valid\n", name.c_str());
				}

				//onBrep->SpSplitClosedFaces();
				//ON_Brep *tbrep = TightenBrep(onBrep);

				mat_t mat;
				MAT_IDN(mat);

				Axis2Placement3D *axis = aBrep->GetAxis2Placement3d();
				if (axis != NULL) {
				    //assign matrix values
				    double translate_to[3];
				    const double *toXaxis = axis->GetXAxis();
				    const double *toYaxis = axis->GetYAxis();
				    const double *toZaxis = axis->GetZAxis();
				    mat_t rot_mat;

				    VMOVE(translate_to,axis->GetOrigin());
				    VSCALE(translate_to,translate_to,LocalUnits::length);

				    MAT_IDN(rot_mat);
				    VMOVE(&rot_mat[0], toXaxis);
				    VMOVE(&rot_mat[4], toYaxis);
				    VMOVE(&rot_mat[8], toZaxis);
				    bn_mat_inv(mat, rot_mat);
				    MAT_DELTAS_VEC(mat, translate_to);
				}

				dotg->WriteBrep(pname, onBrep,mat);

				delete onBrep;
			    }
			}
		    }
		}
		Factory::DeleteObjects();
	    }
	}
    }
    if (Verbose()) {
	std::cerr << std::endl << "     Generating BRL-CAD hierarchy." << std::endl;
    }

    for (int i = 0; i < num_ents; i++) {
	SDAI_Application_instance *sse = instance_list->GetSTEPentity(i);
	if (sse == NULL) {
	    continue;
	}
	std::string name = sse->EntityName();
	std::transform(name.begin(), name.end(), name.begin(), (int(*)(int))std::tolower);

	if ((sse->STEPfile_id > 0) && (sse->IsA(SCHEMA_NAMESPACE::e_context_dependent_shape_representation))) {
	    ContextDependentShapeRepresentation *aCDSR = dynamic_cast<ContextDependentShapeRepresentation *>(Factory::CreateObject(this, (SDAI_Application_instance *)sse));
	    if (aCDSR) {
		int rep_1_id = aCDSR->GetRepresentationRelationshipRep_1()->GetId();
		int rep_2_id = aCDSR->GetRepresentationRelationshipRep_2()->GetId();
		int pid_1 = id2productid_map[rep_1_id];
		int pid_2 = id2productid_map[rep_2_id];
		Axis2Placement3D *axis1 = NULL;
		Axis2Placement3D *axis2 = NULL;
		if ((id2name_map.find(rep_1_id) != id2name_map.end()) && (id2name_map.find(rep_2_id) != id2name_map.end())) {
		    string comb = id2name_map[rep_1_id];
		    string member = id2name_map[rep_2_id];
		    mat_t mat;
		    MAT_IDN(mat);

		    ProductDefinition *relatingProduct = aCDSR->GetRelatingProductDefinition();
		    ProductDefinition *relatedProduct = aCDSR->GetRelatedProductDefinition();
		    if (relatingProduct && relatedProduct) {
			string relatingName = relatingProduct->GetProductName();
			int relatingID = relatingProduct->GetProductId();
			string relatedName = relatedProduct->GetProductName();
			int relatedID = relatedProduct->GetProductId();

			if ((relatingID == pid_1) && (relatedID == pid_2)) {
			    axis1 = aCDSR->GetTransformItem_1();
			    axis2 = aCDSR->GetTransformItem_2();
			    comb = id2name_map[rep_1_id];
			    member = id2name_map[rep_2_id];
			} else if ((relatingID == pid_2) && (relatedID == pid_1)) {
			    axis1 = aCDSR->GetTransformItem_2();
			    axis2 = aCDSR->GetTransformItem_1();
			    comb = id2name_map[rep_2_id];
			    member = id2name_map[rep_1_id];
			} else {
			    std::cerr << "Error: Found Representation Relationship Rep_1(name=" << comb << ",Id=" << rep_1_id << ")" << std::endl;
			    std::cerr << "Error: Found Representation Relationship Rep_2(name=" << member << ",Id=" << rep_2_id << ")" << std::endl;
			    std::cerr << "Error: but Relating ProductDefinition (name=" << relatingName << ",Id=" << relatingID << ")"  << std::endl;
			    std::cerr << "Error:     Related ProductDefinition (name=" << relatedName << ",Id=" << relatedID << ")"  << std::endl;
			}
		    }

		    if ((axis1 != NULL) && (axis2 != NULL)) {
			mat_t to_mat;
			mat_t from_mat;
			mat_t toinv_mat;

			//assign matrix values
			double translate_to[3];
			double translate_from[3];
			const double *toXaxis = axis1->GetXAxis();
			const double *toYaxis = axis1->GetYAxis();
			const double *toZaxis = axis1->GetZAxis();
			const double *fromXaxis = axis2->GetXAxis();
			const double *fromYaxis = axis2->GetYAxis();
			const double *fromZaxis = axis2->GetZAxis();
			VMOVE(translate_to,axis1->GetOrigin());
			VSCALE(translate_to,translate_to,LocalUnits::length);

			VMOVE(translate_from,axis2->GetOrigin());
			VSCALE(translate_from,translate_from,-LocalUnits::length);

			// undo from trans/rot
			MAT_IDN(from_mat);
			VMOVE(&from_mat[0], fromXaxis);
			VMOVE(&from_mat[4], fromYaxis);
			VMOVE(&from_mat[8], fromZaxis);
			MAT_DELTAS_VEC(from_mat, translate_from);

			// do to trans/rot
			MAT_IDN(to_mat);
			VMOVE(&to_mat[0], toXaxis);
			VMOVE(&to_mat[4], toYaxis);
			VMOVE(&to_mat[8], toZaxis);
			bn_mat_inv(toinv_mat, to_mat);
			MAT_DELTAS_VEC(toinv_mat, translate_to);

			bn_mat_mul(mat, toinv_mat, from_mat);
		    }

		    dotg->AddMember(comb,member,mat);
		}
		Factory::DeleteObjects();
	    }
	}
    }
    if (!dotg->WriteCombs()) {
	std::cerr << "Error writing BRL-CAD hierarchy." << std::endl;
    }

    return true;
}
static ON_Brep* MakeTrimmedPlane( ON_TextLog& error_log )
{
  // This example demonstrates how to construct a ON_Brep
  // with the topology shown below.
	//
	//
  //    E-------C--------D
  //    |       /\       | 
  //    |      /  \      |
  //    |     /    \     |
  //    |    e2      e1  |     
  //    |   /        \   |    
  //    |  /          \  |  
  //    | /            \ |  
  //    A-----e0-------->B
  //
  //
  //  Things need to be defined in a valid brep:
	//   1- Vertices
	//   2- 3D Curves (geometry)
	//   3- Edges (topology - reference curve geometry)
	//   4- Surface (geometry)
	//   5- Faces (topology - reference surface geometry)
	//   6- Loops (2D parameter space of faces)
	//   4- Trims and 2D curves (2D parameter space of edges)
	//

  ON_3dPoint point[5] = {
    ON_3dPoint( 0.0, 0.0, 0.0 ),   // point A = geometry for vertex 0 (and surface SW corner)
    ON_3dPoint( 10.0, 0.0, 0.0 ),  // point B = geometry for vertex 1 (and surface SE corner)
    ON_3dPoint( 5.0, 10.0, 0.0 ),  // point C = geometry for vertex 2
		ON_3dPoint( 10.0, 10.0, 0.0 ), // point D (surface NE corner)
		ON_3dPoint( 0.0, 10.0, 0.0 ),  // point E (surface NW corner)

  };

  ON_Brep* brep = new ON_Brep();

  // create three vertices located at the three points
  int vi;
  for ( vi = 0; vi < 3; vi++ ) {
    ON_BrepVertex& v = brep->NewVertex(point[vi]);
    v.m_tolerance = 0.0; // this simple example is exact - for models with
                         // non-exact data, set tolerance as explained in
                         // definition of ON_BrepVertex.
  }


  // Create 3d curve geometry - the orientations are arbitrarily chosen
  // so that the end vertices are in alphabetical order.
  brep->m_C3.Append( CreateLinearCurve( point[A], point[B] ) ); // line AB
  brep->m_C3.Append( CreateLinearCurve( point[B], point[C] ) ); // line BC
  brep->m_C3.Append( CreateLinearCurve( point[A], point[C] ) ); // line CD


  // Create edge topology for each curve in the brep.
  CreateEdges( *brep );


  // Create 3d surface geometry - the orientations are arbitrarily chosen so
  // that some normals point into the cube and others point out of the cube.
  brep->m_S.Append( CreatePlanarSurface( point[A], point[B], point[D], point[E] ) ); // ABDE


  // Create face topology and 2d parameter space loops and trims.
  CreateFaces( *brep );


	//Make sure b-rep is valid
  if ( !brep->IsValid() ) 
  {
    error_log.Print("Trimmed b-rep face is not valid.\n");
    delete brep;
    brep = NULL;
  }

  return brep;
}
Пример #4
0
int
main(int argc, char *argv[])
{
    struct rt_wdb *wdbp = NULL;
    const char *name = "brep";
    ON_Brep *brep = NULL;
    int ret;

    if ( BU_STR_EQUAL(argv[1],"-h") || BU_STR_EQUAL(argv[1],"-?")) {
    	printusage();
    	return 0;
    }
    if (argc >= 1) {
    	printusage();
    	fprintf(stderr,"       Program continues running (will create file breplicator.g):\n");
    }

    bu_log("Breplicating...please wait...\n");

    ON_3dPoint points[8] = {
	/* left */
	ON_3dPoint(0.0, 0.0, 0.0), // 0
	ON_3dPoint(1.0, 0.0, 0.0), // 1
	ON_3dPoint(1.0, 0.0, 2.5), // 2
	ON_3dPoint(0.0, 0.0, 2.5), // 3
	/* right */
	ON_3dPoint(0.0, 1.0, 0.0), // 4
	ON_3dPoint(1.0, 1.0, 0.0), // 5
	ON_3dPoint(1.0, 1.0, 2.5), // 6
	ON_3dPoint(0.0, 1.0, 2.5), // 7
    };

    brep = generate_brep(8, points);
    if (!brep)
	bu_exit(1, "ERROR: We don't have a BREP\n");

    ON_TextLog log(stdout);

    brep->Dump(log);

    if (!brep->IsValid(&log)) {
	delete brep;
	bu_exit(1, "ERROR: We don't have a valid BREP\n");
    }

    brep->Dump(log);

    wdbp = wdb_fopen("breplicator.g");
    if (!wdbp) {
	delete brep;
	bu_exit(2, "ERROR: Unable to open breplicator.g\n");
    }
    mk_id(wdbp, "Breplicator test geometry");

    bu_log("Creating the BREP as BRL-CAD geometry\n");
    ret = mk_brep(wdbp, name, brep);
    if (ret) {
	delete brep;
	wdb_close(wdbp);
	bu_exit(3, "ERROR: Unable to export %s\n", name);
    }

    bu_log("Done.\n");

    delete brep;
    wdb_close(wdbp);

    return 0;
}
Пример #5
0
ON_Brep*
MakeTwistedCube(ON_TextLog& error_log)
{
    ON_3dPoint point[8] = {
	ON_3dPoint( 0.0,  0.0, 11.0), // Point A
	ON_3dPoint(10.0,  0.0, 12.0), // Point B
	ON_3dPoint(10.0,  8.0, 13.0), // Point C
	ON_3dPoint( 0.0,  6.0, 12.0), // Point D
	ON_3dPoint( 1.0,  2.0,  0.0), // Point E
	ON_3dPoint(10.0,  0.0,  0.0), // Point F
	ON_3dPoint(10.0,  7.0, -1.0), // Point G
	ON_3dPoint( 0.0,  6.0,  0.0), // Point H
    };

    ON_Brep* brep = new ON_Brep();

    // create eight vertices located at the eight points
    for (int i = 0; i < 8; i++) {
	ON_BrepVertex& v = brep->NewVertex(point[i]);
	v.m_tolerance = 0.0;
	// this example uses exact tolerance... reference
	// ON_BrepVertex for definition of non-exact data
    }

    // create 3d curve geometry - the orientations are arbitrarily
    // chosen so that the end vertices are in alphabetical order
    brep->m_C3.Append(TwistedCubeEdgeCurve(point[A], point[B])); // AB
    brep->m_C3.Append(TwistedCubeEdgeCurve(point[B], point[C])); // BC
    brep->m_C3.Append(TwistedCubeEdgeCurve(point[C], point[D])); // CD
    brep->m_C3.Append(TwistedCubeEdgeCurve(point[A], point[D])); // AD
    brep->m_C3.Append(TwistedCubeEdgeCurve(point[E], point[F])); // EF
    brep->m_C3.Append(TwistedCubeEdgeCurve(point[F], point[G])); // FG
    brep->m_C3.Append(TwistedCubeEdgeCurve(point[G], point[H])); // GH
    brep->m_C3.Append(TwistedCubeEdgeCurve(point[E], point[H])); // EH
    brep->m_C3.Append(TwistedCubeEdgeCurve(point[A], point[E])); // AE
    brep->m_C3.Append(TwistedCubeEdgeCurve(point[B], point[F])); // BF
    brep->m_C3.Append(TwistedCubeEdgeCurve(point[C], point[G])); // CG
    brep->m_C3.Append(TwistedCubeEdgeCurve(point[D], point[H])); // DH

    // create the 12 edges the connect the corners
    MakeTwistedCubeEdges( *brep );

    // create the 3d surface geometry. the orientations are arbitrary so
    // some normals point into the cube and other point out... not sure why
    brep->m_S.Append(TwistedCubeSideSurface(point[A], point[B], point[C], point[D]));
    brep->m_S.Append(TwistedCubeSideSurface(point[B], point[F], point[G], point[C]));
    brep->m_S.Append(TwistedCubeSideSurface(point[F], point[E], point[H], point[G]));
    brep->m_S.Append(TwistedCubeSideSurface(point[E], point[A], point[D], point[H]));
    brep->m_S.Append(TwistedCubeSideSurface(point[E], point[F], point[B], point[A]));
    brep->m_S.Append(TwistedCubeSideSurface(point[D], point[C], point[G], point[H]));

    // create the faces
    MakeTwistedCubeFaces(*brep);

    if (!brep->IsValid()) {
	error_log.Print("Twisted cube b-rep is not valid!\n");
	delete brep;
	brep = NULL;
    }

    return brep;
}
static ON_Brep* MakeTwistedCube( ON_TextLog& error_log )
{
  // This example demonstrates how to construct a ON_Brep
  // with the topology shown below.
  //
  //
  //             H-------e6-------G
  //            /                /|
  //           / |              / |
  //          /  e7            /  e5
  //         /   |            /   |
  //        /                e10  |
  //       /     |          /     |
  //      e11    E- - e4- -/- - - F
  //     /                /      /
  //    /      /         /      /
  //   D---------e2-----C      e9
  //   |     /          |     /
  //   |    e8          |    /
  //   e3  /            e1  /
  //   |                |  /
  //   | /              | /
  //   |                |/
  //   A-------e0-------B
  //
  //

  ON_3dPoint point[8] = {
    ON_3dPoint(  0.0,  0.0,  0.0 ),  // point A = geometry for vertex 0
    ON_3dPoint( 10.0,  0.0,  0.0 ),  // point B = geometry for vertex 1
    ON_3dPoint( 10.0,  8.0, -1.0 ),  // point C = geometry for vertex 2
    ON_3dPoint(  0.0,  6.0,  0.0 ),  // point D = geometry for vertex 3
    ON_3dPoint(  1.0,  2.0, 11.0 ),  // point E = geometry for vertex 4
    ON_3dPoint( 10.0,  0.0, 12.0 ),  // point F = geometry for vertex 5
    ON_3dPoint( 10.0,  7.0, 13.0 ),  // point G = geometry for vertex 6
    ON_3dPoint(  0.0,  6.0, 12.0 )   // point H = geometry for vertex 7
  };

  ON_Brep* brep = new ON_Brep();

  // create eight vertices located at the eight points
  int vi;
  for ( vi = 0; vi < 8; vi++ ) {
    ON_BrepVertex& v = brep->NewVertex(point[vi]);
    v.m_tolerance = 0.0; // this simple example is exact - for models with
                         // non-exact data, set tolerance as explained in
                         // definition of ON_BrepVertex.
  }

  // Create 3d curve geometry - the orientations are arbitrarily chosen
  // so that the end vertices are in alphabetical order.
  brep->m_C3.Append( TwistedCubeEdgeCurve( point[A], point[B] ) ); // line AB
  brep->m_C3.Append( TwistedCubeEdgeCurve( point[B], point[C] ) ); // line BC
  brep->m_C3.Append( TwistedCubeEdgeCurve( point[C], point[D] ) ); // line CD
  brep->m_C3.Append( TwistedCubeEdgeCurve( point[A], point[D] ) ); // line AD
  brep->m_C3.Append( TwistedCubeEdgeCurve( point[E], point[F] ) ); // line EF
  brep->m_C3.Append( TwistedCubeEdgeCurve( point[F], point[G] ) ); // line FG
  brep->m_C3.Append( TwistedCubeEdgeCurve( point[G], point[H] ) ); // line GH
  brep->m_C3.Append( TwistedCubeEdgeCurve( point[E], point[H] ) ); // line EH
  brep->m_C3.Append( TwistedCubeEdgeCurve( point[A], point[E] ) ); // line AE
  brep->m_C3.Append( TwistedCubeEdgeCurve( point[B], point[F] ) ); // line BF
  brep->m_C3.Append( TwistedCubeEdgeCurve( point[C], point[G] ) ); // line CG
  brep->m_C3.Append( TwistedCubeEdgeCurve( point[D], point[H] ) ); // line DH

  // Create the 12 edges that connect the corners of the cube.
  MakeTwistedCubeEdges( *brep );

  // Create 3d surface geometry - the orientations are arbitrarily chosen so
  // that some normals point into the cube and others point out of the cube.
  brep->m_S.Append( TwistedCubeSideSurface( point[A], point[B], point[C], point[D] ) ); // ABCD
  brep->m_S.Append( TwistedCubeSideSurface( point[B], point[C], point[G], point[F] ) ); // BCGF
  brep->m_S.Append( TwistedCubeSideSurface( point[C], point[D], point[H], point[G] ) ); // CDHG
  brep->m_S.Append( TwistedCubeSideSurface( point[A], point[D], point[H], point[E] ) ); // ADHE
  brep->m_S.Append( TwistedCubeSideSurface( point[A], point[B], point[F], point[E] ) ); // ABFE
  brep->m_S.Append( TwistedCubeSideSurface( point[E], point[F], point[G], point[H] ) ); // EFGH


  // Create the CRhinoBrepFaces
  MakeTwistedCubeFaces( *brep );

  if ( !brep->IsValid() ) 
  {
    error_log.Print("Twisted cube b-rep is not valid.\n");
    delete brep;
    brep = NULL;
  }

  //ON_BOOL32 bIsManifold;
  //ON_BOOL32 bHasBoundary;
  //ON_BOOL32 b = brep->IsManifold( &bIsManifold,&bHasBoundary );

  return brep;
}