/*
Copyright (C) Paul Falstad and Iain Sharp
This file is part of CircuitJS1.
CircuitJS1 is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
CircuitJS1 is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with CircuitJS1. If not, see <http://www.gnu.org/licenses/>.
*/
package com.lushprojects.circuitjs1.client;
//import java.awt.*;
//import java.util.StringTokenizer;
class TransLineElm extends CircuitElm {
double delay, imped;
double voltageL[], voltageR[];
int lenSteps, ptr, width;
public TransLineElm(int xx, int yy) {
super(xx, yy);
delay = 1000*sim.timeStep;
imped = 75;
noDiagonal = true;
reset();
}
public TransLineElm(int xa, int ya, int xb, int yb, int f,
StringTokenizer st) {
super(xa, ya, xb, yb, f);
delay = new Double(st.nextToken()).doubleValue();
imped = new Double(st.nextToken()).doubleValue();
width = new Integer(st.nextToken()).intValue();
// next slot is for resistance (losses), which is not implemented
st.nextToken();
noDiagonal = true;
reset();
}
int getDumpType() { return 171; }
int getPostCount() { return 4; }
int getInternalNodeCount() { return 2; }
String dump() {
return super.dump() + " " + delay + " " + imped + " " + width + " " + 0.;
}
void drag(int xx, int yy) {
xx = sim.snapGrid(xx);
yy = sim.snapGrid(yy);
int w1 = max(sim.gridSize, abs(yy-y));
int w2 = max(sim.gridSize, abs(xx-x));
if (w1 > w2) {
xx = x;
width = w2;
} else {
yy = y;
width = w1;
}
x2 = xx; y2 = yy;
setPoints();
}
Point posts[], inner[];
void reset() {
if (sim.timeStep == 0)
return;
lenSteps = (int) (delay/sim.timeStep);
System.out.println(lenSteps + " steps");
if (lenSteps > 100000)
voltageL = voltageR = null;
else {
voltageL = new double[lenSteps];
voltageR = new double[lenSteps];
}
ptr = 0;
super.reset();
}
void setPoints() {
super.setPoints();
int ds = (dy == 0) ? sign(dx) : -sign(dy);
Point p3 = interpPoint(point1, point2, 0, -width*ds);
Point p4 = interpPoint(point1, point2, 1, -width*ds);
int sep = sim.gridSize/2;
Point p5 = interpPoint(point1, point2, 0, -(width/2-sep)*ds);
Point p6 = interpPoint(point1, point2, 1, -(width/2-sep)*ds);
Point p7 = interpPoint(point1, point2, 0, -(width/2+sep)*ds);
Point p8 = interpPoint(point1, point2, 1, -(width/2+sep)*ds);
// we number the posts like this because we want the lower-numbered
// points to be on the bottom, so that if some of them are unconnected
// (which is often true) then the bottom ones will get automatically
// attached to ground.
posts = new Point[] { p3, p4, point1, point2 };
inner = new Point[] { p7, p8, p5, p6 };
}
void draw(Graphics g) {
setBbox(posts[0], posts[3], 0);
int segments = (int) (dn/2);
int ix0 = ptr-1+lenSteps;
double segf = 1./segments;
int i;
g.setColor(Color.darkGray);
g.fillRect(inner[2].x, inner[2].y,
inner[1].x-inner[2].x+2, inner[1].y-inner[2].y+2);
for (i = 0; i != 4; i++) {
setVoltageColor(g, volts[i]);
drawThickLine(g, posts[i], inner[i]);
}
if (voltageL != null) {
for (i = 0; i != segments; i++) {
int ix1 = (ix0-lenSteps*i/segments) % lenSteps;
int ix2 = (ix0-lenSteps*(segments-1-i)/segments) % lenSteps;
double v = (voltageL[ix1]+voltageR[ix2])/2;
setVoltageColor(g, v);
interpPoint(inner[0], inner[1], ps1, i*segf);
interpPoint(inner[2], inner[3], ps2, i*segf);
g.drawLine(ps1.x, ps1.y, ps2.x, ps2.y);
interpPoint(inner[2], inner[3], ps1, (i+1)*segf);
drawThickLine(g, ps1, ps2);
}
}
setVoltageColor(g, volts[0]);
drawThickLine(g, inner[0], inner[1]);
drawPosts(g);
curCount1 = updateDotCount(-current1, curCount1);
curCount2 = updateDotCount(current2, curCount2);
if (sim.dragElm != this) {
drawDots(g, posts[0], inner[0], curCount1);
drawDots(g, posts[2], inner[2], -curCount1);
drawDots(g, posts[1], inner[1], -curCount2);
drawDots(g, posts[3], inner[3], curCount2);
}
}
int voltSource1, voltSource2;
double current1, current2, curCount1, curCount2;
void setVoltageSource(int n, int v) {
if (n == 0)
voltSource1 = v;
else
voltSource2 = v;
}
void setCurrent(int v, double c) {
if (v == voltSource1)
current1 = c;
else
current2 = c;
}
void stamp() {
sim.stampVoltageSource(nodes[4], nodes[0], voltSource1);
sim.stampVoltageSource(nodes[5], nodes[1], voltSource2);
sim.stampResistor(nodes[2], nodes[4], imped);
sim.stampResistor(nodes[3], nodes[5], imped);
}
void startIteration() {
// calculate voltages, currents sent over wire
if (voltageL == null) {
sim.stop("Transmission line delay too large!", this);
return;
}
voltageL[ptr] = volts[2]-volts[0] + volts[2]-volts[4];
voltageR[ptr] = volts[3]-volts[1] + volts[3]-volts[5];
//System.out.println(volts[2] + " " + volts[0] + " " + (volts[2]-volts[0]) + " " + (imped*current1) + " " + voltageL[ptr]);
/*System.out.println("sending fwd " + currentL[ptr] + " " + current1);
System.out.println("sending back " + currentR[ptr] + " " + current2);*/
//System.out.println("sending back " + voltageR[ptr]);
ptr = (ptr+1) % lenSteps;
}
void doStep() {
if (voltageL == null) {
sim.stop("Transmission line delay too large!", this);
return;
}
sim.updateVoltageSource(nodes[4], nodes[0], voltSource1, -voltageR[ptr]);
sim.updateVoltageSource(nodes[5], nodes[1], voltSource2, -voltageL[ptr]);
if (Math.abs(volts[0]) > 1e-5 || Math.abs(volts[1]) > 1e-5) {
sim.stop("Need to ground transmission line!", this);
return;
}
}
Point getPost(int n) {
return posts[n];
}
//double getVoltageDiff() { return volts[0]; }
int getVoltageSourceCount() { return 2; }
boolean hasGroundConnection(int n1) { return false; }
boolean getConnection(int n1, int n2) {
return false;
/*if (comparePair(n1, n2, 0, 1))
return true;
if (comparePair(n1, n2, 2, 3))
return true;
return false;*/
}
void getInfo(String arr[]) {
arr[0] = "transmission line";
arr[1] = getUnitText(imped, sim.ohmString);
arr[2] = "length = " + getUnitText(2.9979e8*delay, "m");
arr[3] = "delay = " + getUnitText(delay, "s");
}
public EditInfo getEditInfo(int n) {
if (n == 0)
return new EditInfo("Delay (s)", delay, 0, 0);
if (n == 1)
return new EditInfo("Impedance (ohms)", imped, 0, 0);
return null;
}
public void setEditValue(int n, EditInfo ei) {
if (n == 0) {
delay = ei.value;
reset();
}
if (n == 1) {
imped = ei.value;
reset();
}
}
double getCurrentIntoPoint(int xa, int ya) {
if (xa == posts[0].x && ya== posts[0].y)
return current1;
if (xa == posts[2].x && ya == posts[2].y)
return -current1;
if (xa == posts[3].x && ya == posts[3].y)
return -current2;
return current2;
}
}