import * as Inputs from "../../api/inputs/inputs";
export class SolidsService {
    constructor(occ, shapeGettersService, facesService, enumService, entitiesService, converterService, transformsService, vectorHelperService) {
        this.occ = occ;
        this.shapeGettersService = shapeGettersService;
        this.facesService = facesService;
        this.enumService = enumService;
        this.entitiesService = entitiesService;
        this.converterService = converterService;
        this.transformsService = transformsService;
        this.vectorHelperService = vectorHelperService;
    }
    fromClosedShell(inputs) {
        const shell = this.converterService.getActualTypeOfShape(inputs.shape);
        const builder = new this.occ.BRepBuilderAPI_MakeSolid_3(shell);
        const result = builder.Solid();
        builder.delete();
        shell.delete();
        return result;
    }
    createBox(inputs) {
        let center = [...inputs.center];
        if (inputs.originOnCenter === undefined) {
            inputs.originOnCenter = true;
        }
        if (!inputs.originOnCenter) {
            center = [center[0], center[1] + inputs.height / 2, center[2]];
        }
        return this.entitiesService.bRepPrimAPIMakeBox(inputs.width, inputs.length, inputs.height, center);
    }
    createCube(inputs) {
        let center = [...inputs.center];
        if (inputs.originOnCenter === undefined) {
            inputs.originOnCenter = true;
        }
        if (!inputs.originOnCenter) {
            center = [center[0], center[1] + inputs.size / 2, center[2]];
        }
        return this.entitiesService.bRepPrimAPIMakeBox(inputs.size, inputs.size, inputs.size, center);
    }
    createBoxFromCorner(inputs) {
        const box = this.entitiesService.bRepPrimAPIMakeBox(inputs.width, inputs.length, inputs.height, inputs.corner);
        const cornerBox = this.transformsService.translate({ shape: box, translation: [inputs.width / 2, inputs.height / 2, inputs.length / 2] });
        box.delete();
        return cornerBox;
    }
    createCylinder(inputs) {
        const dir = inputs.direction ? inputs.direction : [0., 1., 0.];
        let result;
        let angle;
        if (inputs.angle === undefined) {
            angle = Math.PI * 2;
        }
        else {
            angle = this.vectorHelperService.degToRad(inputs.angle);
        }
        const cyl = this.entitiesService.bRepPrimAPIMakeCylinder(inputs.center, dir, inputs.radius, inputs.height, angle);
        if (inputs.originOnCenter) {
            const halfHeight = -(inputs.height / 2);
            const normDir = this.vectorHelperService.normalize(dir);
            result = this.transformsService.translate({ shape: cyl, translation: [normDir[0] * halfHeight, normDir[1] * halfHeight, normDir[2] * halfHeight] });
            cyl.delete();
        }
        else {
            result = cyl;
        }
        return result;
    }
    createCylindersOnLines(inputs) {
        const cylinders = inputs.lines.map(line => {
            return this.entitiesService.bRepPrimAPIMakeCylinderBetweenPoints(line.start, line.end, inputs.radius);
        });
        return cylinders;
    }
    createSphere(inputs) {
        return this.entitiesService.bRepPrimAPIMakeSphere(inputs.center, [0., 0., 1.], inputs.radius);
    }
    createCone(inputs) {
        const ax = this.entitiesService.gpAx2(inputs.center, inputs.direction);
        const makeCone = new this.occ.BRepPrimAPI_MakeCone_4(ax, inputs.radius1, inputs.radius2, inputs.height, inputs.angle);
        const coneShape = makeCone.Shape();
        makeCone.delete();
        ax.delete();
        return coneShape;
    }
    filterSolidPoints(inputs) {
        const points = [];
        if (inputs.points.length > 0) {
            const classifier = new this.occ.BRepClass3d_SolidClassifier_1();
            classifier.Load(inputs.shape);
            inputs.points.forEach(pt => {
                const gpPnt = this.entitiesService.gpPnt(pt);
                classifier.Perform(gpPnt, inputs.tolerance);
                const top = classifier.State();
                const type = this.enumService.getTopAbsStateEnum(top);
                if (inputs.keepOn && type === Inputs.OCCT.topAbsStateEnum.on) {
                    points.push(pt);
                }
                if (inputs.keepIn && type === Inputs.OCCT.topAbsStateEnum.in) {
                    points.push(pt);
                }
                if (inputs.keepOut && type === Inputs.OCCT.topAbsStateEnum.out) {
                    points.push(pt);
                }
                if (inputs.keepUnknown && type === Inputs.OCCT.topAbsStateEnum.unknown) {
                    points.push(pt);
                }
                gpPnt.delete();
            });
            classifier.delete();
            return points;
        }
        else {
            return [];
        }
    }
    getSolidVolume(inputs) {
        const gprops = new this.occ.GProp_GProps_1();
        this.occ.BRepGProp.VolumeProperties_1(inputs.shape, gprops, true, false, false);
        const vol = gprops.Mass();
        gprops.delete();
        return vol;
    }
    getSolidSurfaceArea(inputs) {
        const faces = this.shapeGettersService.getFaces(inputs);
        const faceAreas = this.facesService.getFacesAreas({ shapes: faces });
        return faceAreas.reduce((p, c) => p + c, 0);
    }
    getSolidsVolumes(inputs) {
        if (inputs.shapes === undefined) {
            throw (Error(("Shapes are not defined")));
        }
        return inputs.shapes.map(s => this.getSolidVolume({ shape: s }));
    }
    getSolidCenterOfMass(inputs) {
        const gprops = new this.occ.GProp_GProps_1();
        this.occ.BRepGProp.VolumeProperties_1(inputs.shape, gprops, true, false, false);
        const gppnt = gprops.CentreOfMass();
        const pt = [gppnt.X(), gppnt.Y(), gppnt.Z()];
        gprops.delete();
        gppnt.delete();
        return pt;
    }
    getSolidsCentersOfMass(inputs) {
        if (inputs.shapes === undefined) {
            throw (Error(("Shapes are not defined")));
        }
        return inputs.shapes.map(s => this.getSolidCenterOfMass({ shape: s }));
    }
    getSolids(inputs) {
        return this.shapeGettersService.getSolids(inputs);
    }
}
