Ejemplo n.º 1
0
bool IfcGeom::Kernel::convert(const IfcSchema::IfcFacetedBrep* l, IfcRepresentationShapeItems& shape) {
    TopoDS_Shape s;
    const SurfaceStyle* collective_style = get_style(l);
    if (convert_shape(l->Outer(),s) ) {
        const SurfaceStyle* indiv_style = get_style(l->Outer());
        shape.push_back(IfcRepresentationShapeItem(s, indiv_style ? indiv_style : collective_style));
        return true;
    }
    return false;
}
Ejemplo n.º 2
0
bool IfcGeom::Kernel::convert(const IfcSchema::IfcFaceBasedSurfaceModel* l, IfcRepresentationShapeItems& shapes) {
    IfcSchema::IfcConnectedFaceSet::list::ptr facesets = l->FbsmFaces();
    const SurfaceStyle* collective_style = get_style(l);
    for( IfcSchema::IfcConnectedFaceSet::list::it it = facesets->begin(); it != facesets->end(); ++ it ) {
        TopoDS_Shape s;
        const SurfaceStyle* shell_style = get_style(*it);
        if (convert_shape(*it,s)) {
            shapes.push_back(IfcRepresentationShapeItem(s, shell_style ? shell_style : collective_style));
        }
    }
    return true;
}
Ejemplo n.º 3
0
bool IfcGeom::Kernel::convert(const IfcSchema::IfcShellBasedSurfaceModel* l, IfcRepresentationShapeItems& shapes) {
    IfcEntityList::ptr shells = l->SbsmBoundary();
    const SurfaceStyle* collective_style = get_style(l);
    for( IfcEntityList::it it = shells->begin(); it != shells->end(); ++ it ) {
        TopoDS_Shape s;
        const SurfaceStyle* shell_style = 0;
        if ((*it)->is(IfcSchema::Type::IfcRepresentationItem)) {
            shell_style = get_style((IfcSchema::IfcRepresentationItem*)*it);
        }
        if (convert_shape(*it,s)) {
            shapes.push_back(IfcRepresentationShapeItem(s, shell_style ? shell_style : collective_style));
        }
    }
    return true;
}
Ejemplo n.º 4
0
bool IfcGeom::Kernel::convert(const IfcSchema::IfcRepresentation* l, IfcRepresentationShapeItems& shapes) {
    IfcSchema::IfcRepresentationItem::list::ptr items = l->Items();
    bool part_succes = false;
    if ( items->size() ) {
        for ( IfcSchema::IfcRepresentationItem::list::it it = items->begin(); it != items->end(); ++ it ) {
            IfcSchema::IfcRepresentationItem* representation_item = *it;
            if ( shape_type(representation_item) == ST_SHAPELIST ) {
                part_succes |= convert_shapes(*it, shapes);
            } else {
                TopoDS_Shape s;
                if (convert_shape(representation_item,s)) {
                    shapes.push_back(IfcRepresentationShapeItem(s, get_style(representation_item)));
                    part_succes |= true;
                }
            }
        }
    }
    return part_succes;
}
Ejemplo n.º 5
0
bool IfcGeom::Kernel::convert(const IfcSchema::IfcGeometricSet* l, IfcRepresentationShapeItems& shapes) {
    IfcEntityList::ptr elements = l->Elements();
    if ( !elements->size() ) return false;
    bool part_succes = false;
    const IfcGeom::SurfaceStyle* parent_style = get_style(l);
    for ( IfcEntityList::it it = elements->begin(); it != elements->end(); ++ it ) {
        IfcSchema::IfcGeometricSetSelect* element = *it;
        TopoDS_Shape s;
        if (convert_shape(element, s)) {
            part_succes = true;
            const IfcGeom::SurfaceStyle* style = 0;
            if (element->is(IfcSchema::Type::IfcPoint)) {
                style = get_style((IfcSchema::IfcPoint*) element);
            } else if (element->is(IfcSchema::Type::IfcCurve)) {
                style = get_style((IfcSchema::IfcCurve*) element);
            } else if (element->is(IfcSchema::Type::IfcSurface)) {
                style = get_style((IfcSchema::IfcSurface*) element);
            }
            shapes.push_back(IfcRepresentationShapeItem(s, style ? style : parent_style));
        }
    }
    return part_succes;
}
Ejemplo n.º 6
0
bool IfcGeom::Kernel::convert(const IfcSchema::IfcCsgSolid* l, TopoDS_Shape& shape) {
    return convert_shape(l->TreeRootExpression(), shape);
}
Ejemplo n.º 7
0
bool IfcGeom::Kernel::convert(const IfcSchema::IfcBooleanResult* l, TopoDS_Shape& shape) {
    TopoDS_Shape s1, s2;
    IfcRepresentationShapeItems items1, items2;
    TopoDS_Wire boundary_wire;
    IfcSchema::IfcBooleanOperand* operand1 = l->FirstOperand();
    IfcSchema::IfcBooleanOperand* operand2 = l->SecondOperand();
    bool is_halfspace = operand2->is(IfcSchema::Type::IfcHalfSpaceSolid);

    if ( shape_type(operand1) == ST_SHAPELIST ) {
        if (!(convert_shapes(operand1, items1) && flatten_shape_list(items1, s1, true))) {
            return false;
        }
    } else if ( shape_type(operand1) == ST_SHAPE ) {
        if ( ! convert_shape(operand1, s1) ) {
            return false;
        }
        {   TopoDS_Solid temp_solid;
            s1 = ensure_fit_for_subtraction(s1, temp_solid);
        }
    } else {
        Logger::Message(Logger::LOG_ERROR, "Invalid representation item for boolean operation", operand1->entity);
        return false;
    }

    const double first_operand_volume = shape_volume(s1);
    if ( first_operand_volume <= ALMOST_ZERO )
        Logger::Message(Logger::LOG_WARNING,"Empty solid for:",l->FirstOperand()->entity);

    bool shape2_processed = false;
    if ( shape_type(operand2) == ST_SHAPELIST ) {
        shape2_processed = convert_shapes(operand2, items2) && flatten_shape_list(items2, s2, true);
    } else if ( shape_type(operand2) == ST_SHAPE ) {
        shape2_processed = convert_shape(operand2,s2);
        if (shape2_processed && !is_halfspace) {
            TopoDS_Solid temp_solid;
            s2 = ensure_fit_for_subtraction(s2, temp_solid);
        }
    } else {
        Logger::Message(Logger::LOG_ERROR, "Invalid representation item for boolean operation", operand2->entity);
    }

    if (!shape2_processed) {
        shape = s1;
        Logger::Message(Logger::LOG_ERROR,"Failed to convert SecondOperand of:",l->entity);
        return true;
    }

    if (!is_halfspace) {
        const double second_operand_volume = shape_volume(s2);
        if ( second_operand_volume <= ALMOST_ZERO )
            Logger::Message(Logger::LOG_WARNING,"Empty solid for:",operand2->entity);
    }

    const IfcSchema::IfcBooleanOperator::IfcBooleanOperator op = l->Operator();

    if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_DIFFERENCE) {

        bool valid_cut = false;
        BRepAlgoAPI_Cut brep_cut(s1,s2);
        if ( brep_cut.IsDone() ) {
            TopoDS_Shape result = brep_cut;

            ShapeFix_Shape fix(result);
            try {
                fix.Perform();
                result = fix.Shape();
            } catch (...) {
                Logger::Message(Logger::LOG_WARNING, "Shape healing failed on boolean result", l->entity);
            }

            bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
            if ( is_valid ) {
                shape = result;
                valid_cut = true;
            }
        }

        if ( valid_cut ) {
            const double volume_after_subtraction = shape_volume(shape);
            if ( ALMOST_THE_SAME(first_operand_volume,volume_after_subtraction) )
                Logger::Message(Logger::LOG_WARNING,"Subtraction yields unchanged volume:",l->entity);
        } else {
            Logger::Message(Logger::LOG_ERROR,"Failed to process subtraction:",l->entity);
            shape = s1;
        }

        return true;

    } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_UNION) {

        BRepAlgoAPI_Fuse brep_fuse(s1,s2);
        if ( brep_fuse.IsDone() ) {
            TopoDS_Shape result = brep_fuse;

            ShapeFix_Shape fix(result);
            fix.Perform();
            result = fix.Shape();

            bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
            if ( is_valid ) {
                shape = result;
                return true;
            }
        }

    } else if (op == IfcSchema::IfcBooleanOperator::IfcBooleanOperator_INTERSECTION) {

        BRepAlgoAPI_Common brep_common(s1,s2);
        if ( brep_common.IsDone() ) {
            TopoDS_Shape result = brep_common;

            ShapeFix_Shape fix(result);
            fix.Perform();
            result = fix.Shape();

            bool is_valid = BRepCheck_Analyzer(result).IsValid() != 0;
            if ( is_valid ) {
                shape = result;
                return true;
            }
        }

    }
    return false;
}
Ejemplo n.º 8
0
bool IfcGeom::Kernel::convert(const IfcSchema::IfcFace* l, TopoDS_Shape& face) {
	IfcSchema::IfcFaceBound::list::ptr bounds = l->Bounds();

	Handle(Geom_Surface) face_surface;
	const bool is_face_surface = l->is(IfcSchema::Type::IfcFaceSurface);

	if (is_face_surface) {
		IfcSchema::IfcFaceSurface* fs = (IfcSchema::IfcFaceSurface*) l;
		fs->FaceSurface();
		// FIXME: Surfaces are interpreted as a TopoDS_Shape
		TopoDS_Shape surface_shape;
		if (!convert_shape(fs->FaceSurface(), surface_shape)) return false;

		// FIXME: Assert this obtaines the only face
		TopExp_Explorer exp(surface_shape, TopAbs_FACE);
		if (!exp.More()) return false;

		TopoDS_Face surface = TopoDS::Face(exp.Current());
		face_surface = BRep_Tool::Surface(surface);
	}
	
	const int num_bounds = bounds->size();
	int num_outer_bounds = 0;

	for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) {
		IfcSchema::IfcFaceBound* bound = *it;
		if (bound->is(IfcSchema::Type::IfcFaceOuterBound)) num_outer_bounds ++;
	}

	// The number of outer bounds should be one according to the schema. Also Open Cascade
	// expects this, but it is not strictly checked. Regardless, if the number is greater,
	// the face will still be processed as long as there are no holes. A compound of faces
	// is returned in that case.
	if (num_bounds > 1 && num_outer_bounds > 1 && num_bounds != num_outer_bounds) {
		Logger::Message(Logger::LOG_ERROR, "Invalid configuration of boundaries for:", l->entity);
		return false;
	}

	TopoDS_Compound compound;
	BRep_Builder builder;
	if (num_outer_bounds > 1) {
		builder.MakeCompound(compound);
	}
	
	// The builder is initialized on the heap because of the various different moments
	// of initialization depending on the configuration of surfaces and boundaries.
	BRepBuilderAPI_MakeFace* mf = 0;
	
	bool success = false;
	int processed = 0;

	for (int process_interior = 0; process_interior <= 1; ++process_interior) {
		for (IfcSchema::IfcFaceBound::list::it it = bounds->begin(); it != bounds->end(); ++it) {
			IfcSchema::IfcFaceBound* bound = *it;
			IfcSchema::IfcLoop* loop = bound->Bound();
		
			bool same_sense = bound->Orientation();
			const bool is_interior = 
				!bound->is(IfcSchema::Type::IfcFaceOuterBound) &&
				(num_bounds > 1) &&
				(num_outer_bounds < num_bounds);

			// The exterior face boundary is processed first
			if (is_interior == !process_interior) continue;
		
			TopoDS_Wire wire;
			if (!convert_wire(loop, wire)) {
				Logger::Message(Logger::LOG_ERROR, "Failed to process face boundary loop", loop->entity);
				delete mf;
				return false;
			}

			/*
			The approach below does not result in a significant speed-up
			if (loop->is(IfcSchema::Type::IfcPolyLoop) && processed == 0 && face_surface.IsNull()) {
				IfcSchema::IfcPolyLoop* polyloop = (IfcSchema::IfcPolyLoop*) loop;
				IfcSchema::IfcCartesianPoint::list::ptr points = polyloop->Polygon();

				if (points->size() == 3) {
					// Help Open Cascade by finding the plane more efficiently
					IfcSchema::IfcCartesianPoint::list::it point_iterator = points->begin();
					gp_Pnt a, b, c;
					convert(*point_iterator++, a);
					convert(*point_iterator++, b);
					convert(*point_iterator++, c);
					const gp_XYZ ab = (b.XYZ() - a.XYZ());
					const gp_XYZ ac = (c.XYZ() - a.XYZ());
					const gp_Vec cross = ab.Crossed(ac);
					if (cross.SquareMagnitude() > ALMOST_ZERO) {
						const gp_Dir n = cross;
						face_surface = new Geom_Plane(a, n);
					}
				}
			}
			*/
		
			if (!same_sense) {
				wire.Reverse();
			}

			bool flattened_wire = false;

			if (!mf) {
			process_wire:

				if (face_surface.IsNull()) {
					mf = new BRepBuilderAPI_MakeFace(wire);
				} else {
					/// @todo check necessity of false here
					mf = new BRepBuilderAPI_MakeFace(face_surface, wire, false); 
				}				

				/* BRepBuilderAPI_FaceError er = mf->Error();
				if (er == BRepBuilderAPI_NotPlanar) {
					ShapeFix_ShapeTolerance FTol;
					FTol.SetTolerance(wire, getValue(GV_PRECISION), TopAbs_WIRE);
					delete mf;
					mf = new BRepBuilderAPI_MakeFace(wire);
				} */

				if (mf->IsDone()) {
					TopoDS_Face outer_face_bound = mf->Face();

					// In case of (non-planar) face surface, p-curves need to be computed.
					// For planar faces, Open Cascade generates p-curves on the fly.
					if (!face_surface.IsNull()) {
						TopExp_Explorer exp(outer_face_bound, TopAbs_EDGE);
						for (; exp.More(); exp.Next()) {
							const TopoDS_Edge& edge = TopoDS::Edge(exp.Current());
							ShapeFix_Edge fix_edge;
							fix_edge.FixAddPCurve(edge, outer_face_bound, false, getValue(GV_PRECISION));
						}
					}
					
					if (BRepCheck_Face(outer_face_bound).OrientationOfWires() == BRepCheck_BadOrientationOfSubshape) {
						wire.Reverse();
						same_sense = !same_sense;
						delete mf;
						if (face_surface.IsNull()) {
							mf = new BRepBuilderAPI_MakeFace(wire);
						} else {
							mf = new BRepBuilderAPI_MakeFace(face_surface, wire); 
						}
						ShapeFix_Face fix(mf->Face());
						fix.FixOrientation();
						fix.Perform();
						outer_face_bound = fix.Face();
					}

					// If the wires are reversed the face needs to be reversed as well in order
					// to maintain the counter-clock-wise ordering of the bounding wire's vertices.
					bool all_reversed = true;
					TopoDS_Iterator jt(outer_face_bound, false);
					for (; jt.More(); jt.Next()) {
						const TopoDS_Wire& w = TopoDS::Wire(jt.Value());
						if ((w.Orientation() != TopAbs_REVERSED) == same_sense) {
							all_reversed = false;
						}
					}

					if (all_reversed) {
						outer_face_bound.Reverse();
					}

					if (num_outer_bounds > 1) {
						builder.Add(compound, outer_face_bound);
						delete mf; mf = 0;
					} else if (num_bounds > 1) {
						// Reinitialize the builder to the outer face 
						// bound in order to add holes more robustly.
						delete mf;
						// TODO: What about the face_surface?
						mf = new BRepBuilderAPI_MakeFace(outer_face_bound);
					} else {
						face = outer_face_bound;
						success = true;
					}
				} else {
					const bool non_planar = mf->Error() == BRepBuilderAPI_NotPlanar;
					delete mf;
					if (!non_planar || flattened_wire || !flatten_wire(wire)) {
						Logger::Message(Logger::LOG_ERROR, "Failed to process face boundary", bound->entity);
						return false;
					} else {
						Logger::Message(Logger::LOG_ERROR, "Flattening face boundary", bound->entity);
						flattened_wire = true;
						goto process_wire;
					}
				}

			} else {
				mf->Add(wire);
			}
			processed ++;
		}
	}

	if (!success) {
		success = processed == num_bounds;
		if (success) {
			if (num_outer_bounds > 1) {
				face = compound;
			} else {
				success = success && mf->IsDone();
				if (success) {
					face = mf->Face();
				}
			}
		}
	}

	if (success) {
		ShapeFix_ShapeTolerance FTol;
		FTol.SetTolerance(face, getValue(GV_PRECISION), TopAbs_FACE);
	}

	delete mf;
	return success;
}