diff --git a/src/components/MotorOutputReordering/MotorOutputReorderingCanvas.js b/src/components/MotorOutputReordering/MotorOutputReorderingCanvas.js index 24c1cd3a..17a3e22e 100644 --- a/src/components/MotorOutputReordering/MotorOutputReorderingCanvas.js +++ b/src/components/MotorOutputReordering/MotorOutputReorderingCanvas.js @@ -70,10 +70,11 @@ class MotorOutputReorderCanvas { this._ctx.clearRect(-this._width / 2, -this._height / 2, this._width, this._height); + this._drawBottomMotors(); this._drawFrame(); this._drawDirectionArrow(); this._markMotors(); - this._drawMotors(); + this._drawTopMotors(); if (this._keepDrawing) { window.requestAnimationFrame(() => @@ -183,6 +184,7 @@ class MotorOutputReorderCanvas let result = -1; let currentDist = Number.MAX_SAFE_INTEGER; + let resultTopMotors = -1; const motors = this._config[this._droneConfiguration].Motors; for (let i = 0; i < motors.length; i++) { @@ -191,26 +193,85 @@ class MotorOutputReorderCanvas if (dist < this._config[this._droneConfiguration].PropRadius && dist < currentDist) { currentDist = dist; result = i; + + if ('top' in motors[i]) { + resultTopMotors = i; + } } } + if (resultTopMotors > -1) { // priority for top motors + result = resultTopMotors; + } + return result; } - _drawMotors() + _drawTopMotors() { + this._drawMotors(false); + } - this._ctx.lineWidth = this._config.PropEdgeLineWidth; - this._ctx.strokeStyle = this._config.PropEdgeColor; + _drawBottomMotors() + { + this._drawMotors(true); + this._clipTopMotors(); + } + + _clipTopMotors() + { const motors = this._config[this._droneConfiguration].Motors; for (let i = 0; i < motors.length; i++) { - this._ctx.beginPath(); - this._ctx.arc(motors[i].x, motors[i].y, this._config[this._droneConfiguration].PropRadius, 0, 2 * Math.PI); - this._ctx.stroke(); + if ('top' in motors[i]) { + this._clipSingleMotor(i); + } } } + _drawMotors(drawBottom) + { + this._ctx.lineWidth = this._config.PropEdgeLineWidth; + this._ctx.strokeStyle = this._config.PropEdgeColor; + const motors = this._config[this._droneConfiguration].Motors; + this._ctx.fillStyle = this._config.PropColor; + + for (let i = 0; i < motors.length; i++) { + const drawCurrentMotor = 'bottom' in motors[i] === drawBottom; + + if (drawCurrentMotor) { + this._drawSingleMotor(i); + } + } + } + + _clipSingleMotor(motorIndex) + { + this._ctx.save(); + const motor = this._config[this._droneConfiguration].Motors[motorIndex]; + this._ctx.beginPath(); + const propRadius = this._config[this._droneConfiguration].PropRadius; + this._arcSingleMotor(motorIndex); + this._ctx.clip(); + this._ctx.clearRect(motor.x - propRadius, motor.y - propRadius, propRadius * 2, propRadius * 2); + this._ctx.closePath(); + this._ctx.restore(); + } + + _drawSingleMotor(motorIndex) + { + this._ctx.beginPath(); + this._arcSingleMotor(motorIndex); + this._ctx.stroke(); + this._ctx.closePath(); + } + + _arcSingleMotor(motorIndex) + { + const motor = this._config[this._droneConfiguration].Motors[motorIndex]; + this._ctx.arc(motor.x, motor.y, this._config[this._droneConfiguration].PropRadius, 0, 2 * Math.PI); + } + _drawDirectionArrow() { this._ctx.beginPath(); @@ -236,6 +297,7 @@ class MotorOutputReorderCanvas switch(this._droneConfiguration) { case "Quad X": case "Quad +": + case "Octo X8": this._ctx.moveTo(motors[0].x, motors[0].y); this._ctx.lineTo(motors[3].x, motors[3].y); this._ctx.moveTo(motors[1].x, motors[1].y); @@ -262,7 +324,52 @@ class MotorOutputReorderCanvas this._ctx.moveTo(motors[4].x, motors[4].y); this._ctx.lineTo(motors[5].x, motors[5].y); break; - } + case "Octo Flat +": + case "Octo Flat X": + this._ctx.moveTo(motors[0].x, motors[0].y); + this._ctx.lineTo(motors[2].x, motors[2].y); + this._ctx.moveTo(motors[1].x, motors[1].y); + this._ctx.lineTo(motors[3].x, motors[3].y); + this._ctx.moveTo(motors[4].x, motors[4].y); + this._ctx.lineTo(motors[6].x, motors[6].y); + this._ctx.moveTo(motors[5].x, motors[5].y); + this._ctx.lineTo(motors[7].x, motors[7].y); + break; + case "Bicopter": + this._ctx.moveTo(motors[0].x, motors[0].y); + this._ctx.lineTo(motors[1].x, motors[1].y); + break; + case "V-tail Quad": + this._ctx.moveTo(motors[0].x, motors[0].y); + this._ctx.lineTo(0, motors[0].y * 1.3); + this._ctx.lineTo(motors[2].x, motors[2].y); + this._ctx.moveTo(0, motors[0].y * 1.3); + this._ctx.lineTo(0, motors[1].y); + this._ctx.moveTo(motors[1].x, motors[1].y); + this._ctx.lineTo(motors[3].x, motors[3].y); + break; + case "A-tail Quad": + this._ctx.moveTo(motors[0].x, motors[0].y); + this._ctx.lineTo(0, motors[0].y * 0.7); + this._ctx.lineTo(motors[2].x, motors[2].y); + this._ctx.moveTo(0, motors[0].y * 0.7); + this._ctx.lineTo(0, motors[1].y); + this._ctx.moveTo(motors[1].x, motors[1].y); + this._ctx.lineTo(motors[3].x, motors[3].y); + break; + case "Y4": + this._ctx.moveTo(motors[1].x, motors[1].y); + this._ctx.lineTo(motors[3].x, motors[3].y); + this._ctx.moveTo(motors[0].x, motors[0].y); + this._ctx.lineTo(motors[0].x, motors[3].y); + break; + case "Y6": + this._ctx.moveTo(motors[1].x, motors[1].y); + this._ctx.lineTo(motors[2].x, motors[2].y); + this._ctx.moveTo(motors[0].x, motors[0].y); + this._ctx.lineTo(motors[0].x, motors[1].y); + break; + } this._ctx.stroke(); } diff --git a/src/components/MotorOutputReordering/MotorOutputReorderingConfig.js b/src/components/MotorOutputReordering/MotorOutputReorderingConfig.js index d83330ad..6a5cbef7 100644 --- a/src/components/MotorOutputReordering/MotorOutputReorderingConfig.js +++ b/src/components/MotorOutputReordering/MotorOutputReorderingConfig.js @@ -1,140 +1,297 @@ 'use strict'; -function MotorOutputReorderConfig(screenSize) +class MotorOutputReorderConfig { - this.FrameColor = 'rgb(186, 186, 186)'; - this.PropEdgeColor = 'rgb(255, 187, 0)'; - this.PropEdgeLineWidth = 3; - this.MotorNumberTextFont = `${screenSize * 0.1}px 'Open Sans', 'Segoe UI', Tahoma, sans-serif`; - this.MotorNumberTextColor = 'rgb(0, 0, 0)'; - this.MotorMouseHoverColor = 'rgba(255, 187, 0, 0.4)'; - this.MotorSpinningColor = 'rgba(255, 0, 0, 0.4)'; - this.MotorReadyColor = 'rgba(0,128,0,0.4)'; - - this.ArrowColor = 'rgb(182,67,67)'; - this.DirectionArrowPoints = [ - {x: -0.03 * screenSize, y: 0.11 * screenSize}, - {x: -0.03 * screenSize, y: -0.01 * screenSize}, - {x: -0.07 * screenSize, y: -0.01 * screenSize}, - {x: 0.0 * screenSize, y: -0.13 * screenSize}, - {x: 0.07 * screenSize, y: -0.01 * screenSize}, - {x: 0.03 * screenSize, y: -0.01 * screenSize}, - {x: 0.03 * screenSize, y: 0.11 * screenSize}, - ]; - - //=========================================== - let frameRaduis = 0.28 * screenSize; - this["Quad X"] = + constructor (screenSize) { - PropRadius: 0.2 * screenSize, - ArmWidth: 0.1 * screenSize, - Motors: - [ - {x: frameRaduis, y: frameRaduis}, - {x: frameRaduis, y: -frameRaduis}, - {x: -frameRaduis, y: frameRaduis}, - {x: -frameRaduis, y: -frameRaduis}, - ], - }; + this.FrameColor = 'rgb(186, 186, 186)'; + this.PropEdgeColor = 'rgb(255, 187, 0)'; + this.PropColor = 'rgb(186, 186, 186, 0.4)'; + this.PropEdgeLineWidth = 3; + this.MotorNumberTextFont = `${screenSize * 0.1}px 'Open Sans', 'Segoe UI', Tahoma, sans-serif`; + this.MotorNumberTextColor = 'rgb(0, 0, 0)'; + this.MotorMouseHoverColor = 'rgba(255, 187, 0, 0.4)'; + this.MotorSpinningColor = 'rgba(255, 0, 0, 0.4)'; + this.MotorReadyColor = 'rgba(0,128,0,0.4)'; - //=========================================== - frameRaduis = 0.28 * screenSize; - this["Quad X 1234"] = + this.ArrowColor = 'rgb(182,67,67)'; + this.DirectionArrowPoints = [ + {x: -0.03 * screenSize, y: 0.11 * screenSize}, + {x: -0.03 * screenSize, y: -0.01 * screenSize}, + {x: -0.07 * screenSize, y: -0.01 * screenSize}, + {x: 0.0 * screenSize, y: -0.13 * screenSize}, + {x: 0.07 * screenSize, y: -0.01 * screenSize}, + {x: 0.03 * screenSize, y: -0.01 * screenSize}, + {x: 0.03 * screenSize, y: 0.11 * screenSize}, + ]; + + //=========================================== + let frameRadius = 0.28 * screenSize; + this["Quad X"] = + { + PropRadius: 0.2 * screenSize, + ArmWidth: 0.1 * screenSize, + Motors: + [ + {x: frameRadius, y: frameRadius}, + {x: frameRadius, y: -frameRadius}, + {x: -frameRadius, y: frameRadius}, + {x: -frameRadius, y: -frameRadius}, + ], + }; + + //=========================================== + frameRadius = 0.28 * screenSize; + this["Quad X 1234"] = + { + PropRadius: 0.2 * screenSize, + ArmWidth: 0.1 * screenSize, + Motors: + [ + {x: -frameRadius, y: -frameRadius}, + {x: frameRadius, y: -frameRadius}, + {x: frameRadius, y: frameRadius}, + {x: -frameRadius, y: frameRadius}, + ], + }; + + //=========================================== + frameRadius = 0.32 * screenSize; + this["Quad +"] = + { + PropRadius: 0.15 * screenSize, + ArmWidth: 0.1 * screenSize, + Motors: + [ + {x: 0, y: frameRadius}, + {x: frameRadius, y: 0 }, + {x: -frameRadius, y: 0 }, + {x: 0, y: -frameRadius}, + ], + }; + + //=========================================== + frameRadius = 0.30 * screenSize; + this["Tricopter"] = + { + PropRadius: 0.15 * screenSize, + ArmWidth: 0.1 * screenSize, + Motors: + [ + {x: 0, y: frameRadius}, + {x: frameRadius, y: -frameRadius}, + {x: -frameRadius, y: -frameRadius}, + ], + }; + + //=========================================== + frameRadius = 0.35 * screenSize; + this["Hex +"] = + { + PropRadius: 0.14 * screenSize, + ArmWidth: 0.1 * screenSize, + Motors: [], + }; + let dAngle = Math.PI / 3; + let angle = 0; + + angle = dAngle * 1; + this["Hex +"].Motors.push({x: Math.sin(angle) * frameRadius, y: Math.cos(angle) * frameRadius}); + + angle = dAngle * 2; + this["Hex +"].Motors.push({x: Math.sin(angle) * frameRadius, y: Math.cos(angle) * frameRadius}); + + angle = -dAngle * 1; + this["Hex +"].Motors.push({x: Math.sin(angle) * frameRadius, y: Math.cos(angle) * frameRadius}); + + angle = -dAngle * 2; + this["Hex +"].Motors.push({x: Math.sin(angle) * frameRadius, y: Math.cos(angle) * frameRadius}); + + angle = dAngle * 3; + this["Hex +"].Motors.push({x: Math.sin(angle) * frameRadius, y: Math.cos(angle) * frameRadius}); + + angle = dAngle * 0; + this["Hex +"].Motors.push({x: Math.sin(angle) * frameRadius, y: Math.cos(angle) * frameRadius}); + + //=========================================== + frameRadius = 0.35 * screenSize; + this["Hex X"] = + { + PropRadius: 0.14 * screenSize, + ArmWidth: 0.1 * screenSize, + Motors: [], + }; + dAngle = Math.PI / 3; + + angle = dAngle * 1; + this["Hex X"].Motors.push({x: Math.cos(angle) * frameRadius, y: Math.sin(angle) * frameRadius}); + + angle = -dAngle * 1; + this["Hex X"].Motors.push({x: Math.cos(angle) * frameRadius, y: Math.sin(angle) * frameRadius}); + + angle = dAngle * 2; + this["Hex X"].Motors.push({x: Math.cos(angle) * frameRadius, y: Math.sin(angle) * frameRadius}); + + angle = -dAngle * 2; + this["Hex X"].Motors.push({x: Math.cos(angle) * frameRadius, y: Math.sin(angle) * frameRadius}); + + angle = dAngle * 0; + this["Hex X"].Motors.push({x: Math.cos(angle) * frameRadius, y: Math.sin(angle) * frameRadius}); + + angle = dAngle * 3; + this["Hex X"].Motors.push({x: Math.cos(angle) * frameRadius, y: Math.sin(angle) * frameRadius}); + + //=========================================== + this._addOcto("Octo Flat +", -Math.PI / 2.0, screenSize); + this._addOcto("Octo Flat X", -Math.PI / 2.0 + Math.PI / 8.0, screenSize); + this._addOctoX8(screenSize); + this._addBicopter(screenSize); + this._addVTailQuad(screenSize); + this._addATailQuad(screenSize); + this._addY4(screenSize); + this._addY6(screenSize); + } + + _addY6(screenSize) { - PropRadius: 0.2 * screenSize, - ArmWidth: 0.1 * screenSize, - Motors: - [ - {x: -frameRaduis, y: -frameRaduis}, - {x: frameRaduis, y: -frameRaduis}, - {x: frameRaduis, y: frameRaduis}, - {x: -frameRaduis, y: frameRaduis}, - ], - }; + const frameRadius = 0.30 * screenSize; + this["Y6"] = + { + PropRadius: 0.15 * screenSize, + ArmWidth: 0.1 * screenSize, + Motors: + [ + {x: 0, y: frameRadius * 0.7, top: true}, + {x: frameRadius * 0.7, y: -frameRadius * 0.7, top: true}, + {x: -frameRadius * 0.7, y: -frameRadius * 0.7, top: true}, + {x: 0, y: frameRadius * 1.1, bottom: true}, + {x: frameRadius * 1.1, y: -frameRadius * 1.1, bottom: true}, + {x: -frameRadius * 1.1, y: -frameRadius * 1.1, bottom: true}, + ], + }; + } - //=========================================== - frameRaduis = 0.32 * screenSize; - this["Quad +"] = + _addY4(screenSize) { - PropRadius: 0.15 * screenSize, - ArmWidth: 0.1 * screenSize, - Motors: - [ - {x: 0, y: frameRaduis}, - {x: frameRaduis, y: 0 }, - {x: -frameRaduis, y: 0 }, - {x: 0, y: -frameRaduis}, - ], - }; + const frameRadius = 0.30 * screenSize; + this["Y4"] = + { + PropRadius: 0.15 * screenSize, + ArmWidth: 0.1 * screenSize, + Motors: + [ + {x: 0, y: frameRadius * 0.7, top: true}, + {x: frameRadius, y: -frameRadius}, + {x: 0, y: frameRadius * 1.1, bottom: true}, + {x: -frameRadius, y: -frameRadius}, + ], + }; + } - //=========================================== - frameRaduis = 0.30 * screenSize; - this["Tricopter"] = + _addVTailQuad(screenSize) { - PropRadius: 0.15 * screenSize, - ArmWidth: 0.1 * screenSize, - Motors: - [ - {x: 0, y: frameRaduis}, - {x: frameRaduis, y: -frameRaduis}, - {x: -frameRaduis, y: -frameRaduis}, - ], - }; + const frameRadius = 0.30 * screenSize; + this["V-tail Quad"] = + { + PropRadius: 0.15 * screenSize, + ArmWidth: 0.1 * screenSize, + Motors: + [ + {x: frameRadius * 0.7, y: frameRadius * 0.7}, + {x: frameRadius, y: -frameRadius}, + {x: -frameRadius * 0.7, y: frameRadius * 0.7}, + {x: -frameRadius, y: -frameRadius}, + ], + }; + } - //=========================================== - frameRaduis = 0.35 * screenSize; - this["Hex +"] = + _addATailQuad(screenSize) { - PropRadius: 0.14 * screenSize, - ArmWidth: 0.1 * screenSize, - Motors: [], - }; - let dAngle = Math.PI / 3; - let angle = 0; + const frameRadius = 0.30 * screenSize; + this["A-tail Quad"] = + { + PropRadius: 0.15 * screenSize, + ArmWidth: 0.1 * screenSize, + Motors: + [ + {x: -frameRadius * 0.7, y: frameRadius * 0.7}, + {x: frameRadius, y: -frameRadius}, + {x: frameRadius * 0.7, y: frameRadius * 0.7}, + {x: -frameRadius, y: -frameRadius}, + ], + }; + } - angle = dAngle * 1; - this["Hex +"].Motors.push({x: Math.sin(angle) * frameRaduis, y: Math.cos(angle) * frameRaduis}); - - angle = dAngle * 2; - this["Hex +"].Motors.push({x: Math.sin(angle) * frameRaduis, y: Math.cos(angle) * frameRaduis}); - - angle = -dAngle * 1; - this["Hex +"].Motors.push({x: Math.sin(angle) * frameRaduis, y: Math.cos(angle) * frameRaduis}); - - angle = -dAngle * 2; - this["Hex +"].Motors.push({x: Math.sin(angle) * frameRaduis, y: Math.cos(angle) * frameRaduis}); - - angle = dAngle * 3; - this["Hex +"].Motors.push({x: Math.sin(angle) * frameRaduis, y: Math.cos(angle) * frameRaduis}); - - angle = dAngle * 0; - this["Hex +"].Motors.push({x: Math.sin(angle) * frameRaduis, y: Math.cos(angle) * frameRaduis}); - - //=========================================== - frameRaduis = 0.35 * screenSize; - this["Hex X"] = + _addBicopter(screenSize) { - PropRadius: 0.14 * screenSize, - ArmWidth: 0.1 * screenSize, - Motors: [], - }; - dAngle = Math.PI / 3; + const frameRadius = 0.35 * screenSize; + this["Bicopter"] = + { + PropRadius: 0.2 * screenSize, + ArmWidth: 0.1 * screenSize, + Motors: + [ + {x: -frameRadius, y: 0,}, + {x: frameRadius, y: 0,}, + ], + }; + } - angle = dAngle * 1; - this["Hex X"].Motors.push({x: Math.cos(angle) * frameRaduis, y: Math.sin(angle) * frameRaduis}); + _addOctoX8(screenSize) + { + const frameRadius = 0.20 * screenSize; + const frameRadius2 = 0.28 * screenSize; + this["Octo X8"] = + { + PropRadius: 0.12 * screenSize, + ArmWidth: 0.1 * screenSize, + Motors: + [ + {x: frameRadius, y: frameRadius, top: true}, + {x: frameRadius, y: -frameRadius, top: true}, + {x: -frameRadius, y: frameRadius, top: true}, + {x: -frameRadius, y: -frameRadius, top: true}, + {x: frameRadius2, y: frameRadius2, bottom: true}, + {x: frameRadius2, y: -frameRadius2, bottom: true}, + {x: -frameRadius2, y: frameRadius2, bottom: true}, + {x: -frameRadius2, y: -frameRadius2, bottom: true}, + ], + }; + } - angle = -dAngle * 1; - this["Hex X"].Motors.push({x: Math.cos(angle) * frameRaduis, y: Math.sin(angle) * frameRaduis}); + _addOcto(frameName, rotateAngle, screenSize) + { + const frameRadius = 0.35 * screenSize; + this[frameName] = + { + PropRadius: 0.10 * screenSize, + ArmWidth: 0.1 * screenSize, + Motors: [], + }; + const dAngle = Math.PI / 4; - angle = dAngle * 2; - this["Hex X"].Motors.push({x: Math.cos(angle) * frameRaduis, y: Math.sin(angle) * frameRaduis}); + let angle = -dAngle * 2 + rotateAngle; + this[frameName].Motors.push({x: Math.cos(angle) * frameRadius, y: Math.sin(angle) * frameRadius}); - angle = -dAngle * 2; - this["Hex X"].Motors.push({x: Math.cos(angle) * frameRaduis, y: Math.sin(angle) * frameRaduis}); + angle = dAngle * 0 + rotateAngle; + this[frameName].Motors.push({x: Math.cos(angle) * frameRadius, y: Math.sin(angle) * frameRadius}); - angle = dAngle * 0; - this["Hex X"].Motors.push({x: Math.cos(angle) * frameRaduis, y: Math.sin(angle) * frameRaduis}); + angle = dAngle * 2 + rotateAngle; + this[frameName].Motors.push({x: Math.cos(angle) * frameRadius, y: Math.sin(angle) * frameRadius}); - angle = dAngle * 3; - this["Hex X"].Motors.push({x: Math.cos(angle) * frameRaduis, y: Math.sin(angle) * frameRaduis}); + angle = dAngle * 4 + rotateAngle; + this[frameName].Motors.push({x: Math.cos(angle) * frameRadius, y: Math.sin(angle) * frameRadius}); + + angle = -dAngle * 1 + rotateAngle; + this[frameName].Motors.push({x: Math.cos(angle) * frameRadius, y: Math.sin(angle) * frameRadius}); + + angle = dAngle * 1 + rotateAngle; + this[frameName].Motors.push({x: Math.cos(angle) * frameRadius, y: Math.sin(angle) * frameRadius}); + + angle = dAngle * 3 + rotateAngle; + this[frameName].Motors.push({x: Math.cos(angle) * frameRadius, y: Math.sin(angle) * frameRadius}); + + angle = -dAngle * 3 + rotateAngle; + this[frameName].Motors.push({x: Math.cos(angle) * frameRadius, y: Math.sin(angle) * frameRadius}); + } }