packageDocumentation module import { BentleyStatus , CompressedId64Set , DbResult , Id64 , Id64Arg , Id64String , IModelStatus } from "@itwin/core-bentley" ; import { Matrix3d , Matrix3dProps , Point3d , Range3d , Range3dProps , Transform , TransformProps , XYZProps , YawPitchRollAngles } from "@itwin/core-geometry" ; import { GeometricElement , IModelDb } from "@itwin/core-backend" ; import { BRepEntity , ColorDefProps , DynamicGraphicsRequest3dProps , EcefLocation , EcefLocationProps , ElementGeometry , ElementGeometryBuilderParams , ElementGeometryBuilderParamsForPart , ElementGeometryDataEntry , ElementGeometryFunction , ElementGeometryInfo , ElementGeometryRequest , FilePropertyProps , GeometricElementProps , GeometryPartProps , IModelError , Placement3dProps } from "@itwin/core-common" ; import { BasicManipulationCommandIpc , BlendEdgesProps , BooleanOperationProps , BRepEntityType , ChamferEdgesProps , ConnectedSubEntityProps , CutProps , DeleteSubEntityProps , EdgeParameterRangeProps , editorBuiltInCmdIds , ElementGeometryCacheFilter , ElementGeometryResultOptions , ElementGeometryResultProps , EmbossProps , EvaluatedEdgeProps , EvaluatedFaceProps , EvaluatedVertexProps , FaceParameterRangeProps , FlatBufferGeometryFilter , HollowFacesProps , ImprintProps , LocateSubEntityProps , LoftProps , OffsetEdgesProps , OffsetFacesProps , PointInsideResultProps , SewSheetProps , SolidModelingCommandIpc , SpinFacesProps , SubEntityAppearanceProps , SubEntityGeometryProps , SubEntityLocationProps , SubEntityProps , SubEntityType , SweepFacesProps , SweepPathProps , ThickenSheetProps , TransformSubEntityProps } from "@itwin/editor-common" ; import { EditCommand } from "./EditCommand" ; alpha export class BasicManipulationCommand extends EditCommand implements BasicManipulationCommandIpc { public static override commandId = editorBuiltInCmdIds . cmdBasicManipulation ; public constructor ( iModel , protected _str ) { super ( iModel ) ; } public async deleteElements ( ids ) { const idSet = CompressedId64Set . decompressSet ( ids ) ; await this . iModel . locks . acquireLocks ( { exclusive : idSet } ) ; for ( const id of idSet ) this . iModel . elements . deleteElement ( id ) ; return IModelStatus . Success ; } public async transformPlacement ( ids , transProps ) { const idSet = CompressedId64Set . decompressSet ( ids ) ; await this . iModel . locks . acquireLocks ( { exclusive : idSet } ) ; const transform = Transform . fromJSON ( transProps ) ; for ( const id of idSet ) { const element = this . iModel . elements . getElement < GeometricElement > ( id ) ; if ( ! element . placement . isValid ) continue ; element . placement . multiplyTransform ( transform ) ; this . iModel . elements . updateElement ( element ) ; } return IModelStatus . Success ; } public async rotatePlacement ( ids , matrixProps , aboutCenter ) { const idSet = CompressedId64Set . decompressSet ( ids ) ; await this . iModel . locks . acquireLocks ( { exclusive : idSet } ) ; const matrix = Matrix3d . fromJSON ( matrixProps ) ; for ( const id of idSet ) { const element = this . iModel . elements . getElement < GeometricElement > ( id ) ; if ( ! element . placement . isValid ) continue ; const fixedPoint = aboutCenter ? element . placement . calculateRange ( ) . center : Point3d . createFrom ( element . placement . origin ) ; const transform = Transform . createFixedPointAndMatrix ( fixedPoint , matrix ) ; element . placement . multiplyTransform ( transform ) ; this . iModel . elements . updateElement ( element ) ; } return IModelStatus . Success ; } public async insertGeometricElement ( props , data ? ) { await this . iModel . locks . acquireLocks ( { shared : props . model } ) ; if ( undefined !== data ) props . elementGeometryBuilderParams = { entryArray : data . entryArray , viewIndependent : data . viewIndependent } ; return this . iModel . elements . insertElement ( props ) ; } public async insertGeometryPart ( props , data ? ) { await this . iModel . locks . acquireLocks ( { shared : props . model } ) ; if ( undefined !== data ) props . elementGeometryBuilderParams = { entryArray : data . entryArray , is2dPart : data . is2dPart } ; return this . iModel . elements . insertElement ( props ) ; } public async updateGeometricElement ( propsOrId , data ? ) { let props ; if ( typeof propsOrId === "string" ) { if ( undefined === data ) throw new IModelError ( DbResult . BE_SQLITE_ERROR , "Flatbuffer data required for update by id" ) ; props = this . iModel . elements . getElement < GeometricElement > ( propsOrId ) ; } else { props = propsOrId ; } if ( undefined === props . id ) throw new IModelError ( DbResult . BE_SQLITE_ERROR , "Element id required for update" ) ; await this . iModel . locks . acquireLocks ( { exclusive : props . id } ) ; if ( undefined !== data ) props . elementGeometryBuilderParams = { entryArray : data . entryArray , viewIndependent : data . viewIndependent } ; this . iModel . elements . updateElement ( props ) ; } public async requestElementGeometry ( elementId , filter ? ) { let accepted ; const onGeometry = ( info ) : void => { accepted = info ; if ( undefined !== filter ) { let numDisplayable = 0 ; for ( const entry of info . entryArray ) { if ( ! ElementGeometry . isDisplayableEntry ( entry ) ) continue ; numDisplayable ++ ; if ( filter . maxDisplayable && numDisplayable > filter . maxDisplayable ) { accepted = undefined ; break ; } if ( filter . reject && filter . reject . some ( ( opcode ) => entry . opcode === opcode ) ) { accepted = undefined ; break ; } if ( filter . accept && ! filter . accept . some ( ( opcode ) => entry . opcode === opcode ) ) { accepted = undefined ; break ; } if ( undefined === filter . geometry ) continue ; let entityType ; if ( filter . geometry . curves && ! ( filter . geometry . surfaces || filter . geometry . solids ) ) entityType = ElementGeometry . isCurve ( entry ) ? BRepEntity . Type . Wire : undefined ; else entityType = ElementGeometry . getBRepEntityType ( entry ) ; switch ( entityType ) { case BRepEntity . Type . Wire : if ( ! filter . geometry . curves ) accepted = undefined ; break ; case BRepEntity . Type . Sheet : if ( ! filter . geometry . surfaces ) accepted = undefined ; break ; case BRepEntity . Type . Solid : if ( ! filter . geometry . solids ) accepted = undefined ; break ; default : accepted = undefined ; break ; } if ( undefined === accepted ) break ; } } } ; const requestProps = { onGeometry , elementId } ; if ( DbResult . BE_SQLITE_OK !== this . iModel . elementGeometryRequest ( requestProps ) ) return undefined ; return accepted ; } public async updateProjectExtents ( extents ) { const newExtents = new Range3d ( ) ; newExtents . setFromJSON ( extents ) ; if ( newExtents . isNull ) throw new IModelError ( DbResult . BE_SQLITE_ERROR , "Invalid project extents" ) ; await this . iModel . acquireSchemaLock ( ) ; this . iModel . updateProjectExtents ( newExtents ) ; const unitsProps = { name : "Units" , namespace : "dgn_Db" } ; const unitsStr = this . iModel . queryFilePropertyString ( unitsProps ) ; if ( undefined !== unitsStr ) { const unitsVal = JSON . parse ( unitsStr ) ; const calculated = 1 ; if ( calculated !== unitsVal . extentsSource ) { unitsVal . extentsSource = calculated ; this . iModel . saveFileProperty ( unitsProps , JSON . stringify ( unitsVal ) ) ; } } } public async updateEcefLocation ( ecefLocation ) { await this . iModel . acquireSchemaLock ( ) ; this . iModel . deleteFileProperty ( { name : "DgnGCS" , namespace : "dgn_Db" } ) ; const newEcefLocation = new EcefLocation ( ecefLocation ) ; this . iModel . updateEcefLocation ( newEcefLocation ) ; } } interface ElementGeometryCacheRequestProps { id ? : Id64String ; } interface ElementGeometryCacheResponseProps { status : BentleyStatus ; numGeom ? : number ; numPart ? : number ; numSolid ? : number ; numSurface ? : number ; numCurve ? : number ; numOther ? : number ; } interface SubEntityGeometryResponseProps { /** The face, edge, or vertex geometry */ geometry : ElementGeometryDataEntry ; /** The face or edge range box for the sub-entity geometry stored as 6 values for low/high */ range ? : Float64Array ; /** Category id for geometry. */ category ? : Id64String ; /** SubCategory id for geometry. */ subCategory ? : Id64String ; /** Material id for geometry. */ material ? : Id64String ; /** color of geometry. */ color ? : ColorDefProps ; /** transparency of geometry. */ transparency ? : number ; /** weight of geometry. */ weight ? : number ; } type GeometrySummaryFunction = ( info : BRepEntityType [ ] ) => void ; type SubEntityGeometryFunction = ( info : SubEntityGeometryResponseProps ) => void ; type SubEntityParameterRangeFunction = ( info : FaceParameterRangeProps | EdgeParameterRangeProps ) => void ; type SubEntityEvaluateFunction = ( info : EvaluatedFaceProps | EvaluatedEdgeProps | EvaluatedVertexProps ) => void ; type SubEntityArrayFunction = ( info : SubEntityProps [ ] ) => void ; type SubEntityLocationArrayFunction = ( info : SubEntityLocationProps [ ] ) => void ; type SubEntityLocationFunction = ( info : SubEntityLocationProps ) => void ; type PointInsideFunction = ( info : PointInsideResultProps [ ] ) => void ; type YesNoFunction = ( info : boolean ) => void ; interface GeometrySummaryRequestProps { /** Callback for result */ onResult : GeometrySummaryFunction ; } interface SubEntityGeometryRequestProps { /** Sub-entity to return geometry for */ subEntity : SubEntityProps ; /** Callback for result */ onResult : SubEntityGeometryFunction ; } interface SubEntityParameterRangeRequestProps { /** Sub-entity to query */ subEntity : SubEntityProps ; /** Callback for result */ onResult : SubEntityParameterRangeFunction ; } interface SubEntityEvaluateRequestProps { /** Sub-entity to query */ subEntity : SubEntityProps ; /** Face or edge u parameter to evaluate */ uParam ? : number ; /** Face v parameter to evaluate */ vParam ? : number ; /** Callback for result */ onResult : SubEntityEvaluateFunction ; } enum QuerySubEntity { /** Return whether the supplied face has a planar surface */ PlanarFace = 0 , /** Return whether the angle between the normals of the supplied edge's faces never exceeds the internal smooth angle tolerance along the length of the edge */ SmoothEdge = 1 , /** Return whether the supplied sub-entity is a laminar edge of a sheet body, i.e. boundary of a single face */ LaminarEdge = 2 , /** Return whether the supplied sub-entity is a linear edge */ LinearEdge = 3 , /** Return whether the angle between the normals of the supplied vertices's edges never exceeds the internal smooth angle tolerance along the length of the edge */ SmoothVertex = 4 , /** Return whether the supplied sub-entity is a redundant edge (containing faces share surface) */ RedundantEdge = 5 } interface QuerySubEntityRequestProps { /** Sub-entity to test */ subEntity : SubEntityProps ; /** What to check */ query : QuerySubEntity ; /** Callback for result */ onResult : YesNoFunction ; } enum QueryBody { /** Return whether the geometric primitive index is a disjoint body */ DisjointBody = 0 , /** Return whether the geometric primitive index is a sheet body with a single planar face */ SingleFacePlanarSheet = 1 , /** Return whether the geometric primitive index is a sheet or solid entity that has all planar faces */ OnlyPlanarFaces = 2 , /** Return whether the geometric primitive index is a body with any edge that is non-linear or any face that is non-planar */ CurvedFaceOrEdge = 3 , /** Return whether the geometric primitive index is a planar sheet or wire body */ PlanarBody = 4 } interface QueryBodyRequestProps { /** Geometric primitive index to test */ index : number ; /** What to check */ query : QueryBody ; /** Callback for result */ onResult : YesNoFunction ; } interface BodySubEntitiesRequestProps { /** What type of sub-entities to return, ex. faces of edge. */ type : SubEntityType ; /** Option to return only first sub-entity of each body instead of all sub-entities. */ firstOnly ? : true ; /** Callback for result */ onResult : SubEntityArrayFunction ; } interface ConnectedSubEntityRequestProps { /** Sub-entity to return connected sub-entities for */ subEntity : SubEntityProps ; /** What type of connected sub-entities to return, ex. faces of edge. */ type : SubEntityType ; /** Options for returning connected edges and adjacent faces. */ options ? : ConnectedSubEntityProps ; /** Callback for result */ onResult : SubEntityArrayFunction ; } interface LocateSubEntityRequestProps { /** Space point for boresite origin */ point : XYZProps ; /** Vector for bosite direction */ direction : XYZProps ; /** The maximum number of faces, edges, and vertices to return */ options : LocateSubEntityProps ; /** Callback for result */ onResult : SubEntityLocationArrayFunction ; } interface LocateFaceRequestProps { /** The face to return the ray intersection for */ subEntity : SubEntityProps ; /** Space point for boresite origin */ point : XYZProps ; /** Vector for bosite direction */ direction : XYZProps ; /** Callback for result */ onResult : SubEntityLocationArrayFunction ; } interface ClosestSubEntityRequestProps { /** Space point */ point : XYZProps ; /** Optional direction for choosing face from edge or vertex hit... */ direction ? : XYZProps ; /** Callback for result */ onResult : SubEntityLocationFunction ; } interface ClosestPointRequestProps { /** Space point */ point : XYZProps ; /** The face or edge sub-entity to return closest point for */ subEntity : SubEntityProps ; /** Callback for result */ onResult : SubEntityLocationFunction ; } interface PointInsideRequestProps { /** Space point */ point : XYZProps ; /** Callback for result */ onResult : PointInsideFunction ; } enum OperationType { GeometrySummary = 0 , SubEntityGeometry = 1 , SubEntityParameterRange = 2 , SubEntityEvaluate = 3 , SubEntityQuery = 4 , BodyQuery = 5 , BodySubEntities = 6 , ConnectedSubEntity = 7 , LocateSubEntity = 8 , LocateFace = 9 , ClosestSubEntity = 10 , ClosestFace = 11 , ClosestPoint = 12 , PointInside = 13 , BooleanOp = 14 , SewSheets = 15 , ThickenSheets = 16 , OffsetFaces = 17 , OffsetEdges = 18 , HollowFaces = 19 , SweepFaces = 20 , SpinFaces = 21 , DeleteSubEntity = 22 , TransformSubEntity = 23 , Blend = 24 , Chamfer = 25 , Cut = 26 , Emboss = 27 , Imprint = 28 , SweepPath = 29 , Loft = 30 } interface ElementGeometryCacheOperationRequestProps { /** Target element id, tool element ids can be supplied by parameters... */ id : Id64String ; /** Requested operation */ op : OperationType ; /** Parameters for operation */ params ? : GeometrySummaryRequestProps | SubEntityGeometryRequestProps | SubEntityParameterRangeRequestProps | SubEntityEvaluateRequestProps | QuerySubEntityRequestProps | QueryBodyRequestProps | BodySubEntitiesRequestProps | ConnectedSubEntityRequestProps | LocateSubEntityRequestProps | LocateFaceRequestProps | ClosestSubEntityRequestProps | ClosestPointRequestProps | PointInsideRequestProps | BooleanOperationProps | SewSheetProps | ThickenSheetProps | CutProps | EmbossProps | ImprintProps | SweepPathProps | LoftProps | OffsetFacesProps | OffsetEdgesProps | HollowFacesProps | SweepFacesProps | SpinFacesProps | DeleteSubEntityProps | TransformSubEntityProps | BlendEdgesProps | ChamferEdgesProps ; /** Callback for result when element's geometry stream is requested in flatbuffer or graphic formats */ onGeometry ? : ElementGeometryFunction ; } alpha export class SolidModelingCommand extends BasicManipulationCommand implements SolidModelingCommandIpc { public static override commandId = editorBuiltInCmdIds . cmdSolidModeling ; private async updateElementGeometryCache ( props ) { return this . iModel . nativeDb . updateElementGeometryCache ( props ) ; } public async createElementGeometryCache ( id , filter ? ) { const result = await this . updateElementGeometryCache ( { id } ) ; if ( BentleyStatus . SUCCESS !== result . status ) return false ; if ( undefined === filter ) return true ; if ( filter . minGeom && ( undefined === result . numGeom || filter . minGeom > result . numGeom ) ) return false ; if ( filter . maxGeom && ( undefined === result . numGeom || filter . maxGeom < result . numGeom ) ) return false ; if ( ! filter . parts && ( result . numPart ?? 0 > 0 ) ) return false ; if ( ! filter . curves && ( result . numCurve ?? 0 > 0 ) ) return false ; if ( ! filter . surfaces && ( result . numSurface ?? 0 > 0 ) ) return false ; if ( ! filter . solids && ( result . numSolid ?? 0 > 0 ) ) return false ; if ( ! filter . other && ( result . numOther ?? 0 > 0 ) ) return false ; return true ; } public async clearElementGeometryCache ( ) { await this . updateElementGeometryCache ( { } ) ; } public async summarizeElementGeometryCache ( id ) { let accepted ; const onResult = ( info ) : void => { accepted = info ; } ; const params = { onResult } ; const props = { id , op : OperationType . GeometrySummary , params } ; this . iModel . nativeDb . elementGeometryCacheOperation ( props ) ; return accepted ; } private requestSubEntityGeometry ( id , subEntity ) { let accepted ; const onResult = ( info ) : void => { accepted = info ; } ; const params = { subEntity , onResult } ; const props = { id , op : OperationType . SubEntityGeometry , params } ; this . iModel . nativeDb . elementGeometryCacheOperation ( props ) ; return accepted ; } public async getSubEntityGeometry ( id , subEntity , opts ) { const geometryProps = this . requestSubEntityGeometry ( id , subEntity ) ; if ( undefined === geometryProps ?. geometry || undefined === geometryProps ?. category ) return undefined ; const resultProps = { } ; if ( opts . wantGeometry ) resultProps . geometry = geometryProps . geometry ; if ( opts . wantRange ) resultProps . range = ( geometryProps ?. range ? ElementGeometry . toElementAlignedBox3d ( geometryProps ?. range ) : undefined ) ; if ( opts . wantAppearance ) { const appearance = { category : geometryProps . category } ; appearance . subCategory = geometryProps . subCategory ; appearance . material = geometryProps . material ; appearance . color = geometryProps . color ; appearance . transparency = geometryProps . transparency ; appearance . weight = geometryProps . weight ; resultProps . appearance = appearance ; } if ( ! opts . wantGraphic ) return resultProps ; const requestId = opts . requestId ? opts . requestId : `SubEntity:${ id }-${ subEntity . id }` ; const toleranceLog10 = ( opts . chordTolerance ? Math . floor ( Math . log10 ( opts . chordTolerance ) ) : - 2 ) ; const requestProps = { id : requestId , modelId : this . iModel . iModelId , toleranceLog10 , type : "3d" , placement : { origin : Point3d . createZero ( ) , angles : YawPitchRollAngles . createDegrees ( 0 , 0 , 0 ) } , categoryId : geometryProps . category , elementId : id , geometry : { format : "flatbuffer" , data : [ geometryProps . geometry ] } } ; resultProps . graphic = await this . iModel . generateElementGraphics ( requestProps ) ; return resultProps ; } public async getSubEntityParameterRange ( id , subEntity ) { let accepted ; const onResult = ( info ) : void => { accepted = info ; } ; const params = { subEntity , onResult } ; const props = { id , op : OperationType . SubEntityParameterRange , params } ; this . iModel . nativeDb . elementGeometryCacheOperation ( props ) ; return accepted ; } public async evaluateSubEntity ( id , subEntity , uParam ? , vParam ? ) { let accepted ; const onResult = ( info ) : void => { accepted = info ; } ; const params = { subEntity , uParam , vParam , onResult } ; const props = { id , op : OperationType . SubEntityEvaluate , params } ; this . iModel . nativeDb . elementGeometryCacheOperation ( props ) ; return accepted ; } private async subEntityQuery ( id , subEntity , query ) { let accepted = false ; const onResult = ( info ) : void => { accepted = info ; } ; const params = { subEntity , query , onResult } ; const props = { id , op : OperationType . SubEntityQuery , params } ; this . iModel . nativeDb . elementGeometryCacheOperation ( props ) ; return accepted ; } public async isPlanarFace ( id , subEntity ) { return this . subEntityQuery ( id , subEntity , QuerySubEntity . PlanarFace ) ; } public async isSmoothEdge ( id , subEntity ) { return this . subEntityQuery ( id , subEntity , QuerySubEntity . SmoothEdge ) ; } public async isLaminarEdge ( id , subEntity ) { return this . subEntityQuery ( id , subEntity , QuerySubEntity . LaminarEdge ) ; } public async isLinearEdge ( id , subEntity ) { return this . subEntityQuery ( id , subEntity , QuerySubEntity . LinearEdge ) ; } public async isRedundantEdge ( id , subEntity ) { return this . subEntityQuery ( id , subEntity , QuerySubEntity . RedundantEdge ) ; } public async isSmoothVertex ( id , subEntity ) { return this . subEntityQuery ( id , subEntity , QuerySubEntity . SmoothVertex ) ; } private async bodyQuery ( id , index , query ) { let accepted = false ; const onResult = ( info ) : void => { accepted = info ; } ; const params = { index , query , onResult } ; const props = { id , op : OperationType . BodyQuery , params } ; this . iModel . nativeDb . elementGeometryCacheOperation ( props ) ; return accepted ; } public async isDisjointBody ( id , index ) { return this . bodyQuery ( id , index , QueryBody . DisjointBody ) ; } public async isPlanarBody ( id , index ) { return this . bodyQuery ( id , index , QueryBody . PlanarBody ) ; } public async isSingleFacePlanarSheet ( id , index ) { return this . bodyQuery ( id , index , QueryBody . SingleFacePlanarSheet ) ; } public async hasOnlyPlanarFaces ( id , index ) { return this . bodyQuery ( id , index , QueryBody . OnlyPlanarFaces ) ; } public async hasCurvedFaceOrEdge ( id , index ) { return this . bodyQuery ( id , index , QueryBody . CurvedFaceOrEdge ) ; } public async getBodySubEntities ( id , type , firstOnly ? ) { let accepted ; const onResult = ( info ) : void => { accepted = info ; } ; const params = { type , firstOnly , onResult } ; const props = { id , op : OperationType . BodySubEntities , params } ; this . iModel . nativeDb . elementGeometryCacheOperation ( props ) ; return accepted ; } public async getConnectedSubEntities ( id , subEntity , type , options ? ) { let accepted ; const onResult = ( info ) : void => { accepted = info ; } ; const params = { subEntity , type , options , onResult } ; const props = { id , op : OperationType . ConnectedSubEntity , params } ; this . iModel . nativeDb . elementGeometryCacheOperation ( props ) ; return accepted ; } public async locateSubEntities ( id , point , direction , options ) { let accepted ; const onResult = ( info ) : void => { accepted = info ; } ; const params = { point , direction , options , onResult } ; const props = { id , op : OperationType . LocateSubEntity , params } ; this . iModel . nativeDb . elementGeometryCacheOperation ( props ) ; return accepted ; } public async locateFace ( id , subEntity , point , direction ) { let accepted ; const onResult = ( info ) : void => { accepted = info ; } ; const params = { subEntity , point , direction , onResult } ; const props = { id , op : OperationType . LocateFace , params } ; this . iModel . nativeDb . elementGeometryCacheOperation ( props ) ; return accepted ; } public async getClosestSubEntity ( id , point ) { let accepted ; const onResult = ( info ) : void => { accepted = info ; } ; const params = { point , onResult } ; const props = { id , op : OperationType . ClosestSubEntity , params } ; this . iModel . nativeDb . elementGeometryCacheOperation ( props ) ; return accepted ; } public async getClosestFace ( id , point , direction ? ) { let accepted ; const onResult = ( info ) : void => { accepted = info ; } ; const params = { point , direction , onResult } ; const props = { id , op : OperationType . ClosestFace , params } ; this . iModel . nativeDb . elementGeometryCacheOperation ( props ) ; return accepted ; } public async getClosestPoint ( id , subEntity , point ) { let accepted ; const onResult = ( info ) : void => { accepted = info ; } ; const params = { subEntity , point , onResult } ; const props = { id , op : OperationType . ClosestPoint , params } ; this . iModel . nativeDb . elementGeometryCacheOperation ( props ) ; return accepted ; } public async isPointInside ( id , point ) { let accepted ; const onResult = ( info ) : void => { accepted = info ; } ; const params = { point , onResult } ; const props = { id , op : OperationType . PointInside , params } ; this . iModel . nativeDb . elementGeometryCacheOperation ( props ) ; return accepted ; } private async getElementGeometryResults ( id , info , opts , tools ? ) { if ( 0 === info . entryArray . length || undefined === info . categoryId || undefined === info . bbox ) return undefined ; const resultProps = { } ; if ( opts . wantGeometry ) resultProps . geometry = info ; if ( opts . wantRange ) resultProps . range = ElementGeometry . toElementAlignedBox3d ( info . bbox ) ; if ( opts . wantAppearance ) resultProps . categoryId = info . categoryId ; if ( ! ( opts . wantGraphic || opts . writeChanges ) ) return resultProps ; let placement ; const sourceToWorld = ( undefined === info ?. sourceToWorld ? undefined : ElementGeometry . toTransform ( info . sourceToWorld ) ) ; if ( undefined === sourceToWorld ) { placement = { origin : Point3d . createZero ( ) , angles : YawPitchRollAngles . createDegrees ( 0 , 0 , 0 ) } ; } else { const origin = sourceToWorld . getOrigin ( ) ; const angles = new YawPitchRollAngles ( ) ; YawPitchRollAngles . createFromMatrix3d ( sourceToWorld . matrix , angles ) ; placement = { origin , angles } ; } if ( opts . writeChanges ) { if ( undefined !== tools ) { if ( opts . insertProps ) { await this . iModel . locks . acquireLocks ( { shared : opts . insertProps . model , exclusive : tools } ) ; } else { await this . iModel . locks . acquireLocks ( { exclusive : [ id , ... tools ] } ) ; } } if ( opts . insertProps ) { opts . insertProps . placement = placement ; delete opts . insertProps . geom ; resultProps . elementId = await this . insertGeometricElement ( opts . insertProps , { entryArray : info . entryArray } ) ; } else { const updateProps = this . iModel . elements . getElementProps < GeometricElementProps > ( { id } ) ; updateProps . category = info . categoryId ; updateProps . placement = placement ; await this . updateGeometricElement ( updateProps , { entryArray : info . entryArray } ) ; resultProps . elementId = id ; } if ( undefined !== tools ) { for ( const toolId of Id64 . iterable ( tools ) ) this . iModel . elements . deleteElement ( toolId ) ; } } if ( ! opts . wantGraphic ) return resultProps ; const requestId = opts . requestId ? opts . requestId : `EGCacheOp:${ id }` ; const toleranceLog10 = ( opts . chordTolerance ? Math . floor ( Math . log10 ( opts . chordTolerance ) ) : - 2 ) ; const requestProps = { id : requestId , modelId : this . iModel . iModelId , toleranceLog10 , type : "3d" , placement , categoryId : info . categoryId , elementId : id , geometry : { format : "flatbuffer" , data : info . entryArray } } ; resultProps . graphic = await this . iModel . generateElementGraphics ( requestProps ) ; return resultProps ; } private async doElementGeometryOperation ( props , opts , tools ? ) { let accepted ; const onGeometry = ( info ) : void => { accepted = info ; } ; props . onGeometry = onGeometry ; this . iModel . nativeDb . elementGeometryCacheOperation ( props ) ; if ( undefined === accepted ) return undefined ; return this . getElementGeometryResults ( props . id , accepted , opts , tools ) ; } public async booleanOperation ( id , params , opts ) { const props = { id , op : OperationType . BooleanOp , params } ; return this . doElementGeometryOperation ( props , opts , undefined === opts . insertProps ? params . tools : undefined ) ; } public async sewSheets ( id , params , opts ) { const props = { id , op : OperationType . SewSheets , params } ; return this . doElementGeometryOperation ( props , opts , undefined === opts . insertProps ? params . tools : undefined ) ; } public async thickenSheets ( id , params , opts ) { const props = { id , op : OperationType . ThickenSheets , params } ; return this . doElementGeometryOperation ( props , opts ) ; } public async cutSolid ( id , params , opts ) { const props = { id , op : OperationType . Cut , params } ; return this . doElementGeometryOperation ( props , opts , ! params . keepProfile ? params . profile : undefined ) ; } public async embossBody ( id , params , opts ) { const props = { id , op : OperationType . Emboss , params } ; return this . doElementGeometryOperation ( props , opts , ! params . keepProfile ? params . profile : undefined ) ; } public async imprintBody ( id , params , opts ) { const props = { id , op : OperationType . Imprint , params } ; return this . doElementGeometryOperation ( props , opts , ! params . keepProfile && "string" === typeof ( params . imprint ) ? params . imprint : undefined ) ; } public async sweepAlongPath ( id , params , opts ) { const props = { id , op : OperationType . SweepPath , params } ; return this . doElementGeometryOperation ( props , opts , ! params . keepPath ? params . path : undefined ) ; } public async loftProfiles ( id , params , opts ) { const toolIds = ( opts . writeChanges && ( ! params . keepTools || ! params . keepGuides ) ) ? new Set < Id64String > ( ) : undefined ; if ( undefined !== toolIds ) { if ( ! params . keepTools ) { for ( const toolId of Id64 . iterable ( params . tools ) ) toolIds . add ( toolId ) ; } if ( undefined !== params . guides && ! params . keepGuides ) { for ( const guideId of Id64 . iterable ( params . guides ) ) toolIds . add ( guideId ) ; } } const props = { id , op : OperationType . Loft , params } ; return this . doElementGeometryOperation ( props , opts , toolIds ) ; } public async offsetFaces ( id , params , opts ) { const props = { id , op : OperationType . OffsetFaces , params } ; return this . doElementGeometryOperation ( props , opts ) ; } public async offsetEdges ( id , params , opts ) { const props = { id , op : OperationType . OffsetEdges , params } ; return this . doElementGeometryOperation ( props , opts ) ; } public async hollowFaces ( id , params , opts ) { const props = { id , op : OperationType . HollowFaces , params } ; return this . doElementGeometryOperation ( props , opts ) ; } public async sweepFaces ( id , params , opts ) { const props = { id , op : OperationType . SweepFaces , params } ; return this . doElementGeometryOperation ( props , opts ) ; } public async spinFaces ( id , params , opts ) { const props = { id , op : OperationType . SpinFaces , params } ; return this . doElementGeometryOperation ( props , opts ) ; } public async deleteSubEntities ( id , params , opts ) { const props = { id , op : OperationType . DeleteSubEntity , params } ; return this . doElementGeometryOperation ( props , opts ) ; } public async transformSubEntities ( id , params , opts ) { const props = { id , op : OperationType . TransformSubEntity , params } ; return this . doElementGeometryOperation ( props , opts ) ; } public async blendEdges ( id , params , opts ) { const props = { id , op : OperationType . Blend , params } ; return this . doElementGeometryOperation ( props , opts ) ; } public async chamferEdges ( id , params , opts ) { const props = { id , op : OperationType . Chamfer , params } ; return this . doElementGeometryOperation ( props , opts ) ; } }