OpenLayers OpenLayers

Changeset 5660

Show
Ignore:
Timestamp:
01/06/08 19:00:08 (1 year ago)
Author:
tschaub
Message:

a bit cleaner and tests

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • sandbox/tschaub/scalebar/examples/scalebar.html

    r5657 r5660  
    8383     
    8484    <div> 
    85         <p>Update the scale bar with the form elements below.  (In IE, click 
    86         away from these form elements to see the scale bar updated.)</p> 
    8785        <select name="displaySystem" id="displaySystem" 
    8886                onchange="updateProperties();"> 
     
    10199        <br /> 
    102100        <input type="checkbox" id="abbreviateLabel" 
    103                onchange="updateProperties();" /> 
     101               onclick="updateProperties();" /> 
    104102        <label for="abbreviateLabel">abbreviated label</label> 
    105103        <br /> 
    106104        <input type="checkbox" id="showMinorMeasures" 
    107                onchange="updateProperties();" /> 
     105               onclick="updateProperties();" /> 
    108106        <label for="showMinorMeasures">show subdivision measures (use CSS to reduce font size)</label> 
    109107        <br /> 
    110108        <input type="checkbox" id="singleLine" 
    111                onchange="updateProperties();" /> 
     109               onclick="updateProperties();" /> 
    112110        <label for="singleLine">single line display (best with abbreviated label)</label> 
    113111        <br /> 
  • sandbox/tschaub/scalebar/lib/OpenLayers/Control/ScaleBar.js

    r5657 r5660  
    269269     */ 
    270270    update: function(scale) { 
    271         if(this.map.baseLayer == null || !this.map.getResolution()) { 
     271        if(this.map.baseLayer == null || !this.map.getScale()) { 
    272272            return; 
    273273        } 
     
    277277        this.element.style.width = this.maxWidth + 'px'; 
    278278        // check each measurement unit in the display system 
    279         var system = this.measurementProperties[this.displaySystem]; 
    280         var numUnits = system.units.length; 
    281         var comp = new Array(numUnits); 
    282         var numDiv = this.divisions * this.subdivisions; 
    283         for(var unitIndex = 0; unitIndex < numUnits; ++unitIndex) { 
    284             comp[unitIndex] = {}; 
    285             var pixelsPerDisplayUnit = OpenLayers.DOTS_PER_INCH * 
    286                                        system.inches[unitIndex] / 
    287                                        this.scale; 
    288             var minSDDisplayLength = ((this.minWidth - this.xOffsetNumbersBox) / 
    289                                        pixelsPerDisplayUnit) / 
    290                                       (numDiv); 
    291             var maxSDDisplayLength = ((this.maxWidth - this.xOffsetNumbersBox) / 
    292                                        pixelsPerDisplayUnit) / 
    293                                       (numDiv); 
    294             // add up scores for each marker (even if numbers aren't displayed) 
    295             for(var valueIndex = 0; valueIndex < (numDiv); ++valueIndex) { 
    296                 var minNumber = minSDDisplayLength * (valueIndex + 1); 
    297                 var maxNumber = maxSDDisplayLength * (valueIndex + 1); 
    298                 var num = this.getHandsomeNumber(minNumber, maxNumber); 
    299                 comp[unitIndex][valueIndex] = { 
    300                     value: (num.value / (valueIndex + 1)), 
    301                     score: 0, 
    302                     tieBreaker: 0, 
    303                     numDec: 0, 
    304                     displayed: 0 
    305                 }; 
    306                 // now tally up scores for all values given this subdivision length 
    307                 for(var valueIndex2 = 0; valueIndex2 < numDiv; ++valueIndex2) { 
    308                     var displayedValuePosition = num.value * (valueIndex2 + 1) / (valueIndex + 1); 
    309                     var num2 = this.getHandsomeNumber(displayedValuePosition, displayedValuePosition); 
    310                     var major = ((valueIndex2 + 1) % this.subdivisions == 0); 
    311                     var last = ((valueIndex2 + 1) == numDiv); 
    312                     if((this.singleLine && last) || 
    313                        (!this.singleLine && (major || this.showMinorMeasures))) { 
    314                         // count scores for displayed marker measurements 
    315                         comp[unitIndex][valueIndex].score += num2.score; 
    316                         comp[unitIndex][valueIndex].tieBreaker += num2.tieBreaker; 
    317                         comp[unitIndex][valueIndex].numDec = Math.max(comp[unitIndex][valueIndex].numDec, num2.numDec); 
    318                         comp[unitIndex][valueIndex].displayed += 1; 
    319                     } else { 
    320                         // count scores for non-displayed marker measurements 
    321                         comp[unitIndex][valueIndex].score += num2.score / this.subdivisions; 
    322                         comp[unitIndex][valueIndex].tieBreaker += num2.tieBreaker / this.subdivisions; 
    323                     } 
    324                 } 
    325                 // adjust scores so numbers closer to 1 are preferred for display 
    326                 var scoreAdjustment = (unitIndex + 1) * 
    327                                       comp[unitIndex][valueIndex].tieBreaker / 
    328                                       comp[unitIndex][valueIndex].displayed; 
    329                 comp[unitIndex][valueIndex].score *= scoreAdjustment; 
    330             } 
    331         } 
     279        var comp = this.getComp(); 
    332280        // get the value (subdivision length) with the lowest cumulative score 
    333         var subdivisionDisplayLength = null; 
    334         var displayUnits = null; 
    335         var displayUnitsAbbr = null; 
    336         var subdivisionPixelLength = null; 
    337         var bestScore = Number.POSITIVE_INFINITY; 
    338         var bestTieBreaker = Number.POSITIVE_INFINITY; 
    339         var numDec = 0; 
    340         for(var unitIndex = 0; unitIndex < comp.length; ++unitIndex) { 
    341             for(valueIndex in comp[unitIndex]) { 
    342                 if((comp[unitIndex][valueIndex].score < bestScore) || 
    343                    ((comp[unitIndex][valueIndex].score == bestScore) && 
    344                     (comp[unitIndex][valueIndex].tieBreaker < bestTieBreaker))) { 
    345                     bestScore = comp[unitIndex][valueIndex].score; 
    346                     bestTieBreaker = comp[unitIndex][valueIndex].tieBreaker; 
    347                     subdivisionDisplayLength = comp[unitIndex][valueIndex].value; 
    348                     numDec = comp[unitIndex][valueIndex].numDec; 
    349                     displayUnits = system.units[unitIndex]; 
    350                     displayUnitsAbbr = system.abbr[unitIndex]; 
    351                     pixelsPerDisplayUnit = OpenLayers.DOTS_PER_INCH * 
    352                                            system.inches[unitIndex] / 
    353                                            this.scale; 
    354                     subdivisionPixelLength = pixelsPerDisplayUnit * subdivisionDisplayLength; // round before use in style 
    355                 } 
    356             } 
    357         } 
     281        this.setSubProps(comp); 
    358282        // clean out any old content from containers 
    359283        this.labelContainer.innerHTML = ""; 
     
    362286        // create all divisions 
    363287        var marker, bar, numbersBox, xOffset; 
     288        var numDiv = this.divisions * this.subdivisions; 
    364289        var alignmentOffset = { 
    365290            left: 0 + (this.singleLine ? 0 : this.xOffsetNumbersBox), 
    366291            center: (this.maxWidth / 2) - (numDiv * 
    367                                            subdivisionPixelLength / 2) - 
     292                                           this.subProps.pixels / 2) - 
    368293                                          (this.singleLine ? this.xOffsetSingleLine / 2 : 0), 
    369294            right: this.maxWidth - (numDiv * 
    370                                     subdivisionPixelLength) - 
     295                                    this.subProps.pixels) - 
    371296                                   (this.singleLine ? this.xOffsetSingleLine : this.xOffsetNumbersBox) 
    372297        } 
     
    375300        for(var divisionIndex = 0; divisionIndex < this.divisions; ++divisionIndex) { 
    376301            // set xPosition and markerMeasure to start of division 
    377             xPosition = divisionIndex * this.subdivisions * subdivisionPixelLength
     302            xPosition = divisionIndex * this.subdivisions * this.subProps.pixels
    378303            xPosition += alignmentOffset[this.align]; 
    379304            markerMeasure = (divisionIndex == 0) ? 
    380305                            0 : ((divisionIndex * this.subdivisions) * 
    381                                  subdivisionDisplayLength).toFixed(numDec); 
     306                                 this.subProps.length).toFixed(this.subProps.dec); 
    382307            // add major marker 
    383308            marker = document.createElement('div'); 
     
    408333                bar.style.position = 'absolute'; 
    409334                bar.style.overflow = 'hidden'; 
    410                 bar.style.width = Math.round(subdivisionPixelLength) + 'px'; 
     335                bar.style.width = Math.round(this.subProps.pixels) + 'px'; 
    411336                if((subdivisionIndex % 2) == 0) { 
    412337                    bar.className = this.displayClass + 'Bar'; 
     
    422347                    // set xPosition and markerMeasure to end of subdivision 
    423348                    xPosition = ((divisionIndex * this.subdivisions) + 
    424                                  (subdivisionIndex + 1)) * subdivisionPixelLength
     349                                 (subdivisionIndex + 1)) * this.subProps.pixels
    425350                    xPosition += alignmentOffset[this.align]; 
    426351                    markerMeasure = (divisionIndex * this.subdivisions + 
    427                                      subdivisionIndex + 1) * subdivisionDisplayLength; 
     352                                     subdivisionIndex + 1) * this.subProps.length; 
    428353                    marker = document.createElement('div'); 
    429354                    marker.className = this.displayClass + 'MarkerMinor'; 
     
    448373        } 
    449374        // set xPosition and markerMeasure to end of divisions 
    450         xPosition = (numDiv) * subdivisionPixelLength
     375        xPosition = numDiv * this.subProps.pixels
    451376        xPosition += alignmentOffset[this.align]; 
    452         markerMeasure = ((numDiv) * 
    453                          subdivisionDisplayLength).toFixed(numDec); 
     377        markerMeasure = (numDiv * this.subProps.length).toFixed(this.subProps.dec); 
    454378        // add the final major marker 
    455379        marker = document.createElement('div'); 
     
    490414            labelBox.className = this.displayClass + 'LabelBox'; 
    491415            labelBox.style.textAlign = 'center'; 
    492             labelBox.style.width = Math.round(numDiv * 
    493                                               subdivisionPixelLength) + 'px' 
     416            labelBox.style.width = Math.round(numDiv * this.subProps.pixels) + 'px' 
    494417            labelBox.style.left = Math.round(alignmentOffset[this.align]) + 'px'; 
    495418            labelBox.style.overflow = 'hidden'; 
    496419        } 
    497420        if(this.abbreviateLabel) { 
    498             labelText += ' ' + displayUnitsAbbr; 
     421            labelText += ' ' + this.subProps.abbr; 
    499422        } else { 
    500             labelText += ' ' + displayUnits; 
     423            labelText += ' ' + this.subProps.units; 
    501424        } 
    502425        labelBox.appendChild(document.createTextNode(labelText)); 
    503426        this.labelContainer.appendChild(labelBox); 
     427    }, 
     428     
     429    /** 
     430     * Method: getComp 
     431     * Get comparison matrix. 
     432     */ 
     433    getComp: function() { 
     434        var system = this.measurementProperties[this.displaySystem]; 
     435        var numUnits = system.units.length; 
     436        var comp = new Array(numUnits); 
     437        var numDiv = this.divisions * this.subdivisions; 
     438        for(var unitIndex = 0; unitIndex < numUnits; ++unitIndex) { 
     439            comp[unitIndex] = {}; 
     440            var pixelsPerDisplayUnit = OpenLayers.DOTS_PER_INCH * 
     441                                       system.inches[unitIndex] / 
     442                                       this.scale; 
     443            var minSDDisplayLength = ((this.minWidth - this.xOffsetNumbersBox) / 
     444                                       pixelsPerDisplayUnit) / numDiv; 
     445            var maxSDDisplayLength = ((this.maxWidth - this.xOffsetNumbersBox) / 
     446                                       pixelsPerDisplayUnit) / numDiv; 
     447            // add up scores for each marker (even if numbers aren't displayed) 
     448            for(var valueIndex = 0; valueIndex < numDiv; ++valueIndex) { 
     449                var minNumber = minSDDisplayLength * (valueIndex + 1); 
     450                var maxNumber = maxSDDisplayLength * (valueIndex + 1); 
     451                var num = this.getHandsomeNumber(minNumber, maxNumber); 
     452                var compNum = { 
     453                    value: (num.value / (valueIndex + 1)), 
     454                    score: 0, 
     455                    tie: 0, 
     456                    dec: 0, 
     457                    displayed: 0 
     458                }; 
     459                // tally up scores for all values given this subdivision length 
     460                for(var valueIndex2 = 0; valueIndex2 < numDiv; ++valueIndex2) { 
     461                    var position = num.value * (valueIndex2 + 1) / (valueIndex + 1); 
     462                    var num2 = this.getHandsomeNumber(position, position); 
     463                    var major = ((valueIndex2 + 1) % this.subdivisions == 0); 
     464                    var last = ((valueIndex2 + 1) == numDiv); 
     465                    if((this.singleLine && last) || 
     466                       (!this.singleLine && (major || this.showMinorMeasures))) { 
     467                        // count scores for displayed marker measurements 
     468                        compNum.score += num2.score; 
     469                        compNum.tie += num2.tie; 
     470                        compNum.dec = Math.max(compNum.dec, num2.dec); 
     471                        compNum.displayed += 1; 
     472                    } else { 
     473                        // count scores for non-displayed marker measurements 
     474                        compNum.score += num2.score / this.subdivisions; 
     475                        compNum.tie += num2.tie / this.subdivisions; 
     476                    } 
     477                } 
     478                // adjust scores so numbers closer to 1 are preferred for display 
     479                var scoreAdjustment = (unitIndex + 1) * 
     480                                      compNum.tie / 
     481                                      compNum.displayed; 
     482                compNum.score *= scoreAdjustment; 
     483                comp[unitIndex][valueIndex] = compNum; 
     484            } 
     485        } 
     486        return comp; 
     487    }, 
     488     
     489    /** 
     490     * Method: setSubProps 
     491     * Set subdivision properties based on comparison matrix. 
     492     */ 
     493    setSubProps: function(comp) { 
     494        var system = this.measurementProperties[this.displaySystem]; 
     495        var length = null; 
     496        var pixels = null; 
     497        var units = null; 
     498        var abbr = null; 
     499        var score = Number.POSITIVE_INFINITY; 
     500        var tie = Number.POSITIVE_INFINITY; 
     501        var dec = 0; 
     502        for(var unitIndex = 0; unitIndex < comp.length; ++unitIndex) { 
     503            for(valueIndex in comp[unitIndex]) { 
     504                if((comp[unitIndex][valueIndex].score < score) || 
     505                   ((comp[unitIndex][valueIndex].score == score) && 
     506                    (comp[unitIndex][valueIndex].tie < tie))) { 
     507                    score = comp[unitIndex][valueIndex].score; 
     508                    tie = comp[unitIndex][valueIndex].tie; 
     509                    length = comp[unitIndex][valueIndex].value; 
     510                    dec = comp[unitIndex][valueIndex].dec; 
     511                    units = system.units[unitIndex]; 
     512                    abbr = system.abbr[unitIndex]; 
     513                    pixelsPerDisplayUnit = OpenLayers.DOTS_PER_INCH * 
     514                                           system.inches[unitIndex] / 
     515                                           this.scale; 
     516                    pixels = pixelsPerDisplayUnit * length; // round before use 
     517                } 
     518            } 
     519        } 
     520        this.subProps = { 
     521            length: length, 
     522            pixels: pixels, 
     523            units: units, 
     524            abbr: abbr, 
     525            dec: dec 
     526        }; 
    504527    }, 
    505528     
     
    592615    /** 
    593616     * Method: getHandsomeNumber 
    594      * Attempts to generate a nice looking number between two other numbers. 
     617     * Attempts to generate a nice looking positive number between two other 
     618     *     positive numbers. 
    595619     * 
    596620     * Parameters: 
    597      * small - {Float}  
    598      * big - {Float}  
    599      * sigFigs - {Integer} 
     621     * small - {Float} Lower positive bound. 
     622     * big - {Float} Upper positive bound. 
     623     * sigFigs - {Integer} Number of significant figures to consider.  Default 
     624     *     is 10. 
    600625     * 
    601626     * Returns: 
     
    608633            value: small, 
    609634            score: Number.POSITIVE_INFINITY, 
    610             tieBreaker: Number.POSITIVE_INFINITY, 
    611             numDec: 3 
     635            tie: Number.POSITIVE_INFINITY, 
     636            dec: 3 
    612637        }; 
    613638        // try the first three comely multiplicands (in order of comliness) 
    614         var cmult, max, numDec, tmult, multiplier, score, tieBreaker
    615         for(var halvingExp = 0; halvingExp < 3; ++halvingExp) { 
    616             cmult = Math.pow(2, (-1 * halvingExp)); 
     639        var cmult, max, dec, tmult, multiplier, score, tie
     640        for(var hexp = 0; hexp < 3; ++hexp) { 
     641            cmult = Math.pow(2, (-1 * hexp)); 
    617642            max = Math.floor(Math.log(big / cmult) / Math.LN10); 
    618643            for(var texp = max; texp > (max - sigFigs + 1); --texp) { 
    619                 numDec = Math.max(halvingExp - texp, 0); 
     644                dec = Math.max(hexp - texp, 0); 
    620645                tmult = cmult * Math.pow(10, texp); 
    621646                // check if there is an integer multiple of tmult 
     
    630655                    } 
    631656                    // test against the best (lower == better) 
    632                     score = multiplier + (2 * halvingExp); 
    633                     tieBreaker = (texp < 0) ? (Math.abs(texp) + 1) : texp; 
     657                    score = multiplier + (2 * hexp); 
     658                    tie = (texp < 0) ? (Math.abs(texp) + 1) : texp; 
    634659                    if((score < num.score) || ((score == num.score) && 
    635                        (tieBreaker < num.tieBreaker))) { 
    636                         num.value = (tmult * multiplier).toFixed(numDec); 
     660                       (tie < num.tie))) { 
     661                        num.value = parseFloat((tmult * multiplier).toFixed(dec)); 
    637662                        num.score = score; 
    638                         num.tieBreaker = tieBreaker
    639                         num.numDec = numDec; 
     663                        num.tie = tie
     664                        num.dec = dec; 
    640665                    } 
    641666                } 
  • sandbox/tschaub/scalebar/tests/list-tests.html

    r5575 r5660  
    8585    <li>Control/test_Permalink.html</li> 
    8686    <li>Control/test_Scale.html</li> 
     87    <li>Control/test_ScaleBar.html</li> 
    8788    <li>Control/test_SelectFeature.html</li> 
    8889    <li>test_Handler.html</li>