All files / app/codeCharta/services/3DExports/3DPreview/CreateGeometryStrategies createTextGeometryStrategy.ts

100% Statements 28/28
100% Branches 13/13
100% Functions 2/2
100% Lines 28/28

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 7611x 11x       11x                       11x         91x 91x 1x   90x 90x 44x     90x               90x 90x 45x     90x 90x 90x 90x   90x           90x       6x 6x 6x 12x         12x 12x 12x     6x      
import { BufferGeometry } from "three"
import { TextGeometry } from "three/examples/jsm/geometries/TextGeometry"
import { Font } from "three/examples/jsm/loaders/FontLoader"
import { CreateGeometryStrategy, CreateGeometryStrategyOptions } from "./createGeometryStrategy"
import { GeometryOptions } from "../preview3DPrintMesh"
import * as BufferGeometryUtils from "three/examples/jsm/utils/BufferGeometryUtils.js"
 
export interface CreateTextGeometryStrategyOptions extends CreateGeometryStrategyOptions {
    font: Font
    text: string
    side: "front" | "back"
    xPosition: number
    yPosition: number
    align: "center" | "left"
    textSize?: number
}
 
export class CreateTextGeometryStrategy implements CreateGeometryStrategy {
    async create(
        geometryOptions: GeometryOptions,
        createTextGeometryStrategyOptions: CreateTextGeometryStrategyOptions
    ): Promise<BufferGeometry> {
        const { font, side, text, xPosition, yPosition, align } = createTextGeometryStrategyOptions
        if (!text) {
            return new BufferGeometry()
        }
        let { textSize } = createTextGeometryStrategyOptions
        if (!textSize) {
            textSize = 0.025
        }
        const textGeometry =
            align === "center" && text.includes("\n")
                ? this.createMultilineCenteredTextGeometry(text, font, textSize, geometryOptions.printHeight)
                : new TextGeometry(text, {
                      font,
                      size: textSize,
                      height: geometryOptions.printHeight
                  })
 
        textGeometry.center()
        if (side === "back") {
            textGeometry.rotateY(Math.PI)
        }
 
        textGeometry.computeBoundingBox()
        const textWidth = textGeometry.boundingBox.max.x - textGeometry.boundingBox.min.x
        const xPositionOffset = align === "center" ? 0 : textWidth / 2
        const xPositionDirection = side === "front" ? 1 : -1
 
        textGeometry.translate(
            xPositionDirection * (xPositionOffset + xPosition),
            yPosition,
            side === "front" ? geometryOptions.printHeight / 2 : -geometryOptions.baseplateHeight + geometryOptions.printHeight / 2
        )
 
        return textGeometry
    }
 
    private createMultilineCenteredTextGeometry(text: string, font: Font, size: number, height: number) {
        const lines = text.split("\n")
        const lineGeometries: BufferGeometry[] = []
        for (const [index, line] of lines.entries()) {
            const lineGeometry = new TextGeometry(line, {
                font,
                size,
                height
            })
            lineGeometry.center()
            lineGeometry.translate(0, -index * size * 1.5, 0)
            lineGeometries.push(lineGeometry)
        }
 
        return BufferGeometryUtils.mergeGeometries(lineGeometries)
    }
}