📄 wfpanel.java
字号:
public JComponent getRowHeader() {
return rowHeader;
//return new WFRowHeader(this);
}
/** Set the WFPanel's master view. */
public void setMasterView (MasterView mv) {
this.mv = mv;
}
/**
* Set the start/end time of the panel. This may be different from the time span
* of the waveform data. For example, traces with different starting times
* can be time aligned in the MultiPanel by setting all their timebounds the
* same. Setting the time bounds can also be used to clip the data.
*/
public void setTimeBounds (double start, double end) {
panelBox.setTimeSpan(start, end);
}
public void setTimeBounds (TimeSpan ts) {
panelBox.setTimeSpan(ts);
}
/**
* Clear this WFPanel so that it blank when displayed on a partially full
* page that contains many WFPanels
*/
public void clear () {
wfv = null;
alternateWf = null;
dataBox.setNull();
panelBox.setNull();
}
// -------------------------------------------------------------------
/**
* Set the WFPanel's scaling factors to fit the WFSelectionBox
*/
void scalePanel () {
// Use the timeSpan of the panel box (for alignment) and the amps
// of the data box (for scaling)
WFSelectionBox box = new WFSelectionBox(panelBox);;
if (wfv.hasTimeSeries()) box.setAmpSpan(dataBox);
setScaleFactors (box);
}
/**
* Set this WFPanel's scaling factors so that the given WFSelectionBox
* (in time-amp space) fits completely inside this WFPanel. And the Waveform
* is drawn at the correct scale.
*/
//void scalePanelToBox (WFSelectionBox box)
void setScaleFactors (WFSelectionBox box) {
// pixels/second (X-axis)
if (box.getTimeSize() == 0.0) {
pixelsPerSecond = (double) getWidth();
} else {
pixelsPerSecond = (double) (getWidth()) / box.getTimeSize();
}
// pixels/count (Y-axis)
if (box.getAmpSize() == 0.0) {
pixelsPerCount = (double) getHeight();
} else {
pixelsPerCount = ((double) getHeight()) / box.getAmpSize();
}
// Y-offset to zero in the data(pixel space is always positive, data
// space can be negative.
transY = box.getMaxAmp();
// debug
//dumpScaleValues();
// System.out.println ("setScaleFactors = "+pixelsPerSecond+"/"+pixelsPerCount+" "+transY);
}
/**
* Dump values (for debugging)
*/
public void dumpScaleValues()
{
System.out.println ("----------- "+wfv.getChannelObj().toString()+" -----------");
System.out.println ("transY " + transY);
// System.out.println ("biasOffset " + biasOffset);
System.out.println ("dataBox " + dataBox.toString() );
// System.out.println ("viewBox " + viewBox.toString() );
System.out.println ("panelBox " + panelBox.toString() );
System.out.println ("panelWidth " + getWidth() );
System.out.println ("panelHeight " + getHeight() );
System.out.println ("pix/Sec " + pixelsPerSecond);
System.out.println ("pix/Count " + pixelsPerCount);
}
// -------------------------------------------------------------------
/**
* Paints one WFView in the WFPanel. Must rescale every time because frame
* may have been resized.
*/
public void paintComponent (Graphics g) {
super.paintComponent(g); // give super and delegate chance to paint
/* IMPORTANT!
* You must recalculate ALL scaling here because this may be called as a result
* of the frame being resized by the user with the frame border widgits.
*/
scalePanel();
paintBackground(g);
paintContents(g);
}
/**
* Paints the contents of the panel. Called after paintBackground();
*/
public void paintContents (Graphics g) {
if ( wfv == null ) return; // bail if no WFView (no data loaded)
paintData(g);
}
/**
* Shared basic painting of background.
* This sets the panel to the color indicating it's selected. Its also
* a workaround to stop a weird behavior where old components get
* painted into the WFPanel on repaints. Just paint over with the background
* color.
*/
public void paintBackground (Graphics g) {
// g.setColor(getBackgroundColor());
// g.fillRect(0, 0, getSize().width, getSize().height);
g.setColor(getBackgroundColor());
g.fillRect(0, 0, getWidth(), getHeight());
// g.setColor(getForeground());
if (getShowPhaseCues()) paintPhaseCues(g); // paint phase location cues
}
/**
* Shared basic painting of foreground "decorations" and data.
*/
public void paintData (Graphics g) {
// Plot all the segments in the view
paintTimeSeries(g);
// draw a scale (should be a seperate method)
paintScale (g);
// Put the picks on the view
paintPickFlags (g);
// Put the amps and codas on the view
paintAmpFlags (g);
paintCodaFlags(g);
// Label the trace
if (getShowChannelLabel()) {
g.setColor(TextColor);
// font ?
// g.setFont(fontBold);
String lab = wfv.getChannelObj().toDelimitedSeedString(' ') + " " +
df1.format(wfv.getDistance()) +"km" ;
g.drawString (lab, 10, 20);
}
} // end of paint()
/**
* Paint the time-series, i.e. the waveform in the WFView (all its segments)
*/
public void paintTimeSeries (Graphics g) {
Waveform wf = getWf();
if (wf == null || !wf.hasTimeSeries()) return;
// last sample drawn in previous segment, to connect segments on plot
Sample previousSample;
// synchronize to make sure another thread doesn't change the wf underneith us
synchronized (wf) {
WFSegment wfseg[] = WFSegment.getArray(wf.getSegmentList());
// optimization step, reduces method calls in loop ??
int count = wfseg.length;
for (int i = 0; i < count; i++) {
// handle continuity between contiguous segments (time tears)
if ( (i > 0) &&
WFSegment.areContiguous(wfseg[i-1], wfseg[i])) {
previousSample = wfseg[i-1].getLastSample();
} else {
previousSample = null;
}
paintSegment(g, wfseg[i], previousSample);
} // end of loop
} // end of synch
}
// --------------------------------------------------------------------
/**
* Paints one WFSegment in the WFPanel.
*/
// This stuff is here in an effort to reduce declarations inside of heavily used
// loops. I'm not sure it really matters.
double pixelsPerInterval;
int offsetX;
int jump;
int pointCount;
int x[];
int y[];
float sample[];
int x0, y0, xPixel;
float maxAmp, minAmp;
// THIS IS ONE OF THE MOST TIME CONSUMING PARTS OF THIS CODE. OPTIMIZE IF POSSIBLE
public void paintSegment (Graphics g, WFSegment wfseg, Sample previousSample) {
if (wfseg == null) return;
/*
* Recalculate 'pixelsPerInterval' because the sample interval (dt)
* could be different for each segment.
*/
// pixels between sample points
pixelsPerInterval = pixelsPerSecond * wfseg.getSampleInterval();
// if time scale is compressed (>4 samples/pixel), paint as bars
if (1.0/pixelsPerInterval >= 4.0) {
paintSegmentAsBars (g, wfseg, previousSample);
return;
}
// for time alignment
offsetX = pixelOfTime(wfseg.getEpochStart());
// Decimation factor is tied to scale such that we "over sample" by about x4.
// I arrived at this value by testing. Decimation speeds things up emmensely.
jump = Math.max(1, (int) (wfseg.size()/getSize().width/2) );
// count of points that will be in decimated plotting array
pointCount = (wfseg.size() / jump);
// instantiate the x-y ploting arrays for use in Graphics.drawPolyline()
x = new int[pointCount];
y = new int[pointCount];
sample = wfseg.getTimeSeries();
// Convert seismogram to pixel coordinate system
// interval w/ decimation
pixelInterval = pixelsPerInterval * (double)jump;
xPosition = (double) offsetX;
int idx = 0;
for (int i = 0 ; i < pointCount; i++) {
x[i] = (int) xPosition;
//"inline" this method to optimize
y[i] = pixelOfAmp(sample[idx]);
//TODO: might round off error accumulate here?
xPosition += pixelInterval; // inc. pixel by decimated interval
idx += jump;
}
// show start of WFSegment if showSegment is true
// do it first so they are behind the waveform
if (getShowSegments()) paintPacketSpans (g);
// set plot color specific to component sh log /sys
g.setColor(WFColor);
// plot line connecting segments if necessary
if (previousSample != null) {
x0 = offsetX + (int) (-1 * pixelsPerInterval);
y0 = pixelOfAmp(previousSample.value);
g.drawLine(x0, y0, x[0], y[0]);
}
// plot the seismogram, this is the major resource sink of the program
g.drawPolyline (x, y, pointCount);
// mark individual samples if scale allows (> 4 pixels per sample)
if (pixelsPerInterval > 4.0) {
// if (showSamples) {
// g.setColor(Color.red);
// int center = pixelOfAmp(wfseg.getBias());
// for (int i = 0 ; i < x.length ; i++) {
// g.drawLine(x[i], y[i], x[i], center);
// }
// }
// } else
if (showSamples) {
g.setColor(Color.red);
for (int i = 0 ; i < x.length ; i++) {
g.drawLine(x[i], y[i]-2, x[i], y[i]+2);
}
}
}
} // end of paintSegment()
/**
* Paints one WFSegment in the WFPanel using a shortcut technique that plot the
* waveform by plotting a vertical bar, one pixel wide, that
* represents the max/min range of the samples that lie within that pixel. This only
* works if the time scale is compressed to the point that there is more than one sample
* per pixel. <p>
* This speeds up plotting and makes the seismograms look better then simple decimation
* without filtering.
* Suggested by Paul Friberg.
*/
public void paintSegmentAsBars (Graphics g, WFSegment wfseg, Sample previousSample) {
/*
* Recalculate 'pixelsPerInterval' because the sample interval (dt)
* could be different for each segment.
*/
// data check
if (!wfseg.hasTimeSeries()) return;
// pixels between sample points
double secPerPixel = 1.0/pixelsPerSecond;
// for time alignment
xPixel = pixelOfTime(wfseg.getEpochStart());
sample = wfseg.getTimeSeries();
if (showSegments) paintPacketSpans (g);
// set plot color specific to component sh log /sys
g.setColor(WFColor);
// Convert seismogram to pixel coordinate system
maxAmp = sample[0];
minAmp = maxAmp;
double pixelEnd = wfseg.getEpochStart() + secPerPixel;
double currentTime = wfseg.getEpochStart();
for (int i = 0; i < sample.length; i++ ) {
maxAmp = Math.max(maxAmp, sample[i]);
minAmp = Math.min(minAmp, sample[i]);
if ( currentTime >= pixelEnd ) { // end of a pixel interval
// draw the bar
g.drawLine(xPixel, pixelOfAmp(maxAmp),
xPixel, pixelOfAmp(minAmp));
// inc. stuff and reset for next sample interval
xPixel++; // one pixel
pixelEnd += secPerPixel;
// this actually included the last sample in the next interval so
// there are no gaps between bars
maxAmp = sample[i];
minAmp = maxAmp;
}
currentTime += wfseg.getSampleInterval(); // increment
}
}
/**
* Draw lines at the packet boundaries.
*/
public void paintPacketSpans(Graphics g) {
int start;
int end;
Waveform wf = getWf();
if (wf != null) {
g.setColor (segEdgeColor);
TimeSpan pkt[] = wf.getPacketSpans();
if (pkt != null) {
for (int i = 0; i< pkt.length; i++) {
start = pixelOfTime(pkt[i].getStart());
end = pixelOfTime(pkt[i].getEnd());
g.drawLine (start, 0 , start, getHeight() );
g.drawLine (end, 0 , end, getHeight() );
}
}
}
}
/**
* Plot the phases on the waveform
*/
//TODO: could set an optional mode that would show deleted phases
public void paintPickFlags (Graphics g)
{
if ( wfv == null ) return; // bail if no WFView (no data loaded)
// get the phase list
Phase ph[] = (Phase[]) wfv.phaseList.getArray();
// wfv.phaseList.toArray(ph);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -