"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const THREE = require("three");
const _taskCache = /* @__PURE__ */ new WeakMap();
class Rhino3dmLoader extends THREE.Loader {
  constructor(manager) {
    super(manager);
    this.libraryPath = "";
    this.libraryPending = null;
    this.libraryBinary = null;
    this.libraryConfig = {};
    this.url = "";
    this.workerLimit = 4;
    this.workerPool = [];
    this.workerNextTaskID = 1;
    this.workerSourceURL = "";
    this.workerConfig = {};
    this.materials = [];
  }
  setLibraryPath(path) {
    this.libraryPath = path;
    return this;
  }
  setWorkerLimit(workerLimit) {
    this.workerLimit = workerLimit;
    return this;
  }
  load(url, onLoad, onProgress, onError) {
    const loader = new THREE.FileLoader(this.manager);
    loader.setPath(this.path);
    loader.setResponseType("arraybuffer");
    loader.setRequestHeader(this.requestHeader);
    this.url = url;
    loader.load(
      url,
      (buffer) => {
        if (_taskCache.has(buffer)) {
          const cachedTask = _taskCache.get(buffer);
          return cachedTask.promise.then(onLoad).catch(onError);
        }
        this.decodeObjects(buffer, url).then(onLoad).catch(onError);
      },
      onProgress,
      onError
    );
  }
  debug() {
    console.log(
      "Task load: ",
      this.workerPool.map((worker) => worker._taskLoad)
    );
  }
  decodeObjects(buffer, url) {
    let worker;
    let taskID;
    const taskCost = buffer.byteLength;
    const objectPending = this._getWorker(taskCost).then((_worker) => {
      worker = _worker;
      taskID = this.workerNextTaskID++;
      return new Promise((resolve, reject) => {
        worker._callbacks[taskID] = { resolve, reject };
        worker.postMessage({ type: "decode", id: taskID, buffer }, [buffer]);
      });
    }).then((message) => this._createGeometry(message.data));
    objectPending.catch(() => true).then(() => {
      if (worker && taskID) {
        this._releaseTask(worker, taskID);
      }
    });
    _taskCache.set(buffer, {
      url,
      promise: objectPending
    });
    return objectPending;
  }
  parse(data, onLoad, onError) {
    this.decodeObjects(data, "").then(onLoad).catch(onError);
  }
  _compareMaterials(material) {
    const mat = {};
    mat.name = material.name;
    mat.color = {};
    mat.color.r = material.color.r;
    mat.color.g = material.color.g;
    mat.color.b = material.color.b;
    mat.type = material.type;
    for (let i = 0; i < this.materials.length; i++) {
      const m = this.materials[i];
      const _mat = {};
      _mat.name = m.name;
      _mat.color = {};
      _mat.color.r = m.color.r;
      _mat.color.g = m.color.g;
      _mat.color.b = m.color.b;
      _mat.type = m.type;
      if (JSON.stringify(mat) === JSON.stringify(_mat)) {
        return m;
      }
    }
    this.materials.push(material);
    return material;
  }
  _createMaterial(material) {
    if (material === void 0) {
      return new THREE.MeshStandardMaterial({
        color: new THREE.Color(1, 1, 1),
        metalness: 0.8,
        name: "default",
        side: 2
      });
    }
    const _diffuseColor = material.diffuseColor;
    const diffusecolor = new THREE.Color(_diffuseColor.r / 255, _diffuseColor.g / 255, _diffuseColor.b / 255);
    if (_diffuseColor.r === 0 && _diffuseColor.g === 0 && _diffuseColor.b === 0) {
      diffusecolor.r = 1;
      diffusecolor.g = 1;
      diffusecolor.b = 1;
    }
    const mat = new THREE.MeshStandardMaterial({
      color: diffusecolor,
      name: material.name,
      side: 2,
      transparent: material.transparency > 0 ? true : false,
      opacity: 1 - material.transparency
    });
    const textureLoader = new THREE.TextureLoader();
    for (let i = 0; i < material.textures.length; i++) {
      const texture = material.textures[i];
      if (texture.image !== null) {
        const map = textureLoader.load(texture.image);
        switch (texture.type) {
          case "Diffuse":
            mat.map = map;
            break;
          case "Bump":
            mat.bumpMap = map;
            break;
          case "Transparency":
            mat.alphaMap = map;
            mat.transparent = true;
            break;
          case "Emap":
            mat.envMap = map;
            break;
        }
      }
    }
    return mat;
  }
  _createGeometry(data) {
    const object = new THREE.Object3D();
    const instanceDefinitionObjects = [];
    const instanceDefinitions = [];
    const instanceReferences = [];
    object.userData["layers"] = data.layers;
    object.userData["groups"] = data.groups;
    object.userData["settings"] = data.settings;
    object.userData["objectType"] = "File3dm";
    object.userData["materials"] = null;
    object.name = this.url;
    let objects = data.objects;
    const materials = data.materials;
    for (let i = 0; i < objects.length; i++) {
      const obj = objects[i];
      const attributes = obj.attributes;
      switch (obj.objectType) {
        case "InstanceDefinition":
          instanceDefinitions.push(obj);
          break;
        case "InstanceReference":
          instanceReferences.push(obj);
          break;
        default:
          let _object;
          if (attributes.materialIndex >= 0) {
            const rMaterial = materials[attributes.materialIndex];
            let material = this._createMaterial(rMaterial);
            material = this._compareMaterials(material);
            _object = this._createObject(obj, material);
          } else {
            const material = this._createMaterial();
            _object = this._createObject(obj, material);
          }
          if (_object === void 0) {
            continue;
          }
          const layer = data.layers[attributes.layerIndex];
          _object.visible = layer ? data.layers[attributes.layerIndex].visible : true;
          if (attributes.isInstanceDefinitionObject) {
            instanceDefinitionObjects.push(_object);
          } else {
            object.add(_object);
          }
          break;
      }
    }
    for (let i = 0; i < instanceDefinitions.length; i++) {
      const iDef = instanceDefinitions[i];
      objects = [];
      for (let j = 0; j < iDef.attributes.objectIds.length; j++) {
        const objId = iDef.attributes.objectIds[j];
        for (let p = 0; p < instanceDefinitionObjects.length; p++) {
          const idoId = instanceDefinitionObjects[p].userData.attributes.id;
          if (objId === idoId) {
            objects.push(instanceDefinitionObjects[p]);
          }
        }
      }
      for (let j = 0; j < instanceReferences.length; j++) {
        const iRef = instanceReferences[j];
        if (iRef.geometry.parentIdefId === iDef.attributes.id) {
          const iRefObject = new THREE.Object3D();
          const xf = iRef.geometry.xform.array;
          const matrix = new THREE.Matrix4();
          matrix.set(
            xf[0],
            xf[1],
            xf[2],
            xf[3],
            xf[4],
            xf[5],
            xf[6],
            xf[7],
            xf[8],
            xf[9],
            xf[10],
            xf[11],
            xf[12],
            xf[13],
            xf[14],
            xf[15]
          );
          iRefObject.applyMatrix4(matrix);
          for (let p = 0; p < objects.length; p++) {
            iRefObject.add(objects[p].clone(true));
          }
          object.add(iRefObject);
        }
      }
    }
    object.userData["materials"] = this.materials;
    return object;
  }
  _createObject(obj, mat) {
    const loader = new THREE.BufferGeometryLoader();
    const attributes = obj.attributes;
    let geometry, material, _color, color;
    switch (obj.objectType) {
      case "Point":
      case "PointSet":
        geometry = loader.parse(obj.geometry);
        if (geometry.attributes.hasOwnProperty("color")) {
          material = new THREE.PointsMaterial({ vertexColors: true, sizeAttenuation: false, size: 2 });
        } else {
          _color = attributes.drawColor;
          color = new THREE.Color(_color.r / 255, _color.g / 255, _color.b / 255);
          material = new THREE.PointsMaterial({ color, sizeAttenuation: false, size: 2 });
        }
        material = this._compareMaterials(material);
        const points = new THREE.Points(geometry, material);
        points.userData["attributes"] = attributes;
        points.userData["objectType"] = obj.objectType;
        if (attributes.name) {
          points.name = attributes.name;
        }
        return points;
      case "Mesh":
      case "Extrusion":
      case "SubD":
      case "Brep":
        if (obj.geometry === null)
          return;
        geometry = loader.parse(obj.geometry);
        if (geometry.attributes.hasOwnProperty("color")) {
          mat.vertexColors = true;
        }
        if (mat === null) {
          mat = this._createMaterial();
          mat = this._compareMaterials(mat);
        }
        const mesh = new THREE.Mesh(geometry, mat);
        mesh.castShadow = attributes.castsShadows;
        mesh.receiveShadow = attributes.receivesShadows;
        mesh.userData["attributes"] = attributes;
        mesh.userData["objectType"] = obj.objectType;
        if (attributes.name) {
          mesh.name = attributes.name;
        }
        return mesh;
      case "Curve":
        geometry = loader.parse(obj.geometry);
        _color = attributes.drawColor;
        color = new THREE.Color(_color.r / 255, _color.g / 255, _color.b / 255);
        material = new THREE.LineBasicMaterial({ color });
        material = this._compareMaterials(material);
        const lines = new THREE.Line(geometry, material);
        lines.userData["attributes"] = attributes;
        lines.userData["objectType"] = obj.objectType;
        if (attributes.name) {
          lines.name = attributes.name;
        }
        return lines;
      case "TextDot":
        geometry = obj.geometry;
        const ctx = document.createElement("canvas").getContext("2d");
        const font = `${geometry.fontHeight}px ${geometry.fontFace}`;
        ctx.font = font;
        const width = ctx.measureText(geometry.text).width + 10;
        const height = geometry.fontHeight + 10;
        const r = window.devicePixelRatio;
        ctx.canvas.width = width * r;
        ctx.canvas.height = height * r;
        ctx.canvas.style.width = width + "px";
        ctx.canvas.style.height = height + "px";
        ctx.setTransform(r, 0, 0, r, 0, 0);
        ctx.font = font;
        ctx.textBaseline = "middle";
        ctx.textAlign = "center";
        color = attributes.drawColor;
        ctx.fillStyle = `rgba(${color.r},${color.g},${color.b},${color.a})`;
        ctx.fillRect(0, 0, width, height);
        ctx.fillStyle = "white";
        ctx.fillText(geometry.text, width / 2, height / 2);
        const texture = new THREE.CanvasTexture(ctx.canvas);
        texture.minFilter = THREE.LinearFilter;
        texture.wrapS = THREE.ClampToEdgeWrapping;
        texture.wrapT = THREE.ClampToEdgeWrapping;
        material = new THREE.SpriteMaterial({ map: texture, depthTest: false });
        const sprite = new THREE.Sprite(material);
        sprite.position.set(geometry.point[0], geometry.point[1], geometry.point[2]);
        sprite.scale.set(width / 10, height / 10, 1);
        sprite.userData["attributes"] = attributes;
        sprite.userData["objectType"] = obj.objectType;
        if (attributes.name) {
          sprite.name = attributes.name;
        }
        return sprite;
      case "Light":
        geometry = obj.geometry;
        let light;
        if (geometry.isDirectionalLight) {
          light = new THREE.DirectionalLight();
          light.castShadow = attributes.castsShadows;
          light.position.set(geometry.location[0], geometry.location[1], geometry.location[2]);
          light.target.position.set(geometry.direction[0], geometry.direction[1], geometry.direction[2]);
          light.shadow.normalBias = 0.1;
        } else if (geometry.isPointLight) {
          light = new THREE.PointLight();
          light.castShadow = attributes.castsShadows;
          light.position.set(geometry.location[0], geometry.location[1], geometry.location[2]);
          light.shadow.normalBias = 0.1;
        } else if (geometry.isRectangularLight) {
          light = new THREE.RectAreaLight();
          const width2 = Math.abs(geometry.width[2]);
          const height2 = Math.abs(geometry.length[0]);
          light.position.set(geometry.location[0] - height2 / 2, geometry.location[1], geometry.location[2] - width2 / 2);
          light.height = height2;
          light.width = width2;
          light.lookAt(new THREE.Vector3(geometry.direction[0], geometry.direction[1], geometry.direction[2]));
        } else if (geometry.isSpotLight) {
          light = new THREE.SpotLight();
          light.castShadow = attributes.castsShadows;
          light.position.set(geometry.location[0], geometry.location[1], geometry.location[2]);
          light.target.position.set(geometry.direction[0], geometry.direction[1], geometry.direction[2]);
          light.angle = geometry.spotAngleRadians;
          light.shadow.normalBias = 0.1;
        } else if (geometry.isLinearLight) {
          console.warn("THREE.3DMLoader:  No conversion exists for linear lights.");
          return;
        }
        if (light) {
          light.intensity = geometry.intensity;
          _color = geometry.diffuse;
          color = new THREE.Color(_color.r / 255, _color.g / 255, _color.b / 255);
          light.color = color;
          light.userData["attributes"] = attributes;
          light.userData["objectType"] = obj.objectType;
        }
        return light;
    }
  }
  _initLibrary() {
    if (!this.libraryPending) {
      const jsLoader = new THREE.FileLoader(this.manager);
      jsLoader.setPath(this.libraryPath);
      const jsContent = new Promise((resolve, reject) => {
        jsLoader.load("rhino3dm.js", resolve, void 0, reject);
      });
      const binaryLoader = new THREE.FileLoader(this.manager);
      binaryLoader.setPath(this.libraryPath);
      binaryLoader.setResponseType("arraybuffer");
      const binaryContent = new Promise((resolve, reject) => {
        binaryLoader.load("rhino3dm.wasm", resolve, void 0, reject);
      });
      this.libraryPending = Promise.all([jsContent, binaryContent]).then(([jsContent2, binaryContent2]) => {
        this.libraryConfig.wasmBinary = binaryContent2;
        const fn = Rhino3dmWorker.toString();
        const body = [
          "/* rhino3dm.js */",
          jsContent2,
          "/* worker */",
          fn.substring(fn.indexOf("{") + 1, fn.lastIndexOf("}"))
        ].join("\n");
        this.workerSourceURL = URL.createObjectURL(new Blob([body]));
      });
    }
    return this.libraryPending;
  }
  _getWorker(taskCost) {
    return this._initLibrary().then(() => {
      if (this.workerPool.length < this.workerLimit) {
        const worker2 = new Worker(this.workerSourceURL);
        worker2._callbacks = {};
        worker2._taskCosts = {};
        worker2._taskLoad = 0;
        worker2.postMessage({
          type: "init",
          libraryConfig: this.libraryConfig
        });
        worker2.onmessage = function(e) {
          const message = e.data;
          switch (message.type) {
            case "decode":
              worker2._callbacks[message.id].resolve(message);
              break;
            case "error":
              worker2._callbacks[message.id].reject(message);
              break;
            default:
              console.error('THREE.Rhino3dmLoader: Unexpected message, "' + message.type + '"');
          }
        };
        this.workerPool.push(worker2);
      } else {
        this.workerPool.sort(function(a, b) {
          return a._taskLoad > b._taskLoad ? -1 : 1;
        });
      }
      const worker = this.workerPool[this.workerPool.length - 1];
      worker._taskLoad += taskCost;
      return worker;
    });
  }
  _releaseTask(worker, taskID) {
    worker._taskLoad -= worker._taskCosts[taskID];
    delete worker._callbacks[taskID];
    delete worker._taskCosts[taskID];
  }
  dispose() {
    for (let i = 0; i < this.workerPool.length; ++i) {
      this.workerPool[i].terminate();
    }
    this.workerPool.length = 0;
    return this;
  }
}
function Rhino3dmWorker() {
  let libraryPending;
  let libraryConfig;
  let rhino;
  onmessage = function(e) {
    const message = e.data;
    switch (message.type) {
      case "init":
        libraryConfig = message.libraryConfig;
        const wasmBinary = libraryConfig.wasmBinary;
        let RhinoModule;
        libraryPending = new Promise(function(resolve) {
          RhinoModule = { wasmBinary, onRuntimeInitialized: resolve };
          rhino3dm(RhinoModule);
        }).then(() => {
          rhino = RhinoModule;
        });
        break;
      case "decode":
        const buffer = message.buffer;
        libraryPending.then(() => {
          const data = decodeObjects(rhino, buffer);
          self.postMessage({ type: "decode", id: message.id, data });
        });
        break;
    }
  };
  function decodeObjects(rhino2, buffer) {
    const arr = new Uint8Array(buffer);
    const doc = rhino2.File3dm.fromByteArray(arr);
    const objects = [];
    const materials = [];
    const layers = [];
    const views = [];
    const namedViews = [];
    const groups = [];
    const objs = doc.objects();
    const cnt = objs.count;
    for (let i = 0; i < cnt; i++) {
      const _object = objs.get(i);
      const object = extractObjectData(_object, doc);
      _object.delete();
      if (object) {
        objects.push(object);
      }
    }
    for (let i = 0; i < doc.instanceDefinitions().count(); i++) {
      const idef = doc.instanceDefinitions().get(i);
      const idefAttributes = extractProperties(idef);
      idefAttributes.objectIds = idef.getObjectIds();
      objects.push({ geometry: null, attributes: idefAttributes, objectType: "InstanceDefinition" });
    }
    const textureTypes = [
      // rhino.TextureType.Bitmap,
      rhino2.TextureType.Diffuse,
      rhino2.TextureType.Bump,
      rhino2.TextureType.Transparency,
      rhino2.TextureType.Opacity,
      rhino2.TextureType.Emap
    ];
    const pbrTextureTypes = [
      rhino2.TextureType.PBR_BaseColor,
      rhino2.TextureType.PBR_Subsurface,
      rhino2.TextureType.PBR_SubsurfaceScattering,
      rhino2.TextureType.PBR_SubsurfaceScatteringRadius,
      rhino2.TextureType.PBR_Metallic,
      rhino2.TextureType.PBR_Specular,
      rhino2.TextureType.PBR_SpecularTint,
      rhino2.TextureType.PBR_Roughness,
      rhino2.TextureType.PBR_Anisotropic,
      rhino2.TextureType.PBR_Anisotropic_Rotation,
      rhino2.TextureType.PBR_Sheen,
      rhino2.TextureType.PBR_SheenTint,
      rhino2.TextureType.PBR_Clearcoat,
      rhino2.TextureType.PBR_ClearcoatBump,
      rhino2.TextureType.PBR_ClearcoatRoughness,
      rhino2.TextureType.PBR_OpacityIor,
      rhino2.TextureType.PBR_OpacityRoughness,
      rhino2.TextureType.PBR_Emission,
      rhino2.TextureType.PBR_AmbientOcclusion,
      rhino2.TextureType.PBR_Displacement
    ];
    for (let i = 0; i < doc.materials().count(); i++) {
      const _material = doc.materials().get(i);
      const _pbrMaterial = _material.physicallyBased();
      let material = extractProperties(_material);
      const textures = [];
      for (let j = 0; j < textureTypes.length; j++) {
        const _texture = _material.getTexture(textureTypes[j]);
        if (_texture) {
          let textureType = textureTypes[j].constructor.name;
          textureType = textureType.substring(12, textureType.length);
          const texture = { type: textureType };
          const image = doc.getEmbeddedFileAsBase64(_texture.fileName);
          if (image) {
            texture.image = "data:image/png;base64," + image;
          } else {
            console.warn(`THREE.3DMLoader: Image for ${textureType} texture not embedded in file.`);
            texture.image = null;
          }
          textures.push(texture);
          _texture.delete();
        }
      }
      material.textures = textures;
      if (_pbrMaterial.supported) {
        console.log("pbr true");
        for (let j = 0; j < pbrTextureTypes.length; j++) {
          const _texture = _material.getTexture(textureTypes[j]);
          if (_texture) {
            const image = doc.getEmbeddedFileAsBase64(_texture.fileName);
            let textureType = textureTypes[j].constructor.name;
            textureType = textureType.substring(12, textureType.length);
            const texture = { type: textureType, image: "data:image/png;base64," + image };
            textures.push(texture);
            _texture.delete();
          }
        }
        const pbMaterialProperties = extractProperties(_material.physicallyBased());
        material = Object.assign(pbMaterialProperties, material);
      }
      materials.push(material);
      _material.delete();
      _pbrMaterial.delete();
    }
    for (let i = 0; i < doc.layers().count(); i++) {
      const _layer = doc.layers().get(i);
      const layer = extractProperties(_layer);
      layers.push(layer);
      _layer.delete();
    }
    for (let i = 0; i < doc.views().count(); i++) {
      const _view = doc.views().get(i);
      const view = extractProperties(_view);
      views.push(view);
      _view.delete();
    }
    for (let i = 0; i < doc.namedViews().count(); i++) {
      const _namedView = doc.namedViews().get(i);
      const namedView = extractProperties(_namedView);
      namedViews.push(namedView);
      _namedView.delete();
    }
    for (let i = 0; i < doc.groups().count(); i++) {
      const _group = doc.groups().get(i);
      const group = extractProperties(_group);
      groups.push(group);
      _group.delete();
    }
    const settings = extractProperties(doc.settings());
    doc.delete();
    return { objects, materials, layers, views, namedViews, groups, settings };
  }
  function extractObjectData(object, doc) {
    const _geometry = object.geometry();
    const _attributes = object.attributes();
    let objectType = _geometry.objectType;
    let geometry, attributes, position, data, mesh;
    switch (objectType) {
      case rhino.ObjectType.Curve:
        const pts = curveToPoints(_geometry, 100);
        position = {};
        attributes = {};
        data = {};
        position.itemSize = 3;
        position.type = "Float32Array";
        position.array = [];
        for (let j = 0; j < pts.length; j++) {
          position.array.push(pts[j][0]);
          position.array.push(pts[j][1]);
          position.array.push(pts[j][2]);
        }
        attributes.position = position;
        data.attributes = attributes;
        geometry = { data };
        break;
      case rhino.ObjectType.Point:
        const pt = _geometry.location;
        position = {};
        const color = {};
        attributes = {};
        data = {};
        position.itemSize = 3;
        position.type = "Float32Array";
        position.array = [pt[0], pt[1], pt[2]];
        const _color = _attributes.drawColor(doc);
        color.itemSize = 3;
        color.type = "Float32Array";
        color.array = [_color.r / 255, _color.g / 255, _color.b / 255];
        attributes.position = position;
        attributes.color = color;
        data.attributes = attributes;
        geometry = { data };
        break;
      case rhino.ObjectType.PointSet:
      case rhino.ObjectType.Mesh:
        geometry = _geometry.toThreejsJSON();
        break;
      case rhino.ObjectType.Brep:
        const faces = _geometry.faces();
        mesh = new rhino.Mesh();
        for (let faceIndex = 0; faceIndex < faces.count; faceIndex++) {
          const face = faces.get(faceIndex);
          const _mesh = face.getMesh(rhino.MeshType.Any);
          if (_mesh) {
            mesh.append(_mesh);
            _mesh.delete();
          }
          face.delete();
        }
        if (mesh.faces().count > 0) {
          mesh.compact();
          geometry = mesh.toThreejsJSON();
          faces.delete();
        }
        mesh.delete();
        break;
      case rhino.ObjectType.Extrusion:
        mesh = _geometry.getMesh(rhino.MeshType.Any);
        if (mesh) {
          geometry = mesh.toThreejsJSON();
          mesh.delete();
        }
        break;
      case rhino.ObjectType.TextDot:
        geometry = extractProperties(_geometry);
        break;
      case rhino.ObjectType.Light:
        geometry = extractProperties(_geometry);
        break;
      case rhino.ObjectType.InstanceReference:
        geometry = extractProperties(_geometry);
        geometry.xform = extractProperties(_geometry.xform);
        geometry.xform.array = _geometry.xform.toFloatArray(true);
        break;
      case rhino.ObjectType.SubD:
        _geometry.subdivide(3);
        mesh = rhino.Mesh.createFromSubDControlNet(_geometry);
        if (mesh) {
          geometry = mesh.toThreejsJSON();
          mesh.delete();
        }
        break;
      default:
        console.warn(`THREE.3DMLoader: TODO: Implement ${objectType.constructor.name}`);
        break;
    }
    if (geometry) {
      attributes = extractProperties(_attributes);
      attributes.geometry = extractProperties(_geometry);
      if (_attributes.groupCount > 0) {
        attributes.groupIds = _attributes.getGroupList();
      }
      if (_attributes.userStringCount > 0) {
        attributes.userStrings = _attributes.getUserStrings();
      }
      if (_geometry.userStringCount > 0) {
        attributes.geometry.userStrings = _geometry.getUserStrings();
      }
      attributes.drawColor = _attributes.drawColor(doc);
      objectType = objectType.constructor.name;
      objectType = objectType.substring(11, objectType.length);
      return { geometry, attributes, objectType };
    } else {
      console.warn(`THREE.3DMLoader: ${objectType.constructor.name} has no associated mesh geometry.`);
    }
  }
  function extractProperties(object) {
    const result = {};
    for (const property in object) {
      const value = object[property];
      if (typeof value !== "function") {
        if (typeof value === "object" && value !== null && value.hasOwnProperty("constructor")) {
          result[property] = { name: value.constructor.name, value: value.value };
        } else {
          result[property] = value;
        }
      }
    }
    return result;
  }
  function curveToPoints(curve, pointLimit) {
    let pointCount = pointLimit;
    let rc = [];
    const ts = [];
    if (curve instanceof rhino.LineCurve) {
      return [curve.pointAtStart, curve.pointAtEnd];
    }
    if (curve instanceof rhino.PolylineCurve) {
      pointCount = curve.pointCount;
      for (let i = 0; i < pointCount; i++) {
        rc.push(curve.point(i));
      }
      return rc;
    }
    if (curve instanceof rhino.PolyCurve) {
      const segmentCount = curve.segmentCount;
      for (let i = 0; i < segmentCount; i++) {
        const segment = curve.segmentCurve(i);
        const segmentArray = curveToPoints(segment, pointCount);
        rc = rc.concat(segmentArray);
        segment.delete();
      }
      return rc;
    }
    if (curve instanceof rhino.ArcCurve) {
      pointCount = Math.floor(curve.angleDegrees / 5);
      pointCount = pointCount < 2 ? 2 : pointCount;
    }
    if (curve instanceof rhino.NurbsCurve && curve.degree === 1) {
      const pLine = curve.tryGetPolyline();
      for (let i = 0; i < pLine.count; i++) {
        rc.push(pLine.get(i));
      }
      pLine.delete();
      return rc;
    }
    const domain = curve.domain;
    const divisions = pointCount - 1;
    for (let j = 0; j < pointCount; j++) {
      const t = domain[0] + j / divisions * (domain[1] - domain[0]);
      if (t === domain[0] || t === domain[1]) {
        ts.push(t);
        continue;
      }
      const tan = curve.tangentAt(t);
      const prevTan = curve.tangentAt(ts.slice(-1)[0]);
      const tS = tan[0] * tan[0] + tan[1] * tan[1] + tan[2] * tan[2];
      const ptS = prevTan[0] * prevTan[0] + prevTan[1] * prevTan[1] + prevTan[2] * prevTan[2];
      const denominator = Math.sqrt(tS * ptS);
      let angle;
      if (denominator === 0) {
        angle = Math.PI / 2;
      } else {
        const theta = (tan.x * prevTan.x + tan.y * prevTan.y + tan.z * prevTan.z) / denominator;
        angle = Math.acos(Math.max(-1, Math.min(1, theta)));
      }
      if (angle < 0.1)
        continue;
      ts.push(t);
    }
    rc = ts.map((t) => curve.pointAt(t));
    return rc;
  }
}
exports.Rhino3dmLoader = Rhino3dmLoader;
//# sourceMappingURL=3DMLoader.cjs.map
