Mercurial > dive4elements > river
comparison flys-artifacts/src/main/java/de/intevation/flys/artifacts/WINFOArtifact.java @ 451:73bc64c4a7b0
Use new logic to calculate "W für ungleichwertige Abfluesse". Not working yet.
flys-artifacts/trunk@1946 c6561f87-3c4e-4783-a992-168aeb5c3f6f
author | Sascha L. Teichmann <sascha.teichmann@intevation.de> |
---|---|
date | Wed, 18 May 2011 17:37:06 +0000 |
parents | c8bb38115290 |
children | 343f248e4c8c |
comparison
equal
deleted
inserted
replaced
450:c8bb38115290 | 451:73bc64c4a7b0 |
---|---|
30 import de.intevation.flys.artifacts.model.MainValuesFactory; | 30 import de.intevation.flys.artifacts.model.MainValuesFactory; |
31 import de.intevation.flys.artifacts.model.WQCKms; | 31 import de.intevation.flys.artifacts.model.WQCKms; |
32 import de.intevation.flys.artifacts.model.WQDay; | 32 import de.intevation.flys.artifacts.model.WQDay; |
33 import de.intevation.flys.artifacts.model.WQKms; | 33 import de.intevation.flys.artifacts.model.WQKms; |
34 import de.intevation.flys.artifacts.model.WstValueTable; | 34 import de.intevation.flys.artifacts.model.WstValueTable; |
35 import de.intevation.flys.artifacts.model.WstValueTable.QPosition; | |
35 import de.intevation.flys.artifacts.model.WstValueTableFactory; | 36 import de.intevation.flys.artifacts.model.WstValueTableFactory; |
36 | 37 |
38 import de.intevation.flys.artifacts.math.LinearRemap; | |
39 | |
40 import gnu.trove.TDoubleArrayList; | |
37 | 41 |
38 /** | 42 /** |
39 * The default WINFO artifact. | 43 * The default WINFO artifact. |
40 * | 44 * |
41 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> | 45 * @author <a href="mailto:ingo.weinzierl@intevation.de">Ingo Weinzierl</a> |
470 } | 474 } |
471 | 475 |
472 return wqkms; | 476 return wqkms; |
473 } | 477 } |
474 | 478 |
475 | |
476 /** | 479 /** |
477 * Returns the data computed by the discharge longitudinal section | 480 * Returns the data computed by the discharge longitudinal section |
478 * computation. | 481 * computation. |
479 * | 482 * |
480 * @return an array of WQKms object - one object for each given Q value. | 483 * @return an array of WQKms object - one object for each given Q value. |
481 */ | 484 */ |
482 public WQKms[] getDischargeLongitudinalSectionData() { | 485 public WQKms [] getDischargeLongitudinalSectionData() { |
486 | |
483 logger.debug("WINFOArtifact.getDischargeLongitudinalSectionData"); | 487 logger.debug("WINFOArtifact.getDischargeLongitudinalSectionData"); |
484 | 488 |
485 River river = getRiver(); | 489 River river = getRiver(); |
486 if (river == null) { | 490 if (river == null) { |
487 logger.error("No river selected."); | 491 logger.error("No river selected."); |
492 return new WQKms[0]; | |
488 } | 493 } |
489 | 494 |
490 WstValueTable wst = WstValueTableFactory.getTable(river); | 495 WstValueTable wst = WstValueTableFactory.getTable(river); |
491 if (wst == null) { | 496 if (wst == null) { |
492 logger.error("No Wst found for selected river."); | 497 logger.error("No wst found for selected river."); |
493 } | 498 return new WQKms[0]; |
494 | 499 } |
495 double[][] dist = getSplittedDistance(); | 500 |
496 int num = dist != null ? dist.length : 0; | 501 double [][] segments = getSplittedDistance(); |
497 | 502 |
498 double[][] allQs = new double[num][]; | 503 if (segments.length < 1) { |
499 double[][] allWs = new double[num][]; | 504 logger.warn("no segments given"); |
500 WQKms[][] wqkms = new WQKms[num][]; | 505 return new WQKms[0]; |
501 | 506 } |
502 boolean qSel = true; | 507 |
503 | 508 if (segments.length == 1) { |
504 for (int i = 0; i < num; i++) { | 509 // fall back to normal "Wasserstand/Wasserspiegellage" calculation |
505 double[] kms = getKms(dist[i]); | 510 double [] qs = toQs(segments[0]); |
506 if (kms == null) { | 511 if (qs == null) { |
507 // XXX maybe we should cancel this operation here. | 512 logger.warn("no qs given"); |
513 return new WQKms[0]; | |
514 } | |
515 if (qs.length == 1) { | |
516 double [] kms = getKms(segments[0]); | |
517 return computeWaterlevelData(kms, qs, wst); | |
518 } | |
519 } | |
520 | |
521 // more than one segment | |
522 | |
523 double [] boundKms; | |
524 | |
525 if (segments.length == 2) { | |
526 boundKms = new double [] { segments[0][0], segments[1][1] }; | |
527 } | |
528 else { | |
529 TDoubleArrayList bounds = new TDoubleArrayList(); | |
530 | |
531 bounds.add(segments[0][0]); | |
532 | |
533 for (int i = 1; i < segments.length-1; ++i) { | |
534 double [] segment = segments[i]; | |
535 | |
536 Gauge gauge = river.determineGauge(segment[0], segment[1]); | |
537 | |
538 if (gauge == null) { | |
539 logger.warn("no gauge found between " + | |
540 segment[0] + " and " + segment[1]); | |
541 bounds.add(0.5*(segment[0] + segment[1])); | |
542 } | |
543 else { | |
544 bounds.add(gauge.getStation().doubleValue()); | |
545 } | |
546 } | |
547 | |
548 bounds.add(segments[segments.length-1][1]); | |
549 boundKms = bounds.toNativeArray(); | |
550 } | |
551 | |
552 if (logger.isDebugEnabled()) { | |
553 logger.debug("bound kms: " + joinDoubles(boundKms)); | |
554 } | |
555 | |
556 double [][] iqs = null; | |
557 | |
558 for (int i = 0; i < segments.length; ++i) { | |
559 double [] iqsi = toQs(segments[i]); | |
560 if (iqsi == null) { | |
561 logger.warn("iqsi == null"); | |
562 return new WQKms[0]; | |
563 } | |
564 | |
565 if (iqs == null) { | |
566 iqs = new double[iqsi.length][boundKms.length]; | |
567 } | |
568 else if (iqs.length != iqsi.length) { | |
569 logger.warn("iqsi.logger != iqs.length: " | |
570 + iqsi.length + " " + iqsi.length); | |
571 return new WQKms[0]; | |
572 } | |
573 | |
574 if (logger.isDebugEnabled()) { | |
575 logger.debug("segments qs[ " + i + "]: " + joinDoubles(iqsi)); | |
576 } | |
577 | |
578 for (int j = 0; j < iqs.length; ++j) { | |
579 iqs[j][i] = iqsi[j]; | |
580 } | |
581 } | |
582 | |
583 if (logger.isDebugEnabled()) { | |
584 for (int i = 0; i < iqs.length; ++i) { | |
585 logger.debug("iqs[" + i + "]: " + joinDoubles(iqs[i])); | |
586 } | |
587 } | |
588 | |
589 double [] boundWs = new double[boundKms.length]; | |
590 double [] boundQs = new double[boundKms.length]; | |
591 | |
592 // XXX: Is there some state missing? | |
593 | |
594 double [] okms = getExplodedValues( | |
595 boundKms[0], boundKms[boundKms.length-1], DEFAULT_KM_STEPS); | |
596 | |
597 ArrayList<WQKms> results = new ArrayList<WQKms>(); | |
598 | |
599 for (int i = 0; i < iqs.length; ++i) { | |
600 double [] iqsi = iqs[i]; | |
601 | |
602 QPosition qPosition = wst.interpolate( | |
603 iqsi[0], 0, boundKms, boundWs, boundQs); | |
604 | |
605 if (qPosition == null) { | |
606 logger.warn("interpolation failed for " + iqsi[i]); | |
508 continue; | 607 continue; |
509 } | 608 } |
510 | 609 |
511 double[] qs = getQs(dist[i]); | 610 LinearRemap remap = new LinearRemap(); |
512 allQs[i] = qs; | 611 |
513 | 612 for (int j = 1; j < boundKms.length; ++j) { |
514 if (qs == null) { | 613 remap.add( |
515 logger.debug("Determine Q values based on a set of W values."); | 614 boundKms[j-1], boundKms[j], |
516 qSel = false; | 615 boundQs[j-1], iqsi[j-1], |
517 | 616 boundQs[j], iqsi[j]); |
518 allWs[i] = getWs(dist[i]); | 617 } |
519 qs = getQsForWs(allWs[i]); | 618 |
520 } | 619 double [] oqs = new double[okms.length]; |
521 | 620 double [] ows = new double[okms.length]; |
522 wqkms[i] = computeWaterlevelData(kms, qs, wst); | 621 |
523 } | 622 wst.interpolate(okms, ows, oqs, qPosition, remap); |
524 | 623 |
525 WQKms[] merged = WQKms.merge(wqkms); | 624 BackJumpCorrector bjc = new BackJumpCorrector(); |
526 int numMerged = merged.length; | 625 if (bjc.doCorrection(okms, ows)) { |
527 WQKms[] computed = new WQKms[numMerged]; | 626 logger.debug("Discharge longitudinal section has backjumps."); |
528 | 627 results.add(new WQCKms(okms, oqs, ows, bjc.getCorrected())); |
529 for (int i = 0; i < numMerged; i++) { | 628 } |
530 computed[i] = computeDischargeLongitudinalSectionData(merged[i]); | 629 else { |
531 | 630 results.add(new WQKms(okms, oqs, ows)); |
532 setDischargeLongitudinalSectionNames( | 631 } |
533 computed[i], | 632 } |
534 qSel ? allQs : allWs, | 633 // TODO: set names |
535 i, | 634 |
536 qSel ? "Q" : "W"); | 635 return results.toArray(new WQKms[results.size()]); |
537 } | 636 } |
538 | 637 |
539 // TODO Introduce a caching mechanism here! | 638 protected static String joinDoubles(double [] x) { |
540 | 639 if (x == null) { |
541 return computed; | 640 return "null"; |
641 } | |
642 StringBuilder sb = new StringBuilder(); | |
643 for (int i = 0; i < x.length; ++i) { | |
644 if (i > 0) sb.append(", "); | |
645 sb.append(x[i]); | |
646 } | |
647 return sb.toString(); | |
648 } | |
649 | |
650 protected double [] toQs(double [] range) { | |
651 double [] qs = getQs(range); | |
652 if (qs == null) { | |
653 logger.debug("Determine Q values based on a set of W values."); | |
654 double [] ws = getWs(range); | |
655 qs = getQsForWs(ws); | |
656 } | |
657 return qs; | |
542 } | 658 } |
543 | 659 |
544 | 660 |
545 /** | 661 /** |
546 * Sets the name for discharge longitudinal section curves where each WQKms | 662 * Sets the name for discharge longitudinal section curves where each WQKms |