Фабри c JS 2D линии в 3D-изображения - PullRequest
0 голосов
/ 19 апреля 2020

Я работаю над сценарием, который позволяет клиентам рисовать так, как они хотят сгибать железо, с подробными углами. все в порядке.

Теперь клиенту нужен трехмерный вид. но я понятия не имею, как это сделать (с тремя. js Я думаю)

Мне нужен простой 3D-вид.

Вот что я делал до сих пор для 2D-вида, основан на Фабри cJS:

$(function(){
                var canvas = this.__canvas = new fabric.Canvas('c', { selection: false });
                fabric.Object.prototype.originX = fabric.Object.prototype.originY = 'center';
                
                var Lines = Array();
                var Points = Array();
                var circleAngles = Array();
                var anglesValues = Array();

                function radianToDegrees(r){
                    r = r * 180/Math.PI;
                    if(r < 0) r = -r;
                    if(360 - r < r) r = 360 - r;

                    return 180 - parseFloat(r).toFixed(0);
                }

                function makeCircle(left, top, line1, line2) {
                    var c = new fabric.Circle({
                    left: left,
                    top: top,
                    strokeWidth: 0,
                    radius: 8,
                    fill: '#000',
                    stroke: '#000'
                    });
                    c.hasControls = c.hasBorders = false;

                    c.line1 = line1;
                    c.line2 = line2;

                    return c;
                }

                function makeLine(coords) {
                    return new fabric.Line(coords, {
                    fill: 'red',
                    stroke: 'red',
                    strokeWidth: 2,
                    selectable: false,
                    evented: false,
                    });
                }

                function makeCircleAngle(angle, startAngle, endAngle){
                    if (angle == 1) color = 'red'; else color = '#003366';
                    circleAngle = new fabric.Circle({
                                    radius: 20,
                                    left: Lines[i].get('x1'),
                                    top: Lines[i].get('y1'),
                                    angle: 0,
                                    startAngle: startAngle,
                                    endAngle: endAngle,
                                    strokeDashArray: [3, 2],
                                    stroke: color,
                                    fill: '',
                                    selectable: false,
                                    evented: false,
                            });

                            return circleAngle;
                }

                function makeText(text, x, y){
                    t = new fabric.Text(text, {
                            left: x, top: y, fontSize: 13, fill: '#003366', fontFamily: 'Arial',
                            selectable: false,
                            evented: false,
                        });
                    return t;
                }

                function drawLinesCanvas(){
                    $.each(Lines, function(i, e){
                        canvas.add(e);
                    })
                }

                function drawDotsCanvas(){
                    Points = Array();
                    p = makeCircle(Lines[0].get('x1'), Lines[0].get('y1'), null, Lines[0]);
                    Points.push(p)
                    canvas.add(p);

                        for(i = 0; i< Lines.length-1; i++){
                                p = makeCircle(Lines[i].get('x2'), Lines[i].get('y2'), Lines[i], Lines[i+1]);
                                Points.push(p)
                                canvas.add( p );
                        }

                    if (Lines.length-1 >= 0){
                        p = makeCircle(Lines[Lines.length-1].get('x2'), Lines[Lines.length-1].get('y2'), Lines[Lines.length-1]);
                        Points.push(p)
                        canvas.add( p );
                    }
                }


                function calculateAndDrawAngles(){
                    $.each(circleAngles, function(i, ce){
                        canvas.remove(ce);
                    })

                    $.each(Lines, function(i, l){
                        canvas.remove(l);
                    })

                    $.each(Points, function(i, p){
                        canvas.remove(p);
                    })

                    $.each(anglesValues, function(i, a){
                        canvas.remove(a);
                    })

                    if(Lines.length >= 2){
                        for(i=1; i<Lines.length; i++){
                            y11 = Lines[i].get('y1');
                            y12 = Lines[i].get('y2');
                            y21 = Lines[i-1].get('y1');
                            y22 = Lines[i-1].get('y2');
                            
                            x11 = Lines[i].get('x1');
                            x12 = Lines[i].get('x2');
                            x21 = Lines[i-1].get('x1');
                            x22 = Lines[i-1].get('x2');
                        
                            angle1 = Math.atan2(y11 - y12, x11 - x12);
                            angle2 = Math.atan2(y21 - y22, x21 - x22);  
                            
                            angle = angle1 - angle2;
                            
                            if (angle < 0){
                                sStartAngle = Math.PI + angle1;
                                sEndAngle =  angle2;
                            } else {
                                sStartAngle = angle1 - Math.PI;
                                sEndAngle = angle2;
                            }
                            
                            myAngle = radianToDegrees(angle1 - angle2);

                            if(sStartAngle > sEndAngle) {
                                c = makeCircleAngle(1, sStartAngle, sEndAngle);
                                c1 = makeCircleAngle(2, sEndAngle, sStartAngle);
                                myAngleText = makeText(myAngle.toString()+'°', Lines[i].get('x1') +20, Lines[i].get('y1') + 20)
                            } else {
                                c = makeCircleAngle(2, sStartAngle, sEndAngle);
                                c1 = makeCircleAngle(1, sEndAngle, sStartAngle);
                                myAngleText = makeText(myAngle.toString()+'°', Lines[i].get('x1') - 20, Lines[i].get('y1') - 20)
                            }
                            
                            circleAngles.push(c, c1);
                            canvas.add(c, c1);

                            canvas.add(myAngleText)

                            anglesValues.push(myAngleText);


                        }
                    
                    drawLinesCanvas();
                    drawDotsCanvas();
                    }
                }


                canvas.on('object:moving', function(e) {
                    
                        var p = e.target;
                        p.line1 && p.line1.set({ 'x2': p.left, 'y2': p.top });
                        p.line2 && p.line2.set({ 'x1': p.left, 'y1': p.top });
                    if (Lines.length > 1){   
                        calculateAndDrawAngles();
                    }
                }); 
                
                canvas.on('mouse:wheel', function(opt) {
                    var delta = opt.e.deltaY;
                    var zoom = canvas.getZoom();
                    zoom = zoom + delta/200;
                    if (zoom > 20) zoom = 5;
                    if (zoom < 0.01) zoom = 0.5;
                    canvas.zoomToPoint({ x: opt.e.offsetX, y: opt.e.offsetY }, zoom);
                    opt.e.preventDefault();
                    opt.e.stopPropagation();
                    var vpt = this.viewportTransform;
                    if (zoom < 400 / 1000) {
                    this.viewportTransform[4] = 200 - 1000 * zoom / 2;
                    this.viewportTransform[5] = 200 - 1000 * zoom / 2;
                    } else {
                    if (vpt[4] >= 0) {
                        this.viewportTransform[4] = 0;
                    } else if (vpt[4] < canvas.getWidth() - 1000 * zoom) {
                        this.viewportTransform[4] = canvas.getWidth() - 1000 * zoom;
                    }
                    if (vpt[5] >= 0) {
                        this.viewportTransform[5] = 0;
                    } else if (vpt[5] < canvas.getHeight() - 1000 * zoom) {
                        this.viewportTransform[5] = canvas.getHeight() - 1000 * zoom;
                    }
                    }
                });
                canvas.on('mouse:down', function(opt) {
                    var evt = opt.e;
                    if (evt.altKey === true) {
                        this.isDragging = true;
                        this.selection = false;
                        this.lastPosX = evt.clientX;
                        this.lastPosY = evt.clientY;
                    }
                });
                canvas.on('mouse:move', function(opt) {
                    if (this.isDragging) {
                        var e = opt.e;
                        this.viewportTransform[4] += e.clientX - this.lastPosX;
                        this.viewportTransform[5] += e.clientY - this.lastPosY;
                        this.requestRenderAll();
                        this.lastPosX = e.clientX;
                        this.lastPosY = e.clientY;
                    }
                });
                canvas.on('mouse:up', function(opt) {
                    this.isDragging = false;
                    this.selection = true;
                });


                $('#addRight').on('click', function(){
                    fromPoint = Lines[Lines.length - 1];
                    Lines.push(makeLine([ fromPoint.get('x2'), fromPoint.get('y2'), fromPoint.get('x2') - 50, fromPoint.get('y2') + 50 ]))

                    calculateAndDrawAngles()
                });

                $('#addLeft').on('click', function(){
                    fromPoint = Lines[0];
                    Lines.unshift(makeLine([ fromPoint.get('x1') + 50, fromPoint.get('y1') + 50, fromPoint.get('x1'), fromPoint.get('y1') ]))

                    calculateAndDrawAngles()
                });


                function drawGrid(){

                    options = {
                        distance: 10,
                        width: c.width,
                        height: c.height,
                        param: {
                            stroke: '#ebebeb',
                            strokeWidth: 1,
                            selectable: false
                        }
                    },
                        gridLen = options.width / options.distance;
                
                    for (var i = 0; i < gridLen; i++) {
                        distance   = i * options.distance,
                        horizontal = new fabric.Line([ distance, 0, distance, options.width], options.param),
                        vertical   = new fabric.Line([ 0, distance, options.width, distance], options.param);
                        canvas.add(horizontal);
                        
                        canvas.add(vertical);
                    if(i%5 === 0){
                        horizontal.set({stroke: '#cccccc'});
                        vertical.set({stroke: '#cccccc'});
                    };
                    canvas.sendBackwards(horizontal);
                    canvas.sendBackwards(vertical);
                    };
                }

                Lines = [makeLine([ 100, 50, 400, 50 ])];
                drawGrid();
                drawLinesCanvas();
                drawDotsCanvas();

            });
