Compare commits
13 Commits
11075db8d2
...
2605183d4a
| Author | SHA1 | Date | |
|---|---|---|---|
| 2605183d4a | |||
| e9490c797d | |||
| 48c9c1a87d | |||
| 39eecd54c6 | |||
| efeef7da5c | |||
| c09245d7b1 | |||
| ab084d867a | |||
| 54b4d4d3e6 | |||
| ce4c8de6f8 | |||
| ee6679de98 | |||
| 38ed739f46 | |||
| f835f7364c | |||
| fba2c4e249 |
@ -22,4 +22,8 @@ export class Point {
|
||||
return new Point(part.x, part.y);
|
||||
}
|
||||
|
||||
minus(start: Point): Point {
|
||||
return new Point(this.x - start.x, this.y - start.y);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -22,9 +22,12 @@ export class Calculation {
|
||||
readonly junctionsWithoutPivot: Junction[],
|
||||
readonly wires: Wire[]) {
|
||||
this.matrixInit(junctionsWithoutPivot.length);
|
||||
|
||||
this.wires.forEach(wire => this.addResistor(wire));
|
||||
this.parts.filter(p => p instanceof Battery).forEach(battery => this.addCurrentSource(battery));
|
||||
|
||||
this.solve();
|
||||
|
||||
this.wires.forEach(wire => this.useCurrent(wire));
|
||||
const minCircuitVoltage = this.potentials.reduce((a, b) => a < b ? a : b, 0);
|
||||
const maxCircuitVoltage = this.potentials.reduce((a, b) => a > b ? a : b, 0);
|
||||
@ -34,9 +37,11 @@ export class Calculation {
|
||||
junction.voltage = this.getPotential(junctionsWithoutPivot.indexOf(junction));
|
||||
console.debug(" junction", junction.fullName, junction.voltage, 'V');
|
||||
});
|
||||
|
||||
pivot.minCircuitVoltage = minCircuitVoltage;
|
||||
pivot.maxCircuitVoltage = maxCircuitVoltage;
|
||||
pivot.voltage = 0;
|
||||
|
||||
const junctionCountIncludingPivot = junctionsWithoutPivot.length + 1;
|
||||
console.debug(` => Circuit #${number} (${parts.length} parts, ${junctionCountIncludingPivot} junctions, ${wires.length} wires)`);
|
||||
}
|
||||
@ -91,7 +96,7 @@ export class Calculation {
|
||||
private addCurrentSource(battery: Battery) {
|
||||
const indexMinus = this.junctionsWithoutPivot.indexOf(battery.minus);
|
||||
const indexPlus = this.junctionsWithoutPivot.indexOf(battery.plus);
|
||||
const current = battery.voltage / battery.resistance;
|
||||
const current = battery.voltage / battery.resistance.resistance;
|
||||
if (indexMinus >= 0) {
|
||||
this.currents[indexMinus] += current;
|
||||
}
|
||||
|
||||
@ -6,9 +6,12 @@ import {Light} from '../parts/light/Light';
|
||||
import {Relay} from '../parts/relay/Relay';
|
||||
import {Junction} from '../junction/Junction';
|
||||
import {Switch} from '../parts/switch/Switch';
|
||||
import {siPrefix} from '../siPrefix';
|
||||
|
||||
export class Circuit {
|
||||
|
||||
private siPrefixRange: number = 2;
|
||||
|
||||
constructor(
|
||||
readonly uuid: string,
|
||||
public name: string,
|
||||
@ -27,7 +30,7 @@ export class Circuit {
|
||||
Calculation.calculate(this);
|
||||
const changedParts = [];
|
||||
for (const part of this.parts) {
|
||||
if (part.loop()) {
|
||||
if (part.postCalculate()) {
|
||||
changedParts.push(part);
|
||||
}
|
||||
}
|
||||
@ -45,22 +48,22 @@ export class Circuit {
|
||||
this.wires.forEach(wire => wire.resetCalculations());
|
||||
}
|
||||
|
||||
newBattery(rasterX: number, rasterY: number, name: string | undefined = undefined, voltage: number = 1.5, resistance: number = 0.5): Battery {
|
||||
newBattery(rasterX: number, rasterY: number, voltage: number = 1.5, resistance: number = 0.5, name: string | undefined = undefined): Battery {
|
||||
name = this.generateName(name, "Batterie");
|
||||
return this.add(new Battery(this, rasterX, rasterY, name, voltage, resistance));
|
||||
}
|
||||
|
||||
newLight(rasterX: number, rasterY: number, name: string | undefined = undefined, voltageMax: number = 3, resistance: number = 100): Light {
|
||||
newLight(rasterX: number, rasterY: number, voltageMax: number = 1.5, resistance: number = 100, name: string | undefined = undefined): Light {
|
||||
name = this.generateName(name, "Licht");
|
||||
return this.add(new Light(this, rasterX, rasterY, name, voltageMax, resistance));
|
||||
}
|
||||
|
||||
newRelay(rasterX: number, rasterY: number, name: string | undefined = undefined, voltageMin: number = 1.0, voltageMax: number = 3, resistance: number = 150): Relay {
|
||||
newRelay(rasterX: number, rasterY: number, voltageMin: number = 1.0, voltageMax: number = 3, resistance: number = 150, name: string | undefined = undefined): Relay {
|
||||
name = this.generateName(name, "Relais");
|
||||
return this.add(new Relay(this, rasterX, rasterY, name, voltageMin, voltageMax, resistance));
|
||||
}
|
||||
|
||||
newSwitch(rasterX: number, rasterY: number, name: string | undefined = undefined, momentary: boolean = false): Switch {
|
||||
newSwitch(rasterX: number, rasterY: number, momentary: boolean = false, name: string | undefined = undefined): Switch {
|
||||
name = this.generateName(name, "Relais");
|
||||
return this.add(new Switch(this, rasterX, rasterY, name, momentary));
|
||||
}
|
||||
@ -85,17 +88,24 @@ export class Circuit {
|
||||
}
|
||||
|
||||
connect(start: Junction, end: Junction) {
|
||||
const wire = new Wire(start, end, RESISTANCE_MIN);
|
||||
const wire = new Wire(start, end, RESISTANCE_MIN, "", (wire) => this.disconnect(wire));
|
||||
this.wires.push(wire);
|
||||
console.log(`Wire connected: ${wire}`);
|
||||
this.calculate();
|
||||
}
|
||||
|
||||
disconnect(wire: Wire) {
|
||||
private disconnect(wire: Wire) {
|
||||
this.wires.splice(this.wires.indexOf(wire), 1);
|
||||
wire.disconnect();
|
||||
console.log("Wire disconnected: ", wire);
|
||||
this.calculate();
|
||||
}
|
||||
|
||||
voltageStr(voltage: number) {
|
||||
return siPrefix(Math.abs(voltage), 'V', 2, -this.siPrefixRange, +this.siPrefixRange);
|
||||
}
|
||||
|
||||
currentStr(current: number) {
|
||||
return siPrefix(Math.abs(current) || 0, 'A', 2, -this.siPrefixRange, +this.siPrefixRange);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -6,14 +6,14 @@ function create() {
|
||||
const circuit = new Circuit("DEMO_002", "2. Reihe und Parallel");
|
||||
const battery0 = circuit.newBattery(1, 1);
|
||||
const battery1 = circuit.newBattery(2, 1);
|
||||
const light0 = circuit.newLight(1, 0);
|
||||
const light1 = circuit.newLight(2, 0);
|
||||
const light2 = circuit.newLight(1, 2);
|
||||
circuit.connect(light0.a, battery0.minus);
|
||||
circuit.connect(light0.b, light1.a);
|
||||
circuit.connect(light1.b, battery1.plus);
|
||||
const lightSeries0 = circuit.newLight(1, 0, 3);
|
||||
const lightSeries1 = circuit.newLight(2, 0, 3);
|
||||
const lightParallel = circuit.newLight(1, 2, 3);
|
||||
circuit.connect(lightSeries0.a, battery0.minus);
|
||||
circuit.connect(lightSeries0.b, lightSeries1.a);
|
||||
circuit.connect(lightSeries1.b, battery1.plus);
|
||||
circuit.connect(battery0.plus, battery1.minus);
|
||||
circuit.connect(light2.a, battery0.minus);
|
||||
circuit.connect(light2.b, battery1.plus);
|
||||
circuit.connect(lightParallel.a, battery0.minus);
|
||||
circuit.connect(lightParallel.b, battery1.plus);
|
||||
return circuit;
|
||||
}
|
||||
|
||||
@ -4,19 +4,25 @@ export const DEMO_003 = create();
|
||||
|
||||
function create() {
|
||||
const circuit = new Circuit("DEMO_003", "3. Relais");
|
||||
const batteryLight = circuit.newBattery(2, 0, "Licht Batterie");
|
||||
const lightInactive = circuit.newLight(2, 1, "Licht Inaktiv");
|
||||
const lightActive = circuit.newLight(2, 2, "Licht Aktiv");
|
||||
const relay = circuit.newRelay(1, 2, "Relais");
|
||||
const relaySwitch = circuit.newSwitch(1, 3, "Taster", true);
|
||||
const batteryRelay = circuit.newBattery(2, 3, "Relais Batterie");
|
||||
circuit.connect(batteryLight.plus, lightInactive.b);
|
||||
|
||||
const lightBattery = circuit.newBattery(2, 0);
|
||||
const lightInactive = circuit.newLight(2, 1);
|
||||
const lightActive = circuit.newLight(2, 2);
|
||||
|
||||
const relay = circuit.newRelay(1, 2);
|
||||
const relaySwitch = circuit.newSwitch(0.3, 3.3, true);
|
||||
const relayBattery = circuit.newBattery(1.6, 3.3);
|
||||
|
||||
circuit.connect(lightBattery.plus, lightInactive.b);
|
||||
circuit.connect(lightInactive.b, lightActive.b);
|
||||
circuit.connect(batteryLight.minus, relay.common);
|
||||
circuit.connect(lightBattery.minus, relay.common);
|
||||
|
||||
circuit.connect(lightInactive.a, relay.inactive);
|
||||
circuit.connect(lightActive.a, relay.active);
|
||||
|
||||
circuit.connect(relaySwitch.common, relay.coilA);
|
||||
circuit.connect(batteryRelay.minus, relaySwitch.active);
|
||||
circuit.connect(batteryRelay.plus, relay.coilB);
|
||||
circuit.connect(relayBattery.plus, relay.coilB);
|
||||
circuit.connect(relayBattery.minus, relaySwitch.active);
|
||||
|
||||
return circuit;
|
||||
}
|
||||
|
||||
@ -5,15 +5,20 @@ export const DEMO_004 = create();
|
||||
function create() {
|
||||
const circuit = new Circuit("DEMO_004", "4. Relais");
|
||||
|
||||
const battery = circuit.newBattery(1, 1);
|
||||
const set = circuit.newSwitch(0, 0, undefined, true);
|
||||
const reset = circuit.newSwitch(2, 0, undefined, true);
|
||||
const relay = circuit.newRelay(1, 0);
|
||||
// circuit.connect(battery.minus, set.common);
|
||||
// circuit.connect(battery.plus, reset.inactive);
|
||||
// circuit.connect(set.active, relay.coilA);
|
||||
// circuit.connect(reset.common, relay.coilB);
|
||||
// circuit.connect(battery.minus, relay.active);
|
||||
// circuit.connect(relay.coilA, relay.common);
|
||||
const battery = circuit.newBattery(2, 0);
|
||||
const set = circuit.newSwitch(1, 0, true);
|
||||
const reset = circuit.newSwitch(2, 2.3, true);
|
||||
const relay = circuit.newRelay(0, 2);
|
||||
const light = circuit.newLight(0, 3);
|
||||
circuit.connect(battery.minus, set.active);
|
||||
circuit.connect(set.common, relay.common);
|
||||
circuit.connect(set.active, relay.active);
|
||||
circuit.connect(relay.common, relay.coilA);
|
||||
circuit.connect(relay.coilB, reset.common);
|
||||
circuit.connect(reset.inactive, battery.plus);
|
||||
|
||||
circuit.connect(relay.coilA, light.a);
|
||||
circuit.connect(relay.coilB, light.b);
|
||||
|
||||
return circuit;
|
||||
}
|
||||
|
||||
@ -1,42 +1,59 @@
|
||||
import {Point} from '../Point';
|
||||
import {Part, RASTER} from '../parts/Part';
|
||||
import {Circuit} from './Circuit';
|
||||
import {Point} from '../Point';
|
||||
|
||||
export class Parts {
|
||||
|
||||
circuit!: Circuit;
|
||||
private _circuit!: Circuit;
|
||||
|
||||
dragStart: Point | null = null;
|
||||
set circuit(circuit: Circuit) {
|
||||
this._circuit = circuit;
|
||||
this.reset();
|
||||
}
|
||||
|
||||
dragStartPart: Part | null = null;
|
||||
get circuit(): Circuit {
|
||||
return this._circuit;
|
||||
}
|
||||
|
||||
dragCursor: Point | null = null;
|
||||
private part: Part | null = null;
|
||||
|
||||
private partStart: Point | null = null;
|
||||
|
||||
private mouseStart: Point | null = null;
|
||||
|
||||
mouseDown(part: Part, $event: MouseEvent) {
|
||||
if ($event.button === 0) {
|
||||
this.dragStartPart = part;
|
||||
this.dragStart = Point.fromPart(part);
|
||||
this.part = part;
|
||||
this.partStart = Point.fromPart(part);
|
||||
this.mouseStart = Point.fromEvent($event);
|
||||
this.mouseMove($event);
|
||||
}
|
||||
}
|
||||
|
||||
mouseMove($event: MouseEvent) {
|
||||
this.updateDragCursor($event);
|
||||
if (this.dragStartPart !== null && this.dragCursor !== null) {
|
||||
this.dragStartPart.rasterCenterX = Math.floor(this.dragCursor.x / RASTER);
|
||||
this.dragStartPart.rasterCenterY = Math.floor(this.dragCursor.y / RASTER);
|
||||
this.dragStartPart.updateJunctionPositions();
|
||||
if ($event.button === 0 && this.part !== null && this.partStart !== null && this.mouseStart !== null) {
|
||||
const diff = Point.fromEvent($event).minus(this.mouseStart);
|
||||
this.part.x = Math.floor((this.partStart.x + diff.x) / RASTER + 0.5) * RASTER;
|
||||
this.part.y = Math.floor((this.partStart.y + diff.y) / RASTER + 0.5) * RASTER;
|
||||
this.part.updateJunctionPositions();
|
||||
}
|
||||
}
|
||||
|
||||
mouseUp($event: MouseEvent) {
|
||||
this.updateDragCursor($event);
|
||||
this.mouseMove($event);
|
||||
if ($event.button === 0) {
|
||||
this.dragStartPart = null;
|
||||
this.reset();
|
||||
}
|
||||
}
|
||||
|
||||
private updateDragCursor($event: MouseEvent) {
|
||||
this.dragCursor = Point.fromEvent($event);
|
||||
private reset() {
|
||||
this.part = null;
|
||||
this.partStart = null;
|
||||
this.mouseStart = null;
|
||||
}
|
||||
|
||||
isDragged(part: Part) {
|
||||
return this.part === part;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,22 +1,10 @@
|
||||
@import "../wire/wire.component.less";
|
||||
|
||||
.circuit {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.wireBack {
|
||||
stroke-linecap: round;
|
||||
stroke-width: 11px;
|
||||
stroke: black;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.wire {
|
||||
stroke-width: 9px;
|
||||
stroke-dasharray: 0 20;
|
||||
stroke-linecap: round;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.wireOpen {
|
||||
stroke: blue;
|
||||
stroke-dasharray: 5px 15px;
|
||||
|
||||
@ -1,8 +1,17 @@
|
||||
<svg class="circuit" (mousemove)="mouseMove($event)" (mouseup)="mouseUp($event)">
|
||||
|
||||
<defs>
|
||||
<pattern id="grid" x="-5" y="-5" width="50" height="50" patternUnits="userSpaceOnUse" stroke="lightgray" stroke-width="0.5px">
|
||||
<line x1="0" y1="5" x2="10" y2="5"></line>
|
||||
<line x1="5" y1="0" x2="5" y2="10"></line>
|
||||
</pattern>
|
||||
</defs>
|
||||
|
||||
<rect width="100%" height="100%" fill="url(#grid)"/>
|
||||
|
||||
<g inner-part *ngFor="let part of circuit.parts" [part]="part" [parts]="parts" [wires]="wires"></g>
|
||||
|
||||
<g inner-wire *ngFor="let wire of circuit.wires" [globalWire]="wire"></g>
|
||||
<g inner-wire *ngFor="let wire of circuit.wires" [globalWire]="wire" extraClassesBack="wireBackGlobal"></g>
|
||||
|
||||
<ng-container *ngIf="wires.dragStart && wires.dragCursor && wires.dragStartJunction">
|
||||
<ng-container *ngIf="wires.dragEnd && wires.dragEndJunction">
|
||||
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.4 KiB |
@ -6,7 +6,7 @@ import {Parts} from './Parts';
|
||||
import {PartComponent} from '../parts/part.component';
|
||||
|
||||
import {Circuit} from './Circuit';
|
||||
import {WireComponent} from '../part-wire/wire.component';
|
||||
import {WireComponent} from '../wire/wire.component';
|
||||
|
||||
@Component({
|
||||
selector: 'app-circuit',
|
||||
|
||||
@ -3,7 +3,6 @@ import {CircuitComponent} from './circuit/circuit.component';
|
||||
import {MessagesComponent} from './message/messages/messages.component';
|
||||
import {MenubarComponent} from './menubar/menubar.component';
|
||||
import {Circuit} from './circuit/Circuit';
|
||||
import {DEMO_003} from './circuit/DEMO_003';
|
||||
import {DEMO_004} from './circuit/DEMO_004';
|
||||
|
||||
@Component({
|
||||
|
||||
@ -68,13 +68,6 @@ export class Junction {
|
||||
this._rect = this.findRect();
|
||||
}
|
||||
|
||||
sumAllBut(plus: Junction) {
|
||||
return this.wires
|
||||
.filter(wire => wire.traverse(this) !== plus)
|
||||
.map(wire => wire.current)
|
||||
.reduce((a, b) => a + b, 0);
|
||||
}
|
||||
|
||||
private findRect(): Rect {
|
||||
const child = document.getElementById(this.uuid);
|
||||
if (!child) {
|
||||
|
||||
@ -1,5 +0,0 @@
|
||||
@import "../parts/part.component.less";
|
||||
|
||||
.partWireBack {
|
||||
stroke-width: 5px;
|
||||
}
|
||||
@ -8,13 +8,9 @@ export abstract class Part {
|
||||
|
||||
readonly uuid: string = self.crypto.randomUUID();
|
||||
|
||||
private _x: number;
|
||||
x: number;
|
||||
|
||||
private _y: number;
|
||||
|
||||
private readonly _w: number;
|
||||
|
||||
private readonly _h: number;
|
||||
y: number;
|
||||
|
||||
protected constructor(
|
||||
readonly circuit: Circuit,
|
||||
@ -22,37 +18,9 @@ export abstract class Part {
|
||||
readonly name: string,
|
||||
rasterX: number,
|
||||
rasterY: number,
|
||||
rasterW: number = 1,
|
||||
rasterH: number = 1,
|
||||
) {
|
||||
this._x = rasterX * 3 * RASTER;
|
||||
this._y = rasterY * 3 * RASTER;
|
||||
this._w = rasterW * 3 * RASTER;
|
||||
this._h = rasterH * 3 * RASTER;
|
||||
}
|
||||
|
||||
get x(): number {
|
||||
return this._x;
|
||||
}
|
||||
|
||||
get y(): number {
|
||||
return this._y;
|
||||
}
|
||||
|
||||
get w(): number {
|
||||
return this._w;
|
||||
}
|
||||
|
||||
get h(): number {
|
||||
return this._h;
|
||||
}
|
||||
|
||||
set rasterCenterX(rx: number) {
|
||||
this._x = rx * RASTER - this._w / 2;
|
||||
}
|
||||
|
||||
set rasterCenterY(ry: number) {
|
||||
this._y = ry * RASTER - this._h / 2;
|
||||
this.x = Math.round(rasterX * 3) * RASTER;
|
||||
this.y = Math.round(rasterY * 3) * RASTER;
|
||||
}
|
||||
|
||||
toString(): string {
|
||||
@ -63,7 +31,7 @@ export abstract class Part {
|
||||
this.junctions.forEach(junction => junction.updatePosition());
|
||||
}
|
||||
|
||||
loop(): boolean {
|
||||
postCalculate(): boolean {
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import {Part} from "../Part";
|
||||
import {Junction} from '../../junction/Junction';
|
||||
import {PartType} from '../PartType';
|
||||
import {siPrefix} from '../../siPrefix';
|
||||
import {Wire} from '../../wire/Wire';
|
||||
import {Circuit} from '../../circuit/Circuit';
|
||||
|
||||
@ -11,32 +10,37 @@ export class Battery extends Part {
|
||||
|
||||
readonly plus: Junction = new Junction(this, 85, 50, "+");
|
||||
|
||||
readonly resistance: Wire;
|
||||
|
||||
current: number = 0;
|
||||
|
||||
constructor(
|
||||
circuit: Circuit,
|
||||
rasterX: number,
|
||||
rasterY: number,
|
||||
name: string,
|
||||
public voltage: number,
|
||||
public resistance: number,
|
||||
resistance: number,
|
||||
) {
|
||||
super(circuit, PartType.Battery, name, rasterX, rasterY);
|
||||
new Wire(this.minus, this.plus, resistance, "Innenwiderstand");
|
||||
this.resistance = new Wire(this.minus, this.plus, resistance, "Innenwiderstand");
|
||||
}
|
||||
|
||||
override get junctions(): Junction[] {
|
||||
return [this.minus, this.plus];
|
||||
}
|
||||
|
||||
get voltageStr(): string {
|
||||
return siPrefix(Math.abs(this.voltage), 'V', 2);
|
||||
override postCalculate(): boolean {
|
||||
this.current = this.minus.wires.map(wire => wire.currentFrom(this.minus)).reduce((a, b) => a + b, -this.resistance.current)
|
||||
return false;
|
||||
}
|
||||
|
||||
get current(): number {
|
||||
return this.minus.sumAllBut(this.plus);
|
||||
get voltageStr(): string {
|
||||
return this.circuit.voltageStr(this.voltage);
|
||||
}
|
||||
|
||||
get currentStr(): string {
|
||||
return siPrefix(Math.abs(this.current) || 0, 'A', 2);
|
||||
return this.circuit.currentStr(this.current);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {Battery} from './Battery';
|
||||
import {WireComponent} from '../../part-wire/wire.component';
|
||||
import {WireComponent} from '../../wire/wire.component';
|
||||
|
||||
@Component({
|
||||
selector: 'g[inner-part-battery]',
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import {Part} from "../Part";
|
||||
import {Junction} from '../../junction/Junction';
|
||||
import {PartType} from '../PartType';
|
||||
import {siPrefix} from '../../siPrefix';
|
||||
|
||||
import {fadeColor} from '../../colorHelpers';
|
||||
import {Wire} from '../../wire/Wire';
|
||||
@ -40,10 +39,6 @@ export class Light extends Part {
|
||||
return this.voltage > this.voltageMax;
|
||||
}
|
||||
|
||||
get voltageStr(): string {
|
||||
return siPrefix(Math.abs(this.voltage), 'V', 2);
|
||||
}
|
||||
|
||||
get current(): number {
|
||||
if (this.a.voltage === null || this.b.voltage === null) {
|
||||
return 0;
|
||||
@ -51,8 +46,12 @@ export class Light extends Part {
|
||||
return (this.b.voltage - this.a.voltage) / this.resistance;
|
||||
}
|
||||
|
||||
get voltageStr(): string {
|
||||
return this.circuit.voltageStr(this.voltage);
|
||||
}
|
||||
|
||||
get currentStr(): string {
|
||||
return siPrefix(Math.abs(this.current) || 0, 'A', 2);
|
||||
return this.circuit.currentStr(this.current);
|
||||
}
|
||||
|
||||
fill(): string {
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
@import "../circuit/circuit.component.less";
|
||||
@import "../wire/wire.component.less";
|
||||
|
||||
.part {
|
||||
border-radius: 0.51em;
|
||||
|
||||
@ -3,9 +3,9 @@
|
||||
*ngFor="let part of parts.circuit.parts"
|
||||
[attr.x]="part.x + 'px'"
|
||||
[attr.y]="part.y + 'px'"
|
||||
[attr.width]="part.w + 'px'"
|
||||
[attr.height]="part.h + 'px'"
|
||||
[class.partDrag]="parts.dragStartPart === part"
|
||||
[attr.width]="RASTER * 3 + 'px'"
|
||||
[attr.height]="RASTER * 3 + 'px'"
|
||||
[class.partDrag]="parts.isDragged(part)"
|
||||
(mousedown)="parts.mouseDown(part, $event)"
|
||||
>
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 831 B After Width: | Height: | Size: 832 B |
@ -1,5 +1,5 @@
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {Part} from './Part';
|
||||
import {Part, RASTER} from './Part';
|
||||
import {Battery} from './battery/Battery';
|
||||
import {Light} from './light/Light';
|
||||
import {BatteryComponent} from './battery/battery.component';
|
||||
@ -70,4 +70,5 @@ export class PartComponent {
|
||||
return part instanceof Switch;
|
||||
}
|
||||
|
||||
protected readonly RASTER = RASTER;
|
||||
}
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import {Part} from "../Part";
|
||||
import {Junction} from '../../junction/Junction';
|
||||
import {PartType} from '../PartType';
|
||||
import {siPrefix} from '../../siPrefix';
|
||||
import {Wire} from '../../wire/Wire';
|
||||
import {RESISTANCE_MIN} from '../../circuit/Calculation';
|
||||
import {Circuit} from '../../circuit/Circuit';
|
||||
@ -54,10 +53,6 @@ export class Relay extends Part {
|
||||
return this.voltage > this.voltageMax;
|
||||
}
|
||||
|
||||
get voltageStr(): string {
|
||||
return siPrefix(Math.abs(this.voltage), 'V', 2);
|
||||
}
|
||||
|
||||
get current(): number {
|
||||
if (this.coilA.voltage === null || this.coilB.voltage === null) {
|
||||
return 0;
|
||||
@ -65,11 +60,15 @@ export class Relay extends Part {
|
||||
return (this.coilB.voltage - this.coilA.voltage) / this.resistance;
|
||||
}
|
||||
|
||||
get currentStr(): string {
|
||||
return siPrefix(Math.abs(this.current) || 0, 'A', 2);
|
||||
get voltageStr(): string {
|
||||
return this.circuit.voltageStr(this.voltage);
|
||||
}
|
||||
|
||||
override loop(): boolean {
|
||||
get currentStr(): string {
|
||||
return this.circuit.currentStr(this.current);
|
||||
}
|
||||
|
||||
override postCalculate(): boolean {
|
||||
const shouldBeActive = this.isCoilActive;
|
||||
const isActive = this.contact.end === this.active;
|
||||
if (isActive != shouldBeActive) {
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {Relay} from './Relay';
|
||||
import {NgIf} from '@angular/common';
|
||||
import {WireComponent} from '../../part-wire/wire.component';
|
||||
import {WireComponent} from '../../wire/wire.component';
|
||||
|
||||
@Component({
|
||||
selector: 'g[inner-part-relay]',
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {Switch} from './Switch';
|
||||
import {WireComponent} from '../../part-wire/wire.component';
|
||||
import {WireComponent} from '../../wire/wire.component';
|
||||
|
||||
@Component({
|
||||
selector: 'g[inner-part-switch]',
|
||||
|
||||
@ -1,18 +1,26 @@
|
||||
export const SI_PREFIXES: string[] = ['f', 'p', 'n', 'µ', 'm', '', 'k', 'M', 'G', 'T', 'E', 'P'];
|
||||
export const SI_PREFIXES: string[] = ['q', 'r', 'y', 'z', 'a', 'f', 'p', 'n', 'µ', 'm', '', 'k', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q'];
|
||||
|
||||
export function siPrefix(value: number, unit: string, minDigits: number): string {
|
||||
export function siPrefix(value: number, unit: string, minDigits: number, minGroup: number = -10, maxGroup: number = +10): string {
|
||||
if (value === 0) {
|
||||
return `0${unit}`;
|
||||
}
|
||||
|
||||
minGroup = Math.max(-10, minGroup);
|
||||
maxGroup = Math.min(+10, maxGroup);
|
||||
|
||||
const negative = value < 0;
|
||||
value = negative ? -value : value;
|
||||
const exp0 = Math.log10(value);
|
||||
const group = Math.floor(exp0 / 3);
|
||||
const index = group + 5;
|
||||
const prefix = SI_PREFIXES[index];
|
||||
const exp1 = group * 3;
|
||||
const factor = Math.pow(10, -exp1);
|
||||
const newValue = factor * value;
|
||||
|
||||
const measureExponent = Math.log10(value);
|
||||
const prefixGroup = Math.max(minGroup, Math.min(maxGroup, Math.floor(measureExponent / 3)));
|
||||
const prefixIndex = prefixGroup + 10;
|
||||
const prefix = SI_PREFIXES[prefixIndex];
|
||||
const scalerExponent = prefixGroup * 3;
|
||||
if (value < Math.pow(10, scalerExponent)) {
|
||||
return `0${unit}`;
|
||||
}
|
||||
const factor = Math.pow(10, -scalerExponent);
|
||||
const newValue = value * factor;
|
||||
const hasDigits = Math.floor(Math.log10(newValue)) + 1;
|
||||
const decimals = Math.max(0, minDigits - hasDigits);
|
||||
const newValueStr2 = newValue.toFixed(decimals);
|
||||
|
||||
@ -1,6 +1,5 @@
|
||||
import {Junction} from "../junction/Junction";
|
||||
import {RESISTANCE_MIN} from '../circuit/Calculation';
|
||||
import {fadeColor} from '../colorHelpers';
|
||||
|
||||
export const ANIMATION_ELECTRON_STEPS = 20;
|
||||
|
||||
@ -13,6 +12,7 @@ export class Wire {
|
||||
readonly end: Junction,
|
||||
public resistance: number,
|
||||
public name: string | null = null,
|
||||
readonly disconnectCallback?: (wire: Wire) => any,
|
||||
) {
|
||||
if (this.resistance === 0) {
|
||||
this.resistance = RESISTANCE_MIN;
|
||||
@ -24,6 +24,9 @@ export class Wire {
|
||||
disconnect() {
|
||||
this.start.wires.splice(this.start.wires.indexOf(this), 1);
|
||||
this.end.wires.splice(this.end.wires.indexOf(this), 1);
|
||||
if (this.disconnectCallback) {
|
||||
this.disconnectCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
toString() {
|
||||
@ -47,15 +50,13 @@ export class Wire {
|
||||
this.current = 0;
|
||||
}
|
||||
|
||||
voltageColor(): string {
|
||||
if (this.start.voltage === null || this.end.voltage === null || this.start.minCircuitVoltage === null || this.start.maxCircuitVoltage === null) {
|
||||
return 'lightgray';
|
||||
currentFrom(junction: Junction) {
|
||||
if (this.start === junction) {
|
||||
return this.current;
|
||||
} else if (this.end === junction) {
|
||||
return -this.current;
|
||||
}
|
||||
const ratio = ((this.end.voltage + this.start.voltage) / 2 - this.start.minCircuitVoltage) / (this.start.maxCircuitVoltage - this.start.minCircuitVoltage);
|
||||
if (ratio < 0.5) {
|
||||
return fadeColor(ratio * 2, '#008cff', 'magenta');
|
||||
}
|
||||
return fadeColor((ratio - 0.5) * 2, 'magenta', 'red');
|
||||
throw new Error(`Wire is not connected to given Junction: wire=${this}, junction=${junction}`);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
17
src/main/angular/src/app/editor/wire/wire.component.less
Normal file
17
src/main/angular/src/app/editor/wire/wire.component.less
Normal file
@ -0,0 +1,17 @@
|
||||
.wireBack {
|
||||
stroke-linecap: round;
|
||||
stroke-width: 11px;
|
||||
stroke: black;
|
||||
}
|
||||
|
||||
.wireBackGlobal:hover {
|
||||
stroke: darkgray;
|
||||
stroke-width: 15px;
|
||||
}
|
||||
|
||||
.wire {
|
||||
stroke-width: 9px;
|
||||
stroke-dasharray: 0 20;
|
||||
stroke-linecap: round;
|
||||
pointer-events: none;
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
<svg width="100%" height="100%">
|
||||
|
||||
<line class="wireBack {{extraClassesBack}}" [attr.x1]="x1" [attr.y1]="y1" [attr.x2]="x2" [attr.y2]="y2">
|
||||
<line class="wireBack {{extraClassesBack}}" [attr.x1]="x1" [attr.y1]="y1" [attr.x2]="x2" [attr.y2]="y2" (contextmenu)="click($event)">
|
||||
<!-- nothing -->
|
||||
</line>
|
||||
|
||||
|
Before Width: | Height: | Size: 462 B After Width: | Height: | Size: 492 B |
@ -1,5 +1,5 @@
|
||||
import {Component, Input} from '@angular/core';
|
||||
import {ANIMATION_ELECTRON_STEPS, Wire} from '../wire/Wire';
|
||||
import {ANIMATION_ELECTRON_STEPS, Wire} from './Wire';
|
||||
import {Junction} from '../junction/Junction';
|
||||
import {fadeColor} from '../colorHelpers';
|
||||
import {NgIf} from '@angular/common';
|
||||
@ -169,4 +169,12 @@ export class WireComponent {
|
||||
return fadeColor((ratio - 0.5) * 2, 'magenta', 'red');
|
||||
}
|
||||
|
||||
click($event: MouseEvent) {
|
||||
console.log($event);
|
||||
$event.preventDefault();
|
||||
if ($event.button === 2 && this.wire) {
|
||||
this.wire.disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user