XbimGeometry icon indicating copy to clipboard operation
XbimGeometry copied to clipboard

Cant create valid IfcSurfaceCurveSweptAreaSolid

Open misterEnthusiastic opened this issue 1 year ago • 1 comments

I am new to xbim and IFC all together. I am trying to model an air duct from code based on coordinates. The IfcSurfaceCurveSweptAreaSolid i created crashed BIMVision and did not appear in XbimExplorer. I was able to create the needed duct with IfcSweptDiskSolid, but the profile does not mach. I was looking through documentations, examples, and trying to make it work for several days, but I could not. I would really apreciate any help.

I merged my code into this class for representation. The rest of the code is based on the ifc 4 wall example.

public static IfcBuildingElementProxy CreateDuct(IfcStore store) { using (var txn = store.BeginTransaction("Create Rectangle Profile")) {

    // rectangular profile for cross section
    var rectangleProfile = store.Instances.New<IfcRectangleProfileDef>();
    rectangleProfile.ProfileType = IfcProfileTypeEnum.AREA;
    rectangleProfile.XDim = 500;
    rectangleProfile.YDim = 1000;

    var placement = store.Instances.New<IfcAxis2Placement2D>();
    placement.Location = store.Instances.New<IfcCartesianPoint>(p => p.SetXY(0, 0));
    rectangleProfile.Position = placement;

    var product = store.Instances.New<IfcBuildingElementProxy>();
    product.Name = "duct base";

    // create the IfcCompositeCurve from a list of IfcCartesianPoint
    var pointList = new List<IfcCartesianPoint>()
    {
        store.Instances.New<IfcCartesianPoint>(p => p.SetXYZ(0, 0, 0)),
        store.Instances.New<IfcCartesianPoint>(p => p.SetXYZ(0, 20000, 0)),
        store.Instances.New<IfcCartesianPoint>(p => p.SetXYZ(20000, 20000, 0)),
    };
    List<IfcCompositeCurveSegment> segments = new List<IfcCompositeCurveSegment>();

    for (int i = 0; i < pointList.Count - 1; i++)
    {
        var startPoint = pointList[i];
        var endPoint = pointList[i + 1];

        var polyline = store.Instances.New<IfcPolyline>();
        polyline.Points.AddRange(new[] { startPoint, endPoint });

        var segment = store.Instances.New<IfcCompositeCurveSegment>();
        segment.ParentCurve = polyline;
        segment.Transition = IfcTransitionCode.CONTSAMEGRADIENTSAMECURVATURE;
        segment.SameSense = true;

        segments.Add(segment);
    }
    var compositeCurve = store.Instances.New<IfcCompositeCurve>();
    compositeCurve.Segments.AddRange(segments);
    compositeCurve.SelfIntersect = new IfcLogical(false);

    // Creating SurfaceCurveSweptAreaSolid
    var sweptAreaSolid = store.Instances.New<IfcSurfaceCurveSweptAreaSolid>();
    sweptAreaSolid.SweptArea = rectangleProfile;
    sweptAreaSolid.Directrix = CreateIfcComponentCurveFromPoints.CreateIfcComponentCurve(store, pointList);

    // Creating the shape representation
    var shape = store.Instances.New<IfcShapeRepresentation>();
    shape.ContextOfItems = store.Instances.FirstOrDefault<IfcGeometricRepresentationContext>();
    shape.RepresentationType = "SweptSolid";
    shape.RepresentationIdentifier = "Body";
    shape.Items.Add(sweptAreaSolid);

    // Create a product definition
    var productDefinition = store.Instances.New<IfcProductDefinitionShape>();
    productDefinition.Representations.Add(shape);

    // Create an IfcBuildingElementProxy
    var buildingElementProxy = store.Instances.New<IfcBuildingElementProxy>();
    buildingElementProxy.ObjectType = "CustomElement";
    buildingElementProxy.Representation = productDefinition;
    txn.Commit();

    return buildingElementProxy;
}

}

the created ifc:

