IFCLoader.js 92 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719
  1. /**
  2. * IfcLoader.js
  3. *
  4. * @author realor
  5. */
  6. import { IFC } from './IFC.js'
  7. import { IFCFile } from './IFCFile.js'
  8. import { Cord } from '../../core/Cord.js'
  9. import { CordGeometry } from '../../core/CordGeometry.js'
  10. import { Profile } from '../../core/Profile.js'
  11. import { ProfileGeometry } from '../../core/ProfileGeometry.js'
  12. import { Solid } from '../../core/Solid.js'
  13. import { SolidGeometry } from '../../core/SolidGeometry.js'
  14. import { ObjectBuilder } from '../../builders/ObjectBuilder.js'
  15. import { Cloner } from '../../builders/Cloner.js'
  16. import { Extruder } from '../../builders/Extruder.js'
  17. import { Revolver } from '../../builders/Revolver.js'
  18. import { BooleanOperator } from '../../builders/BooleanOperator.js'
  19. import { RectangleBuilder } from '../../builders/RectangleBuilder.js'
  20. import { RectangleHollowBuilder } from '../../builders/RectangleHollowBuilder.js'
  21. import { CircleBuilder } from '../../builders/CircleBuilder.js'
  22. import { CircleHollowBuilder } from '../../builders/CircleHollowBuilder.js'
  23. import { EllipseBuilder } from '../../builders/EllipseBuilder.js'
  24. import { IProfileBuilder } from '../../builders/IProfileBuilder.js'
  25. import { LProfileBuilder } from '../../builders/LProfileBuilder.js'
  26. import { TProfileBuilder } from '../../builders/TProfileBuilder.js'
  27. import { UProfileBuilder } from '../../builders/UProfileBuilder.js'
  28. import { ZProfileBuilder } from '../../builders/ZProfileBuilder.js'
  29. import { TrapeziumBuilder } from '../../builders/TrapeziumBuilder.js'
  30. import { IFCVoider } from '../../builders/IFCVoider.js'
  31. import { GeometryUtils } from '../../utils/GeometryUtils.js'
  32. import { WebUtils } from '../../utils/WebUtils.js'
  33. import { ObjectUtils } from '../../utils/ObjectUtils.js'
  34. import { registerIfcHelperClass } from './BaseEntity.js'
  35. import * as THREE from '../../lib/three.module.js'
  36. class IFCLoader extends THREE.Loader {
  37. static options = {
  38. units: 'm', // default model units
  39. minCircleSegments: 16, // minimum circle segments
  40. circleSegmentsByRadius: 64, // circle segments by meter of radius
  41. halfSpaceSize: 30 // half space size in meters
  42. }
  43. constructor(manager) {
  44. super(manager)
  45. }
  46. load(url, onLoad, onProgress, onError, options) {
  47. const fileLoader = new THREE.FileLoader(this.manager)
  48. fileLoader.load(url, text => this.parse(text, onLoad, onProgress, onError, options), onProgress, onError)
  49. }
  50. parse(text, onCompleted, onProgress, onError, options) {
  51. this.options = Object.assign({}, IFCLoader.options, options)
  52. let ifcFile = new IFCFile()
  53. console.info('parsing file...')
  54. this.parseFile(ifcFile, text)
  55. console.info(ifcFile)
  56. return this.buildModel(ifcFile, onCompleted, onProgress, onError)
  57. }
  58. parseFile(ifcFile, text) {
  59. throw 'Not implemented'
  60. }
  61. buildModel(ifcFile, onCompleted, onProgress, onError) {
  62. const model = new THREE.Group()
  63. const types = new THREE.Group()
  64. types.name = 'Types'
  65. types.visible = false
  66. types.userData.selection = { type: 'none' }
  67. model.add(types)
  68. this.modelFactor = 1.0
  69. this.blockCount = 0
  70. this.blocks = new Set()
  71. const schema = ifcFile.schema
  72. /* process project info */
  73. const processProjectInfo = () => {
  74. if (ifcFile.entities.IfcProject) {
  75. let project = ifcFile.entities.IfcProject[0]
  76. model.name = project.Name || project.LongName || 'IFC'
  77. model._ifc = project
  78. model.userData.IFC = {
  79. ifcClassName: 'IfcProject',
  80. GlobalId: project.GlobalId,
  81. Name: this.unBox(project.Name),
  82. Description: this.unBox(project.Description)
  83. }
  84. let contextUnits = project.UnitsInContext
  85. if (contextUnits) {
  86. let units = contextUnits.Units
  87. if (units) {
  88. for (let u = 0; u < units.length; u++) {
  89. let unit = units[u]
  90. if (unit instanceof schema.IfcSIUnit && unit.UnitType === '.LENGTHUNIT.') {
  91. // unit name = METRE
  92. let factor = 1
  93. if (unit.Prefix) {
  94. let prefix = IFC.UNIT_PREFIXES[unit.Prefix]
  95. if (prefix) {
  96. // set factor respect metre unit
  97. factor = prefix.factor
  98. model.userData.units = prefix.symbol + 'm'
  99. }
  100. } else {
  101. // meters
  102. model.userData.units = 'm'
  103. }
  104. project._loader.modelFactor = factor
  105. }
  106. }
  107. }
  108. }
  109. }
  110. }
  111. /* applyStyles */
  112. const applyStyles = () => {
  113. let styledItems = ifcFile.entities.IfcStyledItem
  114. if (styledItems) {
  115. for (let i = 0; i < styledItems.length; i++) {
  116. let styledItem = styledItems[i]
  117. styledItem.helper.applyStyle()
  118. }
  119. }
  120. }
  121. /* create objects */
  122. const createObject = index => {
  123. let product = ifcFile.products[index]
  124. let object3D = product.helper.getObject3D()
  125. if (product.ObjectPlacement instanceof schema.IfcLocalPlacement) {
  126. let matrixWorld = product.ObjectPlacement.helper.getMatrixWorld()
  127. matrixWorld.decompose(object3D.position, object3D.quaternion, object3D.scale)
  128. object3D.matrix.copy(matrixWorld)
  129. object3D.matrixWorldNeedsUpdate = true
  130. model.add(object3D)
  131. } else {
  132. model.add(object3D)
  133. }
  134. }
  135. const createObjects = () => {
  136. let products = ifcFile.products
  137. for (let i = 0; i < products.length; i++) {
  138. createObject(i)
  139. }
  140. }
  141. /* process relationships */
  142. const processRelationships = () => {
  143. let relationships = ifcFile.relationships
  144. for (let relationship of relationships) {
  145. relationship.helper.relate()
  146. }
  147. model.updateMatrixWorld()
  148. }
  149. /* process layer assigments */
  150. const processLayerAssignments = () => {
  151. let assignments = ifcFile.entities.IfcPresentationLayerAssignment
  152. if (assignments) {
  153. for (let assignment of assignments) {
  154. assignment.helper.assign()
  155. }
  156. }
  157. model.updateMatrixWorld()
  158. }
  159. /* voiding objects */
  160. const voidObject = index => {
  161. let product = ifcFile.products[index]
  162. let productObject3D = product.helper.getObject3D()
  163. if (productObject3D) {
  164. let productRepr = productObject3D.getObjectByName(IFC.RepresentationName)
  165. if (productRepr && productRepr.builder instanceof IFCVoider) {
  166. ObjectBuilder.build(productRepr)
  167. }
  168. }
  169. }
  170. const voidObjects = () => {
  171. let products = ifcFile.products
  172. for (let i = 0; i < products.length; i++) {
  173. voidObject(i)
  174. }
  175. }
  176. const processTypeProducts = () => {
  177. let typeProducts = ifcFile.typeProducts
  178. for (let typeProduct of typeProducts) {
  179. if (typeProduct.RepresentationMaps && typeProduct.RepresentationMaps.length > 0) {
  180. const reprMap = typeProduct.RepresentationMaps[0]
  181. const mappedObject3D = reprMap.helper.getObject3D()
  182. if (mappedObject3D && mappedObject3D.parent === null) {
  183. let typeName = typeProduct.Name || typeProduct.GlobalId
  184. if (typeName.startsWith(THREE.Object3D.HIDDEN_PREFIX)) {
  185. typeName = typeName.substring(1)
  186. }
  187. let typeGroup = new THREE.Group()
  188. typeGroup.name = typeName
  189. typeGroup._ifc = typeProduct
  190. typeGroup.add(mappedObject3D)
  191. typeGroup.userData.IFC = {
  192. ifcClassName: typeProduct.constructor.name,
  193. GlobalId: typeProduct.GlobalId,
  194. Name: this.unBox(typeProduct.Name)
  195. }
  196. types.add(typeGroup)
  197. this.blocks.delete(mappedObject3D)
  198. }
  199. }
  200. }
  201. // rest of blocks
  202. for (let mappedObject3D of this.blocks) {
  203. types.add(mappedObject3D)
  204. }
  205. }
  206. /* setup objects */
  207. const setupObjects = () => {
  208. model.traverse(object => {
  209. if (object.userData.IFC) {
  210. var ifcClassName = object.userData.IFC.ifcClassName
  211. if (ifcClassName === 'IfcOpeningElement' || ifcClassName === 'IfcSpace') {
  212. object = object.getObjectByName(IFC.RepresentationName)
  213. if (object) {
  214. ObjectUtils.updateStyle(object, false, false)
  215. }
  216. } else if (ifcClassName === 'IfcSite' || ifcClassName === 'IfcBuilding' || ifcClassName === 'IfcBuildingStorey') {
  217. object.userData.selection.type = 'box'
  218. } else if (ifcClassName === 'IfcDoor') {
  219. object.userData.collision = { enabled: false }
  220. }
  221. }
  222. })
  223. if (types.children.length > 0) {
  224. ObjectUtils.updateVisibility(types, false)
  225. }
  226. }
  227. const paintObject = (object, material) => {
  228. object.traverse(function(object) {
  229. if (object instanceof Solid) {
  230. if (object.material === Solid.FaceMaterial) {
  231. object.material = material
  232. }
  233. }
  234. })
  235. }
  236. const setCastShadowForObject = object => {
  237. object.traverse(function(object) {
  238. if (object instanceof Solid) {
  239. if (object.material.transparent) {
  240. object.castShadow = false
  241. }
  242. }
  243. })
  244. }
  245. const paintObjects = () => {
  246. let products = ifcFile.products
  247. for (let i = 0; i < products.length; i++) {
  248. let product = products[i]
  249. let object3D = product.helper.getObject3D()
  250. if (object3D && object3D.userData && object3D.userData.IFC) {
  251. let reprObject3D = object3D.getObjectByName(IFC.RepresentationName)
  252. if (reprObject3D) {
  253. let ifcClassName = object3D.userData.IFC.ifcClassName
  254. let material = IFCLoader.MATERIALS[ifcClassName]
  255. if (material) {
  256. paintObject(reprObject3D, material)
  257. }
  258. setCastShadowForObject(reprObject3D)
  259. }
  260. }
  261. }
  262. }
  263. // group objects
  264. const groupObjects = () => {
  265. const groupObject = object => {
  266. let groups = {}
  267. let children = object.children.slice(0) // clone children
  268. for (let child of children) {
  269. let ifc = child.userData.IFC
  270. if (ifc) {
  271. let group = groups[ifc.ifcClassName]
  272. if (group === undefined) {
  273. group = new THREE.Group()
  274. group.name = ifc.ifcClassName
  275. groups[ifc.ifcClassName] = group
  276. }
  277. group.add(child)
  278. }
  279. }
  280. let typeNames = Object.getOwnPropertyNames(groups)
  281. typeNames = typeNames.sort()
  282. for (let typeName of typeNames) {
  283. let group = groups[typeName]
  284. object.add(group)
  285. }
  286. }
  287. // group types
  288. groupObject(types)
  289. // group storeys
  290. let storeys = ifcFile.entities.IfcBuildingStorey
  291. if (storeys) {
  292. for (let i = 0; i < storeys.length; i++) {
  293. let storey = storeys[i]
  294. let storeyObject3D = storey.helper.getObject3D()
  295. if (storeyObject3D) {
  296. groupObject(storeyObject3D)
  297. }
  298. }
  299. }
  300. }
  301. if (onCompleted) {
  302. // asynchronous operation
  303. const getIterations = function() {
  304. return ifcFile.products.length
  305. }
  306. WebUtils.executeTasks(
  307. [
  308. { run: processProjectInfo, message: 'Processing project info...' },
  309. { run: applyStyles, message: 'Applying styles...' },
  310. { run: createObject, message: 'Creating objects...', iterations: getIterations },
  311. { run: processRelationships, message: 'Processing relationships...' },
  312. { run: processLayerAssignments, message: 'Processing layers...' },
  313. { run: voidObject, message: 'Voiding objects...', iterations: getIterations },
  314. { run: processTypeProducts, message: 'Processing types...' },
  315. { run: setupObjects, message: 'Setting object properties...' },
  316. { run: paintObjects, message: 'Painting objects...' },
  317. { run: groupObjects, message: 'Grouping objects...' }
  318. ],
  319. () => onCompleted(model),
  320. onProgress,
  321. error => onError(error),
  322. 100,
  323. 10
  324. )
  325. } else {
  326. // synchronous operation
  327. processProjectInfo()
  328. applyStyles()
  329. createObjects()
  330. processRelationships()
  331. processLayerAssignments()
  332. voidObjects()
  333. processTypeProducts()
  334. setupObjects()
  335. paintObjects()
  336. groupObjects()
  337. }
  338. return model
  339. }
  340. unBox(value) {
  341. return value && value.Value !== undefined ? value.Value : value
  342. }
  343. getCircleSegments(radius) {
  344. let meterRadius = radius * this.modelFactor
  345. let segments = Math.max(this.options.minCircleSegments, Math.ceil(this.options.circleSegmentsByRadius * meterRadius))
  346. if (segments % 2 === 1) segments++
  347. return segments
  348. }
  349. cloneObject3D(object, full = false) {
  350. // clone preserving _ifc property
  351. let clonedObject = object.clone(false)
  352. clonedObject._ifc = object._ifc
  353. if (full) {
  354. const start = object instanceof Solid ? 2 : 0
  355. for (let i = start; i < object.children.length; i++) {
  356. let child = object.children[i]
  357. clonedObject.add(this.cloneObject3D(child, full))
  358. }
  359. }
  360. return clonedObject
  361. }
  362. /* default materials */
  363. static MATERIALS = {
  364. IfcWall: new THREE.MeshPhongMaterial({
  365. name: 'Wall',
  366. color: 0xc0c080,
  367. shininess: 1,
  368. flatShading: false,
  369. side: THREE.DoubleSide,
  370. polygonOffset: true,
  371. polygonOffsetFactor: 1.0,
  372. polygonOffsetUnits: 0.5
  373. }),
  374. IfcWallStandardCase: new THREE.MeshPhongMaterial({
  375. name: 'Wall',
  376. color: 0xc0c080,
  377. shininess: 1,
  378. flatShading: false,
  379. side: THREE.DoubleSide,
  380. polygonOffset: true,
  381. polygonOffsetFactor: 1.0,
  382. polygonOffsetUnits: 0.5
  383. }),
  384. IfcSlab: new THREE.MeshPhongMaterial({
  385. name: 'Slab',
  386. color: 0xc0c0c0,
  387. shininess: 1,
  388. flatShading: false,
  389. side: THREE.DoubleSide,
  390. polygonOffset: true,
  391. polygonOffsetFactor: 1.0,
  392. polygonOffsetUnits: 0.5
  393. }),
  394. IfcRailing: new THREE.MeshPhongMaterial({
  395. name: 'Railing',
  396. flatShading: false,
  397. color: 0x606060,
  398. shininess: 1,
  399. side: THREE.DoubleSide
  400. }),
  401. IfcWindow: new THREE.MeshPhongMaterial({
  402. name: 'Window',
  403. flatShading: false,
  404. color: 0x8080ff,
  405. opacity: 0.3,
  406. transparent: true,
  407. side: THREE.DoubleSide
  408. }),
  409. IfcDoor: new THREE.MeshPhongMaterial({
  410. name: 'Door',
  411. flatShading: false,
  412. color: 0xc0c040,
  413. side: THREE.DoubleSide
  414. }),
  415. IfcCovering: new THREE.MeshPhongMaterial({
  416. name: 'Covering',
  417. flatShading: false,
  418. color: 0xc0c0c0,
  419. side: THREE.FrontSide
  420. }),
  421. IfcBeam: new THREE.MeshPhongMaterial({
  422. name: 'Beam',
  423. flatShading: false,
  424. color: 0x606070,
  425. side: THREE.FrontSide
  426. }),
  427. IfcColumn: new THREE.MeshPhongMaterial({
  428. name: 'Column',
  429. flatShading: false,
  430. color: 0x808080,
  431. side: THREE.FrontSide
  432. }),
  433. IfcOpeningElement: new THREE.MeshPhongMaterial({
  434. name: 'Opening',
  435. flatShading: false,
  436. color: 0x8080ff,
  437. opacity: 0.2,
  438. transparent: true,
  439. side: THREE.DoubleSide
  440. }),
  441. IfcSpace: new THREE.MeshPhongMaterial({
  442. name: 'Space',
  443. flatShading: false,
  444. color: 0xc0c0f0,
  445. opacity: 0.2,
  446. transparent: true,
  447. side: THREE.DoubleSide
  448. }),
  449. IfcFlowTerminal: new THREE.MeshPhongMaterial({
  450. name: 'FlowTerminal',
  451. flatShading: false,
  452. color: 0xffffff,
  453. side: THREE.DoubleSide
  454. }),
  455. IfcFurnishingElement: new THREE.MeshPhongMaterial({
  456. name: 'FurnishingElement',
  457. flatShading: false,
  458. color: 0xdeb887,
  459. side: THREE.DoubleSide
  460. }),
  461. IfcStair: new THREE.MeshPhongMaterial({
  462. name: 'FurnishingElement',
  463. flatShading: false,
  464. color: 0xa0522d,
  465. side: THREE.DoubleSide
  466. }),
  467. IfcStairFlight: new THREE.MeshPhongMaterial({
  468. name: 'FurnishingElement',
  469. flatShading: false,
  470. color: 0xa0522d,
  471. side: THREE.DoubleSide
  472. })
  473. }
  474. }
  475. /* helper classes*/
  476. class IfcHelper {
  477. constructor(instance) {
  478. this.instance = instance
  479. }
  480. }
  481. registerIfcHelperClass(IfcHelper)
  482. class IfcProductHelper extends IfcHelper {
  483. constructor(instance) {
  484. super(instance)
  485. this.object3D = null
  486. }
  487. getObject3D() {
  488. if (this.object3D === null) {
  489. const product = this.instance
  490. const schema = this.instance.constructor.schema
  491. const loader = product._loader
  492. var object3D = new THREE.Object3D()
  493. object3D.userData.selection = { group: true }
  494. let name = product.Name ? product.Name : product.constructor.name
  495. if (name.length >= 2 && name[0] === THREE.Object3D.HIDDEN_PREFIX) {
  496. name = name.substring(1)
  497. }
  498. object3D.name = name
  499. object3D.userData.IFC = {
  500. ifcClassName: product.constructor.name,
  501. GlobalId: product.GlobalId,
  502. Name: loader.unBox(product.Name),
  503. Description: loader.unBox(product.Description)
  504. }
  505. object3D._ifc = product
  506. let objectPlacement = product.ObjectPlacement
  507. if (objectPlacement instanceof schema.IfcLocalPlacement) {
  508. let matrix = objectPlacement.helper.getMatrix()
  509. matrix.decompose(object3D.position, object3D.quaternion, object3D.scale)
  510. object3D.matrix.copy(matrix)
  511. object3D.matrixWorldNeedsUpdate = true
  512. }
  513. let productRepr = product.Representation
  514. if (productRepr instanceof schema.IfcProductRepresentation) {
  515. let reprObject3D = productRepr.helper.getObject3D('Body')
  516. if (reprObject3D) {
  517. if (reprObject3D.parent) {
  518. reprObject3D = loader.cloneObject3D(reprObject3D, true)
  519. }
  520. reprObject3D.name = IFC.RepresentationName
  521. let ifcClassName = null
  522. if (reprObject3D.userData.IFC) {
  523. ifcClassName = reprObject3D.userData.IFC.ifcClassName
  524. }
  525. if (
  526. product instanceof schema.IfcElement &&
  527. !(product instanceof schema.IfcOpeningElement) &&
  528. (ifcClassName === 'IfcExtrudedAreaSolid' || ifcClassName === 'IfcBooleanResult' || ifcClassName === 'IfcBooleanClippingResult')
  529. ) {
  530. // set IFCVoider representation
  531. if (reprObject3D instanceof Solid) {
  532. let voider = new Solid()
  533. voider.name = IFC.RepresentationName
  534. voider.material = reprObject3D.material
  535. voider.userData = reprObject3D.userData
  536. voider.position.copy(reprObject3D.position)
  537. voider.rotation.copy(reprObject3D.rotation)
  538. voider.scale.copy(reprObject3D.scale)
  539. voider.updateMatrix()
  540. voider.builder = new IFCVoider()
  541. voider.add(reprObject3D)
  542. reprObject3D.name = 'Unvoided'
  543. reprObject3D.visible = false
  544. reprObject3D.facesVisible = false
  545. reprObject3D.edgesVisible = false
  546. reprObject3D.position.set(0, 0, 0)
  547. reprObject3D.rotation.set(0, 0, 0)
  548. reprObject3D.scale.set(1, 1, 1)
  549. reprObject3D.updateMatrix()
  550. object3D.add(voider)
  551. } else if (reprObject3D instanceof THREE.Group) {
  552. reprObject3D.builder = new IFCVoider()
  553. object3D.add(reprObject3D)
  554. } else throw 'Unexpected representacion object'
  555. } else {
  556. object3D.add(reprObject3D)
  557. }
  558. }
  559. }
  560. this.object3D = object3D
  561. }
  562. return this.object3D
  563. }
  564. }
  565. registerIfcHelperClass(IfcProductHelper)
  566. class IfcProductRepresentationHelper extends IfcHelper {
  567. constructor(instance) {
  568. super(instance)
  569. }
  570. getObject3D(representationIdentifier) {
  571. var reprObject3D = null
  572. var productRepr = this.instance
  573. var repCount = productRepr.Representations.length
  574. for (var i = 0; i < repCount; i++) {
  575. var repr = productRepr.Representations[i] // IfcRepresentation
  576. if (repr.RepresentationIdentifier === representationIdentifier) {
  577. reprObject3D = repr.helper.getObject3D()
  578. if (reprObject3D === null) {
  579. console.warn('Unsupported representation', representationIdentifier, repr)
  580. }
  581. break
  582. }
  583. }
  584. return reprObject3D
  585. }
  586. }
  587. registerIfcHelperClass(IfcProductRepresentationHelper)
  588. class IfcRepresentationHelper extends IfcHelper {
  589. constructor(instance) {
  590. super(instance)
  591. this.object3D = null
  592. }
  593. getObject3D() {
  594. if (this.object3D === null) {
  595. var representation = this.instance
  596. var group = new THREE.Group()
  597. for (var i = 0; i < representation.Items.length; i++) {
  598. var item = representation.Items[i]
  599. if (item && item.helper.getObject3D) {
  600. var itemObject3D = item.helper.getObject3D()
  601. if (itemObject3D) {
  602. itemObject3D.name = 'Item' + i
  603. itemObject3D.userData.IFC = { ifcClassName: item.constructor.name }
  604. group.add(itemObject3D)
  605. if (itemObject3D instanceof Solid && item.helper.material) {
  606. itemObject3D.material = item.helper.material
  607. }
  608. }
  609. }
  610. }
  611. if (group.children.length === 1) {
  612. this.object3D = group.children[0]
  613. group.remove(this.object3D)
  614. } else {
  615. this.object3D = group
  616. }
  617. this.object3D._ifc = representation
  618. }
  619. return this.object3D
  620. }
  621. }
  622. registerIfcHelperClass(IfcRepresentationHelper)
  623. /* Geometric representation item helpers */
  624. class IfcGeometricRepresentationItemHelper extends IfcHelper {
  625. constructor(instance) {
  626. super(instance)
  627. this.object3D = null
  628. }
  629. getObject3D() {
  630. let ifcClassName = this.instance.constructor.name
  631. console.warn('Unsupported item: ' + ifcClassName, this)
  632. return null
  633. }
  634. }
  635. registerIfcHelperClass(IfcGeometricRepresentationItemHelper)
  636. class IfcHalfSpaceSolidHelper extends IfcGeometricRepresentationItemHelper {
  637. constructor(instance) {
  638. super(instance)
  639. }
  640. getObject3D() {
  641. if (this.object3D === null) {
  642. const halfSpace = this.instance
  643. const size = halfSpace._loader.options.halfSpaceSize / halfSpace._loader.modelFactor
  644. const surface = halfSpace.BaseSurface
  645. const flag = halfSpace.AgreementFlag === '.T.'
  646. const plane = surface.Position
  647. const geometry = new SolidGeometry()
  648. let vertices = geometry.vertices
  649. vertices.push(new THREE.Vector3(-size, -size, 0))
  650. vertices.push(new THREE.Vector3(size, -size, 0))
  651. vertices.push(new THREE.Vector3(size, size, 0))
  652. vertices.push(new THREE.Vector3(-size, size, 0))
  653. vertices.push(new THREE.Vector3(-size, -size, size))
  654. vertices.push(new THREE.Vector3(size, -size, size))
  655. vertices.push(new THREE.Vector3(size, size, size))
  656. vertices.push(new THREE.Vector3(-size, size, size))
  657. geometry.addFace(3, 2, 1, 0)
  658. geometry.addFace(4, 5, 6, 7)
  659. geometry.addFace(0, 1, 5, 4)
  660. geometry.addFace(1, 2, 6, 5)
  661. geometry.addFace(2, 3, 7, 6)
  662. geometry.addFace(3, 0, 4, 7)
  663. var matrix = plane.helper.getMatrix()
  664. if (flag) {
  665. matrix = matrix.clone()
  666. var rotMatrix = new THREE.Matrix4()
  667. rotMatrix.makeRotationX(Math.PI)
  668. matrix.multiply(rotMatrix)
  669. }
  670. geometry.applyMatrix4(matrix)
  671. const planeSolid = new Solid(geometry)
  672. planeSolid.name = 'halfSpace'
  673. this.object3D = planeSolid
  674. this.object3D._ifc = halfSpace
  675. }
  676. return this.object3D
  677. }
  678. }
  679. registerIfcHelperClass(IfcHalfSpaceSolidHelper)
  680. class IfcPolygonalBoundedHalfSpaceHelper extends IfcGeometricRepresentationItemHelper {
  681. constructor(instance) {
  682. super(instance)
  683. }
  684. getObject3D() {
  685. if (this.object3D === null) {
  686. const halfSpace = this.instance
  687. const schema = this.instance.constructor.schema
  688. const surface = halfSpace.BaseSurface
  689. const base = halfSpace.Position
  690. const flag = halfSpace.AgreementFlag === '.T.'
  691. const boundary = halfSpace.PolygonalBoundary
  692. if (surface instanceof schema.IfcPlane) {
  693. try {
  694. const size = halfSpace._loader.options.halfSpaceSize / halfSpace._loader.modelFactor
  695. const extruder = new Extruder(size)
  696. // polygon solid
  697. const curvePoints = boundary.helper.getPoints()
  698. let shape = new THREE.Shape()
  699. shape.moveTo(curvePoints[0].x, curvePoints[0].y)
  700. for (let i = 1; i < curvePoints.length; i++) {
  701. shape.lineTo(curvePoints[i].x, curvePoints[i].y)
  702. }
  703. shape.closePath()
  704. const polygonProfile = new Profile(new ProfileGeometry(shape))
  705. polygonProfile.name = 'polygon'
  706. polygonProfile.visible = false
  707. polygonProfile._ifc = boundary
  708. const polygonSolid = new Solid()
  709. polygonSolid.add(polygonProfile)
  710. polygonSolid.builder = extruder
  711. let matrix = base.helper.getMatrix()
  712. matrix.decompose(polygonSolid.position, polygonSolid.rotation, polygonSolid.scale)
  713. polygonSolid.updateMatrix()
  714. // plane solid
  715. const plane = surface.Position
  716. shape = new THREE.Shape()
  717. shape.moveTo(-size, -size)
  718. shape.lineTo(size, -size)
  719. shape.lineTo(size, size)
  720. shape.lineTo(-size, size)
  721. shape.closePath()
  722. let planeProfile = new Profile(new ProfileGeometry(shape))
  723. planeProfile.name = 'plane'
  724. planeProfile.visible = false
  725. let planeSolid = new Solid()
  726. planeSolid.add(planeProfile)
  727. planeSolid.builder = extruder
  728. matrix = plane.helper.getMatrix()
  729. if (!flag) {
  730. matrix = matrix.clone()
  731. let rotMatrix = new THREE.Matrix4()
  732. rotMatrix.makeRotationX(Math.PI)
  733. matrix.multiply(rotMatrix)
  734. }
  735. matrix.decompose(planeSolid.position, planeSolid.rotation, planeSolid.scale)
  736. planeSolid.updateMatrix()
  737. let halfSpaceSolid = new Solid()
  738. halfSpaceSolid.name = 'polygonalHalfSpace'
  739. halfSpaceSolid.add(polygonSolid)
  740. halfSpaceSolid.add(planeSolid)
  741. halfSpaceSolid.builder = new BooleanOperator(BooleanOperator.SUBTRACT)
  742. ObjectBuilder.build(halfSpaceSolid)
  743. this.object3D = halfSpaceSolid
  744. this.object3D._ifc = halfSpace
  745. } catch (ex) {
  746. console.warn(ex)
  747. }
  748. }
  749. }
  750. return this.object3D
  751. }
  752. }
  753. registerIfcHelperClass(IfcPolygonalBoundedHalfSpaceHelper)
  754. class IfcBooleanResultHelper extends IfcGeometricRepresentationItemHelper {
  755. constructor(instance) {
  756. super(instance)
  757. }
  758. getObject3D() {
  759. if (this.object3D === null) {
  760. var result = this.instance
  761. var operator = result.Operator
  762. var firstOperand = result.FirstOperand
  763. var secondOperand = result.SecondOperand
  764. var firstObject = firstOperand.helper.getObject3D()
  765. var secondObject = secondOperand.helper.getObject3D()
  766. if (firstObject instanceof Solid && firstOperand.helper.material) {
  767. firstObject.material = firstOperand.helper.material
  768. }
  769. if (firstObject instanceof Solid && secondObject instanceof Solid) {
  770. let oper = 'subtract'
  771. switch (operator) {
  772. case '.UNION.':
  773. oper = BooleanOperator.UNION
  774. break
  775. case '.INTERSECTION.':
  776. oper = BooleanOperator.INTERSECT
  777. break
  778. case '.DIFFERENCE.':
  779. oper = BooleanOperator.SUBTRACT
  780. break
  781. default:
  782. console.warn('Invalid operator: ' + operator.constant)
  783. }
  784. let object3D = new Solid()
  785. object3D.name = oper
  786. object3D.builder = new BooleanOperator(oper)
  787. firstObject.visible = false
  788. firstObject.facesVisible = false
  789. firstObject.edgesVisible = false
  790. secondObject.visible = false
  791. secondObject.facesVisible = false
  792. secondObject.edgesVisible = false
  793. object3D.attach(firstObject)
  794. object3D.attach(secondObject)
  795. ObjectBuilder.build(object3D)
  796. if (object3D.isValid()) {
  797. this.object3D = object3D
  798. this.object3D.material = firstObject.material
  799. this.object3D._ifc = result
  800. } else {
  801. console.warn('boolean operation failed', result)
  802. this.object3D = firstObject
  803. }
  804. } else {
  805. this.object3D = firstObject || secondObject
  806. }
  807. }
  808. return this.object3D
  809. }
  810. }
  811. registerIfcHelperClass(IfcBooleanResultHelper)
  812. class IfcTriangulatedFaceSetHelper extends IfcGeometricRepresentationItemHelper {
  813. constructor(instance) {
  814. super(instance)
  815. }
  816. getObject3D() {
  817. if (this.object3D === null) {
  818. const faceSet = this.instance
  819. let geometry = new SolidGeometry()
  820. geometry.vertices = faceSet.Coordinates.helper.getPoints()
  821. let coordIndex = faceSet.CoordIndex
  822. for (let t = 0; t < coordIndex.length; t++) {
  823. let triangle = coordIndex[t]
  824. let a = triangle[0] - 1
  825. let b = triangle[1] - 1
  826. let c = triangle[2] - 1
  827. geometry.addFace(a, b, c)
  828. }
  829. let solid = new Solid()
  830. solid.updateGeometry(geometry, true)
  831. this.object3D = solid
  832. this.object3D._ifc = faceSet
  833. }
  834. return this.object3D
  835. }
  836. }
  837. registerIfcHelperClass(IfcTriangulatedFaceSetHelper)
  838. class IfcPolygonalFaceSetHelper extends IfcGeometricRepresentationItemHelper {
  839. constructor(instance) {
  840. super(instance)
  841. }
  842. getObject3D() {
  843. if (this.object3D === null) {
  844. const faceSet = this.instance
  845. let geometry = new SolidGeometry()
  846. geometry.vertices = faceSet.Coordinates.helper.getPoints()
  847. let faces = faceSet.Faces
  848. for (let f = 0; f < faces.length; f++) {
  849. let face = faces[f]
  850. let coordIndex = face.CoordIndex
  851. let faceIndices = []
  852. for (let i = 0; i < coordIndex.length; i++) {
  853. let vertexIndex = coordIndex[i] - 1 // 1-base index
  854. faceIndices.push(vertexIndex)
  855. }
  856. let geomFace = geometry.addFace(...faceIndices)
  857. let innerCoordIndices = face.InnerCoordIndices
  858. if (innerCoordIndices) {
  859. for (let h = 0; h < innerCoordIndices.length; h++) {
  860. let hole = innerCoordIndices[h]
  861. let holeIndices = []
  862. for (let hv = 0; hv < hole.length; hv++) {
  863. let vertexIndex = hole[hv] - 1 // 1-base index
  864. holeIndices.push(vertexIndex)
  865. }
  866. geomFace.addHole(...holeIndices)
  867. }
  868. }
  869. }
  870. this.object3D = new Solid(geometry)
  871. this.object3D._ifc = faceSet
  872. }
  873. return this.object3D
  874. }
  875. }
  876. registerIfcHelperClass(IfcPolygonalFaceSetHelper)
  877. class IfcSweptAreaSolidHelper extends IfcGeometricRepresentationItemHelper {
  878. constructor(instance) {
  879. super(instance)
  880. }
  881. createSolid(builder) {
  882. const swept = this.instance
  883. const schema = this.instance.constructor.schema
  884. const profileDef = swept.SweptArea
  885. if (profileDef instanceof schema.IfcProfileDef) {
  886. let profile = profileDef.helper.getProfile()
  887. if (profile) {
  888. try {
  889. if (profile.parent) {
  890. profile = profile.clone()
  891. }
  892. profile._ifc = profileDef
  893. let solid = new Solid()
  894. solid.add(profile)
  895. solid.builder = builder
  896. ObjectBuilder.build(solid)
  897. solid._ifc = swept
  898. if (swept.Position) {
  899. const matrix = swept.Position.helper.getMatrix()
  900. matrix.decompose(solid.position, solid.quaternion, solid.scale)
  901. solid.updateMatrix()
  902. }
  903. this.object3D = solid
  904. } catch (ex) {
  905. console.warn(ex)
  906. }
  907. } else console.warn('Unsupported profile', profileDef)
  908. }
  909. }
  910. }
  911. registerIfcHelperClass(IfcSweptAreaSolidHelper)
  912. class IfcExtrudedAreaSolidHelper extends IfcSweptAreaSolidHelper {
  913. constructor(instance) {
  914. super(instance)
  915. }
  916. getObject3D() {
  917. if (this.object3D === null) {
  918. const swept = this.instance
  919. const direction = swept.ExtrudedDirection.helper.getDirection()
  920. const depth = swept.Depth
  921. this.createSolid(new Extruder(depth, direction))
  922. }
  923. return this.object3D
  924. }
  925. }
  926. registerIfcHelperClass(IfcExtrudedAreaSolidHelper)
  927. class IfcRevolvedAreaSolidHelper extends IfcSweptAreaSolidHelper {
  928. constructor(instance) {
  929. super(instance)
  930. }
  931. getObject3D() {
  932. if (this.object3D === null) {
  933. const swept = this.instance
  934. const location = swept.Axis.helper.getLocation()
  935. const axis = swept.Axis.helper.getAxis()
  936. const angle = THREE.MathUtils.radToDeg(swept.Angle)
  937. const radius = location.length() + 10 // radius estimate
  938. const segments = swept._loader.getCircleSegments(radius)
  939. this.createSolid(new Revolver(angle, location, axis, segments))
  940. }
  941. return this.object3D
  942. }
  943. }
  944. registerIfcHelperClass(IfcRevolvedAreaSolidHelper)
  945. class IfcSurfaceCurveSweptAreaSolidHelper extends IfcGeometricRepresentationItemHelper {
  946. constructor(instance) {
  947. super(instance)
  948. }
  949. getObject3D() {
  950. if (this.object3D === null) {
  951. const swept = this.instance
  952. const profileDef = swept.SweptArea // IfcProfileDef
  953. const position = swept.Position // IfcAxis2Placement3D
  954. const matrix = position.helper.getMatrix()
  955. const directrix = swept.Directrix // IfcCurve
  956. const startParam = swept.StartParam // IfcParameterValue : number
  957. const endParam = swept.EndParam // IfcParameterValue : number
  958. const surface = swept.ReferenceSurface // IfcSurface: ignored
  959. const cordPoints = directrix.helper.getPoints()
  960. if (cordPoints) {
  961. const profile = profileDef.helper.getProfile()
  962. if (profile) {
  963. try {
  964. const solid = new Solid()
  965. solid.name = 'swept'
  966. solid._ifc = swept
  967. solid.builder = new Extruder()
  968. solid.add(profile)
  969. const cord = new Cord(new CordGeometry(cordPoints))
  970. solid.add(cord)
  971. ObjectBuilder.build(solid)
  972. if (matrix) {
  973. matrix.decompose(solid.position, solid.quaternion, solid.scale)
  974. solid.updateMatrix()
  975. }
  976. this.object3D = solid
  977. } catch (ex) {
  978. console.warn(ex)
  979. }
  980. } else {
  981. console.warn('Unsupported profile', profileDef)
  982. }
  983. } else {
  984. console.warn('Unsupported curve', directrix)
  985. }
  986. }
  987. return this.object3D
  988. }
  989. }
  990. registerIfcHelperClass(IfcSurfaceCurveSweptAreaSolidHelper)
  991. class IfcSweptDiskSolidHelper extends IfcGeometricRepresentationItemHelper {
  992. constructor(instance) {
  993. super(instance)
  994. }
  995. getObject3D() {
  996. if (this.object3D === null) {
  997. const swept = this.instance
  998. const directrix = swept.Directrix // IfcCurve
  999. const radius = swept.Radius
  1000. const innerRadius = swept.InnerRadius
  1001. const segments = swept._loader.getCircleSegments(radius)
  1002. try {
  1003. this.object3D = new Solid()
  1004. const object3D = this.object3D
  1005. object3D.name = 'disk'
  1006. object3D._ifc = swept
  1007. object3D.builder = new Extruder()
  1008. const profile = new Profile()
  1009. if (typeof innerRadius === 'number') {
  1010. profile.builder = new CircleHollowBuilder(radius, radius - innerRadius, segments)
  1011. } else {
  1012. profile.builder = new CircleBuilder(radius, segments)
  1013. }
  1014. object3D.add(profile)
  1015. const cordPoints = directrix.helper.getPoints()
  1016. const cord = new Cord(new CordGeometry(cordPoints))
  1017. object3D.add(cord)
  1018. ObjectBuilder.build(object3D)
  1019. } catch (ex) {
  1020. console.warn(ex)
  1021. }
  1022. }
  1023. return this.object3D
  1024. }
  1025. }
  1026. registerIfcHelperClass(IfcSweptDiskSolidHelper)
  1027. class IfcManifoldSolidBrepHelper extends IfcGeometricRepresentationItemHelper {
  1028. constructor(instance) {
  1029. super(instance)
  1030. }
  1031. getObject3D() {
  1032. if (this.object3D === null) {
  1033. var brep = this.instance
  1034. var outerShell = brep.Outer
  1035. this.object3D = outerShell.helper.getObject3D()
  1036. this.object3D._ifc = brep
  1037. }
  1038. return this.object3D
  1039. }
  1040. }
  1041. registerIfcHelperClass(IfcManifoldSolidBrepHelper)
  1042. class IfcFaceBasedSurfaceModelHelper extends IfcGeometricRepresentationItemHelper {
  1043. constructor(instance) {
  1044. super(instance)
  1045. }
  1046. getObject3D() {
  1047. if (this.object3D === null) {
  1048. this.object3D = new THREE.Group()
  1049. var surface = this.instance
  1050. var faceSets = surface.FbsmFaces // IfcConnectedFaceSet[...]
  1051. for (var i = 0; i < faceSets.length; i++) {
  1052. var faceSet = faceSets[i] // IfcConnectedFaceSet
  1053. var faceSetObject3D = faceSet.helper.getObject3D()
  1054. faceSetObject3D.name = 'FaceSet' + i
  1055. this.object3D.add(faceSetObject3D)
  1056. this.object3D._ifc = surface
  1057. }
  1058. }
  1059. return this.object3D
  1060. }
  1061. }
  1062. registerIfcHelperClass(IfcFaceBasedSurfaceModelHelper)
  1063. class IfcShellBasedSurfaceModelHelper extends IfcGeometricRepresentationItemHelper {
  1064. constructor(instance) {
  1065. super(instance)
  1066. }
  1067. getObject3D() {
  1068. if (this.object3D === null) {
  1069. this.object3D = new THREE.Group()
  1070. var surface = this.instance
  1071. var shells = surface.SbsmBoundary // IfcShell[...]
  1072. for (var i = 0; i < shells.length; i++) {
  1073. var shell = shells[i] // IfcConnectedFaceSet
  1074. var shellObject3D = shell.helper.getObject3D()
  1075. shellObject3D.name = 'Shell' + i
  1076. shellObject3D._ifc = shell
  1077. this.object3D.add(shellObject3D)
  1078. this.object3D._ifc = surface
  1079. }
  1080. }
  1081. return this.object3D
  1082. }
  1083. }
  1084. registerIfcHelperClass(IfcShellBasedSurfaceModelHelper)
  1085. class IfcRepresentationMapHelper extends IfcHelper {
  1086. constructor(instance) {
  1087. super(instance)
  1088. this.object3D = null
  1089. }
  1090. getObject3D() {
  1091. if (this.object3D === null) {
  1092. const reprMap = this.instance
  1093. const repr = reprMap.MappedRepresentation // IfcRepresentation
  1094. const origin = reprMap.MappingOrigin
  1095. const loader = reprMap._loader
  1096. let object3D = repr.helper.getObject3D()
  1097. if (object3D.parent) {
  1098. // already added to scene, clone it
  1099. object3D = loader.cloneObject3D(object3D, true)
  1100. }
  1101. object3D.name = 'block-' + ++loader.blockCount
  1102. object3D.userData.IFC = { ifcClassName: 'IfcRepresentationMap' }
  1103. object3D._ifc = reprMap
  1104. loader.blocks.add(object3D)
  1105. if (origin) {
  1106. let matrix = origin.helper.getMatrix()
  1107. object3D.matrix.multiplyMatrices(matrix, object3D.matrix)
  1108. object3D.matrix.decompose(object3D.position, object3D.quaternion, object3D.scale)
  1109. object3D.matrixWorldNeedsUpdate = true
  1110. }
  1111. this.object3D = object3D
  1112. }
  1113. return this.object3D
  1114. }
  1115. }
  1116. registerIfcHelperClass(IfcRepresentationMapHelper)
  1117. class IfcMappedItemHelper extends IfcGeometricRepresentationItemHelper {
  1118. constructor(instance) {
  1119. super(instance)
  1120. }
  1121. getObject3D() {
  1122. if (this.object3D === null) {
  1123. const mappedItem = this.instance
  1124. const source = mappedItem.MappingSource // IfcRepresentationMap
  1125. const target = mappedItem.MappingTarget
  1126. const loader = mappedItem._loader
  1127. const mappedObject3D = source.helper.getObject3D()
  1128. if (mappedObject3D) {
  1129. const instanceGroup = new THREE.Group()
  1130. if (target) {
  1131. let matrix = target.helper.getMatrix()
  1132. matrix.decompose(instanceGroup.position, instanceGroup.quaternion, instanceGroup.scale)
  1133. instanceGroup.updateMatrix()
  1134. }
  1135. instanceGroup.builder = new Cloner(mappedObject3D)
  1136. ObjectBuilder.build(instanceGroup)
  1137. this.object3D = instanceGroup
  1138. this.object3D._ifc = mappedItem
  1139. }
  1140. }
  1141. return this.object3D
  1142. }
  1143. }
  1144. registerIfcHelperClass(IfcMappedItemHelper)
  1145. /* Profile helpers */
  1146. class IfcProfileDefHelper extends IfcHelper {
  1147. constructor(instance) {
  1148. super(instance)
  1149. this.profile = null
  1150. }
  1151. getProfile() {
  1152. return this.profile
  1153. }
  1154. }
  1155. registerIfcHelperClass(IfcProfileDefHelper)
  1156. class IfcParameterizedProfileDefHelper extends IfcProfileDefHelper {
  1157. constructor(instance) {
  1158. super(instance)
  1159. }
  1160. getProfile() {
  1161. if (this.profile === null) {
  1162. const builder = this.getProfileBuilder()
  1163. if (builder) {
  1164. const profileDef = this.instance
  1165. const profile = new Profile()
  1166. let name = builder.constructor.name
  1167. let index = name.indexOf('Builder')
  1168. if (index !== -1) name = name.substring(0, index)
  1169. profile.name = name
  1170. profile.builder = builder
  1171. ObjectBuilder.build(profile)
  1172. if (profileDef.Position) {
  1173. const profMat = profileDef.Position.helper.getMatrix()
  1174. profMat.decompose(profile.position, profile.quaternion, profile.scale)
  1175. profile.updateMatrix()
  1176. }
  1177. this.profile = profile
  1178. }
  1179. }
  1180. return this.profile
  1181. }
  1182. getProfileBuilder() {
  1183. return null
  1184. }
  1185. }
  1186. registerIfcHelperClass(IfcParameterizedProfileDefHelper)
  1187. class IfcRectangleProfileDefHelper extends IfcParameterizedProfileDefHelper {
  1188. constructor(instance) {
  1189. super(instance)
  1190. }
  1191. getProfileBuilder() {
  1192. const profileDef = this.instance
  1193. return new RectangleBuilder(profileDef.XDim, profileDef.YDim)
  1194. }
  1195. }
  1196. registerIfcHelperClass(IfcRectangleProfileDefHelper)
  1197. class IfcRectangleHollowProfileDefHelper extends IfcRectangleProfileDefHelper {
  1198. constructor(instance) {
  1199. super(instance)
  1200. }
  1201. getProfileBuilder() {
  1202. const profileDef = this.instance
  1203. return new RectangleHollowBuilder(profileDef.XDim, profileDef.YDim, profileDef.WallThickness)
  1204. }
  1205. }
  1206. registerIfcHelperClass(IfcRectangleHollowProfileDefHelper)
  1207. class IfcCircleProfileDefHelper extends IfcParameterizedProfileDefHelper {
  1208. constructor(instance) {
  1209. super(instance)
  1210. }
  1211. getProfileBuilder() {
  1212. const profileDef = this.instance
  1213. const radius = profileDef.Radius
  1214. const segments = profileDef._loader.getCircleSegments(radius)
  1215. return new CircleBuilder(radius, segments)
  1216. }
  1217. }
  1218. registerIfcHelperClass(IfcCircleProfileDefHelper)
  1219. class IfcCircleHollowProfileDefHelper extends IfcCircleProfileDefHelper {
  1220. constructor(instance) {
  1221. super(instance)
  1222. }
  1223. getProfileBuilder() {
  1224. const profileDef = this.instance
  1225. const radius = profileDef.Radius
  1226. const thickness = profileDef.WallThickness
  1227. const segments = profileDef._loader.getCircleSegments(radius)
  1228. return new CircleHollowBuilder(radius, thickness, segments)
  1229. }
  1230. }
  1231. registerIfcHelperClass(IfcCircleHollowProfileDefHelper)
  1232. class IfcEllipseProfileDefHelper extends IfcParameterizedProfileDefHelper {
  1233. constructor(instance) {
  1234. super(instance)
  1235. }
  1236. getProfileBuilder() {
  1237. const profileDef = this.instance
  1238. const xradius = profileDef.SemiAxis1
  1239. const yradius = profileDef.SemiAxis2
  1240. const maxRadius = Math.max(xradius, yradius)
  1241. const segments = profileDef._loader.getCircleSegments(maxRadius)
  1242. return new EllipseBuilder(xradius, yradius, segments)
  1243. }
  1244. }
  1245. registerIfcHelperClass(IfcEllipseProfileDefHelper)
  1246. class IfcIShapeProfileDefHelper extends IfcParameterizedProfileDefHelper {
  1247. constructor(instance) {
  1248. super(instance)
  1249. }
  1250. getProfileBuilder() {
  1251. const profileDef = this.instance
  1252. const width = profileDef.OverallWidth
  1253. const height = profileDef.OverallDepth
  1254. const webThickness = profileDef.WebThickness
  1255. const flangeThickness = profileDef.FlangeThickness
  1256. return new IProfileBuilder(width, height, webThickness, flangeThickness)
  1257. }
  1258. }
  1259. registerIfcHelperClass(IfcIShapeProfileDefHelper)
  1260. class IfcLShapeProfileDefHelper extends IfcParameterizedProfileDefHelper {
  1261. constructor(instance) {
  1262. super(instance)
  1263. }
  1264. getProfileBuilder() {
  1265. const profileDef = this.instance
  1266. const width = profileDef.Width
  1267. const height = profileDef.Depth
  1268. const thickness = profileDef.Thickness
  1269. return new LProfileBuilder(width, height, thickness)
  1270. }
  1271. }
  1272. registerIfcHelperClass(IfcLShapeProfileDefHelper)
  1273. class IfcTShapeProfileDefHelper extends IfcParameterizedProfileDefHelper {
  1274. constructor(instance) {
  1275. super(instance)
  1276. }
  1277. getProfileBuilder() {
  1278. const profileDef = this.instance
  1279. const flangeWidth = profileDef.FlangeWidth
  1280. const height = profileDef.Depth
  1281. const webThickness = profileDef.WebThickness
  1282. const flangeThickness = profileDef.FlangeThickness
  1283. return new TProfileBuilder(flangeWidth, height, webThickness, flangeThickness)
  1284. }
  1285. }
  1286. registerIfcHelperClass(IfcTShapeProfileDefHelper)
  1287. class IfcUShapeProfileDefHelper extends IfcParameterizedProfileDefHelper {
  1288. constructor(instance) {
  1289. super(instance)
  1290. }
  1291. getProfileBuilder() {
  1292. const profileDef = this.instance
  1293. const flangeWidth = profileDef.FlangeWidth
  1294. const height = profileDef.Depth
  1295. const webThickness = profileDef.WebThickness
  1296. const flangeThickness = profileDef.FlangeThickness
  1297. return new UProfileBuilder(flangeWidth, height, webThickness, flangeThickness)
  1298. }
  1299. }
  1300. registerIfcHelperClass(IfcUShapeProfileDefHelper)
  1301. class IfcZShapeProfileDefHelper extends IfcParameterizedProfileDefHelper {
  1302. constructor(instance) {
  1303. super(instance)
  1304. }
  1305. getProfileBuilder() {
  1306. const profileDef = this.instance
  1307. const flangeWidth = profileDef.FlangeWidth
  1308. const height = profileDef.Depth
  1309. const webThickness = profileDef.WebThickness
  1310. const flangeThickness = profileDef.FlangeThickness
  1311. return new ZProfileBuilder(flangeWidth, height, webThickness, flangeThickness)
  1312. }
  1313. }
  1314. registerIfcHelperClass(IfcZShapeProfileDefHelper)
  1315. class IfcTrapeziumProfileDefHelper extends IfcParameterizedProfileDefHelper {
  1316. constructor(instance) {
  1317. super(instance)
  1318. }
  1319. getProfileBuilder() {
  1320. const profileDef = this.instance
  1321. const bottomXDim = profileDef.BottomXDim
  1322. const height = profileDef.YDim
  1323. const topXDim = profileDef.TopXDim
  1324. const topXOffset = profileDef.TopXOffset
  1325. return new TrapeziumBuilder(bottomXDim, height, topXDim, topXOffset)
  1326. }
  1327. }
  1328. registerIfcHelperClass(IfcTrapeziumProfileDefHelper)
  1329. class IfcArbitraryClosedProfileDefHelper extends IfcProfileDefHelper {
  1330. constructor(instance) {
  1331. super(instance)
  1332. this.profile = null
  1333. }
  1334. getProfile() {
  1335. if (this.profile === null) {
  1336. const profileDef = this.instance
  1337. const curve = profileDef.OuterCurve // IfcCurve
  1338. const curvePoints = curve.helper.getPoints()
  1339. if (curvePoints) {
  1340. const shape = new THREE.Shape()
  1341. this.addPointsToPath(shape, curvePoints)
  1342. this.profile = new Profile(new ProfileGeometry(shape))
  1343. } else {
  1344. console.warn('Unsupported curve', curve)
  1345. }
  1346. }
  1347. return this.profile
  1348. }
  1349. addPointsToPath(path, curvePoints) {
  1350. path.moveTo(curvePoints[0].x, curvePoints[0].y)
  1351. for (let i = 1; i < curvePoints.length; i++) {
  1352. path.lineTo(curvePoints[i].x, curvePoints[i].y)
  1353. }
  1354. path.closePath()
  1355. }
  1356. }
  1357. registerIfcHelperClass(IfcArbitraryClosedProfileDefHelper)
  1358. class IfcArbitraryProfileDefWithVoidsHelper extends IfcArbitraryClosedProfileDefHelper {
  1359. constructor(instance) {
  1360. super(instance)
  1361. this.profile = null
  1362. }
  1363. getProfile() {
  1364. if (this.profile === null) {
  1365. const profileDef = this.instance
  1366. const curve = profileDef.OuterCurve // IfcCurve
  1367. let curvePoints = curve.helper.getPoints()
  1368. if (curvePoints) {
  1369. const shape = new THREE.Shape()
  1370. this.addPointsToPath(shape, curvePoints)
  1371. const innerCurves = profileDef.InnerCurves // IfcCurve[]
  1372. for (let innerCurve of innerCurves) {
  1373. curvePoints = innerCurve.helper.getPoints()
  1374. if (curvePoints) {
  1375. let hole = new THREE.Path()
  1376. this.addPointsToPath(hole, curvePoints)
  1377. shape.holes.push(hole)
  1378. } else {
  1379. console.warn('Unsupported inner curve', innerCurve)
  1380. }
  1381. }
  1382. this.profile = new Profile(new ProfileGeometry(shape))
  1383. }
  1384. }
  1385. return this.profile
  1386. }
  1387. }
  1388. registerIfcHelperClass(IfcArbitraryProfileDefWithVoidsHelper)
  1389. /* Curve helpers */
  1390. class IfcCurveHelper extends IfcHelper {
  1391. constructor(instance) {
  1392. super(instance)
  1393. this.points = null
  1394. }
  1395. getPoints() {
  1396. return this.points
  1397. }
  1398. }
  1399. registerIfcHelperClass(IfcCurveHelper)
  1400. class IfcPolylineHelper extends IfcCurveHelper {
  1401. constructor(instance) {
  1402. super(instance)
  1403. }
  1404. getPoints() {
  1405. if (this.points === null) {
  1406. const polyline = this.instance
  1407. this.points = []
  1408. const points = polyline.Points
  1409. for (let i = 0; i < points.length; i++) {
  1410. let point = points[i].helper.getPoint()
  1411. this.points.push(point)
  1412. }
  1413. }
  1414. return this.points
  1415. }
  1416. }
  1417. registerIfcHelperClass(IfcPolylineHelper)
  1418. class IfcIndexedPolyCurveHelper extends IfcCurveHelper {
  1419. constructor(instance) {
  1420. super(instance)
  1421. }
  1422. getPoints() {
  1423. const polyCurve = this.instance
  1424. return polyCurve.Points.helper.getPoints()
  1425. }
  1426. }
  1427. registerIfcHelperClass(IfcIndexedPolyCurveHelper)
  1428. class IfcTrimmedCurveHelper extends IfcCurveHelper {
  1429. constructor(instance) {
  1430. super(instance)
  1431. }
  1432. getPoints() {
  1433. if (this.points === null) {
  1434. const curve = this.instance
  1435. const schema = this.instance.constructor.schema
  1436. const basisCurve = curve.BasisCurve
  1437. const trim1 = curve.Trim1[0]
  1438. const trim2 = curve.Trim2[0]
  1439. if (basisCurve instanceof schema.IfcConic && trim1 instanceof schema.IfcParameterValue && trim2 instanceof schema.IfcParameterValue) {
  1440. let startAngle = trim1.Value
  1441. let endAngle = trim2.Value
  1442. let sense = curve.SenseAgreement === '.T.'
  1443. this.points = basisCurve.helper.getTrimmedPoints(startAngle, endAngle, sense)
  1444. } else {
  1445. console.info('unsupported trimmed curve segment', curve)
  1446. }
  1447. }
  1448. return this.points
  1449. }
  1450. }
  1451. registerIfcHelperClass(IfcTrimmedCurveHelper)
  1452. class IfcCompositeCurveHelper extends IfcCurveHelper {
  1453. constructor(instance) {
  1454. super(instance)
  1455. }
  1456. getPoints() {
  1457. if (this.points === null) {
  1458. const compositeCurve = this.instance
  1459. const schema = this.instance.constructor.schema
  1460. let points = []
  1461. let segments = compositeCurve.Segments
  1462. for (let i = 0; i < segments.length; i++) {
  1463. let segment = segments[i] // IfcCompositeCurveSegment
  1464. let curve = segment.ParentCurve
  1465. let curvePoints = curve.helper.getPoints()
  1466. if (curvePoints) {
  1467. if (segment.SameSense === '.T.') {
  1468. for (let j = 0; j < curvePoints.length; j++) {
  1469. points.push(curvePoints[j])
  1470. }
  1471. } else {
  1472. for (let j = curvePoints.length - 1; j >= 0; j--) {
  1473. points.push(curvePoints[j])
  1474. }
  1475. }
  1476. } else {
  1477. console.info('unsupported curve segment', curve)
  1478. }
  1479. }
  1480. if (points.length > 0) {
  1481. this.points = points
  1482. }
  1483. }
  1484. return this.points
  1485. }
  1486. }
  1487. registerIfcHelperClass(IfcCompositeCurveHelper)
  1488. class IfcConicHelper extends IfcCurveHelper {
  1489. constructor(instance) {
  1490. super(instance)
  1491. }
  1492. getTrimmedPoints(param1, param2, sense) {
  1493. return this.points
  1494. }
  1495. generatePoints(startAngle, endAngle, sense, segments, addPoint) {
  1496. let angle
  1497. if (sense) {
  1498. // anti-clockwise
  1499. if (endAngle < startAngle) endAngle += 2 * Math.PI
  1500. let dif = endAngle - startAngle
  1501. let divs = Math.ceil((dif * segments) / (2 * Math.PI))
  1502. let angleStep = dif / divs
  1503. angle = startAngle
  1504. while (divs > 0) {
  1505. addPoint(angle)
  1506. angle += angleStep
  1507. divs--
  1508. }
  1509. addPoint(endAngle)
  1510. } // clockwise
  1511. else {
  1512. if (endAngle > startAngle) startAngle += 2 * Math.PI
  1513. let dif = startAngle - endAngle
  1514. let divs = Math.ceil((dif * segments) / (2 * Math.PI))
  1515. let angleStep = dif / divs
  1516. angle = startAngle
  1517. while (divs > 0) {
  1518. addPoint(angle)
  1519. angle -= angleStep
  1520. divs--
  1521. }
  1522. addPoint(endAngle)
  1523. }
  1524. }
  1525. }
  1526. registerIfcHelperClass(IfcConicHelper)
  1527. class IfcCircleHelper extends IfcConicHelper {
  1528. constructor(instance) {
  1529. super(instance)
  1530. }
  1531. getPoints() {
  1532. if (this.points === null) {
  1533. this.points = []
  1534. const circle = this.instance
  1535. const matrix = circle.Position.helper.getMatrix()
  1536. const radius = circle.Radius
  1537. const segments = circle._loader.getCircleSegments(radius)
  1538. const angleStep = (2 * Math.PI) / segments
  1539. for (let i = 0; i < segments; i++) {
  1540. let angle = i * angleStep
  1541. let point = new THREE.Vector3()
  1542. point.x = Math.cos(angle) * radius
  1543. point.y = Math.sin(angle) * radius
  1544. point.z = 0
  1545. point.applyMatrix4(matrix)
  1546. this.points.push(point)
  1547. }
  1548. }
  1549. return this.points
  1550. }
  1551. getTrimmedPoints(param1, param2, sense) {
  1552. let points = []
  1553. const circle = this.instance
  1554. const matrix = circle.Position.helper.getMatrix()
  1555. const radius = circle.Radius
  1556. const startAngle = THREE.MathUtils.degToRad(param1)
  1557. const endAngle = THREE.MathUtils.degToRad(param2)
  1558. const segments = circle._loader.getCircleSegments(radius)
  1559. const addPoint = angle => {
  1560. let point = new THREE.Vector3()
  1561. point.x = Math.cos(angle) * radius
  1562. point.y = Math.sin(angle) * radius
  1563. point.z = 0
  1564. point.applyMatrix4(matrix)
  1565. points.push(point)
  1566. }
  1567. this.generatePoints(startAngle, endAngle, sense, segments, addPoint)
  1568. return points
  1569. }
  1570. }
  1571. registerIfcHelperClass(IfcCircleHelper)
  1572. class IfcEllipseHelper extends IfcConicHelper {
  1573. constructor(instance) {
  1574. super(instance)
  1575. }
  1576. getPoints() {
  1577. if (this.points === null) {
  1578. this.points = []
  1579. const ellipse = this.instance
  1580. const matrix = ellipse.Position.helper.getMatrix()
  1581. const semiAxis1 = ellipse.SemiAxis1
  1582. const semiAxis2 = ellipse.SemiAxis2
  1583. const maxAxis = Math.max(semiAxis1, semiAxis2)
  1584. const segments = ellipse._loader.getCircleSegments(maxAxis)
  1585. const angleStep = (2 * Math.PI) / segments
  1586. for (let i = 0; i < segments; i++) {
  1587. let angle = i * angleStep
  1588. let point = new THREE.Vector3()
  1589. point.x = Math.cos(angle) * semiAxis1
  1590. point.y = Math.sin(angle) * semiAxis2
  1591. point.z = 0
  1592. point.applyMatrix4(matrix)
  1593. this.points.push(point)
  1594. }
  1595. }
  1596. return this.points
  1597. }
  1598. getTrimmedPoints(param1, param2, sense) {
  1599. let points = []
  1600. const ellipse = this.instance
  1601. const matrix = ellipse.Position.helper.getMatrix()
  1602. const semiAxis1 = ellipse.SemiAxis1
  1603. const semiAxis2 = ellipse.SemiAxis2
  1604. const maxAxis = Math.max(semiAxis1, semiAxis2)
  1605. const startAngle = THREE.MathUtils.degToRad(param1)
  1606. const endAngle = THREE.MathUtils.degToRad(param2)
  1607. const segments = ellipse._loader.getCircleSegments(maxAxis)
  1608. const addPoint = angle => {
  1609. let point = new THREE.Vector3()
  1610. point.x = Math.cos(angle) * semiAxis1
  1611. point.y = Math.sin(angle) * semiAxis2
  1612. point.z = 0
  1613. point.applyMatrix4(matrix)
  1614. points.push(point)
  1615. }
  1616. this.generatePoints(startAngle, endAngle, sense, segments, addPoint)
  1617. return points
  1618. }
  1619. }
  1620. registerIfcHelperClass(IfcEllipseHelper)
  1621. /* Geometry helpers */
  1622. class IfcConnectedFaceSetHelper extends IfcHelper {
  1623. constructor(instance) {
  1624. super(instance)
  1625. this.object3D = null
  1626. }
  1627. getObject3D() {
  1628. if (this.object3D === null) {
  1629. const faceSet = this.instance
  1630. const schema = this.instance.constructor.schema
  1631. let faces = faceSet.CfsFaces
  1632. let geometry = new SolidGeometry()
  1633. for (let f = 0; f < faces.length; f++) {
  1634. let face = faces[f] // IfcFace
  1635. let bounds = face.Bounds // IfcFaceBound[...]
  1636. let faceVertices = null
  1637. let holes = []
  1638. for (let b = 0; b < bounds.length; b++) {
  1639. let bound = bounds[b] // IfcFaceBound
  1640. let loop = bound.Bound // IfcLoop:
  1641. // (IfcPolyLoop, IfcEdgeLoop, IfcVertexLoop)
  1642. let loopVertices = loop.helper.getPoints()
  1643. let loopOrientation = bound.Orientation
  1644. if (loopOrientation === '.F.') {
  1645. // reverse loop sense
  1646. loopVertices = loopVertices.slice().reverse()
  1647. }
  1648. if (bound instanceof schema.IfcFaceOuterBound) {
  1649. faceVertices = loopVertices
  1650. } else {
  1651. holes.push(loopVertices)
  1652. }
  1653. }
  1654. if (faceVertices && faceVertices.length >= 3) {
  1655. let face = geometry.addFace(...faceVertices)
  1656. for (let holeVertices of holes) {
  1657. if (holeVertices.length >= 3) face.addHole(...holeVertices)
  1658. }
  1659. }
  1660. }
  1661. let solid = new Solid()
  1662. solid.updateGeometry(geometry, true)
  1663. this.object3D = solid
  1664. this.object3D._ifc = faceSet
  1665. }
  1666. return this.object3D
  1667. }
  1668. }
  1669. registerIfcHelperClass(IfcConnectedFaceSetHelper)
  1670. class IfcPolyLoopHelper extends IfcHelper {
  1671. constructor(instance) {
  1672. super(instance)
  1673. this.points = null
  1674. }
  1675. getPoints() {
  1676. if (this.points === null) {
  1677. const loop = this.instance
  1678. const polygon = loop.Polygon
  1679. this.points = []
  1680. for (let i = 0; i < polygon.length; i++) {
  1681. let point = polygon[i].helper.getPoint()
  1682. this.points.push(point)
  1683. }
  1684. }
  1685. return this.points
  1686. }
  1687. }
  1688. registerIfcHelperClass(IfcPolyLoopHelper)
  1689. class IfcEdgeLoopHelper extends IfcHelper {
  1690. constructor(instance) {
  1691. super(instance)
  1692. this.points = null
  1693. }
  1694. getPoints() {
  1695. if (this.points === null) {
  1696. const edges = this.instance.EdgeList // IfcOrientedEdge[]
  1697. this.points = []
  1698. for (let i = 0; i < edges.length; i++) {
  1699. let edge = edges[i]
  1700. let point = edge.Orientation === '.T.' ? edge.EdgeElement.EdgeStart.VertexGeometry.helper.getPoint() : edge.EdgeElement.EdgeEnd.VertexGeometry.helper.getPoint()
  1701. this.points.push(point)
  1702. }
  1703. }
  1704. return this.points
  1705. }
  1706. }
  1707. registerIfcHelperClass(IfcEdgeLoopHelper)
  1708. class IfcVertexLoopHelper extends IfcHelper {
  1709. constructor(instance) {
  1710. super(instance)
  1711. this.points = null
  1712. }
  1713. getPoints() {
  1714. if (this.points === null) {
  1715. const vertex = this.instance.LoopVertex // IfcVertexPoint
  1716. const point = vertex.VertexGeometry.helper.getPoint()
  1717. this.points = [point]
  1718. }
  1719. return this.points
  1720. }
  1721. }
  1722. registerIfcHelperClass(IfcVertexLoopHelper)
  1723. class IfcCartesianPointList2DHelper extends IfcHelper {
  1724. constructor(instance) {
  1725. super(instance)
  1726. this.points = null
  1727. }
  1728. getPoints() {
  1729. if (this.points === null) {
  1730. var list = this.instance
  1731. this.points = []
  1732. for (var i = 0; i < list.CoordList.length; i++) {
  1733. var coord = list.CoordList[i]
  1734. var point = new THREE.Vector3()
  1735. point.x = coord[0]
  1736. point.y = coord[1]
  1737. this.points.push(point)
  1738. }
  1739. }
  1740. return this.points
  1741. }
  1742. }
  1743. registerIfcHelperClass(IfcCartesianPointList2DHelper)
  1744. class IfcCartesianPointList3DHelper extends IfcHelper {
  1745. constructor(instance) {
  1746. super(instance)
  1747. this.points = null
  1748. }
  1749. getPoints() {
  1750. if (this.points === null) {
  1751. var list = this.instance
  1752. this.points = []
  1753. for (var i = 0; i < list.CoordList.length; i++) {
  1754. var coord = list.CoordList[i]
  1755. var point = new THREE.Vector3()
  1756. point.x = coord[0]
  1757. point.y = coord[1]
  1758. point.z = coord[2]
  1759. this.points.push(point)
  1760. }
  1761. }
  1762. return this.points
  1763. }
  1764. }
  1765. registerIfcHelperClass(IfcCartesianPointList3DHelper)
  1766. /* Matrix helpers */
  1767. class IfcLocalPlacementHelper extends IfcHelper {
  1768. constructor(instance) {
  1769. super(instance)
  1770. this.matrix = null // relative matrix
  1771. this.matrixWorld = null // matrixWorld
  1772. }
  1773. getMatrix() {
  1774. if (this.matrix === null) {
  1775. var placement = this.instance
  1776. var relativePlacement = placement.RelativePlacement
  1777. this.matrix = relativePlacement ? relativePlacement.helper.getMatrix() : new THREE.Matrix4()
  1778. }
  1779. return this.matrix
  1780. }
  1781. getMatrixWorld() {
  1782. if (this.matrixWorld === null) {
  1783. const placement = this.instance
  1784. const schema = this.instance.constructor.schema
  1785. var placementRelTo = placement.PlacementRelTo
  1786. if (placementRelTo instanceof schema.IfcLocalPlacement) {
  1787. this.matrixWorld = placementRelTo.helper.getMatrixWorld().clone()
  1788. this.matrixWorld.multiply(this.getMatrix())
  1789. } else this.matrixWorld = this.getMatrix()
  1790. }
  1791. return this.matrixWorld
  1792. }
  1793. }
  1794. registerIfcHelperClass(IfcLocalPlacementHelper)
  1795. class IfcCartesianTransformationOperatorHelper extends IfcHelper {
  1796. constructor(instance) {
  1797. super(instance)
  1798. this.matrix = null
  1799. }
  1800. getMatrix() {
  1801. // TODO: process all parameters
  1802. if (this.matrix === null) {
  1803. var operator = this.instance
  1804. this.matrix = new THREE.Matrix4()
  1805. var origin = operator.LocalOrigin
  1806. if (origin) {
  1807. var point = origin.helper.getPoint()
  1808. this.matrix.makeTranslation(point.x, point.y, point.z)
  1809. }
  1810. }
  1811. return this.matrix
  1812. }
  1813. }
  1814. registerIfcHelperClass(IfcCartesianTransformationOperatorHelper)
  1815. class IfcPlacementHelper extends IfcHelper {
  1816. constructor(instance) {
  1817. super(instance)
  1818. this.matrix = null
  1819. this.location = null
  1820. }
  1821. getLocation() {
  1822. if (this.location === null) {
  1823. var placement = this.instance
  1824. var loc = placement.Location
  1825. this.location = loc ? loc.helper.getPoint() : new THREE.Vector3(0, 0, 0)
  1826. }
  1827. return this.location
  1828. }
  1829. getMatrix() {
  1830. if (this.matrix === null) {
  1831. var placement = this.instance
  1832. this.matrix = new THREE.Matrix4()
  1833. this.matrix.setPosition(this.getLocation())
  1834. }
  1835. return this.matrix
  1836. }
  1837. }
  1838. registerIfcHelperClass(IfcPlacementHelper)
  1839. class IfcAxis1PlacementHelper extends IfcPlacementHelper {
  1840. constructor(instance) {
  1841. super(instance)
  1842. this.axis = null
  1843. }
  1844. getAxis() {
  1845. if (this.axis === null) {
  1846. var placement = this.instance
  1847. var axis = placement.Axis
  1848. this.axis = axis ? axis.helper.getDirection() : new THREE.Vector3(0, 0, 1)
  1849. }
  1850. return this.axis
  1851. }
  1852. getMatrix() {
  1853. if (this.matrix === null) {
  1854. var placement = this.instance
  1855. var loc = this.getLocation()
  1856. var vz = this.getAxis()
  1857. var vy = GeometryUtils.orthogonalVector(vz)
  1858. var vx = new THREE.Vector3()
  1859. vx.crossVectors(vy, vz)
  1860. this.matrix = new THREE.Matrix4()
  1861. this.matrix.set(vx.x, vy.x, vz.x, loc.x, vx.y, vy.y, vz.y, loc.y, vx.z, vy.z, vz.z, loc.z, 0, 0, 0, 1)
  1862. }
  1863. return this.matrix
  1864. }
  1865. }
  1866. registerIfcHelperClass(IfcAxis1PlacementHelper)
  1867. class IfcAxis2Placement2DHelper extends IfcPlacementHelper {
  1868. constructor(instance) {
  1869. super(instance)
  1870. this.refDirection = null
  1871. }
  1872. getRefDirection() {
  1873. if (this.refDirection === null) {
  1874. var placement = this.instance
  1875. var refd = placement.RefDirection
  1876. this.refDirection = refd ? refd.helper.getDirection() : new THREE.Vector3(1, 0, 0)
  1877. }
  1878. return this.refDirection
  1879. }
  1880. getMatrix() {
  1881. if (this.matrix === null) {
  1882. var loc = this.getLocation()
  1883. var vx = this.getRefDirection()
  1884. var vz = new THREE.Vector3(0, 0, 1)
  1885. var vy = new THREE.Vector3()
  1886. vy.crossVectors(vz, vx)
  1887. this.matrix = new THREE.Matrix4()
  1888. this.matrix.set(vx.x, vy.x, vz.x, loc.x, vx.y, vy.y, vz.y, loc.y, vx.z, vy.z, vz.z, loc.z, 0, 0, 0, 1)
  1889. }
  1890. return this.matrix
  1891. }
  1892. }
  1893. registerIfcHelperClass(IfcAxis2Placement2DHelper)
  1894. class IfcAxis2Placement3DHelper extends IfcPlacementHelper {
  1895. constructor(instance) {
  1896. super(instance)
  1897. this.axis = null
  1898. this.refDirection = null
  1899. }
  1900. getAxis() {
  1901. if (this.axis === null) {
  1902. var placement = this.instance
  1903. var axis = placement.Axis
  1904. this.axis = axis ? axis.helper.getDirection() : new THREE.Vector3(0, 0, 1)
  1905. }
  1906. return this.axis
  1907. }
  1908. getRefDirection() {
  1909. if (this.refDirection === null) {
  1910. var placement = this.instance
  1911. var refd = placement.RefDirection
  1912. this.refDirection = refd ? refd.helper.getDirection() : new THREE.Vector3(1, 0, 0)
  1913. }
  1914. return this.refDirection
  1915. }
  1916. getMatrix() {
  1917. if (this.matrix === null) {
  1918. var loc = this.getLocation()
  1919. var vz = this.getAxis()
  1920. var vx = this.getRefDirection()
  1921. var vy = new THREE.Vector3()
  1922. vy.crossVectors(vz, vx)
  1923. this.matrix = new THREE.Matrix4()
  1924. this.matrix.set(vx.x, vy.x, vz.x, loc.x, vx.y, vy.y, vz.y, loc.y, vx.z, vy.z, vz.z, loc.z, 0, 0, 0, 1)
  1925. }
  1926. return this.matrix
  1927. }
  1928. }
  1929. registerIfcHelperClass(IfcAxis2Placement3DHelper)
  1930. /* Relationship helpers */
  1931. class IfcRelationshipHelper extends IfcHelper {
  1932. constructor(instance) {
  1933. super(instance)
  1934. }
  1935. relate() {}
  1936. }
  1937. registerIfcHelperClass(IfcRelationshipHelper)
  1938. class IfcRelDefinesByTypeHelper extends IfcRelationshipHelper {
  1939. constructor(instance) {
  1940. super(instance)
  1941. }
  1942. relate() {
  1943. const rel = this.instance
  1944. const schema = this.instance.constructor.schema
  1945. let objects = rel.RelatedObjects
  1946. let ifcType = rel.RelatingType
  1947. const typeData = { ifcClassName: ifcType.constructor.name }
  1948. for (let key in ifcType) {
  1949. let value = ifcType[key]
  1950. let valueType = typeof value
  1951. if (valueType === 'string' || valueType === 'number' || valueType === 'boolean') {
  1952. typeData[key] = value
  1953. }
  1954. }
  1955. for (let i = 0; i < objects.length; i++) {
  1956. if (objects[i].helper.getObject3D) {
  1957. let object3D = objects[i].helper.getObject3D()
  1958. object3D.userData['IFC_type'] = typeData
  1959. }
  1960. }
  1961. }
  1962. }
  1963. registerIfcHelperClass(IfcRelDefinesByTypeHelper)
  1964. class IfcRelAssociatesClassificationHelper extends IfcRelationshipHelper {
  1965. constructor(instance) {
  1966. super(instance)
  1967. }
  1968. relate() {
  1969. const rel = this.instance
  1970. const schema = this.instance.constructor.schema
  1971. var ifcObjects = rel.RelatedObjects
  1972. var ifcClassifRef = rel.RelatingClassification
  1973. if (ifcClassifRef instanceof schema.IfcClassificationReference) {
  1974. for (var i = 0; i < ifcObjects.length; i++) {
  1975. var ifcObject = ifcObjects[i]
  1976. if (ifcObject.helper && ifcObject.helper.getObject3D) {
  1977. let object3D = ifcObject.helper.getObject3D()
  1978. let ifcClassification = ifcClassifRef.ReferencedSource || {}
  1979. let classifName = 'Unnamed'
  1980. if (ifcClassification.Name) {
  1981. classifName = ifcClassification.Name
  1982. if (ifcClassification.Edition) {
  1983. classifName += '_' + ifcClassification.Edition
  1984. }
  1985. }
  1986. let classifData = {}
  1987. object3D.userData['IFC_classification_' + classifName] = classifData
  1988. for (let key in ifcClassifRef) {
  1989. let value = ifcClassifRef[key]
  1990. let valueType = typeof value
  1991. if (valueType === 'string' || valueType === 'number' || valueType === 'boolean') {
  1992. classifData[key] = value
  1993. }
  1994. }
  1995. }
  1996. }
  1997. }
  1998. }
  1999. }
  2000. registerIfcHelperClass(IfcRelAssociatesClassificationHelper)
  2001. class IfcRelAssignsToGroupHelper extends IfcRelationshipHelper {
  2002. constructor(instance) {
  2003. super(instance)
  2004. }
  2005. relate() {
  2006. const rel = this.instance
  2007. const schema = this.instance.constructor.schema
  2008. var ifcObjects = rel.RelatedObjects
  2009. var ifcObjectsType = rel.RelatedObjectsType
  2010. var ifcGroup = rel.RelatingGroup
  2011. let groupData = { ifcClassName: ifcGroup.constructor.name }
  2012. for (let key in ifcGroup) {
  2013. let value = ifcGroup[key]
  2014. let valueType = typeof value
  2015. if (valueType === 'string' || valueType === 'number' || valueType === 'boolean') {
  2016. groupData[key] = value
  2017. }
  2018. }
  2019. let groupName = ifcGroup.Name || ifcGroup.GlobalId
  2020. groupName = ifcGroup.constructor.name + '_' + groupName
  2021. for (let i = 0; i < ifcObjects.length; i++) {
  2022. let ifcObject = ifcObjects[i]
  2023. if (ifcObject.helper && ifcObject.helper.getObject3D) {
  2024. let object3D = ifcObject.helper.getObject3D()
  2025. object3D.userData['IFC_group_' + groupName] = groupData
  2026. }
  2027. }
  2028. }
  2029. }
  2030. registerIfcHelperClass(IfcRelAssignsToGroupHelper)
  2031. class IfcRelAggregatesHelper extends IfcRelationshipHelper {
  2032. constructor(instance) {
  2033. super(instance)
  2034. }
  2035. relate() {
  2036. const rel = this.instance
  2037. const schema = this.instance.constructor.schema
  2038. var ifcObject = rel.RelatingObject
  2039. if (ifcObject instanceof schema.IfcProduct) {
  2040. var containerObject3D = ifcObject.helper.getObject3D()
  2041. if (containerObject3D) {
  2042. for (var i = 0; i < rel.RelatedObjects.length; i++) {
  2043. var ifcRelatedObject = rel.RelatedObjects[i]
  2044. if (ifcRelatedObject instanceof schema.IfcProduct) {
  2045. var object3D = ifcRelatedObject.helper.getObject3D()
  2046. if (object3D) {
  2047. if (object3D.parent !== containerObject3D) {
  2048. containerObject3D.attach(object3D)
  2049. }
  2050. }
  2051. }
  2052. }
  2053. }
  2054. }
  2055. }
  2056. }
  2057. registerIfcHelperClass(IfcRelAggregatesHelper)
  2058. class IfcRelContainedInSpatialStructureHelper extends IfcRelationshipHelper {
  2059. constructor(instance) {
  2060. super(instance)
  2061. }
  2062. relate() {
  2063. const rel = this.instance
  2064. const schema = this.instance.constructor.schema
  2065. var ifcProduct = rel.RelatingStructure
  2066. if (ifcProduct) {
  2067. var containerObject3D = ifcProduct.helper.getObject3D()
  2068. if (containerObject3D) {
  2069. for (var i = 0; i < rel.RelatedElements.length; i++) {
  2070. var ifcRelatedProduct = rel.RelatedElements[i]
  2071. if (ifcRelatedProduct instanceof schema.IfcProduct) {
  2072. var object3D = ifcRelatedProduct.helper.getObject3D()
  2073. if (object3D) {
  2074. if (object3D.parent !== containerObject3D) {
  2075. var parentIFC = object3D.parent.userData.IFC || {}
  2076. if (parentIFC.ifcClassName === 'IfcOpeningElement') {
  2077. // do not change hierarchy
  2078. } else {
  2079. containerObject3D.attach(object3D)
  2080. }
  2081. }
  2082. }
  2083. }
  2084. }
  2085. }
  2086. }
  2087. }
  2088. }
  2089. registerIfcHelperClass(IfcRelContainedInSpatialStructureHelper)
  2090. class IfcRelVoidsElementHelper extends IfcRelationshipHelper {
  2091. constructor(instance) {
  2092. super(instance)
  2093. }
  2094. relate() {
  2095. var rel = this.instance
  2096. var element = rel.RelatingBuildingElement
  2097. var opening = rel.RelatedOpeningElement
  2098. if (element && opening) {
  2099. var object3D = element.helper.getObject3D()
  2100. if (object3D) {
  2101. var openingObject3D = opening.helper.getObject3D()
  2102. if (openingObject3D) {
  2103. if (object3D !== openingObject3D.parent) {
  2104. object3D.attach(openingObject3D)
  2105. }
  2106. }
  2107. }
  2108. }
  2109. }
  2110. }
  2111. registerIfcHelperClass(IfcRelVoidsElementHelper)
  2112. class IfcRelFillsElementHelper extends IfcRelationshipHelper {
  2113. constructor(instance) {
  2114. super(instance)
  2115. }
  2116. relate() {
  2117. var rel = this.instance
  2118. var opening = rel.RelatingOpeningElement
  2119. var element = rel.RelatedBuildingElement
  2120. if (element && opening) {
  2121. var object3D = element.helper.getObject3D()
  2122. if (object3D) {
  2123. var openingObject3D = opening.helper.getObject3D()
  2124. if (openingObject3D) {
  2125. if (object3D.parent !== openingObject3D) {
  2126. openingObject3D.attach(object3D)
  2127. }
  2128. }
  2129. }
  2130. }
  2131. }
  2132. }
  2133. registerIfcHelperClass(IfcRelFillsElementHelper)
  2134. class IfcRelConnectsPortToElementHelper extends IfcRelationshipHelper {
  2135. constructor(instance) {
  2136. super(instance)
  2137. }
  2138. relate() {
  2139. var rel = this.instance
  2140. var port = rel.RelatingPort
  2141. var element = rel.RelatedElement
  2142. if (port && element) {
  2143. var object3D = element.helper.getObject3D()
  2144. if (object3D) {
  2145. var portObject3D = port.helper.getObject3D()
  2146. if (portObject3D) {
  2147. if (object3D !== portObject3D.parent) {
  2148. object3D.attach(portObject3D)
  2149. }
  2150. }
  2151. }
  2152. }
  2153. }
  2154. }
  2155. registerIfcHelperClass(IfcRelConnectsPortToElementHelper)
  2156. class IfcRelDefinesByPropertiesHelper extends IfcRelationshipHelper {
  2157. constructor(instance) {
  2158. super(instance)
  2159. }
  2160. relate() {
  2161. const rel = this.instance
  2162. const schema = this.instance.constructor.schema
  2163. var propertySet = rel.RelatingPropertyDefinition
  2164. if (propertySet instanceof schema.IfcPropertySet) {
  2165. var psetName = propertySet.Name
  2166. var properties = propertySet.helper.getProperties()
  2167. var relatedObjects = rel.RelatedObjects
  2168. for (var i = 0; i < relatedObjects.length; i++) {
  2169. var relatedObject = relatedObjects[i]
  2170. if (relatedObject instanceof schema.IfcProduct) {
  2171. var object3D = relatedObject.helper.getObject3D()
  2172. if (object3D) {
  2173. object3D.userData['IFC_' + psetName] = properties
  2174. }
  2175. }
  2176. }
  2177. }
  2178. }
  2179. }
  2180. registerIfcHelperClass(IfcRelDefinesByPropertiesHelper)
  2181. /* Other helpers */
  2182. class IfcPointHelper extends IfcHelper {
  2183. constructor(instance) {
  2184. super(instance)
  2185. this.point = null
  2186. }
  2187. getPoint() {
  2188. if (this.point === null) {
  2189. this.point = new THREE.Vector3()
  2190. }
  2191. return this.point
  2192. }
  2193. }
  2194. registerIfcHelperClass(IfcPointHelper)
  2195. class IfcCartesianPointHelper extends IfcPointHelper {
  2196. constructor(instance) {
  2197. super(instance)
  2198. }
  2199. getPoint() {
  2200. if (this.point === null) {
  2201. var point = this.instance
  2202. this.point = new THREE.Vector3()
  2203. this.point.x = point.Coordinates[0]
  2204. if (point.Coordinates.length > 1) {
  2205. this.point.y = point.Coordinates[1]
  2206. if (point.Coordinates.length > 2) {
  2207. this.point.z = point.Coordinates[2]
  2208. }
  2209. }
  2210. }
  2211. return this.point
  2212. }
  2213. }
  2214. registerIfcHelperClass(IfcCartesianPointHelper)
  2215. class IfcDirectionHelper extends IfcHelper {
  2216. constructor(instance) {
  2217. super(instance)
  2218. this.direction = null
  2219. }
  2220. getDirection() {
  2221. if (this.direction === null) {
  2222. var direction = this.instance
  2223. this.direction = new THREE.Vector3()
  2224. this.direction.x = direction.DirectionRatios[0]
  2225. if (direction.DirectionRatios.length > 1) {
  2226. this.direction.y = direction.DirectionRatios[1]
  2227. if (direction.DirectionRatios.length > 2) {
  2228. this.direction.z = direction.DirectionRatios[2]
  2229. }
  2230. }
  2231. }
  2232. return this.direction
  2233. }
  2234. }
  2235. registerIfcHelperClass(IfcDirectionHelper)
  2236. class IfcPresentationLayerAssignmentHelper extends IfcHelper {
  2237. constructor(instance) {
  2238. super(instance)
  2239. }
  2240. assign() {
  2241. const assignment = this.instance
  2242. const schema = this.instance.constructor.schema
  2243. const layerName = assignment.Name
  2244. const layerDescription = assignment.Description
  2245. const assignedItems = assignment.AssignedItems
  2246. const identifier = assignment.Identifier
  2247. for (let assignedItem of assignedItems) {
  2248. if (assignedItem instanceof schema.IfcShapeRepresentation) {
  2249. let items = assignedItem.Items
  2250. for (let item of items) {
  2251. if (item.helper.getObject3D) {
  2252. try {
  2253. let object = item.helper.getObject3D()
  2254. if (object) {
  2255. object.userData.IFC_layer = {
  2256. Name: layerName,
  2257. Description: layerDescription,
  2258. Identifier: identifier
  2259. }
  2260. }
  2261. } catch (ex) {
  2262. console.info(ex)
  2263. console.info(item.helper)
  2264. }
  2265. }
  2266. }
  2267. }
  2268. }
  2269. }
  2270. }
  2271. registerIfcHelperClass(IfcPresentationLayerAssignmentHelper)
  2272. class IfcStyledItemHelper extends IfcHelper {
  2273. constructor(instance) {
  2274. super(instance)
  2275. this.properties = null
  2276. }
  2277. applyStyle() {
  2278. const styledItem = this.instance
  2279. const schema = this.instance.constructor.schema
  2280. var item = styledItem.Item // item to apply style
  2281. var styles = styledItem.Styles // style to apply
  2282. if (item === null || styles === null) return
  2283. var style = styles[0] // apply only first style
  2284. if (style instanceof schema.IfcPresentationStyleAssignment) {
  2285. style = style.Styles[0]
  2286. }
  2287. if (style instanceof schema.IfcSurfaceStyle) {
  2288. const material = style.helper.getMaterial()
  2289. if (item.helper && material) {
  2290. item.helper.material = material
  2291. }
  2292. }
  2293. }
  2294. }
  2295. registerIfcHelperClass(IfcStyledItemHelper)
  2296. class IfcSurfaceStyleHelper extends IfcHelper {
  2297. constructor(instance) {
  2298. super(instance)
  2299. this.material = null
  2300. }
  2301. getMaterial() {
  2302. if (this.material === null) {
  2303. const style = this.instance
  2304. const schema = this.instance.constructor.schema
  2305. const name = style.Name
  2306. const side = style.Side
  2307. const styleItem = style.Styles[0] // consider only first style item
  2308. if (styleItem instanceof schema.IfcSurfaceStyleShading) {
  2309. const color = styleItem.SurfaceColour
  2310. const transparency = styleItem.Transparency
  2311. const red = color.Red
  2312. const green = color.Green
  2313. const blue = color.Blue
  2314. let transparent = transparency > 0
  2315. let opacity = 1 - transparency
  2316. this.material = new THREE.MeshPhongMaterial({
  2317. name: name,
  2318. color: new THREE.Color(red, green, blue),
  2319. flatShading: false,
  2320. opacity: opacity,
  2321. transparent: transparent,
  2322. side: side === '.BOTH.' ? THREE.DoubleSide : THREE.FrontSide
  2323. })
  2324. }
  2325. }
  2326. return this.material
  2327. }
  2328. }
  2329. registerIfcHelperClass(IfcSurfaceStyleHelper)
  2330. class IfcPropertySetHelper extends IfcHelper {
  2331. constructor(instance) {
  2332. super(instance)
  2333. this.properties = null
  2334. }
  2335. getProperties() {
  2336. if (this.properties === null) {
  2337. const pset = this.instance
  2338. const schema = this.instance.constructor.schema
  2339. const loader = pset._loader
  2340. this.properties = {}
  2341. for (var i = 0; i < pset.HasProperties.length; i++) {
  2342. var prop = pset.HasProperties[i]
  2343. if (prop instanceof schema.IfcPropertySingleValue) {
  2344. var name = loader.unBox(prop.Name)
  2345. var value = loader.unBox(prop.NominalValue)
  2346. if (value === '.T.') {
  2347. value = true
  2348. } else if (value === '.F.') {
  2349. value = false
  2350. }
  2351. this.properties[name] = value
  2352. }
  2353. }
  2354. }
  2355. return this.properties
  2356. }
  2357. }
  2358. registerIfcHelperClass(IfcPropertySetHelper)
  2359. export { IFCLoader }