<script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.3/fabric.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>


<canvas id="c" width="500" height="400" style="border:1px solid #ccc;"></canvas>
        <div class="text-center">
            <button class="btn btn-info" id="addLeft">Ajouter un point à gauche</button>
            <button class="btn btn-info" id="addRight">Ajouter un point à droite</button>
        </div>

1 Ответ

2 голосов
/ 19 апреля 2020

Просто вариант, когда вы можете получить координаты точек и использовать их для построения гнутого железа:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, innerWidth / innerHeight, 1, 1000);
camera.position.setScalar(10);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(innerWidth, innerHeight);
document.body.appendChild(renderer.domElement);

var controls = new THREE.OrbitControls(camera, renderer.domElement);

var obtained_data = [];
for (let i = 0; i < 10; i++) {
  obtained_data.push(
    new THREE.Vector2(i, Math.random() * 8 * 0.5 - 0.5) // fill the data with example coordinates
  );
}
//console.log(obtained_data);

var dataLength = obtained_data.length;
var geom = new THREE.PlaneBufferGeometry(1, 10, dataLength - 1, 10); // size on Y and its segmentation is up to you
geom.rotateX(Math.PI * 0.5);

var pos = geom.getAttribute("position");
for (let i = 0; i < pos.count; i++) {
  let idx = i % dataLength;
  let x = obtained_data[idx].x;
  let y = obtained_data[idx].y;
  pos.setXY(i, x, y);
}
pos.needsUpdate = true;

geom.computeVertexNormals();

var mat = new THREE.MeshBasicMaterial({
  color: "aqua",
  wireframe: true
});

var iron = new THREE.Mesh(geom, mat);

scene.add(iron);


renderer.setAnimationLoop(() => {
  renderer.render(scene, camera);
});
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...