ISO-10303-21;
HEADER;
FILE_DESCRIPTION ((''), '2;1');
FILE_NAME ('', '2024-01-19T15:49:05', (''), (''), 'Processor version 5.1.0.0', 'Xbim.IO.MemoryModel', '');
FILE_SCHEMA (('IFC4'));
ENDSEC;
DATA;
#1=IFCPROJECT('3x9ZDPY0v68v4J4JP_BSqW',#2,'databaseObject',$,$,$,$,(#19,#22),#7);
#2=IFCOWNERHISTORY(#5,#6,$,.ADDED.,1705679345,$,$,0);
#3=IFCPERSON($,'user1','user1',$,$,$,$,$);
#4=IFCORGANIZATION($,'org1',$,$,$);
#5=IFCPERSONANDORGANIZATION(#3,#4,$);
#6=IFCAPPLICATION(#4,'version','application','id');
#7=IFCUNITASSIGNMENT((#8,#9,#10,#11,#12,#13,#14,#15,#16));
#8=IFCSIUNIT(*,.LENGTHUNIT.,.MILLI.,.METRE.);
#9=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);
#10=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.);
#11=IFCSIUNIT(*,.SOLIDANGLEUNIT.,$,.STERADIAN.);
#12=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.);
#13=IFCSIUNIT(*,.MASSUNIT.,$,.GRAM.);
#14=IFCSIUNIT(*,.TIMEUNIT.,$,.SECOND.);
#15=IFCSIUNIT(*,.THERMODYNAMICTEMPERATUREUNIT.,$,.DEGREE_CELSIUS.);
#16=IFCSIUNIT(*,.LUMINOUSINTENSITYUNIT.,$,.LUMEN.);
#17=IFCCARTESIANPOINT((0.,0.,0.));
#18=IFCAXIS2PLACEMENT3D(#17,$,$);
#19=IFCGEOMETRICREPRESENTATIONCONTEXT('Building Model','Model',3,1.E-05,#18,$);
#20=IFCCARTESIANPOINT((0.,0.));
#21=IFCAXIS2PLACEMENT2D(#20,$);
#22=IFCGEOMETRICREPRESENTATIONCONTEXT('Building Plan View','Plan',2,1.E-05,#21,$);
#23=IFCBUILDING('1XZeFbGqD54uQsNe0_4H3H',#2,'Default Building',$,$,#24,$,$,.ELEMENT.,$,$,$);
#24=IFCLOCALPLACEMENT($,#25);
#25=IFCAXIS2PLACEMENT3D(#26,$,$);
#26=IFCCARTESIANPOINT((0.,0.,0.));
#27=IFCRELAGGREGATES('2553Sn7WX8je7H2uzAlILv',#2,$,$,#1,(#23));
#28=IFCRECTANGLEPROFILEDEF(.AREA.,$,#29,500.,1000.);
#29=IFCAXIS2PLACEMENT2D(#30,$);
#30=IFCCARTESIANPOINT((0.,0.));
#31=IFCBUILDINGELEMENTPROXY('0$F8HBwqbEhf4DDq_dVdlG',#2,'duct base',$,$,$,$,$,$);
#32=IFCCARTESIANPOINT((0.,0.,0.));
#33=IFCCARTESIANPOINT((0.,20000.,0.));
#34=IFCCARTESIANPOINT((20000.,20000.,0.));
#35=IFCPOLYLINE((#32,#33));
#36=IFCCOMPOSITECURVESEGMENT(.CONTSAMEGRADIENTSAMECURVATURE.,.T.,#35);
#37=IFCPOLYLINE((#33,#34));
#38=IFCCOMPOSITECURVESEGMENT(.CONTSAMEGRADIENTSAMECURVATURE.,.T.,#37);
#39=IFCCOMPOSITECURVE((#36,#38),.F.);
#40=IFCSURFACECURVESWEPTAREASOLID(#28,$,#45,$,$,$);
#41=IFCPOLYLINE((#32,#33));
#42=IFCCOMPOSITECURVESEGMENT(.CONTSAMEGRADIENTSAMECURVATURE.,.T.,#41);
#43=IFCPOLYLINE((#33,#34));
#44=IFCCOMPOSITECURVESEGMENT(.CONTSAMEGRADIENTSAMECURVATURE.,.T.,#43);
#45=IFCCOMPOSITECURVE((#42,#44),.F.);
#46=IFCSHAPEREPRESENTATION(#19,'Body','SweptSolid',(#40));
#47=IFCPRODUCTDEFINITIONSHAPE($,$,(#46));
#48=IFCBUILDINGELEMENTPROXY('2avQ$lXH91Zu4UA0j6DjSY',#2,$,$,'CustomElement',$,#47,$,$);
#49=IFCRELCONTAINEDINSPATIALSTRUCTURE('1dB6nMjYDDfQteYC8KR1wy',#2,$,$,(#48),#23);
ENDSEC;
END-ISO-10303-21;

misterEnthusiastic avatar Jan 19 '24 14:01 misterEnthusiastic

If you validate the IFC with xbim's built-in validator you get this:

Entity #40 (IfcSurfaceCurveSweptAreaSolid) has validation failures.
	IfcSurfaceCurveSweCptAreaSolid.ReferenceSurface is not optional.
Entity #46 (IfcShapeRepresentation) has validation failures.
	Issue of type EntityWhereClauses on IfcShapeRepresentation.CorrectItemsForType.
Entity #48 (IfcBuildingElementProxy) has validation failures.
	Issue of type EntityWhereClauses on IfcProduct.PlacementForShapeRepresentation.
	Issue of type EntityWhereClauses on IfcBuildingElementProxy.HasObjectName.

The main issue issue looks like you're creating a IfcSurfaceCurveSweptAreaSolid, but not providing a ReferenceSurface. Check the docs.

And I think the IfcShapeRepresentation's Representation identifier for that should be 'AdvancedSweptSolid' not 'SweptSolid'

You also don't seem to be using the IfcLocalPlacement on the BuildingElementProxy

IfcSurfaceCurveSweptAreaSolid is quite an advanced representation. There may be something simpler you can use like IfcRevolvedAreaSolid - which has some examples on that page you can follow.

Bottom line: use the built in IFC validator in xbim - if it's highlighting errors you will likely get these kinds of problems when viewing.

andyward avatar Jan 22 '24 14:01 andyward