@itwin/core-geometry 4.9.0-dev.3 → 4.9.0-dev.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"BuildAverageNormalsContext.d.ts","sourceRoot":"","sources":["../../../../src/polyface/multiclip/BuildAverageNormalsContext.ts"],"names":[],"mappings":"AAIA;;GAEG;AAIH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AA8C/C;;;;GAIG;AAEH,qBAAa,0BAA0B;IACrC;;;;;;;;;OASG;WACW,uBAAuB,CAAC,QAAQ,EAAE,eAAe,EAAE,cAAc,EAAE,KAAK;IA6EtF;;;OAGG;WACW,mBAAmB,CAAC,QAAQ,EAAE,eAAe;CAmB5D"}
1
+ {"version":3,"file":"BuildAverageNormalsContext.d.ts","sourceRoot":"","sources":["../../../../src/polyface/multiclip/BuildAverageNormalsContext.ts"],"names":[],"mappings":"AAIA;;GAEG;AAIH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AA8C/C;;;;GAIG;AAEH,qBAAa,0BAA0B;IACrC;;;;;;;;;OASG;WACW,uBAAuB,CAAC,QAAQ,EAAE,eAAe,EAAE,cAAc,EAAE,KAAK;IAkFtF;;;OAGG;WACW,mBAAmB,CAAC,QAAQ,EAAE,eAAe;CAmB5D"}
@@ -74,14 +74,21 @@ class BuildAverageNormalsContext {
74
74
  // create one IndexedAreaNormal structure for each facet.
75
75
  // At each sector of each face, notate (a) IndexedAreaNormal of the facet, (b) the sector index, (c) the point index.
76
76
  while (visitor.moveToNextFacet()) {
77
- const facetNormal = PolygonOps_1.PolygonOps.areaNormalGo(visitor.point);
78
- let area = facetNormal.magnitude();
79
- if (area < smallArea) {
80
- facetNormal.setFromVector3d(defaultNormal);
77
+ let facetNormal = PolygonOps_1.PolygonOps.areaNormalGo(visitor.point);
78
+ let area = 0.0;
79
+ if (!facetNormal) {
80
+ facetNormal = defaultNormal.clone();
81
81
  area = 0.0;
82
82
  }
83
83
  else {
84
- facetNormal.scaleInPlace(1.0 / area);
84
+ area = facetNormal.magnitude();
85
+ if (area < smallArea) {
86
+ facetNormal.setFromVector3d(defaultNormal);
87
+ area = 0.0;
88
+ }
89
+ else {
90
+ facetNormal.scaleInPlace(1.0 / area);
91
+ }
85
92
  }
86
93
  const facetData = new IndexedAreaAndNormal(facetIndex++, area, facetNormal);
87
94
  for (let i = 0; i < visitor.pointCount; i++) {
@@ -107,7 +114,7 @@ class BuildAverageNormalsContext {
107
114
  const clusterNormal = new IndexedAreaAndNormal(clusterIndex++, 0.0, Point3dVector3d_1.Vector3d.createZero());
108
115
  clusters.push(clusterNormal);
109
116
  // Accumulate with equal weights . . .
110
- clusterNormal.addWeightedNormal(1.0, baseData.facetData.normal.clone());
117
+ clusterNormal.addWeightedNormal(1.0, baseData.facetData.normal);
111
118
  for (let candidateSectorIndex = baseSectorIndex; candidateSectorIndex < sectors.length; candidateSectorIndex++) {
112
119
  const candidateSector = sectors[candidateSectorIndex];
113
120
  if (candidateSector.vertexIndex !== vertexIndex)
@@ -1 +1 @@
1
- {"version":3,"file":"BuildAverageNormalsContext.js","sourceRoot":"","sources":["../../../../src/polyface/multiclip/BuildAverageNormalsContext.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Polyface\r\n */\r\n\r\nimport { Vector3d } from \"../../geometry3d/Point3dVector3d\";\r\nimport { PolygonOps } from \"../../geometry3d/PolygonOps\";\r\nimport { IndexedPolyface } from \"../Polyface\";\r\nimport { Geometry } from \"../../Geometry\";\r\nimport { GrowableXYZArray } from \"../../geometry3d/GrowableXYZArray\";\r\nimport { Angle } from \"../../geometry3d/Angle\";\r\n\r\n/**\r\n * Normal vector with area (or other numeric) and source index\r\n * @internal\r\n */\r\nclass IndexedAreaAndNormal {\r\n public constructor(index: number, area: number, normal: Vector3d) {\r\n this.index = index;\r\n this.area = area;\r\n this.normal = normal;\r\n }\r\n public index: number;\r\n public area: number;\r\n public normal: Vector3d;\r\n\r\n public addWeightedNormal(weight: number, normal: Vector3d) {\r\n this.area += weight;\r\n this.normal.addScaledInPlace(normal, weight);\r\n }\r\n public divideNormalByArea() {\r\n this.normal.scaleInPlace(1.0 / this.area);\r\n }\r\n}\r\n\r\n/**\r\n * index data for a single sector of some facet.\r\n * @internal\r\n */\r\nclass SectorData {\r\n private constructor(facetData: IndexedAreaAndNormal, sectorIndex: number, vertexIndex: number) {\r\n this.facetData = facetData;\r\n this.sectorClusterData = undefined;\r\n this.sectorIndex = sectorIndex;\r\n this.vertexIndex = vertexIndex;\r\n }\r\n public facetData: IndexedAreaAndNormal;\r\n public sectorIndex: number;\r\n public vertexIndex: number;\r\n public sectorClusterData: IndexedAreaAndNormal | undefined;\r\n public static cbSectorSort(left: SectorData, right: SectorData): number { return left.sectorIndex - right.sectorIndex; }\r\n public static cbVertexSort(left: SectorData, right: SectorData): number { return left.vertexIndex - right.vertexIndex; }\r\n public static pushToArray(data: SectorData[], facetData: IndexedAreaAndNormal, sectorIndex: number, vertexIndex: number) {\r\n data.push(new SectorData(facetData, sectorIndex, vertexIndex));\r\n }\r\n}\r\n/**\r\n * Helper context for normal averaging.\r\n * All methods are static.\r\n * @internal\r\n */\r\n\r\nexport class BuildAverageNormalsContext {\r\n /**\r\n * * At each vertex of the mesh\r\n * * Find clusters of almost parallel normals\r\n * * Compute simple average of those normals\r\n * * Index to the averages\r\n * * For typical meshes, this correctly clusters adjacent normals.\r\n * * One cam imagine a vertex with multiple \"smooth cone-like\" sets of incident facets such that averaging occurs among two nonadjacent cones. But this does not seem to be a problem in practice.\r\n * @param polyface polyface to update.\r\n * @param toleranceAngle averaging is done between normals up to this angle.\r\n */\r\n public static buildFastAverageNormals(polyface: IndexedPolyface, toleranceAngle: Angle) {\r\n // We ASSUME that the visitor order matches index order in polyface.data .....\r\n const visitor = polyface.createVisitor(0);\r\n const defaultNormal = Vector3d.create(0, 0, 1);\r\n const smallArea = Geometry.smallMetricDistanceSquared; // I DO NOT LIKE THIS TOLERANCE\r\n const sectors: SectorData[] = [];\r\n let facetIndex = 0;\r\n let sectorIndex = 0;\r\n // create one IndexedAreaNormal structure for each facet.\r\n // At each sector of each face, notate (a) IndexedAreaNormal of the facet, (b) the sector index, (c) the point index.\r\n\r\n while (visitor.moveToNextFacet()) {\r\n const facetNormal = PolygonOps.areaNormalGo(visitor.point)!;\r\n let area = facetNormal.magnitude();\r\n if (area < smallArea) {\r\n facetNormal.setFromVector3d(defaultNormal);\r\n area = 0.0;\r\n } else {\r\n facetNormal.scaleInPlace(1.0 / area);\r\n }\r\n const facetData = new IndexedAreaAndNormal(facetIndex++, area, facetNormal);\r\n for (let i = 0; i < visitor.pointCount; i++) {\r\n SectorData.pushToArray(sectors, facetData, sectorIndex++, visitor.clientPointIndex(i));\r\n }\r\n }\r\n // Sort by the vertex index so all the sectors around each vertex are clustered . .\r\n sectors.sort((left, right) => SectorData.cbVertexSort(left, right));\r\n\r\n // Walk the sectors around each vertex . ..\r\n // For each unassigned sector\r\n // walk to further sectors of the same vertex with near-parallel normals, accumulating average normal.\r\n // notate all sectors in the cluster with the averaged-normal structure.\r\n const clusters: IndexedAreaAndNormal[] = [];\r\n let toleranceRadians = toleranceAngle.radians;\r\n if (toleranceRadians < 0.0001)\r\n toleranceRadians = 0.0001;\r\n\r\n let clusterIndex = 0;\r\n for (let baseSectorIndex = 0; baseSectorIndex < sectors.length; baseSectorIndex++) {\r\n const baseData = sectors[baseSectorIndex];\r\n const vertexIndex = baseData.vertexIndex;\r\n const baseFacetData = baseData.facetData;\r\n if (baseData.sectorClusterData === undefined) {\r\n const clusterNormal = new IndexedAreaAndNormal(clusterIndex++, 0.0, Vector3d.createZero());\r\n clusters.push(clusterNormal);\r\n // Accumulate with equal weights . . .\r\n clusterNormal.addWeightedNormal(1.0, baseData.facetData.normal.clone());\r\n for (let candidateSectorIndex = baseSectorIndex;\r\n candidateSectorIndex < sectors.length;\r\n candidateSectorIndex++) {\r\n const candidateSector = sectors[candidateSectorIndex];\r\n if (candidateSector.vertexIndex !== vertexIndex)\r\n break;\r\n if (candidateSector.facetData.normal.angleTo(baseFacetData.normal).radians > toleranceRadians)\r\n continue;\r\n if (candidateSector.sectorClusterData === undefined) {\r\n clusterNormal.addWeightedNormal(1.0, candidateSector.facetData.normal);\r\n candidateSector.sectorClusterData = clusterNormal;\r\n }\r\n }\r\n }\r\n }\r\n // Resort by original sector index.\r\n sectors.sort((left, right) => SectorData.cbSectorSort(left, right));\r\n // normalize the sums and emplace in the facets . . .\r\n polyface.data.normalIndex = [];\r\n polyface.data.normal = new GrowableXYZArray(sectors.length);\r\n for (const cluster of clusters) {\r\n cluster.divideNormalByArea();\r\n cluster.index = polyface.data.normal.length;\r\n polyface.data.normal.push(cluster.normal);\r\n }\r\n // emplace the indices\r\n for (const sector of sectors) {\r\n polyface.data.normalIndex.push(sector.sectorClusterData!.index);\r\n }\r\n }\r\n /**\r\n * Set up indexed normals with one normal in the plane of each facet of the mesh.\r\n * @param polyface mesh to modify\r\n */\r\n public static buildPerFaceNormals(polyface: IndexedPolyface) {\r\n const visitor = polyface.createVisitor(0);\r\n const facetNormal = Vector3d.create(0, 0, 1);\r\n const defaultNormal = Vector3d.create(0, 0, 1);\r\n // polyface.data.clearNormals();\r\n const newNormals = new GrowableXYZArray(polyface.faceCount);\r\n const newIndices: number[] = [];\r\n while (visitor.moveToNextFacet()) {\r\n const thisNormalIndex = newNormals.length;\r\n if (PolygonOps.unitNormal(visitor.point, facetNormal))\r\n newNormals.push(facetNormal);\r\n else\r\n newNormals.push(defaultNormal);\r\n for (let i = 0; i < visitor.pointCount; i++)\r\n newIndices.push(thisNormalIndex);\r\n }\r\n polyface.data.normalIndex = newIndices;\r\n polyface.data.normal = newNormals;\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"BuildAverageNormalsContext.js","sourceRoot":"","sources":["../../../../src/polyface/multiclip/BuildAverageNormalsContext.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Polyface\r\n */\r\n\r\nimport { Vector3d } from \"../../geometry3d/Point3dVector3d\";\r\nimport { PolygonOps } from \"../../geometry3d/PolygonOps\";\r\nimport { IndexedPolyface } from \"../Polyface\";\r\nimport { Geometry } from \"../../Geometry\";\r\nimport { GrowableXYZArray } from \"../../geometry3d/GrowableXYZArray\";\r\nimport { Angle } from \"../../geometry3d/Angle\";\r\n\r\n/**\r\n * Normal vector with area (or other numeric) and source index\r\n * @internal\r\n */\r\nclass IndexedAreaAndNormal {\r\n public constructor(index: number, area: number, normal: Vector3d) {\r\n this.index = index;\r\n this.area = area;\r\n this.normal = normal;\r\n }\r\n public index: number;\r\n public area: number;\r\n public normal: Vector3d;\r\n\r\n public addWeightedNormal(weight: number, normal: Vector3d) {\r\n this.area += weight;\r\n this.normal.addScaledInPlace(normal, weight);\r\n }\r\n public divideNormalByArea() {\r\n this.normal.scaleInPlace(1.0 / this.area);\r\n }\r\n}\r\n\r\n/**\r\n * index data for a single sector of some facet.\r\n * @internal\r\n */\r\nclass SectorData {\r\n private constructor(facetData: IndexedAreaAndNormal, sectorIndex: number, vertexIndex: number) {\r\n this.facetData = facetData;\r\n this.sectorClusterData = undefined;\r\n this.sectorIndex = sectorIndex;\r\n this.vertexIndex = vertexIndex;\r\n }\r\n public facetData: IndexedAreaAndNormal;\r\n public sectorIndex: number;\r\n public vertexIndex: number;\r\n public sectorClusterData: IndexedAreaAndNormal | undefined;\r\n public static cbSectorSort(left: SectorData, right: SectorData): number { return left.sectorIndex - right.sectorIndex; }\r\n public static cbVertexSort(left: SectorData, right: SectorData): number { return left.vertexIndex - right.vertexIndex; }\r\n public static pushToArray(data: SectorData[], facetData: IndexedAreaAndNormal, sectorIndex: number, vertexIndex: number) {\r\n data.push(new SectorData(facetData, sectorIndex, vertexIndex));\r\n }\r\n}\r\n/**\r\n * Helper context for normal averaging.\r\n * All methods are static.\r\n * @internal\r\n */\r\n\r\nexport class BuildAverageNormalsContext {\r\n /**\r\n * * At each vertex of the mesh\r\n * * Find clusters of almost parallel normals\r\n * * Compute simple average of those normals\r\n * * Index to the averages\r\n * * For typical meshes, this correctly clusters adjacent normals.\r\n * * One cam imagine a vertex with multiple \"smooth cone-like\" sets of incident facets such that averaging occurs among two nonadjacent cones. But this does not seem to be a problem in practice.\r\n * @param polyface polyface to update.\r\n * @param toleranceAngle averaging is done between normals up to this angle.\r\n */\r\n public static buildFastAverageNormals(polyface: IndexedPolyface, toleranceAngle: Angle) {\r\n // We ASSUME that the visitor order matches index order in polyface.data .....\r\n const visitor = polyface.createVisitor(0);\r\n const defaultNormal = Vector3d.create(0, 0, 1);\r\n const smallArea = Geometry.smallMetricDistanceSquared; // I DO NOT LIKE THIS TOLERANCE\r\n const sectors: SectorData[] = [];\r\n let facetIndex = 0;\r\n let sectorIndex = 0;\r\n // create one IndexedAreaNormal structure for each facet.\r\n // At each sector of each face, notate (a) IndexedAreaNormal of the facet, (b) the sector index, (c) the point index.\r\n while (visitor.moveToNextFacet()) {\r\n let facetNormal = PolygonOps.areaNormalGo(visitor.point);\r\n let area = 0.0;\r\n if (!facetNormal) {\r\n facetNormal = defaultNormal.clone();\r\n area = 0.0;\r\n } else {\r\n area = facetNormal.magnitude();\r\n if (area < smallArea) {\r\n facetNormal.setFromVector3d(defaultNormal);\r\n area = 0.0;\r\n } else {\r\n facetNormal.scaleInPlace(1.0 / area);\r\n }\r\n }\r\n const facetData = new IndexedAreaAndNormal(facetIndex++, area, facetNormal);\r\n for (let i = 0; i < visitor.pointCount; i++) {\r\n SectorData.pushToArray(sectors, facetData, sectorIndex++, visitor.clientPointIndex(i));\r\n }\r\n }\r\n // Sort by the vertex index so all the sectors around each vertex are clustered . .\r\n sectors.sort((left, right) => SectorData.cbVertexSort(left, right));\r\n\r\n // Walk the sectors around each vertex . ..\r\n // For each unassigned sector\r\n // walk to further sectors of the same vertex with near-parallel normals, accumulating average normal.\r\n // notate all sectors in the cluster with the averaged-normal structure.\r\n const clusters: IndexedAreaAndNormal[] = [];\r\n let toleranceRadians = toleranceAngle.radians;\r\n if (toleranceRadians < 0.0001)\r\n toleranceRadians = 0.0001;\r\n\r\n let clusterIndex = 0;\r\n for (let baseSectorIndex = 0; baseSectorIndex < sectors.length; baseSectorIndex++) {\r\n const baseData = sectors[baseSectorIndex];\r\n const vertexIndex = baseData.vertexIndex;\r\n const baseFacetData = baseData.facetData;\r\n if (baseData.sectorClusterData === undefined) {\r\n const clusterNormal = new IndexedAreaAndNormal(clusterIndex++, 0.0, Vector3d.createZero());\r\n clusters.push(clusterNormal);\r\n // Accumulate with equal weights . . .\r\n clusterNormal.addWeightedNormal(1.0, baseData.facetData.normal);\r\n for (let candidateSectorIndex = baseSectorIndex;\r\n candidateSectorIndex < sectors.length;\r\n candidateSectorIndex++) {\r\n const candidateSector = sectors[candidateSectorIndex];\r\n if (candidateSector.vertexIndex !== vertexIndex)\r\n break;\r\n if (candidateSector.facetData.normal.angleTo(baseFacetData.normal).radians > toleranceRadians)\r\n continue;\r\n if (candidateSector.sectorClusterData === undefined) {\r\n clusterNormal.addWeightedNormal(1.0, candidateSector.facetData.normal);\r\n candidateSector.sectorClusterData = clusterNormal;\r\n }\r\n }\r\n }\r\n }\r\n // Resort by original sector index.\r\n sectors.sort((left, right) => SectorData.cbSectorSort(left, right));\r\n // normalize the sums and emplace in the facets . . .\r\n polyface.data.normalIndex = [];\r\n polyface.data.normal = new GrowableXYZArray(sectors.length);\r\n for (const cluster of clusters) {\r\n cluster.divideNormalByArea();\r\n cluster.index = polyface.data.normal.length;\r\n polyface.data.normal.push(cluster.normal);\r\n }\r\n // emplace the indices\r\n for (const sector of sectors) {\r\n polyface.data.normalIndex.push(sector.sectorClusterData!.index);\r\n }\r\n }\r\n /**\r\n * Set up indexed normals with one normal in the plane of each facet of the mesh.\r\n * @param polyface mesh to modify\r\n */\r\n public static buildPerFaceNormals(polyface: IndexedPolyface) {\r\n const visitor = polyface.createVisitor(0);\r\n const facetNormal = Vector3d.create(0, 0, 1);\r\n const defaultNormal = Vector3d.create(0, 0, 1);\r\n // polyface.data.clearNormals();\r\n const newNormals = new GrowableXYZArray(polyface.faceCount);\r\n const newIndices: number[] = [];\r\n while (visitor.moveToNextFacet()) {\r\n const thisNormalIndex = newNormals.length;\r\n if (PolygonOps.unitNormal(visitor.point, facetNormal))\r\n newNormals.push(facetNormal);\r\n else\r\n newNormals.push(defaultNormal);\r\n for (let i = 0; i < visitor.pointCount; i++)\r\n newIndices.push(thisNormalIndex);\r\n }\r\n polyface.data.normalIndex = newIndices;\r\n polyface.data.normal = newNormals;\r\n }\r\n}\r\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"BuildAverageNormalsContext.d.ts","sourceRoot":"","sources":["../../../../src/polyface/multiclip/BuildAverageNormalsContext.ts"],"names":[],"mappings":"AAIA;;GAEG;AAIH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AA8C/C;;;;GAIG;AAEH,qBAAa,0BAA0B;IACrC;;;;;;;;;OASG;WACW,uBAAuB,CAAC,QAAQ,EAAE,eAAe,EAAE,cAAc,EAAE,KAAK;IA6EtF;;;OAGG;WACW,mBAAmB,CAAC,QAAQ,EAAE,eAAe;CAmB5D"}
1
+ {"version":3,"file":"BuildAverageNormalsContext.d.ts","sourceRoot":"","sources":["../../../../src/polyface/multiclip/BuildAverageNormalsContext.ts"],"names":[],"mappings":"AAIA;;GAEG;AAIH,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAG9C,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AA8C/C;;;;GAIG;AAEH,qBAAa,0BAA0B;IACrC;;;;;;;;;OASG;WACW,uBAAuB,CAAC,QAAQ,EAAE,eAAe,EAAE,cAAc,EAAE,KAAK;IAkFtF;;;OAGG;WACW,mBAAmB,CAAC,QAAQ,EAAE,eAAe;CAmB5D"}
@@ -71,14 +71,21 @@ export class BuildAverageNormalsContext {
71
71
  // create one IndexedAreaNormal structure for each facet.
72
72
  // At each sector of each face, notate (a) IndexedAreaNormal of the facet, (b) the sector index, (c) the point index.
73
73
  while (visitor.moveToNextFacet()) {
74
- const facetNormal = PolygonOps.areaNormalGo(visitor.point);
75
- let area = facetNormal.magnitude();
76
- if (area < smallArea) {
77
- facetNormal.setFromVector3d(defaultNormal);
74
+ let facetNormal = PolygonOps.areaNormalGo(visitor.point);
75
+ let area = 0.0;
76
+ if (!facetNormal) {
77
+ facetNormal = defaultNormal.clone();
78
78
  area = 0.0;
79
79
  }
80
80
  else {
81
- facetNormal.scaleInPlace(1.0 / area);
81
+ area = facetNormal.magnitude();
82
+ if (area < smallArea) {
83
+ facetNormal.setFromVector3d(defaultNormal);
84
+ area = 0.0;
85
+ }
86
+ else {
87
+ facetNormal.scaleInPlace(1.0 / area);
88
+ }
82
89
  }
83
90
  const facetData = new IndexedAreaAndNormal(facetIndex++, area, facetNormal);
84
91
  for (let i = 0; i < visitor.pointCount; i++) {
@@ -104,7 +111,7 @@ export class BuildAverageNormalsContext {
104
111
  const clusterNormal = new IndexedAreaAndNormal(clusterIndex++, 0.0, Vector3d.createZero());
105
112
  clusters.push(clusterNormal);
106
113
  // Accumulate with equal weights . . .
107
- clusterNormal.addWeightedNormal(1.0, baseData.facetData.normal.clone());
114
+ clusterNormal.addWeightedNormal(1.0, baseData.facetData.normal);
108
115
  for (let candidateSectorIndex = baseSectorIndex; candidateSectorIndex < sectors.length; candidateSectorIndex++) {
109
116
  const candidateSector = sectors[candidateSectorIndex];
110
117
  if (candidateSector.vertexIndex !== vertexIndex)
@@ -1 +1 @@
1
- {"version":3,"file":"BuildAverageNormalsContext.js","sourceRoot":"","sources":["../../../../src/polyface/multiclip/BuildAverageNormalsContext.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Polyface\r\n */\r\n\r\nimport { Vector3d } from \"../../geometry3d/Point3dVector3d\";\r\nimport { PolygonOps } from \"../../geometry3d/PolygonOps\";\r\nimport { IndexedPolyface } from \"../Polyface\";\r\nimport { Geometry } from \"../../Geometry\";\r\nimport { GrowableXYZArray } from \"../../geometry3d/GrowableXYZArray\";\r\nimport { Angle } from \"../../geometry3d/Angle\";\r\n\r\n/**\r\n * Normal vector with area (or other numeric) and source index\r\n * @internal\r\n */\r\nclass IndexedAreaAndNormal {\r\n public constructor(index: number, area: number, normal: Vector3d) {\r\n this.index = index;\r\n this.area = area;\r\n this.normal = normal;\r\n }\r\n public index: number;\r\n public area: number;\r\n public normal: Vector3d;\r\n\r\n public addWeightedNormal(weight: number, normal: Vector3d) {\r\n this.area += weight;\r\n this.normal.addScaledInPlace(normal, weight);\r\n }\r\n public divideNormalByArea() {\r\n this.normal.scaleInPlace(1.0 / this.area);\r\n }\r\n}\r\n\r\n/**\r\n * index data for a single sector of some facet.\r\n * @internal\r\n */\r\nclass SectorData {\r\n private constructor(facetData: IndexedAreaAndNormal, sectorIndex: number, vertexIndex: number) {\r\n this.facetData = facetData;\r\n this.sectorClusterData = undefined;\r\n this.sectorIndex = sectorIndex;\r\n this.vertexIndex = vertexIndex;\r\n }\r\n public facetData: IndexedAreaAndNormal;\r\n public sectorIndex: number;\r\n public vertexIndex: number;\r\n public sectorClusterData: IndexedAreaAndNormal | undefined;\r\n public static cbSectorSort(left: SectorData, right: SectorData): number { return left.sectorIndex - right.sectorIndex; }\r\n public static cbVertexSort(left: SectorData, right: SectorData): number { return left.vertexIndex - right.vertexIndex; }\r\n public static pushToArray(data: SectorData[], facetData: IndexedAreaAndNormal, sectorIndex: number, vertexIndex: number) {\r\n data.push(new SectorData(facetData, sectorIndex, vertexIndex));\r\n }\r\n}\r\n/**\r\n * Helper context for normal averaging.\r\n * All methods are static.\r\n * @internal\r\n */\r\n\r\nexport class BuildAverageNormalsContext {\r\n /**\r\n * * At each vertex of the mesh\r\n * * Find clusters of almost parallel normals\r\n * * Compute simple average of those normals\r\n * * Index to the averages\r\n * * For typical meshes, this correctly clusters adjacent normals.\r\n * * One cam imagine a vertex with multiple \"smooth cone-like\" sets of incident facets such that averaging occurs among two nonadjacent cones. But this does not seem to be a problem in practice.\r\n * @param polyface polyface to update.\r\n * @param toleranceAngle averaging is done between normals up to this angle.\r\n */\r\n public static buildFastAverageNormals(polyface: IndexedPolyface, toleranceAngle: Angle) {\r\n // We ASSUME that the visitor order matches index order in polyface.data .....\r\n const visitor = polyface.createVisitor(0);\r\n const defaultNormal = Vector3d.create(0, 0, 1);\r\n const smallArea = Geometry.smallMetricDistanceSquared; // I DO NOT LIKE THIS TOLERANCE\r\n const sectors: SectorData[] = [];\r\n let facetIndex = 0;\r\n let sectorIndex = 0;\r\n // create one IndexedAreaNormal structure for each facet.\r\n // At each sector of each face, notate (a) IndexedAreaNormal of the facet, (b) the sector index, (c) the point index.\r\n\r\n while (visitor.moveToNextFacet()) {\r\n const facetNormal = PolygonOps.areaNormalGo(visitor.point)!;\r\n let area = facetNormal.magnitude();\r\n if (area < smallArea) {\r\n facetNormal.setFromVector3d(defaultNormal);\r\n area = 0.0;\r\n } else {\r\n facetNormal.scaleInPlace(1.0 / area);\r\n }\r\n const facetData = new IndexedAreaAndNormal(facetIndex++, area, facetNormal);\r\n for (let i = 0; i < visitor.pointCount; i++) {\r\n SectorData.pushToArray(sectors, facetData, sectorIndex++, visitor.clientPointIndex(i));\r\n }\r\n }\r\n // Sort by the vertex index so all the sectors around each vertex are clustered . .\r\n sectors.sort((left, right) => SectorData.cbVertexSort(left, right));\r\n\r\n // Walk the sectors around each vertex . ..\r\n // For each unassigned sector\r\n // walk to further sectors of the same vertex with near-parallel normals, accumulating average normal.\r\n // notate all sectors in the cluster with the averaged-normal structure.\r\n const clusters: IndexedAreaAndNormal[] = [];\r\n let toleranceRadians = toleranceAngle.radians;\r\n if (toleranceRadians < 0.0001)\r\n toleranceRadians = 0.0001;\r\n\r\n let clusterIndex = 0;\r\n for (let baseSectorIndex = 0; baseSectorIndex < sectors.length; baseSectorIndex++) {\r\n const baseData = sectors[baseSectorIndex];\r\n const vertexIndex = baseData.vertexIndex;\r\n const baseFacetData = baseData.facetData;\r\n if (baseData.sectorClusterData === undefined) {\r\n const clusterNormal = new IndexedAreaAndNormal(clusterIndex++, 0.0, Vector3d.createZero());\r\n clusters.push(clusterNormal);\r\n // Accumulate with equal weights . . .\r\n clusterNormal.addWeightedNormal(1.0, baseData.facetData.normal.clone());\r\n for (let candidateSectorIndex = baseSectorIndex;\r\n candidateSectorIndex < sectors.length;\r\n candidateSectorIndex++) {\r\n const candidateSector = sectors[candidateSectorIndex];\r\n if (candidateSector.vertexIndex !== vertexIndex)\r\n break;\r\n if (candidateSector.facetData.normal.angleTo(baseFacetData.normal).radians > toleranceRadians)\r\n continue;\r\n if (candidateSector.sectorClusterData === undefined) {\r\n clusterNormal.addWeightedNormal(1.0, candidateSector.facetData.normal);\r\n candidateSector.sectorClusterData = clusterNormal;\r\n }\r\n }\r\n }\r\n }\r\n // Resort by original sector index.\r\n sectors.sort((left, right) => SectorData.cbSectorSort(left, right));\r\n // normalize the sums and emplace in the facets . . .\r\n polyface.data.normalIndex = [];\r\n polyface.data.normal = new GrowableXYZArray(sectors.length);\r\n for (const cluster of clusters) {\r\n cluster.divideNormalByArea();\r\n cluster.index = polyface.data.normal.length;\r\n polyface.data.normal.push(cluster.normal);\r\n }\r\n // emplace the indices\r\n for (const sector of sectors) {\r\n polyface.data.normalIndex.push(sector.sectorClusterData!.index);\r\n }\r\n }\r\n /**\r\n * Set up indexed normals with one normal in the plane of each facet of the mesh.\r\n * @param polyface mesh to modify\r\n */\r\n public static buildPerFaceNormals(polyface: IndexedPolyface) {\r\n const visitor = polyface.createVisitor(0);\r\n const facetNormal = Vector3d.create(0, 0, 1);\r\n const defaultNormal = Vector3d.create(0, 0, 1);\r\n // polyface.data.clearNormals();\r\n const newNormals = new GrowableXYZArray(polyface.faceCount);\r\n const newIndices: number[] = [];\r\n while (visitor.moveToNextFacet()) {\r\n const thisNormalIndex = newNormals.length;\r\n if (PolygonOps.unitNormal(visitor.point, facetNormal))\r\n newNormals.push(facetNormal);\r\n else\r\n newNormals.push(defaultNormal);\r\n for (let i = 0; i < visitor.pointCount; i++)\r\n newIndices.push(thisNormalIndex);\r\n }\r\n polyface.data.normalIndex = newIndices;\r\n polyface.data.normal = newNormals;\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"BuildAverageNormalsContext.js","sourceRoot":"","sources":["../../../../src/polyface/multiclip/BuildAverageNormalsContext.ts"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\r\n* Copyright (c) Bentley Systems, Incorporated. All rights reserved.\r\n* See LICENSE.md in the project root for license terms and full copyright notice.\r\n*--------------------------------------------------------------------------------------------*/\r\n/** @packageDocumentation\r\n * @module Polyface\r\n */\r\n\r\nimport { Vector3d } from \"../../geometry3d/Point3dVector3d\";\r\nimport { PolygonOps } from \"../../geometry3d/PolygonOps\";\r\nimport { IndexedPolyface } from \"../Polyface\";\r\nimport { Geometry } from \"../../Geometry\";\r\nimport { GrowableXYZArray } from \"../../geometry3d/GrowableXYZArray\";\r\nimport { Angle } from \"../../geometry3d/Angle\";\r\n\r\n/**\r\n * Normal vector with area (or other numeric) and source index\r\n * @internal\r\n */\r\nclass IndexedAreaAndNormal {\r\n public constructor(index: number, area: number, normal: Vector3d) {\r\n this.index = index;\r\n this.area = area;\r\n this.normal = normal;\r\n }\r\n public index: number;\r\n public area: number;\r\n public normal: Vector3d;\r\n\r\n public addWeightedNormal(weight: number, normal: Vector3d) {\r\n this.area += weight;\r\n this.normal.addScaledInPlace(normal, weight);\r\n }\r\n public divideNormalByArea() {\r\n this.normal.scaleInPlace(1.0 / this.area);\r\n }\r\n}\r\n\r\n/**\r\n * index data for a single sector of some facet.\r\n * @internal\r\n */\r\nclass SectorData {\r\n private constructor(facetData: IndexedAreaAndNormal, sectorIndex: number, vertexIndex: number) {\r\n this.facetData = facetData;\r\n this.sectorClusterData = undefined;\r\n this.sectorIndex = sectorIndex;\r\n this.vertexIndex = vertexIndex;\r\n }\r\n public facetData: IndexedAreaAndNormal;\r\n public sectorIndex: number;\r\n public vertexIndex: number;\r\n public sectorClusterData: IndexedAreaAndNormal | undefined;\r\n public static cbSectorSort(left: SectorData, right: SectorData): number { return left.sectorIndex - right.sectorIndex; }\r\n public static cbVertexSort(left: SectorData, right: SectorData): number { return left.vertexIndex - right.vertexIndex; }\r\n public static pushToArray(data: SectorData[], facetData: IndexedAreaAndNormal, sectorIndex: number, vertexIndex: number) {\r\n data.push(new SectorData(facetData, sectorIndex, vertexIndex));\r\n }\r\n}\r\n/**\r\n * Helper context for normal averaging.\r\n * All methods are static.\r\n * @internal\r\n */\r\n\r\nexport class BuildAverageNormalsContext {\r\n /**\r\n * * At each vertex of the mesh\r\n * * Find clusters of almost parallel normals\r\n * * Compute simple average of those normals\r\n * * Index to the averages\r\n * * For typical meshes, this correctly clusters adjacent normals.\r\n * * One cam imagine a vertex with multiple \"smooth cone-like\" sets of incident facets such that averaging occurs among two nonadjacent cones. But this does not seem to be a problem in practice.\r\n * @param polyface polyface to update.\r\n * @param toleranceAngle averaging is done between normals up to this angle.\r\n */\r\n public static buildFastAverageNormals(polyface: IndexedPolyface, toleranceAngle: Angle) {\r\n // We ASSUME that the visitor order matches index order in polyface.data .....\r\n const visitor = polyface.createVisitor(0);\r\n const defaultNormal = Vector3d.create(0, 0, 1);\r\n const smallArea = Geometry.smallMetricDistanceSquared; // I DO NOT LIKE THIS TOLERANCE\r\n const sectors: SectorData[] = [];\r\n let facetIndex = 0;\r\n let sectorIndex = 0;\r\n // create one IndexedAreaNormal structure for each facet.\r\n // At each sector of each face, notate (a) IndexedAreaNormal of the facet, (b) the sector index, (c) the point index.\r\n while (visitor.moveToNextFacet()) {\r\n let facetNormal = PolygonOps.areaNormalGo(visitor.point);\r\n let area = 0.0;\r\n if (!facetNormal) {\r\n facetNormal = defaultNormal.clone();\r\n area = 0.0;\r\n } else {\r\n area = facetNormal.magnitude();\r\n if (area < smallArea) {\r\n facetNormal.setFromVector3d(defaultNormal);\r\n area = 0.0;\r\n } else {\r\n facetNormal.scaleInPlace(1.0 / area);\r\n }\r\n }\r\n const facetData = new IndexedAreaAndNormal(facetIndex++, area, facetNormal);\r\n for (let i = 0; i < visitor.pointCount; i++) {\r\n SectorData.pushToArray(sectors, facetData, sectorIndex++, visitor.clientPointIndex(i));\r\n }\r\n }\r\n // Sort by the vertex index so all the sectors around each vertex are clustered . .\r\n sectors.sort((left, right) => SectorData.cbVertexSort(left, right));\r\n\r\n // Walk the sectors around each vertex . ..\r\n // For each unassigned sector\r\n // walk to further sectors of the same vertex with near-parallel normals, accumulating average normal.\r\n // notate all sectors in the cluster with the averaged-normal structure.\r\n const clusters: IndexedAreaAndNormal[] = [];\r\n let toleranceRadians = toleranceAngle.radians;\r\n if (toleranceRadians < 0.0001)\r\n toleranceRadians = 0.0001;\r\n\r\n let clusterIndex = 0;\r\n for (let baseSectorIndex = 0; baseSectorIndex < sectors.length; baseSectorIndex++) {\r\n const baseData = sectors[baseSectorIndex];\r\n const vertexIndex = baseData.vertexIndex;\r\n const baseFacetData = baseData.facetData;\r\n if (baseData.sectorClusterData === undefined) {\r\n const clusterNormal = new IndexedAreaAndNormal(clusterIndex++, 0.0, Vector3d.createZero());\r\n clusters.push(clusterNormal);\r\n // Accumulate with equal weights . . .\r\n clusterNormal.addWeightedNormal(1.0, baseData.facetData.normal);\r\n for (let candidateSectorIndex = baseSectorIndex;\r\n candidateSectorIndex < sectors.length;\r\n candidateSectorIndex++) {\r\n const candidateSector = sectors[candidateSectorIndex];\r\n if (candidateSector.vertexIndex !== vertexIndex)\r\n break;\r\n if (candidateSector.facetData.normal.angleTo(baseFacetData.normal).radians > toleranceRadians)\r\n continue;\r\n if (candidateSector.sectorClusterData === undefined) {\r\n clusterNormal.addWeightedNormal(1.0, candidateSector.facetData.normal);\r\n candidateSector.sectorClusterData = clusterNormal;\r\n }\r\n }\r\n }\r\n }\r\n // Resort by original sector index.\r\n sectors.sort((left, right) => SectorData.cbSectorSort(left, right));\r\n // normalize the sums and emplace in the facets . . .\r\n polyface.data.normalIndex = [];\r\n polyface.data.normal = new GrowableXYZArray(sectors.length);\r\n for (const cluster of clusters) {\r\n cluster.divideNormalByArea();\r\n cluster.index = polyface.data.normal.length;\r\n polyface.data.normal.push(cluster.normal);\r\n }\r\n // emplace the indices\r\n for (const sector of sectors) {\r\n polyface.data.normalIndex.push(sector.sectorClusterData!.index);\r\n }\r\n }\r\n /**\r\n * Set up indexed normals with one normal in the plane of each facet of the mesh.\r\n * @param polyface mesh to modify\r\n */\r\n public static buildPerFaceNormals(polyface: IndexedPolyface) {\r\n const visitor = polyface.createVisitor(0);\r\n const facetNormal = Vector3d.create(0, 0, 1);\r\n const defaultNormal = Vector3d.create(0, 0, 1);\r\n // polyface.data.clearNormals();\r\n const newNormals = new GrowableXYZArray(polyface.faceCount);\r\n const newIndices: number[] = [];\r\n while (visitor.moveToNextFacet()) {\r\n const thisNormalIndex = newNormals.length;\r\n if (PolygonOps.unitNormal(visitor.point, facetNormal))\r\n newNormals.push(facetNormal);\r\n else\r\n newNormals.push(defaultNormal);\r\n for (let i = 0; i < visitor.pointCount; i++)\r\n newIndices.push(thisNormalIndex);\r\n }\r\n polyface.data.normalIndex = newIndices;\r\n polyface.data.normal = newNormals;\r\n }\r\n}\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@itwin/core-geometry",
3
- "version": "4.9.0-dev.3",
3
+ "version": "4.9.0-dev.5",
4
4
  "description": "iTwin.js Core Geometry library",
5
5
  "main": "lib/cjs/core-geometry.js",
6
6
  "module": "lib/esm/core-geometry.js",
@@ -35,11 +35,11 @@
35
35
  "nyc": "^15.1.0",
36
36
  "rimraf": "^3.0.2",
37
37
  "typescript": "~5.3.3",
38
- "@itwin/build-tools": "4.9.0-dev.3"
38
+ "@itwin/build-tools": "4.9.0-dev.5"
39
39
  },
40
40
  "dependencies": {
41
41
  "flatbuffers": "~1.12.0",
42
- "@itwin/core-bentley": "4.9.0-dev.3"
42
+ "@itwin/core-bentley": "4.9.0-dev.5"
43
43
  },
44
44
  "nyc": {
45
45
  "extends": "./node_modules/@itwin/build-tools/.nycrc",