bool IfcGeom::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) {
	BRepOffsetAPI_Sewing builder;
	builder.SetTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
	builder.SetMaxTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
	builder.SetMinTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
	TopExp_Explorer exp(compound,TopAbs_FACE);
	if ( ! exp.More() ) return false;
	for ( ; exp.More(); exp.Next() ) {
		TopoDS_Face face = TopoDS::Face(exp.Current());
		builder.Add(face);
	}
	builder.Perform();
	shape = builder.SewedShape();
	try {
	ShapeFix_Solid sf_solid;
	sf_solid.LimitTolerance(GetValue(GV_POINT_EQUALITY_TOLERANCE));
	shape = sf_solid.SolidFromShell(TopoDS::Shell(shape));
	} catch(...) {}
	return true;
}
Example #2
0
bool IfcGeom::Kernel::convert(const IfcSchema::IfcTriangulatedFaceSet* l, TopoDS_Shape& shape) {
    IfcSchema::IfcCartesianPointList3D* point_list = l->Coordinates();
    const std::vector< std::vector<double> > coordinates = point_list->CoordList();
    std::vector<gp_Pnt> points;
    points.reserve(coordinates.size());
    for (std::vector< std::vector<double> >::const_iterator it = coordinates.begin(); it != coordinates.end(); ++it) {
        const std::vector<double>& coords = *it;
        if (coords.size() != 3) {
            Logger::Message(Logger::LOG_ERROR, "Invalid dimensions encountered on Coordinates", l->entity);
            return false;
        }
        points.push_back(gp_Pnt(coords[0] * getValue(GV_LENGTH_UNIT),
                                coords[1] * getValue(GV_LENGTH_UNIT),
                                coords[2] * getValue(GV_LENGTH_UNIT)));
    }

    std::vector< std::vector<int> > indices = l->CoordIndex();

    std::vector<TopoDS_Face> faces;
    faces.reserve(indices.size());

    for(std::vector< std::vector<int> >::const_iterator it = indices.begin(); it != indices.end(); ++ it) {
        const std::vector<int>& tri = *it;
        if (tri.size() != 3) {
            Logger::Message(Logger::LOG_ERROR, "Invalid dimensions encountered on CoordIndex", l->entity);
            return false;
        }

        const int min_index = *std::min_element(tri.begin(), tri.end());
        const int max_index = *std::max_element(tri.begin(), tri.end());

        if (min_index < 1 || max_index > points.size()) {
            Logger::Message(Logger::LOG_ERROR, "Contents of CoordIndex out of bounds", l->entity);
            return false;
        }

        const gp_Pnt& a = points[tri[0] - 1]; // account for zero- vs
        const gp_Pnt& b = points[tri[1] - 1]; // one-based indices in
        const gp_Pnt& c = points[tri[2] - 1]; // c++ and express

        TopoDS_Wire wire = BRepBuilderAPI_MakePolygon(a, b, c, true).Wire();
        TopoDS_Face face = BRepBuilderAPI_MakeFace(wire).Face();

        TopoDS_Iterator face_it(face, false);
        const TopoDS_Wire& w = TopoDS::Wire(face_it.Value());
        const bool reversed = w.Orientation() == TopAbs_REVERSED;
        if (reversed) {
            face.Reverse();
        }

        if (face_area(face) > getValue(GV_MINIMAL_FACE_AREA)) {
            faces.push_back(face);
        }
    }

    if (faces.empty()) return false;

    const unsigned int num_faces = indices.size();
    bool valid_shell = false;

    if (faces.size() < getValue(GV_MAX_FACES_TO_SEW)) {
        BRepOffsetAPI_Sewing builder;
        builder.SetTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
        builder.SetMaxTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
        builder.SetMinTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));

        for (std::vector<TopoDS_Face>::const_iterator it = faces.begin(); it != faces.end(); ++it) {
            builder.Add(*it);
        }

        try {
            builder.Perform();
            shape = builder.SewedShape();
            valid_shell = BRepCheck_Analyzer(shape).IsValid();
        } catch(...) {}

        if (valid_shell) {
            try {
                ShapeFix_Solid solid;
                solid.LimitTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
                TopoDS_Solid solid_shape = solid.SolidFromShell(TopoDS::Shell(shape));
                if (!solid_shape.IsNull()) {
                    try {
                        BRepClass3d_SolidClassifier classifier(solid_shape);
                        shape = solid_shape;
                    } catch (...) {}
                }
            } catch(...) {}
        } else {
            Logger::Message(Logger::LOG_WARNING, "Failed to sew faceset:", l->entity);
        }
    }

    if (!valid_shell) {
        TopoDS_Compound compound;
        BRep_Builder builder;
        builder.MakeCompound(compound);

        for (std::vector<TopoDS_Face>::const_iterator it = faces.begin(); it != faces.end(); ++it) {
            builder.Add(compound, *it);
        }

        shape = compound;
    }

    return true;
}
Example #3
0
bool IfcGeom::Kernel::convert(const IfcSchema::IfcConnectedFaceSet* l, TopoDS_Shape& shape) {
    IfcSchema::IfcFace::list::ptr faces = l->CfsFaces();
    bool facesAdded = false;
    const unsigned int num_faces = faces->size();
    bool valid_shell = false;
    if ( num_faces < getValue(GV_MAX_FACES_TO_SEW) ) {
        BRepOffsetAPI_Sewing builder;
        builder.SetTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
        builder.SetMaxTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
        builder.SetMinTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
        for( IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++ it ) {
            TopoDS_Face face;
            bool converted_face = false;
            try {
                converted_face = convert_face(*it,face);
            } catch (...) {}
            if ( converted_face && face_area(face) > getValue(GV_MINIMAL_FACE_AREA) ) {
                builder.Add(face);
                facesAdded = true;
            } else {
                Logger::Message(Logger::LOG_WARNING,"Invalid face:",(*it)->entity);
            }
        }
        if ( ! facesAdded ) return false;
        try {
            builder.Perform();
            shape = builder.SewedShape();
            valid_shell = BRepCheck_Analyzer(shape).IsValid();
        } catch(...) {}
        if (valid_shell) {
            try {
                ShapeFix_Solid solid;
                solid.LimitTolerance(getValue(GV_POINT_EQUALITY_TOLERANCE));
                TopoDS_Solid solid_shape = solid.SolidFromShell(TopoDS::Shell(shape));
                if (!solid_shape.IsNull()) {
                    try {
                        BRepClass3d_SolidClassifier classifier(solid_shape);
                        shape = solid_shape;
                    } catch (...) {}
                }
            } catch(...) {}
        } else {
            Logger::Message(Logger::LOG_WARNING,"Failed to sew faceset:",l->entity);
        }
    }
    if (!valid_shell) {
        TopoDS_Compound compound;
        BRep_Builder builder;
        builder.MakeCompound(compound);
        for( IfcSchema::IfcFace::list::it it = faces->begin(); it != faces->end(); ++ it ) {
            TopoDS_Face face;
            bool converted_face = false;
            try {
                converted_face = convert_face(*it,face);
            } catch (...) {}
            if ( converted_face && face_area(face) > getValue(GV_MINIMAL_FACE_AREA) ) {
                builder.Add(compound,face);
                facesAdded = true;
            } else {
                Logger::Message(Logger::LOG_WARNING,"Invalid face:",(*it)->entity);
            }
        }
        if ( ! facesAdded ) return false;
        shape = compound;
    }
    return true;
}