diff --git a/LICENSE.txt b/LICENSE.txt
index 37ec93a1..e10841c5 100644
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,191 +1,21 @@
-Apache License
-Version 2.0, January 2004
-http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-"License" shall mean the terms and conditions for use, reproduction, and
-distribution as defined by Sections 1 through 9 of this document.
-
-"Licensor" shall mean the copyright owner or entity authorized by the copyright
-owner that is granting the License.
-
-"Legal Entity" shall mean the union of the acting entity and all other entities
-that control, are controlled by, or are under common control with that entity.
-For the purposes of this definition, "control" means (i) the power, direct or
-indirect, to cause the direction or management of such entity, whether by
-contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
-outstanding shares, or (iii) beneficial ownership of such entity.
-
-"You" (or "Your") shall mean an individual or Legal Entity exercising
-permissions granted by this License.
-
-"Source" form shall mean the preferred form for making modifications, including
-but not limited to software source code, documentation source, and configuration
-files.
-
-"Object" form shall mean any form resulting from mechanical transformation or
-translation of a Source form, including but not limited to compiled object code,
-generated documentation, and conversions to other media types.
-
-"Work" shall mean the work of authorship, whether in Source or Object form, made
-available under the License, as indicated by a copyright notice that is included
-in or attached to the work (an example is provided in the Appendix below).
-
-"Derivative Works" shall mean any work, whether in Source or Object form, that
-is based on (or derived from) the Work and for which the editorial revisions,
-annotations, elaborations, or other modifications represent, as a whole, an
-original work of authorship. For the purposes of this License, Derivative Works
-shall not include works that remain separable from, or merely link (or bind by
-name) to the interfaces of, the Work and Derivative Works thereof.
-
-"Contribution" shall mean any work of authorship, including the original version
-of the Work and any modifications or additions to that Work or Derivative Works
-thereof, that is intentionally submitted to Licensor for inclusion in the Work
-by the copyright owner or by an individual or Legal Entity authorized to submit
-on behalf of the copyright owner. For the purposes of this definition,
-"submitted" means any form of electronic, verbal, or written communication sent
-to the Licensor or its representatives, including but not limited to
-communication on electronic mailing lists, source code control systems, and
-issue tracking systems that are managed by, or on behalf of, the Licensor for
-the purpose of discussing and improving the Work, but excluding communication
-that is conspicuously marked or otherwise designated in writing by the copyright
-owner as "Not a Contribution."
-
-"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
-of whom a Contribution has been received by Licensor and subsequently
-incorporated within the Work.
-
-2. Grant of Copyright License.
-
-Subject to the terms and conditions of this License, each Contributor hereby
-grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
-irrevocable copyright license to reproduce, prepare Derivative Works of,
-publicly display, publicly perform, sublicense, and distribute the Work and such
-Derivative Works in Source or Object form.
-
-3. Grant of Patent License.
-
-Subject to the terms and conditions of this License, each Contributor hereby
-grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
-irrevocable (except as stated in this section) patent license to make, have
-made, use, offer to sell, sell, import, and otherwise transfer the Work, where
-such license applies only to those patent claims licensable by such Contributor
-that are necessarily infringed by their Contribution(s) alone or by combination
-of their Contribution(s) with the Work to which such Contribution(s) was
-submitted. If You institute patent litigation against any entity (including a
-cross-claim or counterclaim in a lawsuit) alleging that the Work or a
-Contribution incorporated within the Work constitutes direct or contributory
-patent infringement, then any patent licenses granted to You under this License
-for that Work shall terminate as of the date such litigation is filed.
-
-4. Redistribution.
-
-You may reproduce and distribute copies of the Work or Derivative Works thereof
-in any medium, with or without modifications, and in Source or Object form,
-provided that You meet the following conditions:
-
-You must give any other recipients of the Work or Derivative Works a copy of
-this License; and
-You must cause any modified files to carry prominent notices stating that You
-changed the files; and
-You must retain, in the Source form of any Derivative Works that You distribute,
-all copyright, patent, trademark, and attribution notices from the Source form
-of the Work, excluding those notices that do not pertain to any part of the
-Derivative Works; and
-If the Work includes a "NOTICE" text file as part of its distribution, then any
-Derivative Works that You distribute must include a readable copy of the
-attribution notices contained within such NOTICE file, excluding those notices
-that do not pertain to any part of the Derivative Works, in at least one of the
-following places: within a NOTICE text file distributed as part of the
-Derivative Works; within the Source form or documentation, if provided along
-with the Derivative Works; or, within a display generated by the Derivative
-Works, if and wherever such third-party notices normally appear. The contents of
-the NOTICE file are for informational purposes only and do not modify the
-License. You may add Your own attribution notices within Derivative Works that
-You distribute, alongside or as an addendum to the NOTICE text from the Work,
-provided that such additional attribution notices cannot be construed as
-modifying the License.
-You may add Your own copyright statement to Your modifications and may provide
-additional or different license terms and conditions for use, reproduction, or
-distribution of Your modifications, or for any such Derivative Works as a whole,
-provided Your use, reproduction, and distribution of the Work otherwise complies
-with the conditions stated in this License.
-
-5. Submission of Contributions.
-
-Unless You explicitly state otherwise, any Contribution intentionally submitted
-for inclusion in the Work by You to the Licensor shall be under the terms and
-conditions of this License, without any additional terms or conditions.
-Notwithstanding the above, nothing herein shall supersede or modify the terms of
-any separate license agreement you may have executed with Licensor regarding
-such Contributions.
-
-6. Trademarks.
-
-This License does not grant permission to use the trade names, trademarks,
-service marks, or product names of the Licensor, except as required for
-reasonable and customary use in describing the origin of the Work and
-reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty.
-
-Unless required by applicable law or agreed to in writing, Licensor provides the
-Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
-including, without limitation, any warranties or conditions of TITLE,
-NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
-solely responsible for determining the appropriateness of using or
-redistributing the Work and assume any risks associated with Your exercise of
-permissions under this License.
-
-8. Limitation of Liability.
-
-In no event and under no legal theory, whether in tort (including negligence),
-contract, or otherwise, unless required by applicable law (such as deliberate
-and grossly negligent acts) or agreed to in writing, shall any Contributor be
-liable to You for damages, including any direct, indirect, special, incidental,
-or consequential damages of any character arising as a result of this License or
-out of the use or inability to use the Work (including but not limited to
-damages for loss of goodwill, work stoppage, computer failure or malfunction, or
-any and all other commercial damages or losses), even if such Contributor has
-been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability.
-
-While redistributing the Work or Derivative Works thereof, You may choose to
-offer, and charge a fee for, acceptance of support, warranty, indemnity, or
-other liability obligations and/or rights consistent with this License. However,
-in accepting such obligations, You may act only on Your own behalf and on Your
-sole responsibility, not on behalf of any other Contributor, and only if You
-agree to indemnify, defend, and hold each Contributor harmless for any liability
-incurred by, or claims asserted against, such Contributor by reason of your
-accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-APPENDIX: How to apply the Apache License to your work
-
-To apply the Apache License to your work, attach the following boilerplate
-notice, with the fields enclosed by brackets "[]" replaced with your own
-identifying information. (Don't include the brackets!) The text should be
-enclosed in the appropriate comment syntax for the file format. We also
-recommend that a file or class name and description of purpose be included on
-the same "printed page" as the copyright notice for easier identification within
-third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
+The MIT License (MIT)
+
+Copyright (c) 2017 Zalando SE
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/README.md b/README.md
index 3b3360ac..08ca487f 100644
--- a/README.md
+++ b/README.md
@@ -1,54 +1,43 @@
-
+# Tech Radar
-.
+At [Zalando](http://zalando.de), we maintain a public [Tech
+Radar](http://zalando.github.io/tech-radar/) to help our delivery teams
+align on technology choices. Is is based on the pioneering work
+by [ThoughtWorks](https://www.thoughtworks.com/radar).
-# Zalando Tech Radar
+This repository contains the [visualization code](radar.js)
+(js, based on [d3.js v4](https://d3js.org)). Feel free to adapt it
+to your own purposes.
-The **Zalando Tech Radar** is a tool to inspire and support teams to pick the best technologies for new projects. Based on the ideas of [ThoughtWorks](https://www.thoughtworks.com/radar), our Tech Radar sets out the changes in technologies that are interesting in software development: changes that we think our engineering teams should pay attention to and consider using in their projects.
-This repository shares:
+## Usage
-* the *visualization* of the **[latest Zalando Tech Radar release](http://zalando.github.io/tech-radar/)**, including a short summary of what it includes and how we are using it;
+See `docs/index.html` for sample usage. The current release version is
+[radar-0.1.js](http://zalando.github.io/tech-radar/release/radar-0.1.js)
-* *code* for generating the Tech Radar visualization from a simple tabular representation (tsv). The visualization code is based on the [Protovis JavaScript visualization library](http://mbostock.github.io/protovis/) and a fork of [Brett Dargan's Tech Radar visualization tool](https://github.com/bdargan/techradar). We've optimized the layout to make the chart and explanations fit on a double-sided sheet of A4 paper.
-
-
-## Cool. How can I make my own?
-
-Create a Google doc with the following columns:
-
-* **Technology** (e.g. "Hystrix")
-* **Quadrant** (Needs to be exactly and at least one of each quadrants: "Platforms & Infrastructure", "Data Mgt", "Languages", "Techniques; Frameworks & Tools")
-* *[optional] Comments (e.g. "lib for fault tolerance")*
-* **Score** as a float between 2.0 and -2.0 (e.g. "1.8")
-* *[optional] Number of votes, for internal bookkeeping*
-* *[optional] Consensus score, for internal bookkeeping*
-* **Skip** — set to true if entry should not be visualized on chart
-
-Then follow the instructions below.
-
-Note: the score-to-ring mapping we use is not linear:
-
- score 2 ----- 1.5 --------------- 0 ---------- -1 ---------- -2
- ring ADOPT TRIAL ASSESS HOLD
-
-## How to generate a new chart
-
-1. run `gem install liquid` if necessary
-1. on the master google doc, select `File > Download as > Tab-separated values` and store as `data/year_month.tsv`
-1. open `data/year_month.tsv` and delete the first line (which contains the headers)
-1. run `./transform.rb` to generate a new `radar_data.js`
-1. open `index.html` in your browser to inspect the result
-1. repeat the last two steps until you're happy with the arrangement :)
-1. check everything in
-1. merge `master` branch into `gh-pages`
-1. push `gh-pages` to publish the new radar
-
-
-### Notes
-
-* if your google doc is public, you can use `./download.sh` to automate steps 2 and 3
-* the last `.tsv` file (by lexical order) in `data/` is visualized. The next-to-last `.tsv` file (if it exists) is used to find out which blips have moved, relative to the previous radar.
## License
-Apache 2.0 — same as [bdargan/techradar](https://github.com/bdargan/techradar)
+
+```
+The MIT License (MIT)
+
+Copyright (c) 2017 Zalando SE
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+```
\ No newline at end of file
diff --git a/archive/Zalando_Tech_Radar_2016_10.pdf b/docs/archive/Zalando_Tech_Radar_2016_10.pdf
similarity index 100%
rename from archive/Zalando_Tech_Radar_2016_10.pdf
rename to docs/archive/Zalando_Tech_Radar_2016_10.pdf
diff --git a/archive/Zalando_Tech_Radar_2017_03.pdf b/docs/archive/Zalando_Tech_Radar_2017_03.pdf
similarity index 100%
rename from archive/Zalando_Tech_Radar_2017_03.pdf
rename to docs/archive/Zalando_Tech_Radar_2017_03.pdf
diff --git a/archive/Zalando_Tech_Radar_2017_07.pdf b/docs/archive/Zalando_Tech_Radar_2017_07.pdf
similarity index 100%
rename from archive/Zalando_Tech_Radar_2017_07.pdf
rename to docs/archive/Zalando_Tech_Radar_2017_07.pdf
diff --git a/data/2015_12.tsv b/docs/archive/data/2015_12.tsv
similarity index 100%
rename from data/2015_12.tsv
rename to docs/archive/data/2015_12.tsv
diff --git a/data/2016_04.tsv b/docs/archive/data/2016_04.tsv
similarity index 100%
rename from data/2016_04.tsv
rename to docs/archive/data/2016_04.tsv
diff --git a/data/2016_10.tsv b/docs/archive/data/2016_10.tsv
similarity index 100%
rename from data/2016_10.tsv
rename to docs/archive/data/2016_10.tsv
diff --git a/data/2017_03.tsv b/docs/archive/data/2017_03.tsv
similarity index 100%
rename from data/2017_03.tsv
rename to docs/archive/data/2017_03.tsv
diff --git a/data/2017_07.tsv b/docs/archive/data/2017_07.tsv
similarity index 100%
rename from data/2017_07.tsv
rename to docs/archive/data/2017_07.tsv
diff --git a/docs/favicon.ico b/docs/favicon.ico
deleted file mode 100644
index 0e0c0197..00000000
Binary files a/docs/favicon.ico and /dev/null differ
diff --git a/docs/index.html b/docs/index.html
index f204d78b..5bc7f379 100644
--- a/docs/index.html
+++ b/docs/index.html
@@ -1,16 +1,12 @@
+
- Diagram of the Causes of Mortality
- in the Army of the East
-
-
-
- The Areas of the blue, red, & black wedges are each measured from the
- centre as the common vertex
-
The blue wedges measured from the centre of the circle represent area
- for area the deaths from Preventible or Mitigable Zymotic Diseases, the
- red wedges measured from the center the deaths from wounds, & the
- black wedges measured from the center the deaths from all other causes
-
In October 1844, & April 1855, the black area coincides with the
- red, in January & February 1856, the blue coincides with the black
-
The entire areas may be compared by following the blue, the red &
- the black lines enclosing them.
-
- An n-body force, as defined by Coulomb's law or Newton's law of
-gravitation, inversely proportional to the square of the distance between
-particles.
-
- Implements a layout for stacked visualizations, ranging from simple
-stacked bar charts to more elaborate "streamgraphs" composed of stacked
-areas.
-
- Apply a function against an accumulator and each value of the array (from
-left-to-right) as to reduce it to a single value. Implemented in Javascript
-1.8.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {function}f
-
-
-
function to execute on each value in the array.
-
-
- v
- Optional
-
-
object to use as the first argument to the first call of
-t.
-
- Extends
- pv.Mark.
-
-
- Represents an anchor on a given mark. An anchor is itself a mark, but
-without a visual representation. It serves only to provide useful default
-properties that can be inherited by other marks. Each type of mark can define
-any number of named anchors for convenience. If the concrete mark type does
-not define an anchor implementation specifically, one will be inherited from
-the mark's parent class.
-
-
For example, the bar mark provides anchors for its four sides: left,
-right, top and bottom. Adding a label to the top anchor of a bar,
-
-
bar.anchor("top").add(pv.Label);
-
-will render a text label on the top edge of the bar; the top anchor defines
-the appropriate position properties (top and left), as well as text-rendering
-properties for convenience (textAlign and textBaseline).
-
-
Note that anchors do not inherit from their targets; the positional
-properties are copied from the scene graph, which guarantees that the anchors
-are positioned correctly, even if the positional properties are not defined
-deterministically. (In addition, it also improves performance by avoiding
-re-evaluating expensive properties.) If you want the anchor to inherit from
-the target, use pv.Mark#extend before adding. For example:
-
-
bar.anchor("top").extend(bar).add(pv.Label);
-
-The anchor defines it's own positional properties, but other properties (such
-as the title property, say) can be inherited using the above idiom. Also note
-that you can override positional properties in the anchor for custom
-behavior.
-
-
- Defined in: Anchor.js.
-
-
-
-
-
-
- The anchor name. The set of supported anchor names is dependent on the
-concrete mark type; see the mark type for details. For example, bars support
-left, right, top and bottom anchors.
-
-
While anchor names are typically constants, the anchor name is a true
-property, which means you can specify a function to compute the anchor name
-dynamically. For instance, if you wanted to alternate top and bottom anchors,
-saying
-
-
- Returns the anchor target of this mark, if it is derived from an anchor;
-otherwise returns null. For example, if a label is derived from a bar anchor,
-
-
bar.anchor("top").add(pv.Label);
-
-then property functions on the label can refer to the bar via the
-anchorTarget method. This method is also useful for mark types
-defining properties on custom anchors.
-
-
-
-
-
-
-
-
-
-
-
-
-
Returns:
-
-
{pv.Mark} the anchor target of this mark; possibly null.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Documentation generated by JsDoc Toolkit 2.3.2 on Fri May 28 2010 10:13:27 GMT-0700 (PDT)
-
-
- Extends
- pv.Mark.
-
-
- Represents an area mark: the solid area between two series of
-connected line segments. Unsurprisingly, areas are used most frequently for
-area charts.
-
-
Just as a line represents a polyline, the Area mark type
-represents a polygon. However, an area is not an arbitrary polygon;
-vertices are paired either horizontally or vertically into parallel
-spans, and each span corresponds to an associated datum. Either the
-width or the height must be specified, but not both; this determines whether
-the area is horizontally-oriented or vertically-oriented. Like lines, areas
-can be stroked and filled with arbitrary colors.
-
-
- Constructs a new area mark with default properties. Areas are not typically
-constructed directly, but by adding to a panel or an existing mark via
-pv.Mark#add.
-
-
- Default properties for areas. By default, there is no stroke and the fill
-style is a categorical color.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- fillStyle
-
-
-
- The area fill style; if non-null, the interior of the polygon forming the
-area is filled with the specified color. The default value of this property
-is a categorical color.
-
-
This property is fixed for non-segmented areas. See
-pv.Mark.
-
-
-
- The height of a given span, in pixels; used for vertical spans. If the height
-is specified, the width property should be 0 (the default). Either the left
-or right property should be used to space the spans horizontally, typically
-as a multiple of the index.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- interpolate
-
-
-
- How to interpolate between values. Linear interpolation ("linear") is the
-default, producing a straight line between points. For piecewise constant
-functions (i.e., step functions), either "step-before" or "step-after" can be
-specified. To draw open uniform b-splines, specify "basis". To draw cardinal
-splines, specify "cardinal"; see also #tension.
-
-
- The width of stroked lines, in pixels; used in conjunction with
-strokeStyle to stroke the perimeter of the area. Unlike the
-Line mark type, the entire perimeter is stroked, rather than just one
-edge. The default value of this property is 1.5, but since the default stroke
-style is null, area marks are not stroked by default.
-
-
This property is fixed for non-segmented areas. See
-pv.Mark.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {boolean}
- segmented
-
-
-
- Whether the area is segmented; whether variations in fill style, stroke
-style, and the other properties are treated as fixed. Rendering segmented
-areas is noticeably slower than non-segmented areas.
-
-
- The style of stroked lines; used in conjunction with lineWidth to
-stroke the perimeter of the area. Unlike the Line mark type, the
-entire perimeter is stroked, rather than just one edge. The default value of
-this property is null, meaning areas are not stroked by default.
-
-
This property is fixed for non-segmented areas. See
-pv.Mark.
-
-
-
- The tension of cardinal splines; used in conjunction with
-interpolate("cardinal"). A value between 0 and 1 draws cardinal splines with
-the given tension. In some sense, the tension can be interpreted as the
-"length" of the tangent; a tension of 1 will yield all zero tangents (i.e.,
-linear interpolation), and a tension of 0 yields a Catmull-Rom spline. The
-default value is 0.7.
-
-
- The width of a given span, in pixels; used for horizontal spans. If the width
-is specified, the height property should be 0 (the default). Either the top
-or bottom property should be used to space the spans vertically, typically as
-a multiple of the index.
-
-
-
- Constructs a new area anchor with default properties. Areas support five
-different anchors:
-
-
top
-
left
-
center
-
bottom
-
right
-
-
In addition to positioning properties (left, right, top bottom), the
-anchors support text rendering properties (text-align, text-baseline). Text
-is rendered to appear inside the area. The area anchor also propagates the
-interpolate, eccentricity, and tension properties such that an anchored area
-or line will match positions between control points.
-
-
For consistency with the other mark types, the anchor positions are
-defined in terms of their opposite edge. For example, the top anchor defines
-the bottom property, such that an area added to the top anchor grows upward.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {string}name
-
-
-
the anchor name; either a string or a property function.
-
- Extends
- pv.Mark.
-
-
- Represents a bar: an axis-aligned rectangle that can be stroked and
-filled. Bars are used for many chart types, including bar charts, histograms
-and Gantt charts. Bars can also be used as decorations, for example to draw a
-frame border around a panel; in fact, a panel is a special type (a subclass)
-of bar.
-
-
Bars can be positioned in several ways. Most commonly, one of the four
-corners is fixed using two margins, and then the width and height properties
-determine the extent of the bar relative to this fixed location. For example,
-using the bottom and left properties fixes the bottom-left corner; the width
-then extends to the right, while the height extends to the top. As an
-alternative to the four corners, a bar can be positioned exclusively using
-margins; this is convenient as an inset from the containing panel, for
-example. See pv.Mark for details on the prioritization of redundant
-positioning properties.
-
-
- Constructs a new bar mark with default properties. Bars are not typically
-constructed directly, but by adding to a panel or an existing mark via
-pv.Mark#add.
-
-
- Default properties for bars. By default, there is no stroke and the fill
-style is a categorical color.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- fillStyle
-
-
-
- The bar fill style; if non-null, the interior of the bar is filled with the
-specified color. The default value of this property is a categorical color.
-
-
-
- The height of the bar, in pixels. If the bottom position is specified, the
-bar extends upward from the bottom edge; if the top position is specified,
-the bar extends downward from the top edge.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- lineWidth
-
-
-
- The width of stroked lines, in pixels; used in conjunction with
-strokeStyle to stroke the bar's border.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- strokeStyle
-
-
-
- The style of stroked lines; used in conjunction with lineWidth to
-stroke the bar's border. The default value of this property is null, meaning
-bars are not stroked by default.
-
-
-
- The width of the bar, in pixels. If the left position is specified, the bar
-extends rightward from the left edge; if the right position is specified, the
-bar extends leftward from the right edge.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Documentation generated by JsDoc Toolkit 2.3.2 on Fri May 28 2010 10:13:27 GMT-0700 (PDT)
-
-
- Extends
- pv.Behavior.
-
-
- Implements interactive dragging starting with mousedown events.
-Register this behavior on marks that should be draggable by the user, such as
-the selected region for brushing and linking. This behavior can be used in
-tandom with pv.Behavior.select to allow the selected region to be
-dragged interactively.
-
-
After the initial mousedown event is triggered, this behavior listens for
-mousemove and mouseup events on the window. This allows dragging to continue
-even if the mouse temporarily leaves the mark that is being dragged, or even
-the root panel.
-
-
This behavior requires that the data associated with the mark being
-dragged have x and y attributes that correspond to the
-mark's location in pixels. The mark's positional properties are not set
-directly by this behavior; instead, the positional properties should be
-defined as:
-
-
.left(function(d) d.x)
- .top(function(d) d.y)
-
-Thus, the behavior does not move the mark directly, but instead updates the
-mark position by updating the underlying data. Note that if the positional
-properties are defined with bottom and right (rather than top and left), the
-drag behavior will be inverted, which will confuse users!
-
-
The drag behavior is bounded by the parent panel; the x and
-y attributes are clamped such that the mark being dragged does not
-extend outside the enclosing panel's bounds. To facilitate this, the drag
-behavior also queries for dx and dy attributes on the
-underlying data, to determine the dimensions of the bar being dragged. For
-non-rectangular marks, the drag behavior simply treats the mark as a point,
-which means that only the mark's center is bounded.
-
-
The mark being dragged is automatically re-rendered for each mouse event
-as part of the drag operation. In addition, a fix attribute is
-populated on the mark, which allows visual feedback for dragging. For
-example, to change the mark fill color while dragging:
-
-
-
-In some cases, such as with network layouts, dragging the mark may cause
-related marks to change, in which case additional marks may also need to be
-rendered. This can be accomplished by listening for the drag
-psuedo-events:
-
-
dragstart (on mousedown)
-
drag (on mousemove)
-
dragend (on mouseup)
-
-
For example, to render the parent panel while dragging, thus
-re-rendering all sibling marks:
-
-
-
- Extends
- function.
-
-
- Represents a reusable interaction; applies an interactive behavior to
-a given mark. Behaviors are themselves functions designed to be used as event
-handlers. For example, to add pan and zoom support to any panel, say:
-
-
-
-The behavior should be registered on the event that triggers the start of the
-behavior. Typically, the behavior will take care of registering for any
-additional events that are necessary. For example, dragging starts on
-mousedown, while the drag behavior automatically listens for mousemove and
-mouseup events on the window. By listening to the window, the behavior can
-continue to receive mouse events even if the mouse briefly leaves the mark
-being dragged, or even the root panel.
-
-
Each behavior implementation has specific requirements as to which events
-it supports, and how it should be used. For example, the drag behavior
-requires that the data associated with the mark be an object with x
-and y attributes, such as a pv.Vector, storing the mark's
-position. See an implementing class for details.
-
-
- Defined in: Behavior.js.
-
-
-
- Extends
- pv.Behavior.
-
-
- Implements interactive panning starting with mousedown events.
-Register this behavior on panels to allow panning. This behavior can be used
-in tandem with pv.Behavior.zoom to allow both panning and zooming:
-
-
-
-The pan behavior currently supports only mouse events; support for keyboard
-shortcuts to improve accessibility may be added in the future.
-
-
After the initial mousedown event is triggered, this behavior listens for
-mousemove and mouseup events on the window. This allows panning to continue
-even if the mouse temporarily leaves the panel that is being panned, or even
-the root panel.
-
-
The implementation of this behavior relies on the panel's
-transform property, which specifies a matrix transformation that is
-applied to child marks. Note that the transform property only affects the
-panel's children, but not the panel itself; therefore the panel's fill and
-stroke will not change when the contents are panned.
-
-
Panels have transparent fill styles by default; this means that panels may
-not receive the initial mousedown event to start panning. To fix this
-problem, either given the panel a visible fill style (such as "white"), or
-set the events property to "all" such that the panel receives events
-despite its transparent fill.
-
-
The pan behavior has optional support for bounding. If enabled, the user
-will not be able to pan the panel outside of the initial bounds. This feature
-is designed to work in conjunction with the zoom behavior; otherwise,
-bounding the panel effectively disables all panning.
-
-
- Defined in: Pan.js.
-
-
- Sets or gets the bound parameter. If bounding is enabled, the user will not
-be able to pan outside the initial panel bounds; this typically applies
-only when the pan behavior is used in tandem with the zoom behavior.
-Bounding is not enabled by default.
-
-
Note: enabling bounding after panning has already occurred will not
-immediately reset the transform. Bounding should be enabled before the
-panning behavior is applied.
-
-
-
-
- Extends
- pv.Behavior.
-
-
- Implements interactive fuzzy pointing, identifying marks that are in
-close proximity to the mouse cursor. This behavior is an alternative to the
-native mouseover and mouseout events, improving usability. Rather than
-requiring the user to mouseover a mark exactly, the mouse simply needs to
-move near the given mark and a "point" event is triggered. In addition, if
-multiple marks overlap, the point behavior can be used to identify the mark
-instance closest to the cursor, as opposed to the one that is rendered on
-top.
-
-
The point behavior can also identify the closest mark instance for marks
-that produce a continuous graphic primitive. The point behavior can thus be
-used to provide details-on-demand for both discrete marks (such as dots and
-bars), as well as continuous marks (such as lines and areas).
-
-
This behavior is implemented by finding the closest mark instance to the
-mouse cursor on every mousemove event. If this closest mark is within the
-given radius threshold, which defaults to 30 pixels, a "point" psuedo-event
-is dispatched to the given mark instance. If any mark were previously
-pointed, it would receive a corresponding "unpoint" event. These two
-psuedo-event types correspond to the native "mouseover" and "mouseout"
-events, respectively. To increase the radius at which the point behavior can
-be applied, specify an appropriate threshold to the constructor, up to
-Infinity.
-
-
By default, the standard Cartesian distance is computed. However, with
-some visualizations it is desirable to consider only a single dimension, such
-as the x-dimension for an independent variable. In this case, the
-collapse parameter can be set to collapse the y dimension:
-
-
This behavior only listens to mousemove events on the assigned panel,
-which is typically the root panel. The behavior will search recursively for
-descendant marks to point. If the mouse leaves the assigned panel, the
-behavior no longer receives mousemove events; an unpoint psuedo-event is
-automatically dispatched to unpoint any pointed mark. Marks may be re-pointed
-when the mouse reenters the panel.
-
-
Panels have transparent fill styles by default; this means that panels may
-not receive the initial mousemove event to start pointing. To fix this
-problem, either given the panel a visible fill style (such as "white"), or
-set the events property to "all" such that the panel receives events
-despite its transparent fill.
-
-
Note: this behavior does not currently wedge marks.
-
-
- Defined in: Point.js.
-
-
- Sets or gets the collapse parameter. By default, the standard Cartesian
-distance is computed. However, with some visualizations it is desirable to
-consider only a single dimension, such as the x-dimension for an
-independent variable. In this case, the collapse parameter can be set to
-collapse the y dimension:
-
-
-
- Extends
- pv.Behavior.
-
-
- Implements interactive resizing of a selection starting with mousedown
-events. Register this behavior on selection handles that should be resizeable
-by the user, such for brushing and linking. This behavior can be used in
-tandom with pv.Behavior.select and pv.Behavior.drag to allow
-the selected region to be selected and dragged interactively.
-
-
After the initial mousedown event is triggered, this behavior listens for
-mousemove and mouseup events on the window. This allows resizing to continue
-even if the mouse temporarily leaves the assigned panel, or even the root
-panel.
-
-
This behavior requires that the data associated with the mark being
-resized have x, y, dx and dy attributes
-that correspond to the mark's location and dimensions in pixels. The mark's
-positional properties are not set directly by this behavior; instead, the
-positional properties should be defined as:
-
-
-
-Thus, the behavior does not resize the mark directly, but instead updates the
-size by updating the assigned panel's underlying data. Note that if the
-positional properties are defined with bottom and right (rather than top and
-left), the resize behavior will be inverted, which will confuse users!
-
-
The resize behavior is bounded by the assigned mark's enclosing panel; the
-positional attributes are clamped such that the selection does not extend
-outside the panel's bounds.
-
-
The mark being resized is automatically re-rendered for each mouse event
-as part of the resize operation. This behavior may be enhanced in the future
-to allow more flexible configuration. In some cases, such as with parallel
-coordinates, resizing the selection may cause related marks to change, in
-which case additional marks may also need to be rendered. This can be
-accomplished by listening for the select psuedo-events:
-
-
resizestart (on mousedown)
-
resize (on mousemove)
-
resizeend (on mouseup)
-
-
For example, to render the parent panel while resizing, thus
-re-rendering all sibling marks:
-
-
-
-This behavior may be enhanced in the future to allow more flexible
-configuration of the selection behavior.
-
-
- Defined in: Resize.js.
-
-
-
-
-
-
-
- Extends
- pv.Behavior.
-
-
- Implements interactive selecting starting with mousedown events.
-Register this behavior on panels that should be selectable by the user, such
-for brushing and linking. This behavior can be used in tandom with
-pv.Behavior.drag to allow the selected region to be dragged
-interactively.
-
-
After the initial mousedown event is triggered, this behavior listens for
-mousemove and mouseup events on the window. This allows selecting to continue
-even if the mouse temporarily leaves the assigned panel, or even the root
-panel.
-
-
This behavior requires that the data associated with the mark being
-dragged have x, y, dx and dy attributes
-that correspond to the mark's location and dimensions in pixels. The mark's
-positional properties are not set directly by this behavior; instead, the
-positional properties should be defined as:
-
-
-
-Thus, the behavior does not resize the mark directly, but instead updates the
-selection by updating the assigned panel's underlying data. Note that if the
-positional properties are defined with bottom and right (rather than top and
-left), the drag behavior will be inverted, which will confuse users!
-
-
The select behavior is bounded by the assigned panel; the positional
-attributes are clamped such that the selection does not extend outside the
-panel's bounds.
-
-
The panel being selected is automatically re-rendered for each mouse event
-as part of the drag operation. This behavior may be enhanced in the future to
-allow more flexible configuration of select behavior. In some cases, such as
-with parallel coordinates, making a selection may cause related marks to
-change, in which case additional marks may also need to be rendered. This can
-be accomplished by listening for the select psuedo-events:
-
-
selectstart (on mousedown)
-
select (on mousemove)
-
selectend (on mouseup)
-
-
For example, to render the parent panel while selecting, thus
-re-rendering all sibling marks:
-
-
-
-This behavior may be enhanced in the future to allow more flexible
-configuration of the selection behavior.
-
-
- Defined in: Select.js.
-
-
-
-
-
-
-
- Extends
- pv.Behavior.
-
-
- Implements interactive zooming using mousewheel events. Register this
-behavior on panels to allow zooming. This behavior can be used in tandem with
-pv.Behavior.pan to allow both panning and zooming:
-
-
-
-The zoom behavior currently supports only mousewheel events; support for
-keyboard shortcuts and gesture events to improve accessibility may be added
-in the future.
-
-
The implementation of this behavior relies on the panel's
-transform property, which specifies a matrix transformation that is
-applied to child marks. Note that the transform property only affects the
-panel's children, but not the panel itself; therefore the panel's fill and
-stroke will not change when the contents are zoomed. The built-in support for
-transforms only supports uniform scaling and translates, which is sufficient
-for panning and zooming. Note that this is not a strict geometric
-transformation, as the lineWidth property is scale-aware: strokes
-are drawn at constant size independent of scale.
-
-
Panels have transparent fill styles by default; this means that panels may
-not receive mousewheel events to zoom. To fix this problem, either given the
-panel a visible fill style (such as "white"), or set the events
-property to "all" such that the panel receives events despite its transparent
-fill.
-
-
The zoom behavior has optional support for bounding. If enabled, the user
-will not be able to zoom out farther than the initial bounds. This feature is
-designed to work in conjunction with the pan behavior.
-
-
- Defined in: Zoom.js.
-
-
- Sets or gets the bound parameter. If bounding is enabled, the user will not
-be able to zoom out farther than the initial panel bounds. Bounding is not
-enabled by default. If this behavior is used in tandem with the pan
-behavior, both should use the same bound parameter.
-
-
Note: enabling bounding after zooming has already occurred will not
-immediately reset the transform. Bounding should be enabled before the zoom
-behavior is applied.
-
-
-
- Returns a new color that is a brighter version of this color. This method
-applies an arbitrary scale factor to each of the three RGB components of this
-color to create a brighter version of this color. Although brighter and
-darker are inverse operations, the results of a series of invocations of
-these two methods might be inconsistent because of rounding errors.
-
-
-
- Returns a new color that is a darker version of this color. This method
-applies an arbitrary scale factor to each of the three RGB components of this
-color to create a darker version of this color. Although brighter and darker
-are inverse operations, the results of a series of invocations of these two
-methods might be inconsistent because of rounding errors.
-
-
-
-
-
-
- Represents an abstract (possibly translucent) color. The color is
-divided into two parts: the color attribute, an opaque color format
-string, and the opacity attribute, a float in [0, 1]. The color
-space is dependent on the implementing class; all colors support the
-#rgb method to convert to RGB color space for interpolation.
-
-
- Returns a new color that is a brighter version of this color. The behavior of
-this method may vary slightly depending on the underlying color space.
-Although brighter and darker are inverse operations, the results of a series
-of invocations of these two methods might be inconsistent because of rounding
-errors.
-
-
-
- Returns a new color that is a brighter version of this color. The behavior of
-this method may vary slightly depending on the underlying color space.
-Although brighter and darker are inverse operations, the results of a series
-of invocations of these two methods might be inconsistent because of rounding
-errors.
-
-
-
- Returns a new 10-color scheme. The arguments to this constructor are
-optional, and equivalent to calling pv.Scale.OrdinalScale#domain. The
-following colors are used:
-
-
- Returns a new alternative 19-color scheme. The arguments to this constructor
-are optional, and equivalent to calling
-pv.Scale.OrdinalScale#domain. The following colors are used:
-
-
- Returns a new 20-color scheme. The arguments to this constructor are
-optional, and equivalent to calling pv.Scale.OrdinalScale#domain. The
-following colors are used:
-
-
-
- Extends
- pv.Constraint.
-
-
- Constrains particles to within fixed rectangular bounds. For example,
-this constraint can be used to constrain particles in a physics simulation
-within the bounds of an enclosing panel.
-
-
Note that the current implementation treats particles as points, with no
-area. If the particles are rendered as dots, be sure to include some
-additional padding to inset the bounds such that the edges of the dots do not
-get clipped by the panel bounds. If the particles have different radii, this
-constraint would need to be extended using a radius function, similar to
-pv.Constraint.collision.
-
-
- Defined in: BoundConstraint.js.
-
-
-
-
-
- Constraints circles to avoid overlap. Each particle is treated as a
-circle, with the radius of the particle computed using a specified function.
-For example, if the particle has an r attribute storing the radius,
-the radius function(d) d.r specifies a collision constraint using
-this radius. The radius function is passed each pv.Particle as the
-first argument.
-
-
To accelerate collision detection, this implementation uses a quadtree and
-a search radius. The search radius is computed as the maximum radius of all
-particles in the simulation.
-
-
- Defined in: CollisionConstraint.js.
-
-
- Constructs a new collision constraint. The default search radius is 10, and
-the default repeat count is 1. A radius function must be specified to compute
-the radius of particles.
-
-
- Sets or gets the repeat count. If the repeat count is greater than 1, the
-constraint will be applied repeatedly; this is a form of the Gauss-Seidel
-method for constraints relaxation. Repeating the collision constraint makes
-the constraint have more of an effect when there is a potential for many
-co-occurring collisions.
-
-
-
-
-
-
- Represents a constraint that acts on particles. Note that this
-interface does not specify how to bind a constraint to specific particles; in
-general, constraints are applied globally to all particles. However, some
-constraints may be applied to specific particles or between particles, such
-as position constraints, through additional specialization.
-
-
- Defined in: Constraint.js.
-
-
-
-
-
- Constraints particles to a fixed position. The fixed position per
-particle is determined using a given position function, which defaults to
-function(d) d.fix.
-
-
If the position function returns null, then no position constraint is
-applied to the given particle. Otherwise, the particle's position is set to
-the returned position, as expressed by a pv.Vector. (Note: the
-position does not need to be an instance of pv.Vector, but simply an
-object with x and y attributes.)
-
-
This constraint also supports a configurable alpha parameter, which
-defaults to 1. If the alpha parameter is in the range [0,1], then rather than
-setting the particle's new position directly to the position returned by the
-supplied position function, the particle's position is interpolated towards
-the fixed position. This results is a smooth (exponential) drift towards the
-fixed position, which can increase the stability of the physics simulation.
-In addition, the alpha parameter can be decayed over time, relaxing the
-position constraint, which helps to stabilize on an optimal solution.
-
-
- Defined in: PositionConstraint.js.
-
-
Applies this constraint to the specified particles.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Class Detail
-
-
-
- pv.Constraint.position(f)
-
-
-
- Constructs a default position constraint using the fix attribute.
-An optional position function can be specified to determine how the fixed
-position per-particle is determined.
-
-
- Sets or gets the alpha parameter for position interpolation. If the alpha
-parameter is in the range [0,1], then rather than setting the particle's
-new position directly to the position returned by the supplied position
-function, the particle's position is interpolated towards the fixed
-position.
-
-
-
Visits each node in the tree in preorder traversal, applying the specified
-function f.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Class Detail
-
-
-
- pv.Dom.Node(value)
-
-
-
- Constructs a DOM node for the specified value. Instances of this class are
-not typically created directly; instead they are generated from a JavaScript
-map using the pv.Dom operator.
-
-
- Appends the specified child node to this node. If the specified child is
-already part of the DOM, the child is first removed before being added to
-this node.
-
-
-
- Inserts the specified child n before the given reference child
-r of this node. If r is null, this method is equivalent to
-#appendChild. If n is already part of the DOM, it is first
-removed before being inserted.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- n
-
-
-
-
-
- r
-
-
-
-
-
-
-
-
-
-
-
Throws:
-
-
-
-
-
Error if r is non-null and not a child of this node.
- Replaces the specified child r of this node with the node n. If
-n is already part of the DOM, it is first removed before being added.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- n
-
-
-
-
-
- r
-
-
-
-
-
-
-
-
-
-
-
Throws:
-
-
-
-
-
Error if r is not a child of this node.
-
-
-
-
-
-
-
-
-
-
-
-
-
- reverse()
-
-
-
- Reverses all sibling nodes.
-
-
-
-
-
-
-
-
-
-
-
-
-
Returns:
-
-
this.
-
-
-
-
-
-
-
-
-
-
-
-
- sort(f)
-
-
-
- Sorts child nodes of this node, and all descendent nodes recursively, using
-the specified comparator function f. The comparator function is
-passed two nodes to compare.
-
-
Note: during the sort operation, the comparator function should not rely
-on the tree being well-formed; the values of previousSibling and
-nextSibling for the nodes being compared are not defined during the
-sort operation.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {function}f
-
-
-
a comparator function.
-
-
-
-
-
-
-
-
-
Returns:
-
-
this.
-
-
-
-
-
-
-
-
-
-
-
-
- toggle(recursive)
-
-
-
- Toggles the child nodes of this node. If this node is not yet toggled, this
-method removes all child nodes and appends them to a new toggled
-array attribute on this node. Otherwise, if this node is toggled, this method
-re-adds all toggled child nodes and deletes the toggled attribute.
-
-
This method has no effect if the node has no child nodes.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {boolean}recursive
- Optional
-
-
whether the toggle should apply to descendants.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- visitAfter(f)
-
-
-
- Visits each node in the tree in postorder traversal, applying the specified
-function f. The arguments to the function are:
-
-
The current node.
-
The current depth, starting at 0 for the root node.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {function}f
-
-
-
a function to apply to each node.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- visitBefore(f)
-
-
-
- Visits each node in the tree in preorder traversal, applying the specified
-function f. The arguments to the function are:
-
-
The current node.
-
The current depth, starting at 0 for the root node.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {function}f
-
-
-
a function to apply to each node.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Documentation generated by JsDoc Toolkit 2.3.2 on Fri May 28 2010 10:13:28 GMT-0700 (PDT)
-
-
-
-
- Represets a DOM operator for the specified map. This allows easy
-transformation of a hierarchical JavaScript object (such as a JSON map) to a
-W3C Document Object Model hierarchy. For more information on which attributes
-and methods from the specification are supported, see pv.Dom.Node.
-
-
Leaves in the map are determined using an associated leaf function;
-see #leaf. By default, leaves are any value whose type is not
-"object", such as numbers or strings.
-
-
- Defined in: Dom.js.
-
-
Applies the DOM operator, returning the root node.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Class Detail
-
-
-
- pv.Dom(map)
-
-
-
- Constructs a DOM operator for the specified map. This constructor should not
-be invoked directly; use pv.dom instead.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- map
-
-
-
a map from which to construct a DOM.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Method Detail
-
-
-
-
-
-
- leaf(f)
-
-
-
- Sets or gets the leaf function for this DOM operator. The leaf function
-identifies which values in the map are leaves, and which are internal nodes.
-By default, objects are considered internal nodes, and primitives (such as
-numbers and strings) are considered leaves.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {function}f
-
-
-
the new leaf function.
-
-
-
-
-
-
-
-
-
Returns:
-
-
the current leaf function, or this.
-
-
-
-
-
-
-
-
-
-
-
- {array}
- nodes()
-
-
-
- Applies the DOM operator, returning the array of all nodes in preorder
-traversal.
-
-
-
-
- Extends
- pv.Mark.
-
-
- Represents a dot; a dot is simply a sized glyph centered at a given
-point that can also be stroked and filled. The size property is
-proportional to the area of the rendered glyph to encourage meaningful visual
-encodings. Dots can visually encode up to eight dimensions of data, though
-this may be unwise due to integrality. See pv.Mark for details on the
-prioritization of redundant positioning properties.
-
-
- Constructs a new dot mark with default properties. Dots are not typically
-constructed directly, but by adding to a panel or an existing mark via
-pv.Mark#add.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Field Detail
-
-
-
-
-
- {number}
- angle
-
-
-
- The rotation angle, in radians. Used to rotate shapes, such as to turn a
-cross into a plus.
-
-
-
- Default properties for dots. By default, there is no fill and the stroke
-style is a categorical color. The default shape is "circle" with size 20.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- fillStyle
-
-
-
- The fill style; if non-null, the interior of the dot is filled with the
-specified color. The default value of this property is null, meaning dots are
-not filled by default.
-
-
-
These shapes can be further changed using the #angle property;
-for instance, a cross can be turned into a plus by rotating. Similarly, the
-tick, which is vertical by default, can be rotated horizontally. Note that
-some shapes (cross and tick) do not have interior areas, and thus do not
-support fill style meaningfully.
-
-
Note: it may be more natural to use the pv.Rule mark for
-horizontal and vertical ticks. The tick shape is only necessary if angled
-ticks are needed.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- size
-
-
-
- The size of the dot, in square pixels. Square pixels are used such that the
-area of the dot is linearly proportional to the value of the size property,
-facilitating representative encodings.
-
-
-
- The style of stroked lines; used in conjunction with lineWidth to
-stroke the dot's shape. The default value of this property is a categorical
-color.
-
-
-
- Constructs a new dot anchor with default properties. Dots support five
-different anchors:
-
-
top
-
left
-
center
-
bottom
-
right
-
-
In addition to positioning properties (left, right, top bottom), the
-anchors support text rendering properties (text-align, text-baseline). Text is
-rendered to appear outside the dot. Note that this behavior is different from
-other mark anchors, which default to rendering text inside the mark.
-
-
For consistency with the other mark types, the anchor positions are
-defined in terms of their opposite edge. For example, the top anchor defines
-the bottom property, such that a bar added to the top anchor grows upward.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {string}name
-
-
-
the anchor name; either a string or a property function.
-
-
-
- Represents a flatten operator for the specified array. Flattening
-allows hierarchical maps to be flattened into an array. The levels in the
-input tree are specified by key functions.
-
-
For example, consider the following hierarchical data structure of Barley
-yields, from various sites in Minnesota during 1931-2:
-
-
- Flattens using the specified key function. Multiple keys may be added to the
-flatten; the tiers of the underlying tree must correspond to the specified
-keys, in order. The order of the returned array is undefined; however, you
-can easily sort it.
-
-
-
- Flattens using the specified leaf function. This is an alternative to
-specifying an explicit set of keys; the tiers of the underlying tree will be
-determined dynamically by recursing on the values, and the resulting keys
-will be stored in the entries keys attribute. The leaf function must
-return true for leaves, and false for internal nodes.
-
-
-
-
-
-
- An n-body force, as defined by Coulomb's law or Newton's law of
-gravitation, inversely proportional to the square of the distance between
-particles. Note that the force is independent of the mass of the
-associated particles, and that the particles do not have charges of varying
-magnitude; instead, the attraction or repulsion of all particles is globally
-specified as the charge #constant.
-
-
- Constructs a new charge force, with an optional charge constant. The charge
-constant can be negative for repulsion (e.g., particles with electrical
-charge of equal sign), or positive for attraction (e.g., massive particles
-with mutual gravity). The default charge constant is -40.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {number}k
- Optional
-
-
the charge constant.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Method Detail
-
-
-
-
-
-
- apply(particles, q)
-
-
-
- Applies this force to the specified particles. The force is applied between
-all pairs of particles within the domain, using the specified quadtree to
-accelerate n-body force calculation using the Barnes-Hut approximation
-criterion.
-
-
-
- Sets or gets the charge constant. If an argument is specified, it is the
-new charge constant. The charge constant can be negative for repulsion
-(e.g., particles with electrical charge of equal sign), or positive for
-attraction (e.g., massive particles with mutual gravity). The default
-charge constant is -40.
-
-
-
- Sets or gets the domain; specifies the minimum and maximum domain within
-which charge forces are applied. A minimum distance threshold avoids
-applying forces that are two strong (due to granularity of the simulation's
-numeric integration). A maximum distance threshold improves performance by
-skipping force calculations for particles that are far apart.
-
-
- Sets or gets the Barnes-Hut approximation factor. The Barnes-Hut
-approximation criterion is the ratio of the size of the quadtree node to
-the distance from the point to the node's center of mass is beneath some
-threshold.
-
-
-
-
- Extends
- pv.Force.
-
-
- Implements a drag force, simulating friction. The drag force is
-applied in the opposite direction of the particle's velocity. Since Position
-Verlet integration does not track velocities explicitly, the error term with
-this estimate of velocity is fairly high, so the drag force may be
-inaccurate.
-
-
- Defined in: DragForce.js.
-
-
- Sets or gets the drag constant, in the range [0,1]. The default drag
-constant is 0.1. The drag forces scales linearly with the particle's
-velocity based on the given drag constant.
-
-
-
-
-
-
- Represents a force that acts on particles. Note that this interface
-does not specify how to bind a force to specific particles; in general,
-forces are applied globally to all particles. However, some forces may be
-applied to specific particles or between particles, such as spring forces,
-through additional specialization.
-
-
- Defined in: Force.js.
-
-
-
- Extends
- pv.Force.
-
-
- Implements a spring force, per Hooke's law. The spring force can be
-configured with a tension constant, rest length, and damping factor. The
-tension and damping will automatically be normalized using the inverse square
-root of the maximum link degree of attached nodes; this makes springs weaker
-between nodes of high link degree.
-
-
Unlike other forces (such as charge and drag forces) which may be applied
-globally, spring forces are only applied between linked particles. Therefore,
-an array of links must be specified before this force can be applied; the
-links should be an array of pv.Layout.Network.Links. See also
-pv.Layout.Force for an example of using spring and charge forces for
-network layout.
-
-
- Defined in: SpringForce.js.
-
-
Sets or gets the links associated with this spring force.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Class Detail
-
-
-
- pv.Force.spring(k)
-
-
-
- Constructs a new spring force with the specified constant. The links
-associated with this spring force must be specified before the spring force
-can be applied.
-
-
- Sets or gets the spring constant. The default value is 0.1; greater values
-will result in stronger tension. The spring tension is automatically
-normalized using the inverse square root of the maximum link degree of
-attached nodes.
-
-
-
- The spring damping factor, in the range [0,1]. Damping functions
-identically to drag forces, damping spring bounciness by applying a force
-in the opposite direction of attached nodes' velocities. The default value
-is 0.1. The spring damping is automatically normalized using the inverse
-square root of the maximum link degree of attached nodes.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {number}x
-
-
-
the new spring damping factor.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{pv.Force.spring} this, or the current spring damping factor.
- Sets or gets the links associated with this spring force. Unlike other
-forces (such as charge and drag forces) which may be applied globally,
-spring forces are only applied between linked particles. Therefore, an
-array of links must be specified before this force can be applied; the
-links should be an array of pv.Layout.Network.Links.
-
-
-
-
- Extends
- pv.Format.
-
-
- The format string is in the same format expected by the
-strftime function in C. The following conversion specifications are
-supported:
-
-
%a - abbreviated weekday name.
-
%A - full weekday name.
-
%b - abbreviated month names.
-
%B - full month names.
-
%c - locale's appropriate date and time.
-
%C - century number.
-
%d - day of month [01,31] (zero padded).
-
%D - same as %m/%d/%y.
-
%e - day of month [ 1,31] (space padded).
-
%h - same as %b.
-
%H - hour (24-hour clock) [00,23] (zero padded).
-
%I - hour (12-hour clock) [01,12] (zero padded).
-
%m - month number [01,12] (zero padded).
-
%M - minute [0,59] (zero padded).
-
%n - newline character.
-
%p - locale's equivalent of a.m. or p.m.
-
%r - same as %I:%M:%S %p.
-
%R - same as %H:%M.
-
%S - second [00,61] (zero padded).
-
%t - tab character.
-
%T - same as %H:%M:%S.
-
%x - same as %m/%d/%y.
-
%X - same as %I:%M:%S %p.
-
%y - year with century [00,99] (zero padded).
-
%Y - year including century.
-
%% - %.
-
-
The following conversion specifications are currently unsupported
-for formatting:
-
-
%j - day number [1,366].
-
%u - weekday number [1,7].
-
%U - week number [00,53].
-
%V - week number [01,53].
-
%w - weekday number [0,6].
-
%W - week number [00,53].
-
%Z - timezone name or abbreviation.
-
-
In addition, the following conversion specifications are currently
-unsupported for parsing:
-
-
%a - day of week, either abbreviated or full name.
-
-
-
- Represents an abstract text formatter and parser. A format is a
-function that converts an object of a given type, such as a Date, to
-a human-readable string representation. The format may also have a
-#parse method for converting a string representation back to the
-given object type.
-
-
Because formats are themselves functions, they can be used directly as
-mark properties. For example, if the data associated with a label are dates,
-a date format can be used as label text:
-
-
.text(pv.Format.date("%m/%d/%y"))
-
-And as with scales, if the format is used in multiple places, it can be
-convenient to declare it as a global variable and then reference it from the
-appropriate property functions. For example, if the data has a date
-attribute, and format references a given date format:
-
-
.text(function(d) format(d.date))
-
-Similarly, to parse a string into a date:
-
-
var date = format.parse("4/30/2010");
-
-Not all format implementations support parsing. See the implementing class
-for details.
-
-
- Defined in: Format.js.
-
-
-
-
-
-
-
-
-
- Represents a number format, converting between a number and a
-string. This class allows numbers to be formatted with variable
-precision (both for the integral and fractional part of the number), optional
-thousands grouping, and optional padding. The thousands (",") and decimal
-(".") separator can be customized.
-
-
- Defined in: NumberFormat.js.
-
-
- Sets or gets the minimum and maximum number of fraction digits. The
-controls the number of decimal digits to display after the decimal
-separator for the fractional part of the number. If the number of digits is
-smaller than the minimum, the digits are padded; if the number of digits is
-larger, the fractional part is rounded, showing only the higher-order
-digits. The default range is [0, 0].
-
-
If only one argument is specified to this method, this value is used as
-both the minimum and maximum number. If no arguments are specified, a
-two-element array is returned containing the minimum and the maximum.
-
-
-
- Sets or gets the minimum and maximum number of integer digits. This
-controls the number of decimal digits to display before the decimal
-separator for the integral part of the number. If the number of digits is
-smaller than the minimum, the digits are padded; if the number of digits is
-larger, the digits are truncated, showing only the lower-order digits. The
-default range is [0, Infinity].
-
-
If only one argument is specified to this method, this value is used as
-both the minimum and maximum number. If no arguments are specified, a
-two-element array is returned containing the minimum and the maximum.
-
-
-
- Parses the specified string as a number. Before parsing, leading and
-trailing padding is removed. Group separators are also removed, and the
-decimal separator is replaced with the standard point ("."). The integer
-part is truncated per the maximum integer digits, and the fraction part is
-rounded per the maximum fraction digits.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {string}x
-
-
-
the string to parse.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{number} the parsed number.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Documentation generated by JsDoc Toolkit 2.3.2 on Fri May 28 2010 10:13:28 GMT-0700 (PDT)
-
-
- Extends
- pv.Format.
-
-
- Represents a time format, converting between a number
-representing a duration in milliseconds, and a string. Two types of
-time formats are supported: "short" and "long". The short format type
-returns a string such as "3.3 days" or "12.1 minutes", while the long
-format returns "13:04:12" or similar.
-
-
- Defined in: TimeFormat.js.
-
-
-
-
-
- Represents a geographic projection. This class provides the core
-implementation for pv.Geo.scales, mapping between geographic
-coordinates (latitude and longitude) and normalized screen space in the range
-[-1,1]. The remaining mapping between normalized screen space and actual
-pixels is performed by pv.Geo.scale.
-
-
Many geographic projections have a point around which the projection is
-centered. Rather than have each implementation add support for a
-user-specified center point, the pv.Geo.scale translates the
-geographic coordinates relative to the center point for both the forward and
-inverse projection.
-
-
In general, this class should not be used directly, unless the desire is
-to implement a new geographic projection. Instead, use pv.Geo.scale.
-Implementations are not required to implement inverse projections, but are
-needed for some forms of interactivity. Also note that some inverse
-projections are ambiguous, such as the connecting points in Dymaxian maps.
-
-
- Defined in: Projection.js.
-
-
-
-
-
- Tick functions for geographic scales. Because geographic scales
-represent two-dimensional transformations (as opposed to one-dimensional
-transformations typical of other scales), the tick values are similarly
-represented as two-dimensional coordinates in the input domain, i.e.,
-pv.Geo.LatLng objects.
-
-
Also, note that non-rectilinear projections, such as sinsuoidal and
-aitoff, may not produce straight lines for constant longitude or constant
-latitude. Therefore the returned array of ticks is a two-dimensional array,
-sampling various latitudes as constant longitude, and vice versa.
-
-
The tick lines can therefore be approximated as polylines, either with
-"linear" or "cardinal" interpolation. This is not as accurate as drawing
-the true curve through the projection space, but is usually sufficient.
-
-
- Defined in: GeoScale.js.
-
-
-
-
-
- Represents a geographic scale; a mapping between latitude-longitude
-coordinates and screen pixel coordinates. By default, the domain is inferred
-from the geographic coordinates, so that the domain fills the output range.
-
-
Note that geographic scales are two-dimensional transformations, rather
-than the one-dimensional bidrectional mapping typical of other scales.
-Rather than mapping (for example) between a numeric domain and a numeric
-range, geographic scales map between two coordinate objects: {@link
-pv.Geo.LatLng} and pv.Vector.
-
-
- Defined in: GeoScale.js.
-
-
- Returns a view of this scale by the specified accessor function f.
-Given a scale g, g.by(function(d) d.foo) is equivalent to
-function(d) g(d.foo). This method should be used judiciously; it
-is typically more clear to invoke the scale directly, passing in the value
-to be scaled.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {function}f
-
-
-
an accessor function.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{pv.Geo.scale} a view of this scale by the specified accessor
-function.
- Sets or gets the input domain. Note that unlike quantitative scales, the
-domain cannot be reduced to a simple rectangle (i.e., minimum and maximum
-values for latitude and longitude). Instead, the domain values must be
-projected to normalized space, effectively finding the domain in normalized
-space rather than in terms of latitude and longitude. Thus, changing the
-projection requires recomputing the normalized domain.
-
-
This method can be invoked several ways:
-
-
1. domain(values...)
-
-
Specifying the domain as a series of pv.Geo.LatLngs is the most
-explicit and recommended approach. However, if the domain values are
-derived from data, you may find the second method more appropriate.
-
-
2. domain(array, f)
-
-
Rather than enumerating the domain explicitly, you can specify a single
-argument of an array. In addition, you can specify an optional accessor
-function to extract the domain values (as pv.Geo.LatLngs) from the
-array. If the specified array has fewer than two elements, this scale will
-default to the full normalized domain.
-
-
2. domain()
-
-
Invoking the domain method with no arguments returns the
-current domain as an array.
-
-
-
- Inverts the specified value in the output range, returning the
-corresponding value in the input domain. This is frequently used to convert
-the mouse location (see pv.Mark#mouse) to a value in the input
-domain. Inversion is only supported for numeric ranges, and not colors.
-
-
Note that this method does not do any rounding or bounds checking. If
-the input domain is discrete (e.g., an array index), the returned value
-should be rounded. If the specified y value is outside the range,
-the returned value may be equivalently outside the input domain.
-
-
-
- Sets or gets the output range. This method can be invoked several ways:
-
-
1. range(min, max)
-
-
If two objects are specified, the arguments should be pv.Vectors
-which specify the minimum and maximum values of the x- and y-coordinates
-explicitly.
-
-
2. range(width, height)
-
-
If two numbers are specified, the arguments specify the maximum values
-of the x- and y-coordinates explicitly; the minimum values are implicitly
-zero.
-
-
3. range()
-
-
Invoking the range method with no arguments returns the current
-range as an array of two pv.Vectors: the minimum (top-left) and
-maximum (bottom-right) values.
-
-
-
-
- Extends
- pv.Bar.
-
-
- Represents an image, either a static resource or a dynamically-
-generated pixel buffer. Images share the same layout and style properties as
-bars. The external image resource is specified via the #url
-property. The optional fill, if specified, appears beneath the image, while
-the optional stroke appears above the image.
-
-
Dynamic images such as heatmaps are supported using the #image
-psuedo-property. This function is passed the x and y index, in
-addition to the current data stack. The return value is a pv.Color,
-or null for transparent. A string can also be returned, which will be parsed
-into a color; however, it is typically much faster to return an object with
-r, g, b and a attributes, to avoid the
-cost of parsing and object instantiation.
-
-
See pv.Bar for details on positioning properties.
-
-
- Defined in: Image.js.
-
-
- Constructs a new image with default properties. Images are not typically
-constructed directly, but by adding to a panel or an existing mark via
-pv.Mark#add.
-
-
- Default properties for images. By default, there is no stroke or fill style.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- imageHeight
-
-
-
- The height of the image in pixels. For static images, this property is
-computed implicitly from the loaded image resources. For dynamic images, this
-property can be used to specify the height of the pixel buffer; otherwise, the
-value is derived from the height property.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- imageWidth
-
-
-
- The width of the image in pixels. For static images, this property is
-computed implicitly from the loaded image resources. For dynamic images, this
-property can be used to specify the width of the pixel buffer; otherwise, the
-value is derived from the width property.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- url
-
-
-
- The URL of the image to display. The set of supported image types is
-browser-dependent; PNG and JPEG are recommended.
-
-
-
- Specifies the dynamic image function. By default, no image function is
-specified and the url property is used to load a static image
-resource. If an image function is specified, it will be invoked for each
-pixel in the image, based on the related imageWidth and
-imageHeight properties.
-
-
For example, given a two-dimensional array heatmap, containing
-numbers in the range [0, 1] in row-major order, a simple monochrome heatmap
-image can be specified as:
-
-
-
-For fastest performance, use an ordinal scale which caches the fixed color
-palette, or return an object literal with r, g, b
-and a attributes. A pv.Color or string can also be returned,
-though this typically results in slower performance.
-
-
-
-
- Extends
- pv.Mark.
-
-
- Represents a text label, allowing textual annotation of other marks or
-arbitrary text within the visualization. The character data must be plain
-text (unicode), though the text can be styled using the #font
-property. If rich text is needed, external HTML elements can be overlaid on
-the canvas by hand.
-
-
Labels are positioned using the box model, similarly to Dot. Thus,
-a label has no width or height, but merely a text anchor location. The text
-is positioned relative to this anchor location based on the
-#textAlign, #textBaseline and #textMargin properties.
-Furthermore, the text may be rotated using #textAngle.
-
-
Labels ignore events, so as to not interfere with event handlers on
-underlying marks, such as bars. In the future, we may support event handlers
-on labels.
-
-
- Constructs a new label mark with default properties. Labels are not typically
-constructed directly, but by adding to a panel or an existing mark via
-pv.Mark#add.
-
-
- Default properties for labels. See the individual properties for the default
-values.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- font
-
-
-
- The font format, per the CSS Level 2 specification. The default font is "10px
-sans-serif", for consistency with the HTML 5 canvas element specification.
-Note that since text is not wrapped, any line-height property will be
-ignored. The other font-style, font-variant, font-weight, font-size and
-font-family properties are supported.
-
-
-
- The character data to render; a string. The default value of the text
-property is the identity function, meaning the label's associated datum will
-be rendered using its toString.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- textAlign
-
-
-
- The horizontal text alignment. One of:
-
-
left
-
center
-
right
-
-
The default horizontal alignment is left.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- textAngle
-
-
-
- The rotation angle, in radians. Text is rotated clockwise relative to the
-anchor location. For example, with the default left alignment, an angle of
-Math.PI / 2 causes text to proceed downwards. The default angle is zero.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- textBaseline
-
-
-
- The vertical text alignment. One of:
-
-
top
-
middle
-
bottom
-
-
The default vertical alignment is bottom.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- textDecoration
-
-
-
- A list of decoration to be applied to text, per the CSS Text Level 3
-text-decoration property. An example specification is "underline".
-
-
-
- The text margin; may be specified in pixels, or in font-dependent units (such
-as ".1ex"). The margin can be used to pad text away from its anchor location,
-in a direction dependent on the horizontal and vertical alignment
-properties. For example, if the text is left- and middle-aligned, the margin
-shifts the text to the right. The default margin is 3 pixels.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- textShadow
-
-
-
- A list of shadow effects to be applied to text, per the CSS Text Level 3
-text-shadow property. An example specification is "0.1em 0.1em 0.1em
-rgba(0,0,0,.5)"; the first length is the horizontal offset, the second the
-vertical offset, and the third the blur radius.
-
-
-
- The text color. The name "textStyle" is used for consistency with "fillStyle"
-and "strokeStyle", although it might be better to rename this property (and
-perhaps use the same name as "strokeStyle"). The default color is black.
-
-
-
-
- Extends
- pv.Layout.Network.
-
-
- Implements a layout for arc diagrams. An arc diagram is a network
-visualization with a one-dimensional layout of nodes, using circular arcs to
-render links between nodes. For undirected networks, arcs are rendering on a
-single side; this makes arc diagrams useful as annotations to other
-two-dimensional network layouts, such as rollup, matrix or table layouts. For
-directed networks, links in opposite directions can be rendered on opposite
-sides using directed(true).
-
-
Arc layouts are particularly sensitive to node ordering; for best results,
-order the nodes such that related nodes are close to each other. A poor
-(e.g., random) order may result in large arcs with crossovers that impede
-visual processing. A future improvement to this layout may include automatic
-reordering using, e.g., spectral graph layout or simulated annealing.
-
-
This visualization technique is related to that developed by
-M. Wattenberg, "Arc
-Diagrams: Visualizing Structure in Strings" in IEEE InfoVis, 2002.
-However, this implementation is limited to simple node-link networks, as
-opposed to structures with hierarchical self-similarity (such as strings).
-
-
As with other network layouts, three mark prototypes are provided:
- Constructs a new, empty arc layout. Layouts are not typically constructed
-directly; instead, they are added to an existing panel via
-pv.Mark#add.
-
-
- Default properties for arc layouts. By default, the orientation is "bottom".
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {boolean}
- directed
-
-
-
- Whether this arc digram is directed (bidirectional); only applies to
-non-radial orientations. By default, arc digrams are undirected, such that
-all arcs appear on one side. If the arc digram is directed, then forward
-links are drawn on the conventional side (the same as as undirected
-links--right, left, bottom and top for left, right, top and bottom,
-respectively), while reverse links are drawn on the opposite side.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- orient
-
-
-
- The orientation. The default orientation is "left", which means that nodes
-will be positioned from left-to-right in the order they are specified in the
-nodes property. The following orientations are supported:
-
-
left - left-to-right.
-
right - right-to-left.
-
top - top-to-bottom.
-
bottom - bottom-to-top.
-
radial - radially, starting at 12 o'clock and proceeding clockwise.
- Specifies an optional sort function. The sort function follows the same
-comparator contract required by pv.Dom.Node#sort. Specifying a sort
-function provides an alternative to sort the nodes as they are specified by
-the nodes property; the main advantage of doing this is that the
-comparator function can access implicit fields populated by the network
-layout, such as the linkDegree.
-
-
Note that arc diagrams are particularly sensitive to order. This is
-referred to as the seriation problem, and many different techniques exist to
-find good node orders that emphasize clusters, such as spectral layout and
-simulated annealing.
-
-
-
- Constructs a new, empty bullet layout. Layouts are not typically constructed
-directly; instead, they are added to an existing panel via
-pv.Mark#add.
-
-
-
- Extends
- pv.Layout.Cluster.
-
-
- A variant of cluster layout that is space-filling. The meaning of the
-exported mark prototypes changes slightly in the space-filling
-implementation:
-
-
node - for rendering nodes; typically a pv.Bar for
-non-radial orientations, and a pv.Wedge for radial orientations.
-
-
link - unsupported; undefined. Links are encoded implicitly
-in the arrangement of the space-filling nodes.
-
-
label - for rendering node labels; typically a
-pv.Label.
-
-
For more details on how to use this layout, see
-pv.Layout.Cluster.
-
-
- Defined in: Cluster.js.
-
-
-
-
-
-
- Constructs a new, empty space-filling cluster layout. Layouts are not
-typically constructed directly; instead, they are added to an existing panel
-via pv.Mark#add.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Documentation generated by JsDoc Toolkit 2.3.2 on Fri May 28 2010 10:13:28 GMT-0700 (PDT)
-
-
- Extends
- pv.Layout.Hierarchy.
-
-
- Implements a hierarchical layout using the cluster (or dendrogram)
-algorithm. This layout provides both node-link and space-filling
-implementations of cluster diagrams. In many ways it is similar to
-pv.Layout.Partition, except that leaf nodes are positioned at maximum
-depth, and the depth of internal nodes is based on their distance from their
-deepest descendant, rather than their distance from the root.
-
-
The cluster layout supports a "group" property, which if true causes
-siblings to be positioned closer together than unrelated nodes at the same
-depth. Unlike the partition layout, this layout does not support dynamic
-sizing for leaf nodes; all leaf nodes are the same size.
-
-
- Constructs a new, empty cluster layout. Layouts are not typically
-constructed directly; instead, they are added to an existing panel via
-pv.Mark#add.
-
-
- Defaults for cluster layouts. The default group parameter is 0 and the
-default orientation is "top".
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- group
-
-
-
- The group parameter; defaults to 0, disabling grouping of siblings. If this
-parameter is set to a positive number (or true, which is equivalent to 1),
-then additional space will be allotted between sibling groups. In other
-words, siblings (nodes that share the same parent) will be positioned more
-closely than nodes at the same depth that do not share a parent.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- innerRadius
-
-
-
- The inner radius; defaults to 0. This property applies only to radial
-orientations, and can be used to compress the layout radially. Note that for
-the node-link implementation, the root node is always at the center,
-regardless of the value of this property; this property only affects internal
-and leaf nodes. For the space-filling implementation, a non-zero value of
-this property will result in the root node represented as a ring rather than
-a circle.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- orient
-
-
-
- The orientation. The default orientation is "top", which means that the root
-node is placed on the top edge, leaf nodes appear on the bottom edge, and
-internal nodes are in-between. The following orientations are supported:
-
-
left - left-to-right.
-
right - right-to-left.
-
top - top-to-bottom.
-
bottom - bottom-to-top.
-
radial - radially, with the root at the center.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- outerRadius
-
-
-
- The outer radius; defaults to fill the containing panel, based on the height
-and width of the layout. If the layout has no height and width specified, it
-will extend to fill the enclosing panel.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Documentation generated by JsDoc Toolkit 2.3.2 on Fri May 28 2010 10:13:28 GMT-0700 (PDT)
-
-
- Extends
- pv.Layout.Network.
-
-
- Implements force-directed network layout as a node-link diagram. This
-layout uses the Fruchterman-Reingold algorithm, which applies an attractive
-spring force between neighboring nodes, and a repulsive electrical charge
-force between all nodes. An additional drag force improves stability of the
-simulation. See pv.Force.spring, pv.Force.drag and {@link
-pv.Force.charge} for more details; note that the n-body charge force is
-approximated using the Barnes-Hut algorithm.
-
-
This layout is implemented on top of pv.Simulation, which can be
-used directly for more control over simulation parameters. The simulation
-uses Position Verlet integration, which does not compute velocities
-explicitly, but allows for easy geometric constraints, such as bounding the
-nodes within the layout panel. Many of the configuration properties supported
-by this layout are simply passed through to the underlying forces and
-constraints of the simulation.
-
-
Force layouts are typically interactive. The gradual movement of the nodes
-as they stabilize to a local stress minimum can help reveal the structure of
-the network, as can pv.Behavior.drag, which allows the user to pick
-up nodes and reposition them while the physics simulation continues. This
-layout can also be used with pan & zoom behaviors for interaction.
-
-
To facilitate interaction, this layout by default automatically re-renders
-using a setInterval every 42 milliseconds. This can be disabled via
-the iterations property, which if non-null specifies the number of
-simulation iterations to run before the force-directed layout is finalized.
-Be careful not to use too high an iteration count, as this can lead to an
-annoying delay on page load.
-
-
As with other network layouts, the network data can be updated
-dynamically, provided the property cache is reset. See
-pv.Layout.Network for details. New nodes are initialized with random
-positions near the center. Alternatively, positions can be specified manually
-by setting the x and y attributes on nodes.
-
-
- Defined in: Force.js.
-
-
- Constructs a new, empty force-directed layout. Layouts are not typically
-constructed directly; instead, they are added to an existing panel via
-pv.Mark#add.
-
-
- The bound parameter; true if nodes should be constrained within the layout
-panel. Bounding is disabled by default. Currently the layout does not observe
-the radius of the nodes; strictly speaking, only the center of the node is
-constrained to be within the panel, with an additional 6-pixel offset for
-padding. A future enhancement could extend the bound constraint to observe
-the node's radius, which would also support bounding for variable-size nodes.
-
-
Note that if this layout is used in conjunction with pan & zoom
-behaviors, those behaviors should have their bound parameter set to the same
-value.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- chargeConstant
-
-
-
- The charge constant, which should be a negative number. The default value is
--40; more negative values will result in a stronger repulsive force, which
-may lead to faster convergence at the risk of instability. Too strong
-repulsive charge forces can cause comparatively weak springs to be stretched
-well beyond their rest length, emphasizing global structure over local
-structure. A nonnegative value will break the Fruchterman-Reingold algorithm,
-and is for entertainment purposes only.
-
-
-
- The maximum distance at which charge forces are applied. This improves
-performance by ignoring weak charge forces at great distances. Note that this
-parameter is partly redundant, as the Barnes-Hut algorithm for n-body forces
-already improves performance for far-away particles through approximation.
-
-
-
- The minimum distance at which charge forces are applied. The default minimum
-distance of 2 avoids applying forces that are two strong; because the physics
-simulation is run at discrete time intervals, it is possible for two same-
-charged particles to become very close or even a singularity! Since the
-charge force is inversely proportional to the square of the distance, very
-small distances can break the simulation.
-
-
In rare cases, two particles can become stuck on top of each other, as a
-minimum distance threshold will prevent the charge force from repelling them.
-However, this occurs very rarely because other forces and momentum typically
-cause the particles to become separated again, at which point the repulsive
-charge force kicks in.
-
-
-
- The Barnes-Hut approximation factor. The Barnes-Hut approximation criterion
-is the ratio of the size of the quadtree node to the distance from the point
-to the node's center of mass is beneath some threshold. The default value is
-0.9.
-
-
-
- Default properties for force-directed layouts. The default drag constant is
-0.1, the default charge constant is -40 (with a domain of [2, 500] and theta
-of 0.9), and the default spring constant is 0.1 (with a damping of 0.3 and a
-rest length of 20).
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- dragConstant
-
-
-
- The drag constant, in the range [0,1]. A value of 0 means no drag (a
-perfectly frictionless environment), while a value of 1 means friction
-immediately cancels all momentum. The default value is 0.1, which provides a
-minimum amount of drag that helps stabilize bouncy springs; lower values may
-result in excessive bounciness, while higher values cause the simulation to
-take longer to converge.
-
-
-
- The number of simulation iterations to run, or null if this layout is
-interactive. Force-directed layouts are interactive by default, using a
-setInterval to advance the physics simulation and re-render
-automatically.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- springConstant
-
-
-
- The spring constant, which should be a positive number. The default value is
-0.1; greater values will result in a stronger attractive force, which may
-lead to faster convergence at the risk of instability. Too strong spring
-forces can cause comparatively weak charge forces to be ignored, emphasizing
-local structure over global structure. A nonpositive value will break the
-Fruchterman-Reingold algorithm, and is for entertainment purposes only.
-
-
The spring tension is automatically normalized using the inverse square
-root of the maximum link degree of attached nodes.
-
-
-
- The spring damping factor, in the range [0,1]. Damping functions identically
-to drag forces, damping spring bounciness by applying a force in the opposite
-direction of attached nodes' velocities. The default value is 0.3.
-
-
The spring damping is automatically normalized using the inverse square
-root of the maximum link degree of attached nodes.
-
-
-
- The spring rest length. The default value is 20 pixels. Larger values may be
-appropriate if the layout panel is larger, or if the nodes are rendered
-larger than the default dot size of 20.
-
-
-
-
- Extends
- pv.Layout.
-
-
- Implements a grid layout with regularly-sized rows and columns. The
-number of rows and columns are determined from their respective
-properties. For example, the 2×3 array:
-
-
1 2 3
-4 5 6
-
-can be represented using the rows property as:
-
-
[[1, 2, 3], [4, 5, 6]]
-
-If your data is in column-major order, you can equivalently use the
-columns property. If the rows property is an array, it
-takes priority over the columns property. The data is implicitly
-transposed, as if the pv.transpose operator were applied.
-
-
This layout exports a single cell mark prototype, which is
-intended to be used with a bar, panel, layout, or subclass thereof. The data
-property of the cell prototype is defined as the elements in the array. For
-example, if the array is a two-dimensional array of values in the range
-[0,1], a simple heatmap can be generated as:
-
-
-
-The grid subdivides the full width and height of the parent panel into equal
-rectangles. Note, however, that for large, interactive, or animated heatmaps,
-you may see significantly better performance through dynamic pv.Image
-generation.
-
-
For irregular grids using value-based spatial partitioning, see {@link
-pv.Layout.Treemap}.
-
-
- Defined in: Grid.js.
-
-
- Constructs a new, empty grid layout. Layouts are not typically constructed
-directly; instead, they are added to an existing panel via
-pv.Mark#add.
-
-
- The cell prototype. This prototype is intended to be used with a bar,
-panel, or layout (or subclass thereof) to render the grid cells.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- cols
-
-
-
- The number of columns. This property can also be specified as the data in
-column-major order; in this case, the cols property is implicitly set to the
-length of the array, and the rows property is set to the length of the first
-element in the array.
-
-
-
- Default properties for grid layouts. By default, there is one row and one
-column, and the data is the propagated to the child cell.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- rows
-
-
-
- The number of rows. This property can also be specified as the data in
-row-major order; in this case, the rows property is implicitly set to the
-length of the array, and the cols property is set to the length of the first
-element in the array.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Documentation generated by JsDoc Toolkit 2.3.2 on Fri May 28 2010 10:13:29 GMT-0700 (PDT)
-
-
- Extends
- pv.Layout.Network.
-
-
- Represents an abstract layout for hierarchy diagrams. This class is a
-specialization of pv.Layout.Network, providing the basic structure
-for both hierarchical node-link diagrams (such as Reingold-Tilford trees) and
-space-filling hierarchy diagrams (such as sunbursts and treemaps).
-
-
Unlike general network layouts, the links property need not be
-defined explicitly. Instead, the links are computed implicitly from the
-parentNode attribute of the node objects, as defined by the
-nodes property. This implementation is also available as
-#links, for reuse with non-hierarchical layouts; for example, to
-render a tree using force-directed layout.
-
-
Correspondingly, the nodes property is represented as a union of
-pv.Layout.Network.Node and pv.Dom.Node. To construct a node
-hierarchy from a simple JSON map, use the pv.Dom operator; this
-operator also provides an easy way to sort nodes before passing them to the
-layout.
-
-
- Constructs a new, empty hierarchy layout. Layouts are not typically
-constructed directly; instead, they are added to an existing panel via
-pv.Mark#add.
-
-
This layout exports a single band mark prototype, which is
-intended to be used with an area mark. The band mark is contained in a panel
-which is replicated per band (and for negative/positive bands). For example,
-to create a simple horizon graph given an array of numbers:
-
-
-
-The layout can be further customized by changing the number of bands, and
-toggling whether the negative bands are mirrored or offset. (See the
-above-referenced paper for guidance.)
-
-
The fillStyle of the area can be overridden, though typically it
-is easier to customize the layout's behavior through the custom
-backgroundStyle, positiveStyle and negativeStyle
-properties. By default, the background is white, positive bands are blue, and
-negative bands are red. For the most accurate presentation, use fully-opaque
-colors of equal intensity for the negative and positive bands.
-
-
- Defined in: Horizon.js.
-
-
- Constructs a new, empty horizon layout. Layouts are not typically constructed
-directly; instead, they are added to an existing panel via
-pv.Mark#add.
-
-
- The background color. The panel background is filled with the specified
-color, and the negative and positive bands are filled with an interpolated
-color between this color and the respective band color. The default value of
-this property is white. For accurate blending, this color should be fully
-opaque.
-
-
-
- Default properties for horizon layouts. By default, there are two bands, the
-mode is "offset", the background style is "white", the positive style is
-blue, negative style is red.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- mode
-
-
-
- The horizon mode: offset, mirror, or color. The default is "offset".
-
-
-
- The negative band color; if non-null, the interior of negative bands are
-filled with the specified color. The default value of this property is red.
-For accurate blending, this color should be fully opaque.
-
-
-
- The positive band color; if non-null, the interior of positive bands are
-filled with the specified color. The default value of this property is blue.
-For accurate blending, this color should be fully opaque.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Documentation generated by JsDoc Toolkit 2.3.2 on Fri May 28 2010 10:13:29 GMT-0700 (PDT)
-
-
- Extends
- pv.Layout.Hierarchy.
-
-
- Implements a hierarchical layout using the indent algorithm. This
-layout implements a node-link diagram where the nodes are presented in
-preorder traversal, and nodes are indented based on their depth from the
-root. This technique is used ubiquitously by operating systems to represent
-file directories; although it requires much vertical space, indented trees
-allow efficient interactive exploration of trees to find a specific
-node. In addition they allow rapid scanning of node labels, and multivariate
-data such as file sizes can be displayed adjacent to the hierarchy.
-
-
The indent layout can be configured using the depth and
-breadth properties, which control the increments in pixel space for
-each indent and row in the layout. This layout does not support multiple
-orientations; the root node is rendered in the top-left, while
-breadth is a vertical offset from the top, and depth is a
-horizontal offset from the left.
-
-
- Constructs a new, empty indent layout. Layouts are not typically constructed
-directly; instead, they are added to an existing panel via
-pv.Mark#add.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Field Detail
-
-
-
-
-
- {number}
- breadth
-
-
-
- The vertical offset between nodes; defaults to 15.
-
-
-
-
- Extends
- pv.Layout.Network.
-
-
- Implements a network visualization using a matrix view. This is, in
-effect, a visualization of the graph's adjacency matrix: the cell at
-row i, column j, corresponds to the link from node i to
-node j. The fill color of each cell is binary by default, and
-corresponds to whether a link exists between the two nodes. If the underlying
-graph has links with variable values, the fillStyle property can be
-substited to use an appropriate color function, such as pv.ramp.
-
-
For undirected networks, the matrix is symmetric around the diagonal. For
-directed networks, links in opposite directions can be rendered on opposite
-sides of the diagonal using directed(true). The graph is assumed to
-be undirected by default.
-
-
The mark prototypes for this network layout are slightly different than
-other implementations:
-
-
node - unsupported; undefined. No mark is needed to visualize
-nodes directly, as the nodes are implicit in the location (rows and columns)
-of the links.
-
-
link - for rendering links; typically a pv.Bar. The
-link mark is added directly to the layout, with the data property defined as
-all possible pairs of nodes. Each pair is represented as a
-pv.Network.Layout.Link, though the linkValue attribute may
-be 0 if no link exists in the graph.
-
-
label - for rendering node labels; typically a
-pv.Label. The label mark is added directly to the layout, with the
-data property defined via the layout's nodes property; note,
-however, that the nodes are duplicated so as to provide a label across the
-top and down the side. Properties such as strokeStyle and
-fillStyle can be overridden to compute properties from node data
-dynamically.
-
-
For more details on how to use this layout, see
-pv.Layout.Network.
-
-
- Defined in: Matrix.js.
-
-
-
-
-
-
- Constructs a new, empty matrix network layout. Layouts are not typically
-constructed directly; instead, they are added to an existing panel via
-pv.Mark#add.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Field Detail
-
-
-
-
-
- {boolean}
- directed
-
-
-
- Whether this matrix visualization is directed (bidirectional). By default,
-the graph is assumed to be undirected, such that the visualization is
-symmetric across the matrix diagonal. If the network is directed, then
-forward links are drawn above the diagonal, while reverse links are drawn
-below.
-
-
-
- Specifies an optional sort function. The sort function follows the same
-comparator contract required by pv.Dom.Node#sort. Specifying a sort
-function provides an alternative to sort the nodes as they are specified by
-the nodes property; the main advantage of doing this is that the
-comparator function can access implicit fields populated by the network
-layout, such as the linkDegree.
-
-
Note that matrix visualizations are particularly sensitive to order. This
-is referred to as the seriation problem, and many different techniques exist
-to find good node orders that emphasize clusters, such as spectral layout and
-simulated annealing.
-
-
-
-
-
-
- Represents a link in a network layout. There is no explicit
-constructor; this class merely serves to document the attributes that are
-used on links in network layouts. For hierarchical layouts, this class is
-used to represent the parent-child links.
-
-
- Defined in: Network.js.
-
-
- The link value, or weight; optional. If not specified (or not a number), the
-default value of 1 is used.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- source
-
-
-
- Alias for sourceNode, as expressed by the index of the source node.
-This attribute is not populated automatically, but may be used as a more
-convenient identification of the link's source, for example in a static JSON
-representation.
-
-
-
- The link's source node. If not set, this value will be derived from the
-source attribute index.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- target
-
-
-
- Alias for targetNode, as expressed by the index of the target node.
-This attribute is not populated automatically, but may be used as a more
-convenient identification of the link's target, for example in a static JSON
-representation.
-
-
-
- The link's target node. If not set, this value will be derived from the
-target attribute index.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- value
-
-
-
- Alias for linkValue. This attribute is not populated automatically,
-but may be used instead of the linkValue attribute when specifying
-links.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Documentation generated by JsDoc Toolkit 2.3.2 on Fri May 28 2010 10:13:29 GMT-0700 (PDT)
-
-
-
-
- Represents a node in a network layout. There is no explicit
-constructor; this class merely serves to document the attributes that are
-used on nodes in network layouts. (Note that hierarchical nodes place
-additional requirements on node representation, vis pv.Dom.Node.)
-
-
- Defined in: Network.js.
-
-
- The node index, zero-based. This attribute is populated automatically based
-on the index in the array returned by the nodes property.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- linkDegree
-
-
-
- The link degree; the sum of link values for all incoming and outgoing links.
-This attribute is populated automatically.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- nodeName
-
-
-
- The node name; optional. If present, this attribute will be used to provide
-the text for node labels. If not present, the label text will fallback to the
-nodeValue attribute.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {object}
- nodeValue
-
-
-
- The node value; optional. If present, and no nodeName attribute is
-present, the node value will be used as the label text. This attribute is
-also automatically populated if the nodes are specified as an array of
-primitives, such as strings or numbers.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Documentation generated by JsDoc Toolkit 2.3.2 on Fri May 28 2010 10:13:29 GMT-0700 (PDT)
-
-
- Extends
- pv.Layout.
-
-
- Represents an abstract layout for network diagrams. This class
-provides the basic structure for both node-link diagrams (such as
-force-directed graph layout) and space-filling network diagrams (such as
-sunbursts and treemaps). Note that "network" here is a general term that
-includes hierarchical structures; a tree is represented using links from
-child to parent.
-
-
Network layouts require the graph data structure to be defined using two
-properties:
-
-
nodes - an array of objects representing nodes. Objects in this
-array must conform to the pv.Layout.Network.Node interface; which is
-to say, be careful to avoid naming collisions with automatic attributes such
-as index and linkDegree. If the nodes property is defined
-as an array of primitives, such as numbers or strings, these primitives are
-automatically wrapped in an object; the resulting object's nodeValue
-attribute points to the original primitive value.
-
-
links - an array of objects representing links. Objects in
-this array must conform to the pv.Layout.Network.Link interface; at a
-minimum, either source and target indexes or
-sourceNode and targetNode references must be set. Note that
-if the links property is defined after the nodes property, the links can be
-defined in terms of this.nodes().
-
-
-
-
Three standard mark prototypes are provided:
-
-
node - for rendering nodes; typically a pv.Dot. The node
-mark is added directly to the layout, with the data property defined via the
-layout's nodes property. Properties such as strokeStyle and
-fillStyle can be overridden to compute properties from node data
-dynamically.
-
-
link - for rendering links; typically a pv.Line. The
-link mark is added to a child panel, whose data property is defined as
-layout's links property. The link's data property is then a
-two-element array of the source node and target node. Thus, poperties such as
-strokeStyle and fillStyle can be overridden to compute
-properties from either the node data (the first argument) or the link data
-(the second argument; the parent panel data) dynamically.
-
-
label - for rendering node labels; typically a
-pv.Label. The label mark is added directly to the layout, with the
-data property defined via the layout's nodes property. Properties
-such as strokeStyle and fillStyle can be overridden to
-compute properties from node data dynamically.
-
-
Note that some network implementations may not support all three
-standard mark prototypes; for example, space-filling hierarchical layouts
-typically do not use a link prototype, as the parent-child links are
-implied by the structure of the space-filling node marks. Check the
-specific network layout for implementation details.
-
-
Network layout properties, including nodes and links,
-are typically cached rather than re-evaluated with every call to render. This
-is a performance optimization, as network layout algorithms can be
-expensive. If the network structure changes, call #reset to clear the
-cache before rendering. Note that although the network layout properties are
-cached, child mark properties, such as the marks used to render the nodes and
-links, are not. Therefore, non-structural changes to the network
-layout, such as changing the color of a mark on mouseover, do not need to
-reset the layout.
-
-
- Defined in: Network.js.
-
-
- Constructs a new, empty network layout. Layouts are not typically constructed
-directly; instead, they are added to an existing panel via
-pv.Mark#add.
-
-
- The node label prototype, which renders the node name adjacent to the node.
-This prototype is provided as an alternative to using the anchor on the
-node mark; it is primarily intended to be used with radial node-link
-layouts, since it provides a convenient mechanism to set the text angle.
-
-
-
- The link prototype, which renders edges between source nodes and target
-nodes. This prototype is intended to be used with a Line mark in
-conjunction with the node prototype.
-
-
-
- Resets the cache, such that changes to layout property definitions will be
-visible on subsequent render. Unlike normal marks (and normal layouts),
-properties associated with network layouts are not automatically re-evaluated
-on render; the properties are cached, and any expensive layout algorithms are
-only run after the layout is explicitly reset.
-
-
-
-
- Extends
- pv.Layout.Hierarchy.
-
-
- Implements a hierarchical layout using circle-packing. The meaning of
-the exported mark prototypes changes slightly in the space-filling
-implementation:
-
-
node - for rendering nodes; typically a pv.Dot.
-
-
link - unsupported; undefined. Links are encoded implicitly
-in the arrangement of the space-filling nodes.
-
-
label - for rendering node labels; typically a
-pv.Label.
-
-
The pack layout support dynamic sizing for leaf nodes, if a
-#size psuedo-property is specified. The default size function returns
-1, causing all leaf nodes to be sized equally, and all internal nodes to be
-sized by the number of leaf nodes they have as descendants.
-
-
The size function can be used in conjunction with the order property,
-which allows the nodes to the sorted by the computed size. Note: for sorting
-based on other data attributes, simply use the default null for the
-order property, and sort the nodes beforehand using the pv.Dom
-operator.
-
-
- Constructs a new, empty circle-packing layout. Layouts are not typically
-constructed directly; instead, they are added to an existing panel via
-pv.Mark#add.
-
-
- Default properties for circle-packing layouts. The default spacing parameter
-is 1 and the default order is "ascending".
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- order
-
-
-
- The sibling node order. The default order is null, which means to
-use the sibling order specified by the nodes property as-is. A value of
-"ascending" will sort siblings in ascending order of size, while "descending"
-will do the reverse. For sorting based on data attributes other than size,
-use the default null for the order property, and sort the nodes
-beforehand using the pv.Dom operator.
-
-
-
- The spacing parameter; defaults to 1, which provides a little bit of padding
-between sibling nodes and the enclosing circle. Larger values increase the
-spacing, by making the sibling nodes smaller; a value of zero makes the leaf
-nodes as large as possible, with no padding on enclosing circles.
-
-
-
- Specifies the sizing function. By default, a sizing function is disabled and
-all nodes are given constant size. The sizing function is invoked for each
-leaf node in the tree (passed to the constructor).
-
-
For example, if the tree data structure represents a file system, with
-files as leaf nodes, and each file has a bytes attribute, you can
-specify a size function as:
-
-
.size(function(d) d.bytes)
-
-As with other properties, a size function may specify additional arguments to
-access the data associated with the layout and any enclosing panels.
-
-
-
-
- Extends
- pv.Layout.Partition.
-
-
- A variant of partition layout that is space-filling. The meaning of
-the exported mark prototypes changes slightly in the space-filling
-implementation:
-
-
node - for rendering nodes; typically a pv.Bar for
-non-radial orientations, and a pv.Wedge for radial orientations.
-
-
link - unsupported; undefined. Links are encoded implicitly
-in the arrangement of the space-filling nodes.
-
-
label - for rendering node labels; typically a
-pv.Label.
-
-
- Constructs a new, empty space-filling partition layout. Layouts are not
-typically constructed directly; instead, they are added to an existing panel
-via pv.Mark#add.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Documentation generated by JsDoc Toolkit 2.3.2 on Fri May 28 2010 10:13:29 GMT-0700 (PDT)
-
-
- Extends
- pv.Layout.Hierarchy.
-
-
- Implemeents a hierarchical layout using the partition (or sunburst,
-icicle) algorithm. This layout provides both node-link and space-filling
-implementations of partition diagrams. In many ways it is similar to
-pv.Layout.Cluster, except that leaf nodes are positioned based on
-their distance from the root.
-
-
The partition layout support dynamic sizing for leaf nodes, if a
-#size psuedo-property is specified. The default size function returns
-1, causing all leaf nodes to be sized equally, and all internal nodes to be
-sized by the number of leaf nodes they have as descendants.
-
-
The size function can be used in conjunction with the order property,
-which allows the nodes to the sorted by the computed size. Note: for sorting
-based on other data attributes, simply use the default null for the
-order property, and sort the nodes beforehand using the pv.Dom
-operator.
-
-
- Constructs a new, empty partition layout. Layouts are not typically
-constructed directly; instead, they are added to an existing panel via
-pv.Mark#add.
-
-
- Default properties for partition layouts. The default orientation is "top".
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- innerRadius
-
-
-
- The inner radius; defaults to 0. This property applies only to radial
-orientations, and can be used to compress the layout radially. Note that for
-the node-link implementation, the root node is always at the center,
-regardless of the value of this property; this property only affects internal
-and leaf nodes. For the space-filling implementation, a non-zero value of
-this property will result in the root node represented as a ring rather than
-a circle.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- order
-
-
-
- The sibling node order. The default order is null, which means to
-use the sibling order specified by the nodes property as-is. A value of
-"ascending" will sort siblings in ascending order of size, while "descending"
-will do the reverse. For sorting based on data attributes other than size,
-use the default null for the order property, and sort the nodes
-beforehand using the pv.Dom operator.
-
-
-
- The orientation. The default orientation is "top", which means that the root
-node is placed on the top edge, leaf nodes appear at the bottom, and internal
-nodes are in-between. The following orientations are supported:
-
-
left - left-to-right.
-
right - right-to-left.
-
top - top-to-bottom.
-
bottom - bottom-to-top.
-
radial - radially, with the root at the center.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- outerRadius
-
-
-
- The outer radius; defaults to fill the containing panel, based on the height
-and width of the layout. If the layout has no height and width specified, it
-will extend to fill the enclosing panel.
-
-
-
- Specifies the sizing function. By default, a sizing function is disabled and
-all nodes are given constant size. The sizing function is invoked for each
-leaf node in the tree (passed to the constructor).
-
-
For example, if the tree data structure represents a file system, with
-files as leaf nodes, and each file has a bytes attribute, you can
-specify a size function as:
-
-
.size(function(d) d.bytes)
-
-As with other properties, a size function may specify additional arguments to
-access the data associated with the layout and any enclosing panels.
-
-
-
-
- Extends
- pv.Layout.Network.
-
-
- Implements a network visualization using a node-link diagram where
-nodes are rolled up along two dimensions. This implementation is based on the
-"PivotGraph" designed by Martin Wattenberg:
-
-
The method is designed for graphs that are "multivariate", i.e.,
-where each node is associated with several attributes. Unlike visualizations
-which emphasize global graph topology, PivotGraph uses a simple grid-based
-approach to focus on the relationship between node attributes &
-connections.
-
-This layout requires two psuedo-properties to be specified, which assign node
-positions along the two dimensions #x and #y, corresponding
-to the left and top properties, respectively. Typically, these functions are
-specified using an pv.Scale.ordinal. Nodes that share the same
-position in x and y are "rolled up" into a meta-node, and
-similarly links are aggregated between meta-nodes. For example, to construct
-a rollup to analyze links by gender and affiliation, first define two ordinal
-scales:
-
-
var x = pv.Scale.ordinal(nodes, function(d) d.gender).split(0, w),
- y = pv.Scale.ordinal(nodes, function(d) d.aff).split(0, h);
-
-Next, define the position psuedo-properties:
-
-
-
-Linear and other quantitative scales can alternatively be used to position
-the nodes along either dimension. Note, however, that the rollup requires
-that the positions match exactly, and thus ordinal scales are recommended to
-avoid precision errors.
-
-
Note that because this layout provides a visualization of the rolled up
-graph, the data properties for the mark prototypes (node,
-link and label) are different from most other network
-layouts: they reference the rolled-up nodes and links, rather than the nodes
-and links of the full network. The underlying nodes and links for each
-rolled-up node and link can be accessed via the nodes and
-links attributes, respectively. The aggregated link values for
-rolled-up links can similarly be accessed via the linkValue
-attribute.
-
-
For undirected networks, links are duplicated in both directions. For
-directed networks, use directed(true). The graph is assumed to be
-undirected by default.
-
-
- Defined in: Rollup.js.
-
-
- Constructs a new, empty rollup network layout. Layouts are not typically
-constructed directly; instead, they are added to an existing panel via
-pv.Mark#add.
-
-
- Whether the underlying network is directed. By default, the graph is assumed
-to be undirected, and links are rendered in both directions. If the network
-is directed, then forward links are drawn above the diagonal, while reverse
-links are drawn below.
-
-
-
- Specifies the x-position function used to rollup nodes. The rolled up
-nodes are positioned horizontally using the return values from the given
-function. Typically the function is specified as an ordinal scale. For
-single-dimension rollups, a constant value can be specified.
-
-
-
- Specifies the y-position function used to rollup nodes. The rolled up
-nodes are positioned vertically using the return values from the given
-function. Typically the function is specified as an ordinal scale. For
-single-dimension rollups, a constant value can be specified.
-
-
-
-
- Extends
- pv.Layout.
-
-
- Implements a layout for stacked visualizations, ranging from simple
-stacked bar charts to more elaborate "streamgraphs" composed of stacked
-areas. Stack layouts uses length as a visual encoding, as opposed to
-position, as the layers do not share an aligned axis.
-
-
Marks can be stacked vertically or horizontally. For example,
-
-
-
-specifies a vertically-stacked area chart, using the default "bottom-left"
-orientation with "zero" offset. This visualization can be easily changed into
-a streamgraph using the "wiggle" offset, which attempts to minimize change in
-slope weighted by layer thickness. See the #offset property for more
-supported streamgraph algorithms.
-
-
In the simplest case, the layer data can be specified as a two-dimensional
-array of numbers. The x and y psuedo-properties are used to
-define the thickness of each layer at the given position, respectively; in
-the above example of the "bottom-left" orientation, the x and
-y psuedo-properties are equivalent to the left and
-height properties that you might use if you implemented a stacked
-area by hand.
-
-
The advantage of using the stack layout is that the baseline, i.e., the
-bottom property is computed automatically using the specified offset
-algorithm. In addition, the order of layers can be computed using a built-in
-algorithm via the order property.
-
-
With the exception of the "expand" offset, the stack layout does
-not perform any automatic scaling of data; the values returned from
-x and y specify pixel sizes. To simplify scaling math, use
-this layout in conjunction with pv.Scale.linear or similar.
-
-
In other cases, the values psuedo-property can be used to define
-the data more flexibly. As with a typical panel & area, the
-layers property corresponds to the data in the enclosing panel,
-while the values psuedo-property corresponds to the data for the
-area within the panel. For example, given an array of data values:
-
-
-
-As with the panel & area case, the datum that is passed to the
-psuedo-properties x and y are the values (an element in
-crimea); the second argument is the layer data (a string in
-causes). Additional arguments specify the data of enclosing panels,
-if any.
-
-
- Defined in: Stack.js.
-
-
-
-
-
-
- Constructs a new, empty stack layout. Layouts are not typically constructed
-directly; instead, they are added to an existing panel via
-pv.Mark#add.
-
-
- Default properties for stack layouts. The default orientation is
-"bottom-left", the default offset is "zero", and the default layers is
-[[]].
-
-
-
- The layer prototype. This prototype is intended to be used with an area,
-bar or panel mark (or subclass thereof). Other mark types may be possible,
-though note that the stack layout is not currently designed to support
-radial stacked visualizations using wedges.
-
-
The layer is not a direct child of the stack layout; a hidden panel is
-used to replicate layers.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {array[]}
- layers
-
-
-
- The layer data in row-major order. The value of this property is typically a
-two-dimensional (i.e., nested) array, but any array can be used, provided the
-values psuedo-property is defined accordingly.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- offset
-
-
-
- The layer offset; the y-position of the bottom of the lowest layer. The
-following values are supported:
-
-
zero - use a zero baseline, i.e., the y-axis.
-
silohouette - center the stream, i.e., ThemeRiver.
-
wiggle - minimize weighted change in slope.
-
expand - expand layers to fill the enclosing layout dimensions.
-
-
For details on these offset algorithms, refer to "Stacked Graphs --
-Geometry & Aesthetics" by L. Byron and M. Wattenberg, IEEE TVCG
-November/December 2008.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- order
-
-
-
- The layer order. The following values are supported:
-
-
null - use given layer order.
-
inside-out - sort by maximum value, with balanced order.
-
reverse - use reverse of given layer order.
-
-
For details on the inside-out order algorithm, refer to "Stacked Graphs
--- Geometry & Aesthetics" by L. Byron and M. Wattenberg, IEEE TVCG
-November/December 2008.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- orient
-
-
-
- The layer orientation. The following values are supported:
-
-
bottom-left == bottom
-
bottom-right
-
top-left == top
-
top-right
-
left-top
-
left-bottom == left
-
right-top
-
right-bottom == right
-
-
. The default value is "bottom-left", which means that the layers will
-be built from the bottom-up, and the values within layers will be laid out
-from left-to-right.
-
-
Note that with non-zero baselines, some orientations may give similar
-results. For example, offset("silohouette") centers the layers, resulting in
-a streamgraph. Thus, the orientations "bottom-left" and "top-left" will
-produce similar results, differing only in the layer order.
-
-
-
- The values function; determines the values for a given layer. The default
-value is the identity function, which assumes that the layers property is
-specified as a two-dimensional (i.e., nested) array.
-
-
-
- The x psuedo-property; determines the position of the value within the layer.
-This typically corresponds to the independent variable. For example, with the
-default "bottom-left" orientation, this function defines the "left" property.
-
-
-
- The y psuedo-property; determines the thickness of the layer at the given
-value. This typically corresponds to the dependent variable. For example,
-with the default "bottom-left" orientation, this function defines the
-"height" property.
-
-
-
-
- Extends
- pv.Layout.Hierarchy.
-
-
- Implements a node-link tree diagram using the Reingold-Tilford "tidy"
-tree layout algorithm. The specific algorithm used by this layout is based on
-"Improving
-Walker's Algorithm to Run in Linear Time" by C. Buchheim, M. Jünger
-& S. Leipert, Graph Drawing 2002. This layout supports both cartesian and
-radial orientations orientations for node-link diagrams.
-
-
The tree layout supports a "group" property, which if true causes siblings
-to be positioned closer together than unrelated nodes at the same depth. The
-layout can be configured using the depth and breadth
-properties, which control the increments in pixel space between nodes in both
-dimensions, similar to the indent layout.
-
-
- Constructs a new, empty tree layout. Layouts are not typically constructed
-directly; instead, they are added to an existing panel via
-pv.Mark#add.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Field Detail
-
-
-
-
-
- {number}
- breadth
-
-
-
- The offset between siblings nodes; defaults to 15.
-
-
-
- Default properties for tree layouts. The default orientation is "top", the
-default group parameter is 1, and the default breadth and depth offsets are
-15 and 60 respectively.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- depth
-
-
-
- The offset between parent and child nodes; defaults to 60.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- group
-
-
-
- The sibling grouping, i.e., whether differentiating space is placed between
-sibling groups. The default is 1 (or true), causing sibling leaves to be
-separated by one breadth offset. Setting this to false (or 0) causes
-non-siblings to be adjacent.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- orient
-
-
-
- The orientation. The default orientation is "top", which means that the root
-node is placed on the top edge, leaf nodes appear at the bottom, and internal
-nodes are in-between. The following orientations are supported:
-
-
left - left-to-right.
-
right - right-to-left.
-
top - top-to-bottom.
-
bottom - bottom-to-top.
-
radial - radially, with the root at the center.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Documentation generated by JsDoc Toolkit 2.3.2 on Fri May 28 2010 10:13:29 GMT-0700 (PDT)
-
-
- Extends
- pv.Layout.Hierarchy.
-
-
- Implements a space-filling rectangular layout, with the hierarchy
-represented via containment. Treemaps represent nodes as boxes, with child
-nodes placed within parent boxes. The size of each box is proportional to the
-size of the node in the tree. This particular algorithm is taken from Bruls,
-D.M., C. Huizing, and J.J. van Wijk, "Squarified Treemaps" in
-Data Visualization 2000, Proceedings of the Joint Eurographics and IEEE
-TCVG Sumposium on Visualization, 2000, pp. 33-42.
-
-
The meaning of the exported mark prototypes changes slightly in the
-space-filling implementation:
-
-
node - for rendering nodes; typically a pv.Bar. The node
-data is populated with dx and dy attributes, in addition to
-the standard x and y position attributes.
-
-
leaf - for rendering leaf nodes only, with no fill or stroke
-style by default; typically a pv.Panel or another layout!
-
-
link - unsupported; undefined. Links are encoded implicitly
-in the arrangement of the space-filling nodes.
-
-
label - for rendering node labels; typically a
-pv.Label.
-
-
- Constructs a new, empty treemap layout. Layouts are not typically
-constructed directly; instead, they are added to an existing panel via
-pv.Mark#add.
-
-
- Default propertiess for treemap layouts. The default mode is "squarify" and
-the default order is "ascending".
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- mode
-
-
-
- The treemap algorithm. The default value is "squarify". The "slice-and-dice"
-algorithm may also be used, which alternates between horizontal and vertical
-slices for different depths. In addition, the "slice" and "dice" algorithms
-may be specified explicitly to control whether horizontal or vertical slices
-are used, which may be useful for nested treemap layouts.
-
-
-
- The sibling node order. A null value means to use the sibling order
-specified by the nodes property as-is; "reverse" will reverse the given
-order. The default value "ascending" will sort siblings in ascending order of
-size, while "descending" will do the reverse. For sorting based on data
-attributes other than size, use the default null for the order
-property, and sort the nodes beforehand using the pv.Dom operator.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- paddingBottom
-
-
-
- The bottom inset between parent and child in pixels. Defaults to 0.
-
-
-
- Whether node sizes should be rounded to integer values. This has a similar
-effect to setting antialias(false) for node values, but allows the
-treemap algorithm to accumulate error related to pixel rounding.
-
-
-
- Specifies the sizing function. By default, the size function uses the
-nodeValue attribute of nodes as a numeric value: function(d)
-Number(d.nodeValue).
-
-
The sizing function is invoked for each leaf node in the tree, per the
-nodes property. For example, if the tree data structure represents a
-file system, with files as leaf nodes, and each file has a bytes
-attribute, you can specify a size function as:
-
-
-
- Extends
- pv.Panel.
-
-
- Represents an abstract layout, encapsulating a visualization technique
-such as a streamgraph or treemap. Layouts are themselves containers,
-extending from pv.Panel, and defining a set of mark prototypes as
-children. These mark prototypes provide default properties that together
-implement the given visualization technique.
-
-
Layouts do not initially contain any marks; any exported marks (such as a
-network layout's link and node) are intended to be used as
-prototypes. By adding a concrete mark, such as a pv.Bar, to the
-appropriate mark prototype, the mark is added to the layout and inherits the
-given properties. This approach allows further customization of the layout,
-either by choosing a different mark type to add, or more simply by overriding
-some of the layout's defined properties.
-
-
Each concrete layout, such as treemap or circle-packing, has different
-behavior and may export different mark prototypes, depending on what marks
-are typically needed to render the desired visualization. Therefore it is
-important to understand how each layout is structured, such that the provided
-mark prototypes are used appropriately.
-
-
In addition to the mark prototypes, layouts may define custom properties
-that affect the overall behavior of the layout. For example, a treemap layout
-might use a property to specify which layout algorithm to use. These
-properties are just like other mark properties, and can be defined as
-constants or as functions. As with panels, the data property can be used to
-replicate layouts, and properties can be defined to in terms of layout data.
-
-
- Defined in: Layout.js.
-
-
- Constructs a new, empty layout with default properties. Layouts are not
-typically constructed directly; instead, a concrete subclass is added to an
-existing panel via pv.Mark#add.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Documentation generated by JsDoc Toolkit 2.3.2 on Fri May 28 2010 10:13:28 GMT-0700 (PDT)
-
-
- Extends
- pv.Mark.
-
-
- Represents a series of connected line segments, or polyline,
-that can be stroked with a configurable color and thickness. Each
-articulation point in the line corresponds to a datum; for n points,
-n-1 connected line segments are drawn. The point is positioned using
-the box model. Arbitrary paths are also possible, allowing radar plots and
-other custom visualizations.
-
-
Like areas, lines can be stroked and filled with arbitrary colors. In most
-cases, lines are only stroked, but the fill style can be used to construct
-arbitrary polygons.
-
-
- Constructs a new line mark with default properties. Lines are not typically
-constructed directly, but by adding to a panel or an existing mark via
-pv.Mark#add.
-
-
- Default properties for lines. By default, there is no fill and the stroke
-style is a categorical color. The default interpolation is linear.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- eccentricity
-
-
-
- The eccentricity of polar line segments; used in conjunction with
-interpolate("polar"). The default value of 0 means that line segments are
-drawn as circular arcs. A value of 1 draws a straight line. A value between 0
-and 1 draws an elliptical arc with the given eccentricity.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- fillStyle
-
-
-
- The line fill style; if non-null, the interior of the line is closed and
-filled with the specified color. The default value of this property is a
-null, meaning that lines are not filled by default.
-
-
- How to interpolate between values. Linear interpolation ("linear") is the
-default, producing a straight line between points. For piecewise constant
-functions (i.e., step functions), either "step-before" or "step-after" can be
-specified. To draw a clockwise circular arc between points, specify "polar";
-to draw a counterclockwise circular arc between points, specify
-"polar-reverse". To draw open uniform b-splines, specify "basis". To draw
-cardinal splines, specify "cardinal"; see also #tension.
-
-
- The type of corners where two lines meet. Accepted values are "bevel",
-"round" and "miter". The default value is "miter".
-
-
For segmented lines, only "miter" joins and "linear" interpolation are
-currently supported. Any other value, including null, will disable joins,
-producing disjoint line segments. Note that the miter joins must be computed
-manually (at least in the current SVG renderer); since this calculation may
-be expensive and unnecessary for small lines, specifying null can improve
-performance significantly.
-
-
- The width of stroked lines, in pixels; used in conjunction with
-strokeStyle to stroke the line.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {boolean}
- segmented
-
-
-
- Whether the line is segmented; whether variations in stroke style, line width
-and the other properties are treated as fixed. Rendering segmented lines is
-noticeably slower than non-segmented lines.
-
-
- The tension of cardinal splines; used in conjunction with
-interpolate("cardinal"). A value between 0 and 1 draws cardinal splines with
-the given tension. In some sense, the tension can be interpreted as the
-"length" of the tangent; a tension of 1 will yield all zero tangents (i.e.,
-linear interpolation), and a tension of 0 yields a Catmull-Rom spline. The
-default value is 0.7.
-
-
- Constructs a new line anchor with default properties. Lines support five
-different anchors:
-
-
top
-
left
-
center
-
bottom
-
right
-
-
In addition to positioning properties (left, right, top bottom), the
-anchors support text rendering properties (text-align, text-baseline). Text is
-rendered to appear outside the line. Note that this behavior is different
-from other mark anchors, which default to rendering text inside the
-mark.
-
-
For consistency with the other mark types, the anchor positions are
-defined in terms of their opposite edge. For example, the top anchor defines
-the bottom property, such that a bar added to the top anchor grows upward.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {string}name
-
-
-
the anchor name; either a string or a property function.
-
-
-
- Represents a data-driven graphical mark. The Mark class is
-the base class for all graphical marks in Protovis; it does not provide any
-specific rendering functionality, but together with Panel establishes
-the core framework.
-
-
Concrete mark types include familiar visual elements such as bars, lines
-and labels. Although a bar mark may be used to construct a bar chart, marks
-know nothing about charts; it is only through their specification and
-composition that charts are produced. These building blocks permit many
-combinatorial possibilities.
-
-
Marks are associated with data: a mark is generated once per
-associated datum, mapping the datum to visual properties such as
-position and color. Thus, a single mark specification represents a set of
-visual elements that share the same data and visual encoding. The type of
-mark defines the names of properties and their meaning. A property may be
-static, ignoring the associated datum and returning a constant; or, it may be
-dynamic, derived from the associated datum or index. Such dynamic encodings
-can be specified succinctly using anonymous functions. Special properties
-called event handlers can be registered to add interactivity.
-
-
Protovis uses inheritance to simplify the specification of related
-marks: a new mark can be derived from an existing mark, inheriting its
-properties. The new mark can then override properties to specify new
-behavior, potentially in terms of the old behavior. In this way, the old mark
-serves as the prototype for the new mark. Most mark types share the
-same basic properties for consistency and to facilitate inheritance.
-
-
The prioritization of redundant properties is as follows:
-
-
If the width property is not specified (i.e., null), its value
-is the width of the parent panel, minus this mark's left and right margins;
-the left and right margins are zero if not specified.
-
-
Otherwise, if the right margin is not specified, its value is
-the width of the parent panel, minus this mark's width and left margin; the
-left margin is zero if not specified.
-
-
Otherwise, if the left property is not specified, its value is
-the width of the parent panel, minus this mark's width and the right margin.
-
-
This prioritization is then duplicated for the height,
-bottom and top properties, respectively.
-
-
While most properties are variable, some mark types, such as lines
-and areas, generate a single visual element rather than a distinct visual
-element per datum. With these marks, some properties may be fixed.
-Fixed properties can vary per mark, but not per datum! These
-properties are evaluated solely for the first (0-index) datum, and typically
-are specified as a constant. However, it is valid to use a function if the
-property varies between panels or is dynamically generated.
-
-
Renders this mark, including recursively rendering all child marks if this is
-a panel.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Class Detail
-
-
-
- pv.Mark()
-
-
-
- Constructs a new mark with default properties. Marks, with the exception of
-the root panel, are not typically constructed directly; instead, they are
-added to a panel or an existing mark via pv.Mark#add.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Field Detail
-
-
-
-
-
- {number}
- bottom
-
-
-
- The bottom margin; the distance, in pixels, between the bottom edge of the
-enclosing panel and the bottom edge of this mark. Note that in some cases
-this property may be redundant with the top property, or with the conjunction
-of top and height.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- childIndex
-
-
-
- The child index. -1 if the enclosing parent panel is null; otherwise, the
-zero-based index of this mark into the parent panel's children array.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- cursor
-
-
-
- The cursor property; corresponds to the CSS cursor property. This is
-typically used in conjunction with event handlers to indicate interactivity.
-
-
-
- The data property; an array of objects. The size of the array determines the
-number of marks that will be instantiated; each element in the array will be
-passed to property functions to compute the property values. Typically, the
-data property is specified as a constant array, such as
-
-
m.data([1, 2, 3, 4, 5]);
-
-However, it is perfectly acceptable to define the data property as a
-function. This function might compute the data dynamically, allowing
-different data to be used per enclosing panel. For instance, in the stacked
-area graph example (see #scene), the data function on the area mark
-dereferences each series.
-
-
-
- Default properties for all mark types. By default, the data array is the
-parent data as a single-element array; if the data property is not specified,
-this causes each mark to be instantiated as a singleton with the parents
-datum. The visible property is true by default, and the reverse property is
-false.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- events
-
-
-
- The events property; corresponds to the SVG pointer-events property,
-specifying how the mark should participate in mouse events. The default value
-is "painted". Supported values are:
-
-
"painted": The given mark may receive events when the mouse is over a
-"painted" area. The painted areas are the interior (i.e., fill) of the mark
-if a 'fillStyle' is specified, and the perimeter (i.e., stroke) of the mark
-if a 'strokeStyle' is specified.
-
-
"all": The given mark may receive events when the mouse is over either the
-interior (i.e., fill) or the perimeter (i.e., stroke) of the mark, regardless
-of the specified fillStyle and strokeStyle.
-
-
"none": The given mark may not receive events.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- index
-
-
-
- The mark index. The value of this field depends on which instance (i.e.,
-which element of the data array) is currently being evaluated. During the
-build phase, the index is incremented over each datum; when handling events,
-the index is set to the instance that triggered the event.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- left
-
-
-
- The left margin; the distance, in pixels, between the left edge of the
-enclosing panel and the left edge of this mark. Note that in some cases this
-property may be redundant with the right property, or with the conjunction of
-right and width.
-
-
-
- The enclosing parent panel. The parent panel is generally undefined only for
-the root panel; however, it is possible to create "offscreen" marks that are
-used only for inheritance purposes.
-
-
-
- The mark prototype, possibly undefined, from which to inherit property
-functions. The mark prototype is not necessarily of the same type as this
-mark. Any properties defined on this mark will override properties inherited
-either from the prototype or from the type-specific defaults.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {boolean}
- reverse
-
-
-
- The reverse property; a boolean determining whether marks are ordered from
-front-to-back or back-to-front. SVG does not support explicit z-ordering;
-shapes are rendered in the order they appear. Thus, by default, marks are
-rendered in data order. Setting the reverse property to false reverses the
-order in which they are rendered; however, the properties are still evaluated
-(i.e., built) in forward order.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- right
-
-
-
- The right margin; the distance, in pixels, between the right edge of the
-enclosing panel and the right edge of this mark. Note that in some cases this
-property may be redundant with the left property, or with the conjunction of
-left and width.
-
-
-
- The root parent panel. This may be undefined for "offscreen" marks that are
-created for inheritance purposes only.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- scale
-
-
-
- The current scale factor, based on any enclosing transforms. The current
-scale can be used to create scale-independent graphics. For example, to
-define a dot that has a radius of 10 irrespective of any zooming, say:
-
-
dot.radius(function() 10 / this.scale)
-
-Note that the stroke width and font size are defined irrespective of scale
-(i.e., in screen space) already. Also note that when a transform is applied
-to a panel, the scale affects only the child marks, not the panel itself.
-
-
-
- The title property; corresponds to the HTML/SVG title property, allowing the
-general of simple plain text tooltips.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- top
-
-
-
- The top margin; the distance, in pixels, between the top edge of the
-enclosing panel and the top edge of this mark. Note that in some cases this
-property may be redundant with the bottom property, or with the conjunction
-of bottom and height.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- type
-
-
-
- The mark type; a lower camelCase name. The type name controls rendering
-behavior, and unless the rendering engine is extended, must be one of the
-built-in concrete mark types: area, bar, dot, image, label, line, panel,
-rule, or wedge.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {boolean}
- visible
-
-
-
- The visible property; a boolean determining whether or not the mark instance
-is visible. If a mark instance is not visible, its other properties will not
-be evaluated. Similarly, for panels no child marks will be rendered.
-
-
-
- Adds a new mark of the specified type to the enclosing parent panel, whilst
-simultaneously setting the prototype of the new mark to be this mark.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {function}type
-
-
-
the type of mark to add; a constructor, such as
-pv.Bar.
- Returns an anchor with the specified name. All marks support the five
-standard anchor names:
-
-
top
-
left
-
center
-
bottom
-
right
-
-
In addition to positioning properties (left, right, top bottom), the
-anchors support text rendering properties (text-align, text-baseline). Text is
-rendered to appear inside the mark by default.
-
-
To facilitate stacking, anchors are defined in terms of their opposite
-edge. For example, the top anchor defines the bottom property, such that the
-mark extends upwards; the bottom anchor instead defines the top property,
-such that the mark extends downwards. See also pv.Layout.Stack.
-
-
While anchor names are typically constants, the anchor name is a true
-property, which means you can specify a function to compute the anchor name
-dynamically. See the pv.Anchor#name property for details.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {string}name
-
-
-
the anchor name; either a string or a property function.
- Returns the anchor target of this mark, if it is derived from an anchor;
-otherwise returns null. For example, if a label is derived from a bar anchor,
-
-
bar.anchor("top").add(pv.Label);
-
-then property functions on the label can refer to the bar via the
-anchorTarget method. This method is also useful for mark types
-defining properties on custom anchors.
-
-
-
-
-
-
-
-
-
-
-
-
-
Returns:
-
-
{pv.Mark} the anchor target of this mark; possibly null.
-
-
-
-
-
-
-
-
-
-
-
-
- def(name, v)
-
-
-
- Defines a custom property on this mark. Custom properties are currently
-fixed, in that they are initialized once per mark set (i.e., per parent panel
-instance). Custom properties can be used to store local state for the mark,
-such as data needed by other properties (e.g., a custom scale) or interaction
-state.
-
-
WARNING We plan on changing this feature in a future release to define
-standard properties, as opposed to fixed properties that behave
-idiosyncratically within event handlers. Furthermore, we recommend storing
-state in an external data structure, rather than tying it to the
-visualization specification as with defs.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {string}name
-
-
-
the name of the local variable.
-
-
- {function}v
- Optional
-
-
an optional initializer; may be a constant or a
-function.
- Registers an event handler for the specified event type with this mark. When
-an event of the specified type is triggered, the specified handler will be
-invoked. The handler is invoked in a similar method to property functions:
-the context is this mark instance, and the arguments are the full
-data stack. Event handlers can use property methods to manipulate the display
-properties of the mark:
-
-
-
-The return value of the event handler determines which mark gets re-rendered.
-Use defs (#def) to set temporary state from event handlers.
-
-
The complete set of event types is defined by SVG; see the reference
-below. The set of supported event types is:
-
-
click
-
mousedown
-
mouseup
-
mouseover
-
mousemove
-
mouseout
-
-
Since Protovis does not specify any concept of focus, it does not
-support key events; these should be handled outside the visualization using
-standard JavaScript. In the future, support for interaction may be extended
-to support additional event types, particularly those most relevant to
-interactive visualization, such as selection.
-
-
TODO In the current implementation, event handlers are not inherited from
-prototype marks. They must be defined explicitly on each interactive mark. In
-addition, only one event handler for a given event type can be defined; when
-specifying multiple event handlers for the same type, only the last one will
-be used.
-
-
-
- Sets the prototype of this mark to the specified mark. Any properties not
-defined on this mark may be inherited from the specified prototype mark, or
-its prototype, and so on. The prototype mark need not be the same type of
-mark as this mark. (Note that for inheritance to be useful, properties with
-the same name on different mark types should have equivalent meaning.)
-
-
-
- Returns the current location of the mouse (cursor) relative to this mark's
-parent. The x coordinate corresponds to the left margin, while the
-y coordinate corresponds to the top margin.
-
-
-
- Renders this mark, including recursively rendering all child marks if this is
-a panel. This method finds all instances of this mark and renders them. This
-method descends recursively to the level of the mark to be rendered, finding
-all visible instances of the mark. After the marks are rendered, the scene
-and index attributes are removed from the mark to restore them to a clean
-state.
-
-
If an enclosing panel has an index property set (as is the case inside in
-an event handler), then only instances of this mark inside the given instance
-of the panel will be rendered; otherwise, all visible instances of the mark
-will be rendered.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Documentation generated by JsDoc Toolkit 2.3.2 on Fri May 28 2010 10:13:29 GMT-0700 (PDT)
-
-
-
-
- Represents a Nest operator for the specified array. Nesting
-allows elements in an array to be grouped into a hierarchical tree
-structure. The levels in the tree are specified by key functions. The
-leaf nodes of the tree can be sorted by value, while the internal nodes can
-be sorted by key. Finally, the tree can be returned either has a
-multidimensional array via #entries, or as a hierarchical map via
-#map. The #rollup routine similarly returns a map, collapsing
-the elements in each leaf node using a summary function.
-
-
For example, consider the following tabular data structure of Barley
-yields, from various sites in Minnesota during 1931-2:
-
-
- Constructs a nest operator for the specified array. This constructor should
-not be invoked directly; use pv.nest instead.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {array}array
-
-
-
an array of elements to nest.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Method Detail
-
-
-
-
-
-
- entries()
-
-
-
- Returns a hierarchical nested array. This method is similar to
-pv.entries, but works recursively on the entire hierarchy. Rather
-than returning a map like #map, this method returns a nested
-array. Each element of the array has a key and values
-field. For leaf nodes, the values array will be a subset of the
-underlying elements array; for non-leaf nodes, the values array will
-contain more key-values pairs.
-
-
For an example usage, see the Nest constructor.
-
-
-
- Nests using the specified key function. Multiple keys may be added to the
-nest; the array elements will be nested in the order keys are specified.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {function}key
-
-
-
a key function; must return a string or suitable map
-key.
- Returns a hierarchical map of values. Each key adds one level to the
-hierarchy. With only a single key, the returned map will have a key for each
-distinct value of the key function; the correspond value with be an array of
-elements with that key value. If a second key is added, this will be a nested
-map. For example:
-
-
-
-returns a map m such that m[variety][site] is an array, a subset of
-yields, with each element having the given variety and site.
-
-
-
-
-
-
-
-
-
-
-
-
-
Returns:
-
-
a hierarchical map of values.
-
-
-
-
-
-
-
-
-
-
-
-
- rollup(f)
-
-
-
- Returns a rollup map. The behavior of this method is the same as
-#map, except that the leaf values are replaced with the return value
-of the specified rollup function f. For example,
-
-
- Sorts the previously-added keys. The natural sort order is used by default
-(see pv.naturalOrder); if an alternative order is desired,
-order should be a comparator function. If this method is not called
-(i.e., keys are unsorted), keys will appear in the order they appear
-in the underlying elements array. For example,
-
-
-
-groups yield data by year, then variety, and sorts the variety groups
-lexicographically (since the variety attribute is a string).
-
-
Key sort order is only used in conjunction with #entries, which
-returns an array of key-values pairs. If the nest is used to construct a
-#map instead, keys are unsorted.
-
-
-
- Sorts the leaf values. The natural sort order is used by default (see
-pv.naturalOrder); if an alternative order is desired, order
-should be a comparator function. If this method is not called (i.e., values
-are unsorted), values will appear in the order they appear in the
-underlying elements array. For example,
-
-
-
- Extends
- pv.Bar.
-
-
- Represents a container mark. Panels allow repeated or nested
-structures, commonly used in small multiple displays where a small
-visualization is tiled to facilitate comparison across one or more
-dimensions. Other types of visualizations may benefit from repeated and
-possibly overlapping structure as well, such as stacked area charts. Panels
-can also offset the position of marks to provide padding from surrounding
-content.
-
-
All Protovis displays have at least one panel; this is the root panel to
-which marks are rendered. The box model properties (four margins, width and
-height) are used to offset the positions of contained marks. The data
-property determines the panel count: a panel is generated once per associated
-datum. When nested panels are used, property functions can declare additional
-arguments to access the data associated with enclosing panels.
-
-
Panels can be rendered inline, facilitating the creation of sparklines.
-This allows designers to reuse browser layout features, such as text flow and
-tables; designers can also overlay HTML elements such as rich text and
-images.
-
-
All panels have a children array (possibly empty) containing the
-child marks in the order they were added. Panels also have a root
-field which points to the root (outermost) panel; the root panel's root field
-points to itself.
-
-
- Constructs a new, empty panel with default properties. Panels, with the
-exception of the root panel, are not typically constructed directly; instead,
-they are added to an existing panel or mark via pv.Mark#add.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Field Detail
-
-
-
-
-
- {string}
- canvas
-
-
-
- The canvas element; either the string ID of the canvas element in the current
-document, or a reference to the canvas element itself. If null, a canvas
-element will be created and inserted into the document at the location of the
-script element containing the current Protovis specification. This property
-only applies to root panels and is ignored on nested panels.
-
-
Note: the "canvas" element here refers to a div (or other suitable
-HTML container element), not a canvas element. The name of
-this property is a historical anachronism from the first implementation that
-used HTML 5 canvas, rather than SVG.
-
-
-
- The transform to be applied to child marks. The default transform is
-identity, which has no effect. Note that the panel's own fill and stroke are
-not affected by the transform, and panel's transform only affects the
-scale of child marks, not the panel itself.
-
-
-
- Adds a new mark of the specified type to this panel. Unlike the normal
-Mark#add behavior, adding a mark to a panel does not cause the mark
-to inherit from the panel. Since the contained marks are offset by the panel
-margins already, inheriting properties is generally undesirable; of course,
-it is always possible to change this behavior by calling Mark#extend
-explicitly.
-
-
-
- Returns an anchor with the specified name. This method is overridden such
-that adding to a panel's anchor adds to the panel, rather than to the panel's
-parent.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {string}name
-
-
-
the anchor name; either a string or a property function.
- Abstract; not implemented. There is no explicit constructor; this class
-merely serves to document the attributes that are used on particles in
-physics simulations.
-
-
- The child node for the fourth quadrant, if any.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {boolean}
- leaf
-
-
-
- True if this node is a leaf node; i.e., it has no children. Note that both
-leaf nodes and non-leaf (internal) nodes may have associated particles. If
-this is a non-leaf node, then at least one of #c1, #c2,
-#c3 or #c4 is guaranteed to be non-null.
-
-
-
-
-
-
- Represents a quadtree: a two-dimensional recursive spatial
-subdivision. This particular implementation uses square partitions, dividing
-each square into four equally-sized squares. Each particle exists in a unique
-node; if multiple particles are in the same position, some particles may be
-stored on internal nodes rather than leaf nodes.
-
-
This quadtree can be used to accelerate various spatial operations, such
-as the Barnes-Hut approximation for computing n-body forces, or collision
-detection.
-
-
- Defined in: Quadtree.js.
-
-
-
- Extends
- pv.Mark.
-
-
- Represents a horizontal or vertical rule. Rules are frequently used
-for axes and grid lines. For example, specifying only the bottom property
-draws horizontal rules, while specifying only the left draws vertical
-rules. Rules can also be used as thin bars. The visual style is controlled in
-the same manner as lines.
-
-
Rules are positioned exclusively the standard box model properties. The
-following combinations of properties are supported:
-
-
-
Properties
Orientation
-
-
left
vertical
-
right
vertical
-
left, bottom, top
vertical
-
right, bottom, top
vertical
-
top
horizontal
-
bottom
horizontal
-
top, left, right
horizontal
-
bottom, left, right
horizontal
-
left, top, height
vertical
-
left, bottom, height
vertical
-
right, top, height
vertical
-
right, bottom, height
vertical
-
left, top, width
horizontal
-
left, bottom, width
horizontal
-
right, top, width
horizontal
-
right, bottom, width
horizontal
-
-
-
-
Small rules can be used as tick marks; alternatively, a Dot with
-the "tick" shape can be used.
-
-
- Constructs a new rule with default properties. Rules are not typically
-constructed directly, but by adding to a panel or an existing mark via
-pv.Mark#add.
-
-
- Constructs a new rule anchor with default properties. Rules support five
-different anchors:
-
-
top
-
left
-
center
-
bottom
-
right
-
-
In addition to positioning properties (left, right, top bottom), the
-anchors support text rendering properties (text-align, text-baseline). Text is
-rendered to appear outside the rule. Note that this behavior is different
-from other mark anchors, which default to rendering text inside the
-mark.
-
-
For consistency with the other mark types, the anchor positions are
-defined in terms of their opposite edge. For example, the top anchor defines
-the bottom property, such that a bar added to the top anchor grows upward.
-
-
-
- Default properties for rules. By default, a single-pixel black line is
-stroked.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- height
-
-
-
- The height of the rule, in pixels. If the bottom position is specified, the
-rule extends upward from the bottom edge; if the top position is specified,
-the rule extends downward from the top edge.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- lineWidth
-
-
-
- The width of stroked lines, in pixels; used in conjunction with
-strokeStyle to stroke the rule. The default value is 1 pixel.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- strokeStyle
-
-
-
- The style of stroked lines; used in conjunction with lineWidth to
-stroke the rule. The default value of this property is black.
-
-
-
- The width of the rule, in pixels. If the left position is specified, the rule
-extends rightward from the left edge; if the right position is specified, the
-rule extends leftward from the right edge.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Documentation generated by JsDoc Toolkit 2.3.2 on Fri May 28 2010 10:13:29 GMT-0700 (PDT)
-
-
- Extends
- function.
-
-
- Represents a scale; a function that performs a transformation from
-data domain to visual range. For quantitative and quantile scales, the domain
-is expressed as numbers; for ordinal scales, the domain is expressed as
-strings (or equivalently objects with unique string representations). The
-"visual range" may correspond to pixel space, colors, font sizes, and the
-like.
-
-
Note that scales are functions, and thus can be used as properties
-directly, assuming that the data associated with a mark is a number. While
-this is convenient for single-use scales, frequently it is desirable to
-define scales globally:
-
-
var y = pv.Scale.linear(0, 100).range(0, 640);
-
-The y scale can now be equivalently referenced within a property:
-
-
.height(function(d) y(d))
-
-Alternatively, if the data are not simple numbers, the appropriate value can
-be passed to the y scale (e.g., d.foo). The #by
-method similarly allows the data to be mapped to a numeric value before
-performing the linear transformation.
-
-
- Defined in: Scale.js.
-
-
-
-
-
-
- Returns a view of this scale by the specified accessor function f.
-Given a scale y, y.by(function(d) d.foo) is equivalent to
-function(d) y(d.foo).
-
-
This method is provided for convenience, such that scales can be
-succinctly defined inline. For example, given an array of data elements that
-have a score attribute with the domain [0, 1], the height property
-could be specified as:
-
-
-
- Extends
- pv.Scale.quantitative.
-
-
- Represents a linear scale; a function that performs a linear
-transformation. Most
-commonly, a linear scale represents a 1-dimensional linear transformation
-from a numeric domain of input data [d0,
-d1] to a numeric range of pixels [r0,
-r1]. The equation for such a scale is:
-
-
f(x) = (x - d0) / (d1 - d0) *
-(r1 - r0) + r0
-
-For example, a linear scale from the domain [0, 100] to range [0, 640]:
-
-
-
-Note that the scale is itself a function, and thus can be used as a property
-directly, assuming that the data associated with a mark is a number. While
-this is convenient for single-use scales, frequently it is desirable to
-define scales globally:
-
-
var y = pv.Scale.linear(0, 100).range(0, 640);
-
-The y scale can now be equivalently referenced within a property:
-
-
.height(function(d) y(d))
-
-Alternatively, if the data are not simple numbers, the appropriate value can
-be passed to the y scale (e.g., d.foo). The #by
-method similarly allows the data to be mapped to a numeric value before
-performing the linear transformation.
-
-
- Defined in: LinearScale.js.
-
-
-
-
-
-
- Returns a linear scale for the specified domain. The arguments to this
-constructor are optional, and equivalent to calling #domain.
-The default domain and range are [0,1].
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {number...}domain...
-
-
-
optional domain values.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Documentation generated by JsDoc Toolkit 2.3.2 on Fri May 28 2010 10:13:29 GMT-0700 (PDT)
-
-
- Extends
- pv.Scale.quantitative.
-
-
- Represents a log scale. Most commonly, a log scale
-represents a 1-dimensional log transformation from a numeric domain of input
-data [d0, d1] to a numeric range of
-pixels [r0, r1]. The equation for such a
-scale is:
-
-
-
-where log(x) represents the zero-symmetric logarthim of x using
-the scale's associated base (default: 10, see pv.logSymmetric). For
-example, a log scale from the domain [1, 100] to range [0, 640]:
-
-
-
-Note that the scale is itself a function, and thus can be used as a property
-directly, assuming that the data associated with a mark is a number. While
-this is convenient for single-use scales, frequently it is desirable to
-define scales globally:
-
-
var y = pv.Scale.log(1, 100).range(0, 640);
-
-The y scale can now be equivalently referenced within a property:
-
-
.height(function(d) y(d))
-
-Alternatively, if the data are not simple numbers, the appropriate value can
-be passed to the y scale (e.g., d.foo). The #by
-method similarly allows the data to be mapped to a numeric value before
-performing the log transformation.
-
-
- Defined in: LogScale.js.
-
-
-
-
-
-
- Returns a log scale for the specified domain. The arguments to this
-constructor are optional, and equivalent to calling #domain.
-The default domain is [1,10] and the default range is [0,1].
-
-
- "Nices" this scale, extending the bounds of the input domain to
-evenly-rounded values. This method uses pv.logFloor and
-pv.logCeil. Nicing is useful if the domain is computed dynamically
-from data, and may be irregular. For example, given a domain of
-[0.20147987687960267, 0.996679553296417], a call to nice() might
-extend the domain to [0.1, 1].
-
-
This method must be invoked each time after setting the domain (and
-base).
-
-
-
- Formats the specified tick value using the appropriate precision, assuming
-base 10.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {number}t
-
-
-
a tick value.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{string} a formatted tick value.
-
-
-
-
-
-
-
-
-
-
-
- {number[]}
- ticks()
-
-
-
- Returns an array of evenly-spaced, suitably-rounded values in the input
-domain. These values are frequently used in conjunction with
-pv.Rule to display tick marks or grid lines.
-
-
-
-
-
-
-
-
-
-
-
-
-
Returns:
-
-
{number[]} an array input domain values to use as ticks.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Documentation generated by JsDoc Toolkit 2.3.2 on Fri May 28 2010 10:13:29 GMT-0700 (PDT)
-
-
- Extends
- pv.Scale.
-
-
- Represents an ordinal scale. An ordinal scale represents a
-pairwise mapping from n discrete values in the input domain to
-n discrete values in the output range. For example, an ordinal scale
-might map a domain of species ["setosa", "versicolor", "virginica"] to colors
-["red", "green", "blue"]. Thus, saying
-
-
.fillStyle(function(d) {
- switch (d.species) {
- case "setosa": return "red";
- case "versicolor": return "green";
- case "virginica": return "blue";
- }
- })
-
-If the mapping from species to color does not need to be specified
-explicitly, the domain can be omitted. In this case it will be inferred
-lazily from the data:
-
-
-
-When the domain is inferred, the first time the scale is invoked, the first
-element from the range will be returned. Subsequent calls with unique values
-will return subsequent elements from the range. If the inferred domain grows
-larger than the range, range values will be reused. However, it is strongly
-recommended that the domain and the range contain the same number of
-elements.
-
-
A range can be discretized from a continuous interval (e.g., for pixel
-positioning) by using #split, #splitFlush or
-#splitBanded after the domain has been set. For example, if
-states is an array of the fifty U.S. state names, the state name can
-be encoded in the left position:
-
-
N.B.: ordinal scales are not invertible (at least not yet), since the
-domain and range and discontinuous. A workaround is to use a linear scale.
-
-
- Defined in: OrdinalScale.js.
-
-
- Returns a view of this scale by the specified accessor function f.
-Given a scale y, y.by(function(d) d.foo) is equivalent to
-function(d) y(d.foo). This method should be used judiciously; it
-is typically more clear to invoke the scale directly, passing in the value
-to be scaled.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {function}f
-
-
-
an accessor function.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{pv.Scale.ordinal} a view of this scale by the specified accessor
-function.
- Sets or gets the input domain. This method can be invoked several ways:
-
-
1. domain(values...)
-
-
Specifying the domain as a series of values is the most explicit and
-recommended approach. However, if the domain values are derived from data,
-you may find the second method more appropriate.
-
-
2. domain(array, f)
-
-
Rather than enumerating the domain values as explicit arguments to this
-method, you can specify a single argument of an array. In addition, you can
-specify an optional accessor function to extract the domain values from the
-array.
-
-
3. domain()
-
-
Invoking the domain method with no arguments returns the
-current domain as an array.
-
-
-
- Sets or gets the output range. This method can be invoked several ways:
-
-
1. range(values...)
-
-
Specifying the range as a series of values is the most explicit and
-recommended approach. However, if the range values are derived from data,
-you may find the second method more appropriate.
-
-
2. range(array, f)
-
-
Rather than enumerating the range values as explicit arguments to this
-method, you can specify a single argument of an array. In addition, you can
-specify an optional accessor function to extract the range values from the
-array.
-
-
3. range()
-
-
Invoking the range method with no arguments returns the
-current range as an array.
-
-
-
- Sets the range from the given continuous interval. The interval
-[min, max] is subdivided into n equispaced points,
-where n is the number of (unique) values in the domain. The first
-and last point are offset from the edge of the range by half the distance
-between points.
-
-
This method must be called after the domain is set.
-
-
-
- Sets the range from the given continuous interval. The interval
-[min, max] is subdivided into n equispaced bands,
-where n is the number of (unique) values in the domain. The first
-and last band are offset from the edge of the range by the distance between
-bands.
-
-
The band width argument, band, is typically in the range [0, 1]
-and defaults to 1. This fraction corresponds to the amount of space in the
-range to allocate to the bands, as opposed to padding. A value of 0.5 means
-that the band width will be equal to the padding width. The computed
-absolute band width can be retrieved from the range as
-scale.range().band.
-
-
If the band width argument is negative, this method will allocate bands
-of a fixed width -band, rather than a relative fraction of
-the available space.
-
-
Tip: to inset the bands by a fixed amount p, specify a minimum
-value of min + p (or simply p, if min is
-0). Then set the mark width to scale.range().band - p.
-
-
This method must be called after the domain is set.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {number}min
-
-
-
minimum value of the output range.
-
-
- {number}max
-
-
-
maximum value of the output range.
-
-
- {number}band
- Optional
-
-
the fractional band width in [0, 1]; defaults to 1.
- Sets the range from the given continuous interval. The interval
-[min, max] is subdivided into n equispaced points,
-where n is the number of (unique) values in the domain. The first
-and last point are exactly on the edge of the range.
-
-
This method must be called after the domain is set.
-
-
-
-
- Extends
- pv.Scale.
-
-
- Represents a quantile scale; a function that maps from a value within
-a sortable domain to a quantized numeric range. Typically, the domain is a
-set of numbers, but any sortable value (such as strings) can be used as the
-domain of a quantile scale. The range defaults to [0,1], with 0 corresponding
-to the smallest value in the domain, 1 the largest, .5 the median, etc.
-
-
By default, the number of quantiles in the range corresponds to the number
-of values in the domain. The #quantiles method can be used to specify
-an explicit number of quantiles; for example, quantiles(4) produces
-a standard quartile scale. A quartile scale's range is a set of four discrete
-values, such as [0, 1/3, 2/3, 1]. Calling the #range method will
-scale these discrete values accordingly, similar to {@link
-pv.Scale.ordinal#splitFlush}.
-
-
For example, given the strings ["c", "a", "b"], a default quantile scale:
-
-
pv.Scale.quantile("c", "a", "b")
-
-will return 0 for "a", .5 for "b", and 1 for "c".
-
-
- Defined in: QuantileScale.js.
-
-
-
-
-
-
- Constructs a default quantile scale. The arguments to this constructor are
-optional, and equivalent to calling #domain. The default domain is
-the empty set, and the default range is [0,1].
-
-
- Returns a view of this scale by the specified accessor function f.
-Given a scale y, y.by(function(d) d.foo) is equivalent to
-function(d) y(d.foo).
-
-
This method is provided for convenience, such that scales can be
-succinctly defined inline. For example, given an array of data elements
-that have a score attribute with the domain [0, 1], the height
-property could be specified as:
-
-
- Sets or gets the input domain. This method can be invoked several ways:
-
-
1. domain(values...)
-
-
Specifying the domain as a series of values is the most explicit and
-recommended approach. However, if the domain values are derived from data,
-you may find the second method more appropriate.
-
-
2. domain(array, f)
-
-
Rather than enumerating the domain values as explicit arguments to this
-method, you can specify a single argument of an array. In addition, you can
-specify an optional accessor function to extract the domain values from the
-array.
-
-
3. domain()
-
-
Invoking the domain method with no arguments returns the
-current domain as an array.
-
-
-
- Sets or gets the quantile boundaries. By default, each element in the
-domain is in its own quantile. If the argument to this method is a number,
-it specifies the number of equal-sized quantiles by which to divide the
-domain.
-
-
If no arguments are specified, this method returns the quantile
-boundaries; the first element is always the minimum value of the domain,
-and the last element is the maximum value of the domain. Thus, the length
-of the returned array is always one greater than the number of quantiles.
-
-
-
- Sets or gets the output range. This method can be invoked several ways:
-
-
1. range(min, ..., max)
-
-
The range may be specified as a series of numbers or colors. Most
-commonly, two numbers are specified: the minimum and maximum pixel values.
-For a color scale, values may be specified as pv.Colors or
-equivalent strings. For a diverging scale, or other subdivided non-uniform
-scales, multiple values can be specified. For example:
-
-
.range("red", "white", "green")
-
-
Currently, only numbers and colors are supported as range values. The
-number of range values must exactly match the number of domain values, or
-the behavior of the scale is undefined.
-
-
2. range()
-
-
Invoking the range method with no arguments returns the current
-range as an array of numbers or colors.
-
-
-
-
- Extends
- pv.Scale.
-
-
- Represents an abstract quantitative scale; a function that performs a
-numeric transformation. This class is typically not used directly; see one of
-the quantitative scale implementations (linear, log, root, etc.)
-instead. A quantitative
-scale represents a 1-dimensional transformation from a numeric domain of
-input data [d0, d1] to a numeric range of
-pixels [r0, r1]. In addition to
-readability, scales offer several useful features:
-
-
1. The range can be expressed in colors, rather than pixels. For example:
-
-
-
-will fill the marks "red" on an input value of 0, "green" on an input value
-of 100, and some color in-between for intermediate values.
-
-
2. The domain and range can be subdivided for a non-uniform
-transformation. For example, you may want a diverging color scale that is
-increasingly red for negative values, and increasingly green for positive
-values:
-
-
-
-The domain can be specified as a series of n monotonically-increasing
-values; the range must also be specified as n values, resulting in
-n - 1 contiguous linear scales.
-
-
3. Quantitative scales can be inverted for interaction. The
-#invert method takes a value in the output range, and returns the
-corresponding value in the input domain. This is frequently used to convert
-the mouse location (see pv.Mark#mouse) to a value in the input
-domain. Note that inversion is only supported for numeric ranges, and not
-colors.
-
-
4. A scale can be queried for reasonable "tick" values. The #ticks
-method provides a convenient way to get a series of evenly-spaced rounded
-values in the input domain. Frequently these are used in conjunction with
-pv.Rule to display tick marks or grid lines.
-
-
5. A scale can be "niced" to extend the domain to suitable rounded
-numbers. If the minimum and maximum of the domain are messy because they are
-derived from data, you can use #nice to round these values down and
-up to even numbers.
-
-
- Defined in: QuantitativeScale.js.
-
-
Returns an array of evenly-spaced, suitably-rounded values in the input
-domain.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Class Detail
-
-
-
- pv.Scale.quantitative()
-
-
-
- Returns a default quantitative, linear, scale for the specified domain. The
-arguments to this constructor are optional, and equivalent to calling
-#domain. The default domain and range are [0,1].
-
-
This constructor is typically not used directly; see one of the
-quantitative scale implementations instead.
-
-
- Returns a view of this scale by the specified accessor function f.
-Given a scale y, y.by(function(d) d.foo) is equivalent to
-function(d) y(d.foo).
-
-
This method is provided for convenience, such that scales can be
-succinctly defined inline. For example, given an array of data elements
-that have a score attribute with the domain [0, 1], the height
-property could be specified as:
-
-
- Sets or gets the input domain. This method can be invoked several ways:
-
-
1. domain(min, ..., max)
-
-
Specifying the domain as a series of numbers is the most explicit and
-recommended approach. Most commonly, two numbers are specified: the minimum
-and maximum value. However, for a diverging scale, or other subdivided
-non-uniform scales, multiple values can be specified. Values can be derived
-from data using pv.min and pv.max. For example:
-
-
.domain(0, pv.max(array))
-
-An alternative method for deriving minimum and maximum values from data
-follows.
-
-
2. domain(array, minf, maxf)
-
-
When both the minimum and maximum value are derived from data, the
-arguments to the domain method can be specified as the array of
-data, followed by zero, one or two accessor functions. For example, if the
-array of data is just an array of numbers:
-
-
.domain(array)
-
-On the other hand, if the array elements are objects representing stock
-values per day, and the domain should consider the stock's daily low and
-daily high:
-
-
-
-The first method of setting the domain is preferred because it is more
-explicit; setting the domain using this second method should be used only
-if brevity is required.
-
-
3. domain()
-
-
Invoking the domain method with no arguments returns the
-current domain as an array of numbers.
-
-
-
- Inverts the specified value in the output range, returning the
-corresponding value in the input domain. This is frequently used to convert
-the mouse location (see pv.Mark#mouse) to a value in the input
-domain. Inversion is only supported for numeric ranges, and not colors.
-
-
Note that this method does not do any rounding or bounds checking. If
-the input domain is discrete (e.g., an array index), the returned value
-should be rounded. If the specified y value is outside the range,
-the returned value may be equivalently outside the input domain.
-
-
-
- "Nices" this scale, extending the bounds of the input domain to
-evenly-rounded values. Nicing is useful if the domain is computed
-dynamically from data, and may be irregular. For example, given a domain of
-[0.20147987687960267, 0.996679553296417], a call to nice() might
-extend the domain to [0.2, 1].
-
-
This method must be invoked each time after setting the domain.
-
-
-
- Sets or gets the output range. This method can be invoked several ways:
-
-
1. range(min, ..., max)
-
-
The range may be specified as a series of numbers or colors. Most
-commonly, two numbers are specified: the minimum and maximum pixel values.
-For a color scale, values may be specified as pv.Colors or
-equivalent strings. For a diverging scale, or other subdivided non-uniform
-scales, multiple values can be specified. For example:
-
-
.range("red", "white", "green")
-
-
Currently, only numbers and colors are supported as range values. The
-number of range values must exactly match the number of domain values, or
-the behavior of the scale is undefined.
-
-
2. range()
-
-
Invoking the range method with no arguments returns the current
-range as an array of numbers or colors.
-
-
-
- Formats the specified tick value using the appropriate precision, based on
-the step interval between tick marks. If #ticks has not been called,
-the argument is converted to a string, but no formatting is applied.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {number}t
-
-
-
a tick value.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{string} a formatted tick value.
-
-
-
-
-
-
-
-
-
-
-
- {number[]}
- ticks(m)
-
-
-
- Returns an array of evenly-spaced, suitably-rounded values in the input
-domain. This method attempts to return between 5 and 10 tick values. These
-values are frequently used in conjunction with pv.Rule to display
-tick marks or grid lines.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {number}m
- Optional
-
-
optional number of desired ticks.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{number[]} an array input domain values to use as ticks.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Documentation generated by JsDoc Toolkit 2.3.2 on Fri May 28 2010 10:13:29 GMT-0700 (PDT)
-
-
- Extends
- pv.Scale.quantitative.
-
-
- Represents a root scale; a function that performs a power
-transformation. Most
-commonly, a root scale represents a 1-dimensional root transformation from a
-numeric domain of input data [d0, d1] to
-a numeric range of pixels [r0, r1].
-
-
Note that the scale is itself a function, and thus can be used as a
-property directly, assuming that the data associated with a mark is a
-number. While this is convenient for single-use scales, frequently it is
-desirable to define scales globally:
-
-
var y = pv.Scale.root(0, 100).range(0, 640);
-
-The y scale can now be equivalently referenced within a property:
-
-
.height(function(d) y(d))
-
-Alternatively, if the data are not simple numbers, the appropriate value can
-be passed to the y scale (e.g., d.foo). The #by
-method similarly allows the data to be mapped to a numeric value before
-performing the root transformation.
-
-
- Defined in: RootScale.js.
-
-
-
-
-
-
- Returns a root scale for the specified domain. The arguments to this
-constructor are optional, and equivalent to calling #domain.
-The default domain and range are [0,1].
-
-
-
-
-
- Represents a particle simulation. Particles are massive points in
-two-dimensional space. Forces can be applied to these particles, causing them
-to move. Constraints can also be applied to restrict particle movement, for
-example, constraining particles to a fixed position, or simulating collision
-between circular particles with area.
-
-
The simulation uses Position Verlet
-integration, due to the ease with which geometric constraints can be
-implemented. For each time step, Verlet integration is performed, new forces
-are accumulated, and then constraints are applied.
-
-
The simulation makes two simplifying assumptions: all particles are
-equal-mass, and the time step of the simulation is fixed. It would be easy to
-incorporate variable-mass particles as a future enhancement. Variable time
-steps are also possible, but are likely to introduce instability in the
-simulation.
-
-
This class can be used directly to simulate particle interaction.
-Alternatively, for network diagrams, see pv.Layout.Force.
-
-
- Defined in: Simulation.js.
-
-
-
-
-
- Represents a transformation matrix. The transformation matrix is
-limited to expressing translate and uniform scale transforms only; shearing,
-rotation, general affine, and other transforms are not supported.
-
-
The methods on this class treat the transform as immutable, returning a
-copy of the transformation matrix with the specified transform applied. Note,
-alternatively, that the matrix fields can be get and set directly.
-
-
- Defined in: Transform.js.
-
-
-
-
-
- Represents a tree operator for the specified array. The tree operator
-allows a hierarchical map to be constructed from an array; it is similar to
-the pv.Nest operator, except the hierarchy is derived dynamically
-from the array elements.
-
-
For example, given an array of size information for ActionScript classes:
-
-
-
-For visualizations with large data sets, performance improvements may be seen
-by storing the data in a tree format, and then flattening it into an array at
-runtime with pv.Flatten.
-
-
- Defined in: Tree.js.
-
-
-
-
-
-
- Assigns a keys function to this operator; required. The keys function
-returns an array of strings for each element in the associated
-array; these keys determine how the elements are nested in the tree. The
-returned keys should be unique for each element in the array; otherwise, the
-behavior of this operator is undefined.
-
-
-
- Returns a hierarchical map of values. The hierarchy is determined by the keys
-function; the values in the map are determined by the value function.
-
-
-
- Assigns a value function to this operator; optional. The value
-function specifies an optional transformation of the element in the array
-before it is inserted into the map. If no value function is specified, it is
-equivalent to using the identity function.
-
-
-
-
-
-
- Represents a two-dimensional vector; a 2-tuple ⟨x,
-y⟩. The intent of this class is to simplify vector math. Note that
-in performance-sensitive cases it may be more efficient to represent 2D
-vectors as simple objects with x and y attributes, rather
-than using instances of this class.
-
-
- Defined in: Vector.js.
-
-
Returns a scaled copy of this vector: ⟨x * k, y * k⟩.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Class Detail
-
-
-
- pv.Vector(x, y)
-
-
-
- Constructs a pv.Vector for the specified x and y
-coordinate. This constructor should not be invoked directly; use
-pv.vector instead.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {number}x
-
-
-
the x coordinate.
-
-
- {number}y
-
-
-
the y coordinate.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Method Detail
-
-
-
-
-
- {number}
- dot(x, y)
-
-
-
- Returns the dot product of this vector and the vector v: x * v.x +
-y * v.y. If only one argument is specified, it is interpreted as the
-vector v.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {number}x
-
-
-
the x coordinate to dot.
-
-
- {number}y
-
-
-
the y coordinate to dot.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{number} a dot product.
-
-
-
-
-
-
-
-
-
-
-
- {number}
- length()
-
-
-
- Returns the magnitude of this vector, defined as sqrt(x * x + y * y).
-
-
-
- Returns a normalized copy of this vector: a vector with the same direction,
-but unit length. If this vector has zero length this method returns a copy of
-this vector.
-
-
-
-
- Extends
- pv.Mark.
-
-
- Represents a wedge, or pie slice. Specified in terms of start and end
-angle, inner and outer radius, wedges can be used to construct donut charts
-and polar bar charts as well. If the #angle property is used, the end
-angle is implied by adding this value to start angle. By default, the start
-angle is the previously-generated wedge's end angle. This design allows
-explicit control over the wedge placement if desired, while offering
-convenient defaults for the construction of radial graphs.
-
-
The center point of the circle is positioned using the standard box model.
-The wedge can be stroked and filled, similar to pv.Bar.
-
-
- Constructs a new wedge with default properties. Wedges are not typically
-constructed directly, but by adding to a panel or an existing mark via
-pv.Mark#add.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Field Detail
-
-
-
-
-
- {number}
- angle
-
-
-
- The angular span of the wedge, in radians. This property is used if end angle
-is not specified.
-
-
-
- Default properties for wedges. By default, there is no stroke and the fill
-style is a categorical color.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- endAngle
-
-
-
- The end angle of the wedge, in radians. If not specified, the end angle is
-implied as the start angle plus the #angle.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- fillStyle
-
-
-
- The wedge fill style; if non-null, the interior of the wedge is filled with
-the specified color. The default value of this property is a categorical
-color.
-
-
-
- The inner radius of the wedge, in pixels. The default value of this property
-is zero; a positive value will produce a donut slice rather than a pie slice.
-The inner radius can vary per-wedge.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- lineWidth
-
-
-
- The width of stroked lines, in pixels; used in conjunction with
-strokeStyle to stroke the wedge's border.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- outerRadius
-
-
-
- The outer radius of the wedge, in pixels. This property is required. For
-pies, only this radius is required; for donuts, the inner radius must be
-specified as well. The outer radius can vary per-wedge.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {number}
- startAngle
-
-
-
- The start angle of the wedge, in radians. The start angle is measured
-clockwise from the 3 o'clock position. The default value of this property is
-the end angle of the previous instance (the Mark#sibling), or -PI / 2
-for the first wedge; for pie and donut charts, typically only the
-#angle property needs to be specified.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {string}
- strokeStyle
-
-
-
- The style of stroked lines; used in conjunction with lineWidth to
-stroke the wedge's border. The default value of this property is null,
-meaning wedges are not stroked by default.
-
-
-
- Constructs a new wedge anchor with default properties. Wedges support five
-different anchors:
-
-
outer
-
inner
-
center
-
start
-
end
-
-
In addition to positioning properties (left, right, top bottom), the
-anchors support text rendering properties (text-align, text-baseline,
-textAngle). Text is rendered to appear inside the wedge.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {string}name
-
-
-
the anchor name; either a string or a property function.
- Returns true if the specified angle is considered "upright", as in, text
-rendered at that angle would appear upright. If the angle is not upright,
-text is rotated 180 degrees to be upright, and the text alignment properties
-are correspondingly changed.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {number}angle
-
-
-
an angle, in radius.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{boolean} true if the specified angle is upright.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Documentation generated by JsDoc Toolkit 2.3.2 on Fri May 28 2010 10:13:30 GMT-0700 (PDT)
-
-
- Extends
- array.
-
-
- Represents a bin returned by the pv.histogram operator. Bins
-are themselves arrays containing the data elements present in the given bin
-(prior to the accessor function being invoked to convert the data object to a
-numeric value). These bin arrays have additional attributes with meta
-information about the bin.
-
-
- Defined in: Histogram.js.
-
-
Sets or gets whether this histogram operator returns frequencies or
-probabilities.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Class Detail
-
-
-
- pv.histogram(data, f)
-
-
-
- Returns a histogram operator for the specified data, with an optional
-accessor function. If the data specified is not an array of numbers, an
-accessor function must be specified to map the data to numeric values.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {array}data
-
-
-
an array of numbers or objects.
-
-
- {function}f
- Optional
-
-
an optional accessor function.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Method Detail
-
-
-
-
-
- {array}
- bins(ticks)
-
-
-
- Returns the computed histogram bins. An optional array of numbers,
-ticks, may be specified as the break points. If the ticks are
-not specified, default ticks will be computed using a linear scale on the
-data domain.
-
-
The returned array contains pv.histogram.Bins. The x
-attribute corresponds to the bin's start value (inclusive), while the
-dx attribute stores the bin size (end - start). The y
-attribute stores either the frequency count or probability, depending on
-how the histogram operator has been configured.
-
-
The pv.histogram.Bin objects are themselves arrays, containing
-the data elements present in each bin, i.e., the elements in the
-data array (prior to invoking the accessor function, if any).
-For example, if the data represented countries, and the accessor function
-returned the GDP of each country, the returned bins would be arrays of
-countries (not GDPs).
-
-
-
Returns a pv.Vector for the specified x and y
-coordinate.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Namespace Detail
-
-
-
- pv
-
-
-
- The top-level Protovis namespace. All public methods and fields should be
-registered on this object. Note that core Protovis source is surrounded by an
-anonymous function, so any other declared globals will not be visible outside
-of core methods. This also allows multiple versions of Protovis to coexist,
-since each version will see their own pv namespace.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Field Detail
-
-
-
-
<static>
-
- {Event}
- pv.event
-
-
-
- Stores the current event. This field is only set within event handlers.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Method Detail
-
-
-
-
<static>
-
- {array}
- pv.blend(arrays)
-
-
-
- Given the specified array of arrays, concatenates the arrays into a single
-array. If the individual arrays are explicitly known, an alternative to blend
-is to use JavaScript's concat method directly. These two equivalent
-expressions:
- Returns the pv.Color for the specified color format string. Colors
-may have an associated opacity, or alpha channel. Color formats are specified
-by CSS Color Modular Level 3, using either in RGB or HSL color space. For
-example:
-
-
#f00 // #rgb
-
#ff0000 // #rrggbb
-
rgb(255, 0, 0)
-
rgb(100%, 0%, 0%)
-
hsl(0, 100%, 50%)
-
rgba(0, 0, 255, 0.5)
-
hsla(120, 100%, 50%, 1)
-
-
The SVG 1.0 color keywords names are also supported, such as "aliceblue"
-and "yellowgreen". The "transparent" keyword is supported for fully-
-transparent black.
-
-
If the format argument is already an instance of Color,
-the argument is returned with no further processing.
-
-
- Defined in: Color.js.
-
-
-
- Returns a new categorical color encoding using the specified colors. The
-arguments to this method are an array of colors; see pv.color. For
-example, to create a categorical color encoding using the species
-attribute:
-
-
-
-The result of this expression can be used as a fill- or stroke-style
-property. This assumes that the data's species attribute is a
-string.
-
-
- Defined in: Colors.js.
-
-
-
- Given two arrays a and b, returns an array of all possible
-pairs of elements [ai, bj]. The outer loop is on array
-a, while the inner loop is on b, such that the order of
-returned elements is [a0, b0], [a0,
-b1], ... [a0, bm], [a1,
-b0], [a1, b1], ... [a1,
-bm], ... [an, bm]. If either array is empty,
-an empty array is returned.
-
-
- Defined in: Arrays.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {array}a
-
-
-
an array.
-
-
- {array}b
-
-
-
an array.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{array} an array of pairs of elements in a and b.
-
-
-
-
-
-
-
-
-
-
<static>
-
-
- pv.degrees(radians)
-
-
-
- Returns the number of degrees corresponding to the specified radians.
-
-
- Defined in: Numbers.js.
-
-
-
- Returns an unbiased estimation of the standard deviation of a population,
-given the specified random sample. If the specified array is not an array of
-numbers, an optional accessor function f can be specified to map the
-elements to numbers. See #normalize for an example. Accessor
-functions can refer to this.index.
-
-
- Defined in: Numbers.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {array}array
-
-
-
an array of objects, or numbers.
-
-
- {function}f
- Optional
-
-
an optional accessor function.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{number} the standard deviation of the specified array.
-
-
-
-
-
-
-
-
-
-
<static>
-
-
- pv.dict(keys, f)
-
-
-
- Returns a map constructed from the specified keys, using the
-function f to compute the value for each key. The single argument to
-the value function is the key. The callback is invoked only for indexes of
-the array which have assigned values; it is not invoked for indexes which
-have been deleted or which have never been assigned values.
-
-
For example, this expression creates a map from strings to string length:
-
-
- Returns a pv.Dom operator for the given map. This is a convenience
-factory method, equivalent to new pv.Dom(map). To apply the operator
-and retrieve the root node, call pv.Dom#root; to retrieve all nodes
-flattened, use pv.Dom#nodes.
-
-
- Defined in: Dom.js.
-
-
-
- Returns all of the entries (key-value pairs) of the specified object (a
-map). The order of the returned array is not defined. Each key-value pair is
-represented as an object with key and value attributes,
-e.g., {key: "foo", value: 42}.
-
-
- Defined in: Objects.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- map
-
-
-
an object.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{array} an array of key-value pairs corresponding to the keys.
- Returns a pv.Flatten operator for the specified map. This is a
-convenience factory method, equivalent to new pv.Flatten(map).
-
-
- Defined in: Flatten.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- map
-
-
-
a map to flatten.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{pv.Flatten} a flatten operator for the specified map.
- Constructs a new HSL color with the specified values.
-
-
- Defined in: Color.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {number}h
-
-
-
the hue, an integer in [0, 360].
-
-
- {number}s
-
-
-
the saturation, a float in [0, 1].
-
-
- {number}l
-
-
-
the lightness, a float in [0, 1].
-
-
- {number}a
- Optional
-
-
the opacity, a float in [0, 1].
-
-
-
-
-
-
-
-
-
Returns:
-
-
pv.Color.Hsl
-
-
-
-
-
-
-
-
-
-
<static>
-
-
- pv.identity(x)
-
-
-
- Returns the passed-in argument, x; the identity function. This method
-is provided for convenience since it is used as the default behavior for a
-number of property functions.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- x
-
-
-
a value.
-
-
-
-
-
-
-
-
-
Returns:
-
-
the value x.
-
-
-
-
-
-
-
-
-
-
<static>
-
-
- pv.index()
-
-
-
- Returns this.index. This method is provided for convenience for use
-with scales. For example, to color bars by their index, say:
-
-
.fillStyle(pv.Colors.category10().by(pv.index))
-
-This method is equivalent to function() this.index, but more
-succinct. Note that the index property is also supported for
-accessor functions with pv.max, pv.min and other array
-utility methods.
-
-
-
- Returns all of the property names (keys) of the specified object (a map). The
-order of the returned array is not defined.
-
-
- Defined in: Objects.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- map
-
-
-
an object.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{string[]} an array of strings corresponding to the keys.
- Returns the logarithm with a given base value.
-
-
- Defined in: Numbers.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {number}x
-
-
-
the number for which to compute the logarithm.
-
-
- {number}b
-
-
-
the base of the logarithm.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{number} the logarithm value.
-
-
-
-
-
-
-
-
-
-
<static>
-
- {number}
- pv.logAdjusted(x, b)
-
-
-
- Computes a zero-symmetric logarithm, with adjustment to values between zero
-and the logarithm base. This adjustment introduces distortion for values less
-than the base number, but enables simultaneous plotting of log-transformed
-data involving both positive and negative numbers.
-
-
- Defined in: Numbers.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {number}x
-
-
-
the number for which to compute the logarithm.
-
-
- {number}b
-
-
-
the base of the logarithm.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{number} the adjusted, symmetric log value.
-
-
-
-
-
-
-
-
-
-
<static>
-
- {number}
- pv.logCeil(x, b)
-
-
-
- Rounds an input value up according to its logarithm. The method takes the
-ceiling of the logarithm of the value and then uses the resulting value as an
-exponent for the base value.
-
-
- Defined in: Numbers.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {number}x
-
-
-
the number for which to compute the logarithm ceiling.
-
-
- {number}b
-
-
-
the base of the logarithm.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{number} the rounded-by-logarithm value.
-
-
-
-
-
-
-
-
-
-
<static>
-
- {number}
- pv.logFloor(x, b)
-
-
-
- Rounds an input value down according to its logarithm. The method takes the
-floor of the logarithm of the value and then uses the resulting value as an
-exponent for the base value.
-
-
- Defined in: Numbers.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {number}x
-
-
-
the number for which to compute the logarithm floor.
-
-
- {number}b
-
-
-
the base of the logarithm.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{number} the rounded-by-logarithm value.
-
-
-
-
-
-
-
-
-
-
<static>
-
- {number}
- pv.logSymmetric(x, b)
-
-
-
- Computes a zero-symmetric logarithm. Computes the logarithm of the absolute
-value of the input, and determines the sign of the output according to the
-sign of the input value.
-
-
- Defined in: Numbers.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {number}x
-
-
-
the number for which to compute the logarithm.
-
-
- {number}b
-
-
-
the base of the logarithm.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{number} the symmetric log value.
-
-
-
-
-
-
-
-
-
-
<static>
-
- {number}
- pv.max(array, f)
-
-
-
- Returns the maximum value of the specified array. If the specified array is
-not an array of numbers, an optional accessor function f can be
-specified to map the elements to numbers. See #normalize for an
-example. Accessor functions can refer to this.index.
-
-
- Defined in: Numbers.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {array}array
-
-
-
an array of objects, or numbers.
-
-
- {function}f
- Optional
-
-
an optional accessor function.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{number} the maximum value of the specified array.
-
-
-
-
-
-
-
-
-
-
<static>
-
- {number}
- pv.mean(array, f)
-
-
-
- Returns the arithmetic mean, or average, of the specified array. If the
-specified array is not an array of numbers, an optional accessor function
-f can be specified to map the elements to numbers. See
-#normalize for an example. Accessor functions can refer to
-this.index.
-
-
- Defined in: Numbers.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {array}array
-
-
-
an array of objects, or numbers.
-
-
- {function}f
- Optional
-
-
an optional accessor function.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{number} the mean of the specified array.
-
-
-
-
-
-
-
-
-
-
<static>
-
- {number}
- pv.median(array, f)
-
-
-
- Returns the median of the specified array. If the specified array is not an
-array of numbers, an optional accessor function f can be specified
-to map the elements to numbers. See #normalize for an example.
-Accessor functions can refer to this.index.
-
-
- Defined in: Numbers.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {array}array
-
-
-
an array of objects, or numbers.
-
-
- {function}f
- Optional
-
-
an optional accessor function.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{number} the median of the specified array.
-
-
-
-
-
-
-
-
-
-
<static>
-
- {number}
- pv.min(array, f)
-
-
-
- Returns the minimum value of the specified array of numbers. If the specified
-array is not an array of numbers, an optional accessor function f
-can be specified to map the elements to numbers. See #normalize for
-an example. Accessor functions can refer to this.index.
-
-
- Defined in: Numbers.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {array}array
-
-
-
an array of objects, or numbers.
-
-
- {function}f
- Optional
-
-
an optional accessor function.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{number} the minimum value of the specified array.
-
-
-
-
-
-
-
-
-
-
<static>
-
- {number}
- pv.naturalOrder(a, b)
-
-
-
- The comparator function for natural order. This can be used in conjunction with
-the built-in array sort method to sort elements by their natural
-order, ascending. Note that if no comparator function is specified to the
-built-in sort method, the default order is lexicographic, not
-natural!
-
-
- Defined in: Arrays.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- a
-
-
-
an element to compare.
-
-
- b
-
-
-
an element to compare.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{number} negative if a < b; positive if a > b; otherwise 0.
- Returns a pv.Nest operator for the specified array. This is a
-convenience factory method, equivalent to new pv.Nest(array).
-
-
- Defined in: Nest.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {array}array
-
-
-
an array of elements to nest.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{pv.Nest} a nest operator for the specified array.
- Given a flat array of values, returns a simple DOM with each value wrapped by
-a node that is a child of the root node.
-
-
- Defined in: Dom.js.
-
-
-
- Returns a normalized copy of the specified array, such that the sum of the
-returned elements sum to one. If the specified array is not an array of
-numbers, an optional accessor function f can be specified to map the
-elements to numbers. For example, if array is an array of objects,
-and each object has a numeric property "foo", the expression
-
-
pv.normalize(array, function(d) d.foo)
-
-returns a normalized array on the "foo" property. If an accessor function is
-not specified, the identity function is used. Accessor functions can refer to
-this.index.
-
-
- Defined in: Arrays.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {array}array
-
-
-
an array of objects, or numbers.
-
-
- {function}f
- Optional
-
-
an optional accessor function.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{number[]} an array of numbers that sums to one.
-
-
-
-
-
-
-
-
-
-
<static>
-
-
- pv.numerate(keys, f)
-
-
-
- Returns a map from key to index for the specified keys array. For
-example,
-
-
pv.numerate(["a", "b", "c"])
-
-returns {a: 0, b: 1, c: 2}. Note that since JavaScript maps only
-support string keys, keys must contain strings, or other values that
-naturally map to distinct string values. Alternatively, an optional accessor
-function f can be specified to compute the string key for the given
-element. Accessor functions can refer to this.index.
-
-
- Defined in: Arrays.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {array}keys
-
-
-
an array, usually of string keys.
-
-
- {function}f
- Optional
-
-
an optional key function.
-
-
-
-
-
-
-
-
-
Returns:
-
-
a map from key to index.
-
-
-
-
-
-
-
-
-
-
<static>
-
-
- pv.parent()
-
-
-
- Returns this.parent.index. This method is provided for convenience
-for use with scales. This method is provided for convenience for use with
-scales. For example, to color bars by their parent index, say:
-
-
.fillStyle(pv.Colors.category10().by(pv.parent))
-
-Tthis method is equivalent to function() this.parent.index, but more
-succinct.
-
-
-
- Returns a permutation of the specified array, using the specified array of
-indexes. The returned array contains the corresponding element in
-array for each index in indexes, in order. For example,
-
-
pv.permute(["a", "b", "c"], [1, 2, 0])
-
-returns ["b", "c", "a"]. It is acceptable for the array of indexes
-to be a different length from the array of elements, and for indexes to be
-duplicated or omitted. The optional accessor function f can be used
-to perform a simultaneous mapping of the array elements. Accessor functions
-can refer to this.index.
-
-
- Defined in: Arrays.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {array}array
-
-
-
an array.
-
-
- {number[]}indexes
-
-
-
an array of indexes into array.
-
-
- {function}f
- Optional
-
-
an optional accessor function.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{array} an array of elements from array; a permutation.
-
-
-
-
-
-
-
-
-
-
<static>
-
-
- pv.radians(degrees)
-
-
-
- Returns the number of radians corresponding to the specified degrees.
-
-
- Defined in: Numbers.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- degrees
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
<static>
-
- {Function}
- pv.ramp(start, end)
-
-
-
- Returns a linear color ramp from the specified start color to the
-specified end color. The color arguments may be specified either as
-strings or as pv.Colors. This is equivalent to:
-
-
- Returns a random number in the range [start, stop) that is
-a multiple of step. More specifically, the returned number is of the
-form start + n * step, where n is a
-nonnegative integer. If step is not specified, it defaults to 1,
-returning a random integer if start is also an integer.
-
-
- Defined in: Numbers.js.
-
-
-
- Returns an array of numbers, starting at start, incrementing by
-step, until stop is reached. The stop value is
-exclusive. If only a single argument is specified, this value is interpeted
-as the stop value, with the start value as zero. If only two
-arguments are specified, the step value is implied to be one.
-
-
The method is modeled after the built-in range method from
-Python. See the Python documentation for more details.
-
-
- Defined in: Numbers.js.
-
-
-
- Concatenates the specified array with itself n times. For example,
-pv.repeat([1, 2]) returns [1, 2, 1, 2].
-
-
- Defined in: Arrays.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {array}a
-
-
-
an array.
-
-
- {number}n
- Optional
-
-
the number of times to repeat; defaults to two.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{array} an array that repeats the specified array.
-
-
-
-
-
-
-
-
-
-
<static>
-
- {number}
- pv.reverseOrder(a, b)
-
-
-
- The comparator function for reverse natural order. This can be used in
-conjunction with the built-in array sort method to sort elements by
-their natural order, descending. Note that if no comparator function is
-specified to the built-in sort method, the default order is
-lexicographic, not natural!
-
-
- Defined in: Arrays.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- a
-
-
-
an element to compare.
-
-
- b
-
-
-
an element to compare.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{number} negative if a < b; positive if a > b; otherwise 0.
- Constructs a new RGB color with the specified channel values.
-
-
- Defined in: Color.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {number}r
-
-
-
the red channel, an integer in [0,255].
-
-
- {number}g
-
-
-
the green channel, an integer in [0,255].
-
-
- {number}b
-
-
-
the blue channel, an integer in [0,255].
-
-
- {number}a
- Optional
-
-
the alpha channel, a float in [0,1].
-
-
-
-
-
-
-
-
-
Returns:
-
-
pv.Color.Rgb
-
-
-
-
-
-
-
-
-
-
<static>
-
-
- pv.search(array, value, f)
-
-
-
- Searches the specified array of numbers for the specified value using the
-binary search algorithm. The array must be sorted (as by the sort
-method) prior to making this call. If it is not sorted, the results are
-undefined. If the array contains multiple elements with the specified value,
-there is no guarantee which one will be found.
-
-
The insertion point is defined as the point at which the value
-would be inserted into the array: the index of the first element greater than
-the value, or array.length, if all elements in the array are less
-than the specified value. Note that this guarantees that the return value
-will be nonnegative if and only if the value is found.
-
-
- Defined in: Arrays.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {number[]}array
-
-
-
the array to be searched.
-
-
- {number}value
-
-
-
the value to be searched for.
-
-
- {function}f
- Optional
-
-
an optional key function.
-
-
-
-
-
-
-
-
-
Returns:
-
-
the index of the search value, if it is contained in the array;
-otherwise, (-(insertion point) - 1).
- Returns the sum of the specified array. If the specified array is not an
-array of numbers, an optional accessor function f can be specified
-to map the elements to numbers. See #normalize for an example.
-Accessor functions can refer to this.index.
-
-
- Defined in: Numbers.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {array}array
-
-
-
an array of objects, or numbers.
-
-
- {function}f
- Optional
-
-
an optional accessor function.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{number} the sum of the specified array.
-
-
-
-
-
-
-
-
-
-
<static>
-
- {array[]}
- pv.transpose(arrays)
-
-
-
- Given the specified array of arrays, transposes each element
-arrayij with arrayji. If the array has dimensions
-n×m, it will have dimensions m×n
-after this method returns. This method transposes the elements of the array
-in place, mutating the array, and returning a reference to the array.
-
-
- Defined in: Arrays.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {array[]}arrays
-
-
-
an array of arrays.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{array[]} the passed-in array, after transposing the elements.
- Returns a pv.Tree operator for the specified array. This is a
-convenience factory method, equivalent to new pv.Tree(array).
-
-
- Defined in: Tree.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {array}array
-
-
-
an array from which to construct a tree.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{pv.Tree} a tree operator for the specified array.
- Returns the unique elements in the specified array, in the order they appear.
-Note that since JavaScript maps only support string keys, array must
-contain strings, or other values that naturally map to distinct string
-values. Alternatively, an optional accessor function f can be
-specified to compute the string key for the given element. Accessor functions
-can refer to this.index.
-
-
- Defined in: Arrays.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {array}array
-
-
-
an array, usually of string keys.
-
-
- {function}f
- Optional
-
-
an optional key function.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{array} the unique values.
-
-
-
-
-
-
-
-
-
-
<static>
-
- {array}
- pv.values(map)
-
-
-
- Returns all of the values (attribute values) of the specified object (a
-map). The order of the returned array is not defined.
-
-
- Defined in: Objects.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- map
-
-
-
an object.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{array} an array of objects corresponding to the values.
- Returns the unweighted variance of the specified array. If the specified
-array is not an array of numbers, an optional accessor function f
-can be specified to map the elements to numbers. See #normalize for
-an example. Accessor functions can refer to this.index.
-
-
- Defined in: Numbers.js.
-
-
-
- Returns a pv.Vector for the specified x and y
-coordinate. This is a convenience factory method, equivalent to new
-pv.Vector(x, y).
-
-
- Defined in: Vector.js.
-
-
-
-
-
-
-
-
-
Parameters:
-
-
- {number}x
-
-
-
the x coordinate.
-
-
- {number}y
-
-
-
the y coordinate.
-
-
-
-
-
-
-
-
-
Returns:
-
-
{pv.Vector} a vector for the specified coordinates.
1/**
- 2 * Abstract; see an implementing class for details.
- 3 *
- 4 * @class Represents a reusable interaction; applies an interactive behavior to
- 5 * a given mark. Behaviors are themselves functions designed to be used as event
- 6 * handlers. For example, to add pan and zoom support to any panel, say:
- 7 *
- 8 * <pre> .event("mousedown", pv.Behavior.pan())
- 9 * .event("mousewheel", pv.Behavior.zoom())</pre>
- 10 *
- 11 * The behavior should be registered on the event that triggers the start of the
- 12 * behavior. Typically, the behavior will take care of registering for any
- 13 * additional events that are necessary. For example, dragging starts on
- 14 * mousedown, while the drag behavior automatically listens for mousemove and
- 15 * mouseup events on the window. By listening to the window, the behavior can
- 16 * continue to receive mouse events even if the mouse briefly leaves the mark
- 17 * being dragged, or even the root panel.
- 18 *
- 19 * <p>Each behavior implementation has specific requirements as to which events
- 20 * it supports, and how it should be used. For example, the drag behavior
- 21 * requires that the data associated with the mark be an object with <tt>x</tt>
- 22 * and <tt>y</tt> attributes, such as a {@link pv.Vector}, storing the mark's
- 23 * position. See an implementing class for details.
- 24 *
- 25 * @see pv.Behavior.drag
- 26 * @see pv.Behavior.pan
- 27 * @see pv.Behavior.point
- 28 * @see pv.Behavior.select
- 29 * @see pv.Behavior.zoom
- 30 * @extends function
- 31 */
- 32pv.Behavior={};
- 33
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_behavior_Drag.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_behavior_Drag.js.html
deleted file mode 100644
index 6e973c6f..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_behavior_Drag.js.html
+++ /dev/null
@@ -1,120 +0,0 @@
-
1/**
- 2 * Returns a new drag behavior to be registered on mousedown events.
- 3 *
- 4 * @class Implements interactive dragging starting with mousedown events.
- 5 * Register this behavior on marks that should be draggable by the user, such as
- 6 * the selected region for brushing and linking. This behavior can be used in
- 7 * tandom with {@link pv.Behavior.select} to allow the selected region to be
- 8 * dragged interactively.
- 9 *
- 10 * <p>After the initial mousedown event is triggered, this behavior listens for
- 11 * mousemove and mouseup events on the window. This allows dragging to continue
- 12 * even if the mouse temporarily leaves the mark that is being dragged, or even
- 13 * the root panel.
- 14 *
- 15 * <p>This behavior requires that the data associated with the mark being
- 16 * dragged have <tt>x</tt> and <tt>y</tt> attributes that correspond to the
- 17 * mark's location in pixels. The mark's positional properties are not set
- 18 * directly by this behavior; instead, the positional properties should be
- 19 * defined as:
- 20 *
- 21 * <pre> .left(function(d) d.x)
- 22 * .top(function(d) d.y)</pre>
- 23 *
- 24 * Thus, the behavior does not move the mark directly, but instead updates the
- 25 * mark position by updating the underlying data. Note that if the positional
- 26 * properties are defined with bottom and right (rather than top and left), the
- 27 * drag behavior will be inverted, which will confuse users!
- 28 *
- 29 * <p>The drag behavior is bounded by the parent panel; the <tt>x</tt> and
- 30 * <tt>y</tt> attributes are clamped such that the mark being dragged does not
- 31 * extend outside the enclosing panel's bounds. To facilitate this, the drag
- 32 * behavior also queries for <tt>dx</tt> and <tt>dy</tt> attributes on the
- 33 * underlying data, to determine the dimensions of the bar being dragged. For
- 34 * non-rectangular marks, the drag behavior simply treats the mark as a point,
- 35 * which means that only the mark's center is bounded.
- 36 *
- 37 * <p>The mark being dragged is automatically re-rendered for each mouse event
- 38 * as part of the drag operation. In addition, a <tt>fix</tt> attribute is
- 39 * populated on the mark, which allows visual feedback for dragging. For
- 40 * example, to change the mark fill color while dragging:
- 41 *
- 42 * <pre> .fillStyle(function(d) d.fix ? "#ff7f0e" : "#aec7e8")</pre>
- 43 *
- 44 * In some cases, such as with network layouts, dragging the mark may cause
- 45 * related marks to change, in which case additional marks may also need to be
- 46 * rendered. This can be accomplished by listening for the drag
- 47 * psuedo-events:<ul>
- 48 *
- 49 * <li>dragstart (on mousedown)
- 50 * <li>drag (on mousemove)
- 51 * <li>dragend (on mouseup)
- 52 *
- 53 * </ul>For example, to render the parent panel while dragging, thus
- 54 * re-rendering all sibling marks:
- 55 *
- 56 * <pre> .event("mousedown", pv.Behavior.drag())
- 57 * .event("drag", function() this.parent)</pre>
- 58 *
- 59 * This behavior may be enhanced in the future to allow more flexible
- 60 * configuration of drag behavior.
- 61 *
- 62 * @extends pv.Behavior
- 63 * @see pv.Behavior
- 64 * @see pv.Behavior.select
- 65 * @see pv.Layout.force
- 66 */
- 67pv.Behavior.drag=function(){
- 68varscene,// scene context
- 69index,// scene context
- 70p,// particle being dragged
- 71v1,// initial mouse-particle offset
- 72max;
- 73
- 74/** @private */
- 75functionmousedown(d){
- 76index=this.index;
- 77scene=this.scene;
- 78varm=this.mouse();
- 79v1=((p=d).fix=pv.vector(d.x,d.y)).minus(m);
- 80max={
- 81x:this.parent.width()-(d.dx||0),
- 82y:this.parent.height()-(d.dy||0)
- 83};
- 84scene.mark.context(scene,index,function(){this.render();});
- 85pv.Mark.dispatch("dragstart",scene,index);
- 86}
- 87
- 88/** @private */
- 89functionmousemove(){
- 90if(!scene)return;
- 91scene.mark.context(scene,index,function(){
- 92varm=this.mouse();
- 93p.x=p.fix.x=Math.max(0,Math.min(v1.x+m.x,max.x));
- 94p.y=p.fix.y=Math.max(0,Math.min(v1.y+m.y,max.y));
- 95this.render();
- 96});
- 97pv.Mark.dispatch("drag",scene,index);
- 98}
- 99
-100/** @private */
-101functionmouseup(){
-102if(!scene)return;
-103p.fix=null;
-104scene.mark.context(scene,index,function(){this.render();});
-105pv.Mark.dispatch("dragend",scene,index);
-106scene=null;
-107}
-108
-109pv.listen(window,"mousemove",mousemove);
-110pv.listen(window,"mouseup",mouseup);
-111returnmousedown;
-112};
-113
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_behavior_Pan.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_behavior_Pan.js.html
deleted file mode 100644
index 8bf15657..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_behavior_Pan.js.html
+++ /dev/null
@@ -1,118 +0,0 @@
-
1/**
- 2 * Returns a new pan behavior to be registered on mousedown events.
- 3 *
- 4 * @class Implements interactive panning starting with mousedown events.
- 5 * Register this behavior on panels to allow panning. This behavior can be used
- 6 * in tandem with {@link pv.Behavior.zoom} to allow both panning and zooming:
- 7 *
- 8 * <pre> .event("mousedown", pv.Behavior.pan())
- 9 * .event("mousewheel", pv.Behavior.zoom())</pre>
- 10 *
- 11 * The pan behavior currently supports only mouse events; support for keyboard
- 12 * shortcuts to improve accessibility may be added in the future.
- 13 *
- 14 * <p>After the initial mousedown event is triggered, this behavior listens for
- 15 * mousemove and mouseup events on the window. This allows panning to continue
- 16 * even if the mouse temporarily leaves the panel that is being panned, or even
- 17 * the root panel.
- 18 *
- 19 * <p>The implementation of this behavior relies on the panel's
- 20 * <tt>transform</tt> property, which specifies a matrix transformation that is
- 21 * applied to child marks. Note that the transform property only affects the
- 22 * panel's children, but not the panel itself; therefore the panel's fill and
- 23 * stroke will not change when the contents are panned.
- 24 *
- 25 * <p>Panels have transparent fill styles by default; this means that panels may
- 26 * not receive the initial mousedown event to start panning. To fix this
- 27 * problem, either given the panel a visible fill style (such as "white"), or
- 28 * set the <tt>events</tt> property to "all" such that the panel receives events
- 29 * despite its transparent fill.
- 30 *
- 31 * <p>The pan behavior has optional support for bounding. If enabled, the user
- 32 * will not be able to pan the panel outside of the initial bounds. This feature
- 33 * is designed to work in conjunction with the zoom behavior; otherwise,
- 34 * bounding the panel effectively disables all panning.
- 35 *
- 36 * @extends pv.Behavior
- 37 * @see pv.Behavior.zoom
- 38 * @see pv.Panel#transform
- 39 */
- 40pv.Behavior.pan=function(){
- 41varscene,// scene context
- 42index,// scene context
- 43m1,// transformation matrix at the start of panning
- 44v1,// mouse location at the start of panning
- 45k,// inverse scale
- 46bound;// whether to bound to the panel
- 47
- 48/** @private */
- 49functionmousedown(){
- 50index=this.index;
- 51scene=this.scene;
- 52v1=pv.vector(pv.event.pageX,pv.event.pageY);
- 53m1=this.transform();
- 54k=1/(m1.k*this.scale);
- 55if(bound){
- 56bound={
- 57x:(1-m1.k)*this.width(),
- 58y:(1-m1.k)*this.height()
- 59};
- 60}
- 61}
- 62
- 63/** @private */
- 64functionmousemove(){
- 65if(!scene)return;
- 66scene.mark.context(scene,index,function(){
- 67varx=(pv.event.pageX-v1.x)*k,
- 68y=(pv.event.pageY-v1.y)*k,
- 69m=m1.translate(x,y);
- 70if(bound){
- 71m.x=Math.max(bound.x,Math.min(0,m.x));
- 72m.y=Math.max(bound.y,Math.min(0,m.y));
- 73}
- 74this.transform(m).render();
- 75});
- 76pv.Mark.dispatch("pan",scene,index);
- 77}
- 78
- 79/** @private */
- 80functionmouseup(){
- 81scene=null;
- 82}
- 83
- 84/**
- 85 * Sets or gets the bound parameter. If bounding is enabled, the user will not
- 86 * be able to pan outside the initial panel bounds; this typically applies
- 87 * only when the pan behavior is used in tandem with the zoom behavior.
- 88 * Bounding is not enabled by default.
- 89 *
- 90 * <p>Note: enabling bounding after panning has already occurred will not
- 91 * immediately reset the transform. Bounding should be enabled before the
- 92 * panning behavior is applied.
- 93 *
- 94 * @function
- 95 * @returns {pv.Behavior.pan} this, or the current bound parameter.
- 96 * @name pv.Behavior.pan.prototype.bound
- 97 * @param {boolean} [x] the new bound parameter.
- 98 */
- 99mousedown.bound=function(x){
-100if(arguments.length){
-101bound=Boolean(x);
-102returnthis;
-103}
-104returnBoolean(bound);
-105};
-106
-107pv.listen(window,"mousemove",mousemove);
-108pv.listen(window,"mouseup",mouseup);
-109returnmousedown;
-110};
-111
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_behavior_Point.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_behavior_Point.js.html
deleted file mode 100644
index 7d7a695b..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_behavior_Point.js.html
+++ /dev/null
@@ -1,165 +0,0 @@
-
1/**
- 2 * Returns a new point behavior to be registered on mousemove events.
- 3 *
- 4 * @class Implements interactive fuzzy pointing, identifying marks that are in
- 5 * close proximity to the mouse cursor. This behavior is an alternative to the
- 6 * native mouseover and mouseout events, improving usability. Rather than
- 7 * requiring the user to mouseover a mark exactly, the mouse simply needs to
- 8 * move near the given mark and a "point" event is triggered. In addition, if
- 9 * multiple marks overlap, the point behavior can be used to identify the mark
- 10 * instance closest to the cursor, as opposed to the one that is rendered on
- 11 * top.
- 12 *
- 13 * <p>The point behavior can also identify the closest mark instance for marks
- 14 * that produce a continuous graphic primitive. The point behavior can thus be
- 15 * used to provide details-on-demand for both discrete marks (such as dots and
- 16 * bars), as well as continuous marks (such as lines and areas).
- 17 *
- 18 * <p>This behavior is implemented by finding the closest mark instance to the
- 19 * mouse cursor on every mousemove event. If this closest mark is within the
- 20 * given radius threshold, which defaults to 30 pixels, a "point" psuedo-event
- 21 * is dispatched to the given mark instance. If any mark were previously
- 22 * pointed, it would receive a corresponding "unpoint" event. These two
- 23 * psuedo-event types correspond to the native "mouseover" and "mouseout"
- 24 * events, respectively. To increase the radius at which the point behavior can
- 25 * be applied, specify an appropriate threshold to the constructor, up to
- 26 * <tt>Infinity</tt>.
- 27 *
- 28 * <p>By default, the standard Cartesian distance is computed. However, with
- 29 * some visualizations it is desirable to consider only a single dimension, such
- 30 * as the <i>x</i>-dimension for an independent variable. In this case, the
- 31 * collapse parameter can be set to collapse the <i>y</i> dimension:
- 32 *
- 33 * <pre> .event("mousemove", pv.Behavior.point(Infinity).collapse("y"))</pre>
- 34 *
- 35 * <p>This behavior only listens to mousemove events on the assigned panel,
- 36 * which is typically the root panel. The behavior will search recursively for
- 37 * descendant marks to point. If the mouse leaves the assigned panel, the
- 38 * behavior no longer receives mousemove events; an unpoint psuedo-event is
- 39 * automatically dispatched to unpoint any pointed mark. Marks may be re-pointed
- 40 * when the mouse reenters the panel.
- 41 *
- 42 * <p>Panels have transparent fill styles by default; this means that panels may
- 43 * not receive the initial mousemove event to start pointing. To fix this
- 44 * problem, either given the panel a visible fill style (such as "white"), or
- 45 * set the <tt>events</tt> property to "all" such that the panel receives events
- 46 * despite its transparent fill.
- 47 *
- 48 * <p>Note: this behavior does not currently wedge marks.
- 49 *
- 50 * @extends pv.Behavior
- 51 *
- 52 * @param {number} [r] the fuzzy radius threshold in pixels
- 53 * @see <a href="http://www.tovigrossman.com/papers/chi2005bubblecursor.pdf"
- 54 * >"The Bubble Cursor: Enhancing Target Acquisition by Dynamic Resizing of the
- 55 * Cursor's Activation Area"</a> by T. Grossman & R. Balakrishnan, CHI 2005.
- 56 */
- 57pv.Behavior.point=function(r){
- 58varunpoint,// the current pointer target
- 59collapse=null,// dimensions to collapse
- 60kx=1,// x-dimension cost scale
- 61ky=1,// y-dimension cost scale
- 62r2=arguments.length?r*r:900;// fuzzy radius
- 63
- 64/** @private Search for the mark closest to the mouse. */
- 65functionsearch(scene,index){
- 66vars=scene[index],
- 67point={cost:Infinity};
- 68for(vari=0,n=s.visible&&s.children.length;i<n;i++){
- 69varchild=s.children[i],mark=child.mark,p;
- 70if(mark.type=="panel"){
- 71mark.scene=child;
- 72for(varj=0,m=child.length;j<m;j++){
- 73mark.index=j;
- 74p=search(child,j);
- 75if(p.cost<point.cost)point=p;
- 76}
- 77deletemark.scene;
- 78deletemark.index;
- 79}elseif(mark.$handlers.point){
- 80varv=mark.mouse();
- 81for(varj=0,m=child.length;j<m;j++){
- 82varc=child[j],
- 83dx=v.x-c.left-(c.width||0)/2,
- 84dy=v.y-c.top-(c.height||0)/2,
- 85dd=kx*dx*dx+ky*dy*dy;
- 86if(dd<point.cost){
- 87point.distance=dx*dx+dy*dy;
- 88point.cost=dd;
- 89point.scene=child;
- 90point.index=j;
- 91}
- 92}
- 93}
- 94}
- 95returnpoint;
- 96}
- 97
- 98/** @private */
- 99functionmousemove(){
-100/* If the closest mark is far away, clear the current target. */
-101varpoint=search(this.scene,this.index);
-102if((point.cost==Infinity)||(point.distance>r2))point=null;
-103
-104/* Unpoint the old target, if it's not the new target. */
-105if(unpoint){
-106if(point
-107&&(unpoint.scene==point.scene)
-108&&(unpoint.index==point.index))return;
-109pv.Mark.dispatch("unpoint",unpoint.scene,unpoint.index);
-110}
-111
-112/* Point the new target, if there is one. */
-113if(unpoint=point){
-114pv.Mark.dispatch("point",point.scene,point.index);
-115
-116/* Unpoint when the mouse leaves the root panel. */
-117pv.listen(this.root.canvas(),"mouseout",mouseout);
-118}
-119}
-120
-121/** @private */
-122functionmouseout(e){
-123if(unpoint&&!pv.ancestor(this,e.relatedTarget)){
-124pv.Mark.dispatch("unpoint",unpoint.scene,unpoint.index);
-125unpoint=null;
-126}
-127}
-128
-129/**
-130 * Sets or gets the collapse parameter. By default, the standard Cartesian
-131 * distance is computed. However, with some visualizations it is desirable to
-132 * consider only a single dimension, such as the <i>x</i>-dimension for an
-133 * independent variable. In this case, the collapse parameter can be set to
-134 * collapse the <i>y</i> dimension:
-135 *
-136 * <pre> .event("mousemove", pv.Behavior.point(Infinity).collapse("y"))</pre>
-137 *
-138 * @function
-139 * @returns {pv.Behavior.point} this, or the current collapse parameter.
-140 * @name pv.Behavior.point.prototype.collapse
-141 * @param {string} [x] the new collapse parameter
-142 */
-143mousemove.collapse=function(x){
-144if(arguments.length){
-145collapse=String(x);
-146switch(collapse){
-147case"y":kx=1;ky=0;break;
-148case"x":kx=0;ky=1;break;
-149default:kx=1;ky=1;break;
-150}
-151returnmousemove;
-152}
-153returncollapse;
-154};
-155
-156returnmousemove;
-157};
-158
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_behavior_Resize.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_behavior_Resize.js.html
deleted file mode 100644
index 51956e2c..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_behavior_Resize.js.html
+++ /dev/null
@@ -1,112 +0,0 @@
-
1/**
- 2 * Returns a new resize behavior to be registered on mousedown events.
- 3 *
- 4 * @class Implements interactive resizing of a selection starting with mousedown
- 5 * events. Register this behavior on selection handles that should be resizeable
- 6 * by the user, such for brushing and linking. This behavior can be used in
- 7 * tandom with {@link pv.Behavior.select} and {@link pv.Behavior.drag} to allow
- 8 * the selected region to be selected and dragged interactively.
- 9 *
- 10 * <p>After the initial mousedown event is triggered, this behavior listens for
- 11 * mousemove and mouseup events on the window. This allows resizing to continue
- 12 * even if the mouse temporarily leaves the assigned panel, or even the root
- 13 * panel.
- 14 *
- 15 * <p>This behavior requires that the data associated with the mark being
- 16 * resized have <tt>x</tt>, <tt>y</tt>, <tt>dx</tt> and <tt>dy</tt> attributes
- 17 * that correspond to the mark's location and dimensions in pixels. The mark's
- 18 * positional properties are not set directly by this behavior; instead, the
- 19 * positional properties should be defined as:
- 20 *
- 21 * <pre> .left(function(d) d.x)
- 22 * .top(function(d) d.y)
- 23 * .width(function(d) d.dx)
- 24 * .height(function(d) d.dy)</pre>
- 25 *
- 26 * Thus, the behavior does not resize the mark directly, but instead updates the
- 27 * size by updating the assigned panel's underlying data. Note that if the
- 28 * positional properties are defined with bottom and right (rather than top and
- 29 * left), the resize behavior will be inverted, which will confuse users!
- 30 *
- 31 * <p>The resize behavior is bounded by the assigned mark's enclosing panel; the
- 32 * positional attributes are clamped such that the selection does not extend
- 33 * outside the panel's bounds.
- 34 *
- 35 * <p>The mark being resized is automatically re-rendered for each mouse event
- 36 * as part of the resize operation. This behavior may be enhanced in the future
- 37 * to allow more flexible configuration. In some cases, such as with parallel
- 38 * coordinates, resizing the selection may cause related marks to change, in
- 39 * which case additional marks may also need to be rendered. This can be
- 40 * accomplished by listening for the select psuedo-events:<ul>
- 41 *
- 42 * <li>resizestart (on mousedown)
- 43 * <li>resize (on mousemove)
- 44 * <li>resizeend (on mouseup)
- 45 *
- 46 * </ul>For example, to render the parent panel while resizing, thus
- 47 * re-rendering all sibling marks:
- 48 *
- 49 * <pre> .event("mousedown", pv.Behavior.resize("left"))
- 50 * .event("resize", function() this.parent)</pre>
- 51 *
- 52 * This behavior may be enhanced in the future to allow more flexible
- 53 * configuration of the selection behavior.
- 54 *
- 55 * @extends pv.Behavior
- 56 * @see pv.Behavior.select
- 57 * @see pv.Behavior.drag
- 58 */
- 59pv.Behavior.resize=function(side){
- 60varscene,// scene context
- 61index,// scene context
- 62r,// region being selected
- 63m1;// initial mouse position
- 64
- 65/** @private */
- 66functionmousedown(d){
- 67index=this.index;
- 68scene=this.scene;
- 69m1=this.mouse();
- 70r=d;
- 71switch(side){
- 72case"left":m1.x=r.x+r.dx;break;
- 73case"right":m1.x=r.x;break;
- 74case"top":m1.y=r.y+r.dy;break;
- 75case"bottom":m1.y=r.y;break;
- 76}
- 77pv.Mark.dispatch("resizestart",scene,index);
- 78}
- 79
- 80/** @private */
- 81functionmousemove(){
- 82if(!scene)return;
- 83scene.mark.context(scene,index,function(){
- 84varm2=this.mouse();
- 85r.x=Math.max(0,Math.min(m1.x,m2.x));
- 86r.y=Math.max(0,Math.min(m1.y,m2.y));
- 87r.dx=Math.min(this.parent.width(),Math.max(m2.x,m1.x))-r.x;
- 88r.dy=Math.min(this.parent.height(),Math.max(m2.y,m1.y))-r.y;
- 89this.render();
- 90});
- 91pv.Mark.dispatch("resize",scene,index);
- 92}
- 93
- 94/** @private */
- 95functionmouseup(){
- 96if(!scene)return;
- 97pv.Mark.dispatch("resizeend",scene,index);
- 98scene=null;
- 99}
-100
-101pv.listen(window,"mousemove",mousemove);
-102pv.listen(window,"mouseup",mouseup);
-103returnmousedown;
-104};
-105
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_behavior_Select.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_behavior_Select.js.html
deleted file mode 100644
index b59fd719..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_behavior_Select.js.html
+++ /dev/null
@@ -1,108 +0,0 @@
-
1/**
- 2 * Returns a new select behavior to be registered on mousedown events.
- 3 *
- 4 * @class Implements interactive selecting starting with mousedown events.
- 5 * Register this behavior on panels that should be selectable by the user, such
- 6 * for brushing and linking. This behavior can be used in tandom with
- 7 * {@link pv.Behavior.drag} to allow the selected region to be dragged
- 8 * interactively.
- 9 *
- 10 * <p>After the initial mousedown event is triggered, this behavior listens for
- 11 * mousemove and mouseup events on the window. This allows selecting to continue
- 12 * even if the mouse temporarily leaves the assigned panel, or even the root
- 13 * panel.
- 14 *
- 15 * <p>This behavior requires that the data associated with the mark being
- 16 * dragged have <tt>x</tt>, <tt>y</tt>, <tt>dx</tt> and <tt>dy</tt> attributes
- 17 * that correspond to the mark's location and dimensions in pixels. The mark's
- 18 * positional properties are not set directly by this behavior; instead, the
- 19 * positional properties should be defined as:
- 20 *
- 21 * <pre> .left(function(d) d.x)
- 22 * .top(function(d) d.y)
- 23 * .width(function(d) d.dx)
- 24 * .height(function(d) d.dy)</pre>
- 25 *
- 26 * Thus, the behavior does not resize the mark directly, but instead updates the
- 27 * selection by updating the assigned panel's underlying data. Note that if the
- 28 * positional properties are defined with bottom and right (rather than top and
- 29 * left), the drag behavior will be inverted, which will confuse users!
- 30 *
- 31 * <p>The select behavior is bounded by the assigned panel; the positional
- 32 * attributes are clamped such that the selection does not extend outside the
- 33 * panel's bounds.
- 34 *
- 35 * <p>The panel being selected is automatically re-rendered for each mouse event
- 36 * as part of the drag operation. This behavior may be enhanced in the future to
- 37 * allow more flexible configuration of select behavior. In some cases, such as
- 38 * with parallel coordinates, making a selection may cause related marks to
- 39 * change, in which case additional marks may also need to be rendered. This can
- 40 * be accomplished by listening for the select psuedo-events:<ul>
- 41 *
- 42 * <li>selectstart (on mousedown)
- 43 * <li>select (on mousemove)
- 44 * <li>selectend (on mouseup)
- 45 *
- 46 * </ul>For example, to render the parent panel while selecting, thus
- 47 * re-rendering all sibling marks:
- 48 *
- 49 * <pre> .event("mousedown", pv.Behavior.drag())
- 50 * .event("select", function() this.parent)</pre>
- 51 *
- 52 * This behavior may be enhanced in the future to allow more flexible
- 53 * configuration of the selection behavior.
- 54 *
- 55 * @extends pv.Behavior
- 56 * @see pv.Behavior.drag
- 57 */
- 58pv.Behavior.select=function(){
- 59varscene,// scene context
- 60index,// scene context
- 61r,// region being selected
- 62m1;// initial mouse position
- 63
- 64/** @private */
- 65functionmousedown(d){
- 66index=this.index;
- 67scene=this.scene;
- 68m1=this.mouse();
- 69r=d;
- 70r.x=m1.x;
- 71r.y=m1.y;
- 72r.dx=r.dy=0;
- 73pv.Mark.dispatch("selectstart",scene,index);
- 74}
- 75
- 76/** @private */
- 77functionmousemove(){
- 78if(!scene)return;
- 79scene.mark.context(scene,index,function(){
- 80varm2=this.mouse();
- 81r.x=Math.max(0,Math.min(m1.x,m2.x));
- 82r.y=Math.max(0,Math.min(m1.y,m2.y));
- 83r.dx=Math.min(this.width(),Math.max(m2.x,m1.x))-r.x;
- 84r.dy=Math.min(this.height(),Math.max(m2.y,m1.y))-r.y;
- 85this.render();
- 86});
- 87pv.Mark.dispatch("select",scene,index);
- 88}
- 89
- 90/** @private */
- 91functionmouseup(){
- 92if(!scene)return;
- 93pv.Mark.dispatch("selectend",scene,index);
- 94scene=null;
- 95}
- 96
- 97pv.listen(window,"mousemove",mousemove);
- 98pv.listen(window,"mouseup",mouseup);
- 99returnmousedown;
-100};
-101
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_behavior_Zoom.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_behavior_Zoom.js.html
deleted file mode 100644
index 16875feb..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_behavior_Zoom.js.html
+++ /dev/null
@@ -1,93 +0,0 @@
-
1/**
- 2 * Returns a new zoom behavior to be registered on mousewheel events.
- 3 *
- 4 * @class Implements interactive zooming using mousewheel events. Register this
- 5 * behavior on panels to allow zooming. This behavior can be used in tandem with
- 6 * {@link pv.Behavior.pan} to allow both panning and zooming:
- 7 *
- 8 * <pre> .event("mousedown", pv.Behavior.pan())
- 9 * .event("mousewheel", pv.Behavior.zoom())</pre>
- 10 *
- 11 * The zoom behavior currently supports only mousewheel events; support for
- 12 * keyboard shortcuts and gesture events to improve accessibility may be added
- 13 * in the future.
- 14 *
- 15 * <p>The implementation of this behavior relies on the panel's
- 16 * <tt>transform</tt> property, which specifies a matrix transformation that is
- 17 * applied to child marks. Note that the transform property only affects the
- 18 * panel's children, but not the panel itself; therefore the panel's fill and
- 19 * stroke will not change when the contents are zoomed. The built-in support for
- 20 * transforms only supports uniform scaling and translates, which is sufficient
- 21 * for panning and zooming. Note that this is not a strict geometric
- 22 * transformation, as the <tt>lineWidth</tt> property is scale-aware: strokes
- 23 * are drawn at constant size independent of scale.
- 24 *
- 25 * <p>Panels have transparent fill styles by default; this means that panels may
- 26 * not receive mousewheel events to zoom. To fix this problem, either given the
- 27 * panel a visible fill style (such as "white"), or set the <tt>events</tt>
- 28 * property to "all" such that the panel receives events despite its transparent
- 29 * fill.
- 30 *
- 31 * <p>The zoom behavior has optional support for bounding. If enabled, the user
- 32 * will not be able to zoom out farther than the initial bounds. This feature is
- 33 * designed to work in conjunction with the pan behavior.
- 34 *
- 35 * @extends pv.Behavior
- 36 * @see pv.Panel#transform
- 37 * @see pv.Mark#scale
- 38 * @param {number} speed
- 39 */
- 40pv.Behavior.zoom=function(speed){
- 41varbound;// whether to bound to the panel
- 42
- 43if(!arguments.length)speed=1/48;
- 44
- 45/** @private */
- 46functionmousewheel(){
- 47varv=this.mouse(),
- 48k=pv.event.wheel*speed,
- 49m=this.transform().translate(v.x,v.y)
- 50.scale((k<0)?(1e3/(1e3-k)):((1e3+k)/1e3))
- 51.translate(-v.x,-v.y);
- 52if(bound){
- 53m.k=Math.max(1,m.k);
- 54m.x=Math.max((1-m.k)*this.width(),Math.min(0,m.x));
- 55m.y=Math.max((1-m.k)*this.height(),Math.min(0,m.y));
- 56}
- 57this.transform(m).render();
- 58pv.Mark.dispatch("zoom",this.scene,this.index);
- 59}
- 60
- 61/**
- 62 * Sets or gets the bound parameter. If bounding is enabled, the user will not
- 63 * be able to zoom out farther than the initial panel bounds. Bounding is not
- 64 * enabled by default. If this behavior is used in tandem with the pan
- 65 * behavior, both should use the same bound parameter.
- 66 *
- 67 * <p>Note: enabling bounding after zooming has already occurred will not
- 68 * immediately reset the transform. Bounding should be enabled before the zoom
- 69 * behavior is applied.
- 70 *
- 71 * @function
- 72 * @returns {pv.Behavior.zoom} this, or the current bound parameter.
- 73 * @name pv.Behavior.zoom.prototype.bound
- 74 * @param {boolean} [x] the new bound parameter.
- 75 */
- 76mousewheel.bound=function(x){
- 77if(arguments.length){
- 78bound=Boolean(x);
- 79returnthis;
- 80}
- 81returnBoolean(bound);
- 82};
- 83
- 84returnmousewheel;
- 85};
- 86
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_color_Color.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_color_Color.js.html
deleted file mode 100644
index d4241a2f..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_color_Color.js.html
+++ /dev/null
@@ -1,606 +0,0 @@
-
1/**
- 2 * Returns the {@link pv.Color} for the specified color format string. Colors
- 3 * may have an associated opacity, or alpha channel. Color formats are specified
- 4 * by CSS Color Modular Level 3, using either in RGB or HSL color space. For
- 5 * example:<ul>
- 6 *
- 7 * <li>#f00 // #rgb
- 8 * <li>#ff0000 // #rrggbb
- 9 * <li>rgb(255, 0, 0)
- 10 * <li>rgb(100%, 0%, 0%)
- 11 * <li>hsl(0, 100%, 50%)
- 12 * <li>rgba(0, 0, 255, 0.5)
- 13 * <li>hsla(120, 100%, 50%, 1)
- 14 *
- 15 * </ul>The SVG 1.0 color keywords names are also supported, such as "aliceblue"
- 16 * and "yellowgreen". The "transparent" keyword is supported for fully-
- 17 * transparent black.
- 18 *
- 19 * <p>If the <tt>format</tt> argument is already an instance of <tt>Color</tt>,
- 20 * the argument is returned with no further processing.
- 21 *
- 22 * @param {string} format the color specification string, such as "#f00".
- 23 * @returns {pv.Color} the corresponding <tt>Color</tt>.
- 24 * @see <a href="http://www.w3.org/TR/SVG/types.html#ColorKeywords">SVG color
- 25 * keywords</a>
- 26 * @see <a href="http://www.w3.org/TR/css3-color/">CSS3 color module</a>
- 27 */
- 28pv.color=function(format){
- 29if(format.rgb)returnformat.rgb();
- 30
- 31/* Handle hsl, rgb. */
- 32varm1=/([a-z]+)\((.*)\)/i.exec(format);
- 33if(m1){
- 34varm2=m1[2].split(","),a=1;
- 35switch(m1[1]){
- 36case"hsla":
- 37case"rgba":{
- 38a=parseFloat(m2[3]);
- 39if(!a)returnpv.Color.transparent;
- 40break;
- 41}
- 42}
- 43switch(m1[1]){
- 44case"hsla":
- 45case"hsl":{
- 46varh=parseFloat(m2[0]),// degrees
- 47s=parseFloat(m2[1])/100,// percentage
- 48l=parseFloat(m2[2])/100;// percentage
- 49return(newpv.Color.Hsl(h,s,l,a)).rgb();
- 50}
- 51case"rgba":
- 52case"rgb":{
- 53functionparse(c){// either integer or percentage
- 54varf=parseFloat(c);
- 55return(c[c.length-1]=='%')?Math.round(f*2.55):f;
- 56}
- 57varr=parse(m2[0]),g=parse(m2[1]),b=parse(m2[2]);
- 58returnpv.rgb(r,g,b,a);
- 59}
- 60}
- 61}
- 62
- 63/* Named colors. */
- 64varnamed=pv.Color.names[format];
- 65if(named)returnnamed;
- 66
- 67/* Hexadecimal colors: #rgb and #rrggbb. */
- 68if(format.charAt(0)=="#"){
- 69varr,g,b;
- 70if(format.length==4){
- 71r=format.charAt(1);r+=r;
- 72g=format.charAt(2);g+=g;
- 73b=format.charAt(3);b+=b;
- 74}elseif(format.length==7){
- 75r=format.substring(1,3);
- 76g=format.substring(3,5);
- 77b=format.substring(5,7);
- 78}
- 79returnpv.rgb(parseInt(r,16),parseInt(g,16),parseInt(b,16),1);
- 80}
- 81
- 82/* Otherwise, pass-through unsupported colors. */
- 83returnnewpv.Color(format,1);
- 84};
- 85
- 86/**
- 87 * Constructs a color with the specified color format string and opacity. This
- 88 * constructor should not be invoked directly; use {@link pv.color} instead.
- 89 *
- 90 * @class Represents an abstract (possibly translucent) color. The color is
- 91 * divided into two parts: the <tt>color</tt> attribute, an opaque color format
- 92 * string, and the <tt>opacity</tt> attribute, a float in [0, 1]. The color
- 93 * space is dependent on the implementing class; all colors support the
- 94 * {@link #rgb} method to convert to RGB color space for interpolation.
- 95 *
- 96 * <p>See also the <a href="../../api/Color.html">Color guide</a>.
- 97 *
- 98 * @param {string} color an opaque color format string, such as "#f00".
- 99 * @param {number} opacity the opacity, in [0,1].
-100 * @see pv.color
-101 */
-102pv.Color=function(color,opacity){
-103/**
-104 * An opaque color format string, such as "#f00".
-105 *
-106 * @type string
-107 * @see <a href="http://www.w3.org/TR/SVG/types.html#ColorKeywords">SVG color
-108 * keywords</a>
-109 * @see <a href="http://www.w3.org/TR/css3-color/">CSS3 color module</a>
-110 */
-111this.color=color;
-112
-113/**
-114 * The opacity, a float in [0, 1].
-115 *
-116 * @type number
-117 */
-118this.opacity=opacity;
-119};
-120
-121/**
-122 * Returns a new color that is a brighter version of this color. The behavior of
-123 * this method may vary slightly depending on the underlying color space.
-124 * Although brighter and darker are inverse operations, the results of a series
-125 * of invocations of these two methods might be inconsistent because of rounding
-126 * errors.
-127 *
-128 * @param [k] {number} an optional scale factor; defaults to 1.
-129 * @see #darker
-130 * @returns {pv.Color} a brighter color.
-131 */
-132pv.Color.prototype.brighter=function(k){
-133returnthis.rgb().brighter(k);
-134};
-135
-136/**
-137 * Returns a new color that is a brighter version of this color. The behavior of
-138 * this method may vary slightly depending on the underlying color space.
-139 * Although brighter and darker are inverse operations, the results of a series
-140 * of invocations of these two methods might be inconsistent because of rounding
-141 * errors.
-142 *
-143 * @param [k] {number} an optional scale factor; defaults to 1.
-144 * @see #brighter
-145 * @returns {pv.Color} a darker color.
-146 */
-147pv.Color.prototype.darker=function(k){
-148returnthis.rgb().darker(k);
-149};
-150
-151/**
-152 * Constructs a new RGB color with the specified channel values.
-153 *
-154 * @param {number} r the red channel, an integer in [0,255].
-155 * @param {number} g the green channel, an integer in [0,255].
-156 * @param {number} b the blue channel, an integer in [0,255].
-157 * @param {number} [a] the alpha channel, a float in [0,1].
-158 * @returns pv.Color.Rgb
-159 */
-160pv.rgb=function(r,g,b,a){
-161returnnewpv.Color.Rgb(r,g,b,(arguments.length==4)?a:1);
-162};
-163
-164/**
-165 * Constructs a new RGB color with the specified channel values.
-166 *
-167 * @class Represents a color in RGB space.
-168 *
-169 * @param {number} r the red channel, an integer in [0,255].
-170 * @param {number} g the green channel, an integer in [0,255].
-171 * @param {number} b the blue channel, an integer in [0,255].
-172 * @param {number} a the alpha channel, a float in [0,1].
-173 * @extends pv.Color
-174 */
-175pv.Color.Rgb=function(r,g,b,a){
-176pv.Color.call(this,a?("rgb("+r+","+g+","+b+")"):"none",a);
-177
-178/**
-179 * The red channel, an integer in [0, 255].
-180 *
-181 * @type number
-182 */
-183this.r=r;
-184
-185/**
-186 * The green channel, an integer in [0, 255].
-187 *
-188 * @type number
-189 */
-190this.g=g;
-191
-192/**
-193 * The blue channel, an integer in [0, 255].
-194 *
-195 * @type number
-196 */
-197this.b=b;
-198
-199/**
-200 * The alpha channel, a float in [0, 1].
-201 *
-202 * @type number
-203 */
-204this.a=a;
-205};
-206pv.Color.Rgb.prototype=pv.extend(pv.Color);
-207
-208/**
-209 * Constructs a new RGB color with the same green, blue and alpha channels as
-210 * this color, with the specified red channel.
-211 *
-212 * @param {number} r the red channel, an integer in [0,255].
-213 */
-214pv.Color.Rgb.prototype.red=function(r){
-215returnpv.rgb(r,this.g,this.b,this.a);
-216};
-217
-218/**
-219 * Constructs a new RGB color with the same red, blue and alpha channels as this
-220 * color, with the specified green channel.
-221 *
-222 * @param {number} g the green channel, an integer in [0,255].
-223 */
-224pv.Color.Rgb.prototype.green=function(g){
-225returnpv.rgb(this.r,g,this.b,this.a);
-226};
-227
-228/**
-229 * Constructs a new RGB color with the same red, green and alpha channels as
-230 * this color, with the specified blue channel.
-231 *
-232 * @param {number} b the blue channel, an integer in [0,255].
-233 */
-234pv.Color.Rgb.prototype.blue=function(b){
-235returnpv.rgb(this.r,this.g,b,this.a);
-236};
-237
-238/**
-239 * Constructs a new RGB color with the same red, green and blue channels as this
-240 * color, with the specified alpha channel.
-241 *
-242 * @param {number} a the alpha channel, a float in [0,1].
-243 */
-244pv.Color.Rgb.prototype.alpha=function(a){
-245returnpv.rgb(this.r,this.g,this.b,a);
-246};
-247
-248/**
-249 * Returns the RGB color equivalent to this color. This method is abstract and
-250 * must be implemented by subclasses.
-251 *
-252 * @returns {pv.Color.Rgb} an RGB color.
-253 * @function
-254 * @name pv.Color.prototype.rgb
-255 */
-256
-257/**
-258 * Returns this.
-259 *
-260 * @returns {pv.Color.Rgb} this.
-261 */
-262pv.Color.Rgb.prototype.rgb=function(){returnthis;};
-263
-264/**
-265 * Returns a new color that is a brighter version of this color. This method
-266 * applies an arbitrary scale factor to each of the three RGB components of this
-267 * color to create a brighter version of this color. Although brighter and
-268 * darker are inverse operations, the results of a series of invocations of
-269 * these two methods might be inconsistent because of rounding errors.
-270 *
-271 * @param [k] {number} an optional scale factor; defaults to 1.
-272 * @see #darker
-273 * @returns {pv.Color.Rgb} a brighter color.
-274 */
-275pv.Color.Rgb.prototype.brighter=function(k){
-276k=Math.pow(0.7,arguments.length?k:1);
-277varr=this.r,g=this.g,b=this.b,i=30;
-278if(!r&&!g&&!b)returnpv.rgb(i,i,i,this.a);
-279if(r&&(r<i))r=i;
-280if(g&&(g<i))g=i;
-281if(b&&(b<i))b=i;
-282returnpv.rgb(
-283Math.min(255,Math.floor(r/k)),
-284Math.min(255,Math.floor(g/k)),
-285Math.min(255,Math.floor(b/k)),
-286this.a);
-287};
-288
-289/**
-290 * Returns a new color that is a darker version of this color. This method
-291 * applies an arbitrary scale factor to each of the three RGB components of this
-292 * color to create a darker version of this color. Although brighter and darker
-293 * are inverse operations, the results of a series of invocations of these two
-294 * methods might be inconsistent because of rounding errors.
-295 *
-296 * @param [k] {number} an optional scale factor; defaults to 1.
-297 * @see #brighter
-298 * @returns {pv.Color.Rgb} a darker color.
-299 */
-300pv.Color.Rgb.prototype.darker=function(k){
-301k=Math.pow(0.7,arguments.length?k:1);
-302returnpv.rgb(
-303Math.max(0,Math.floor(k*this.r)),
-304Math.max(0,Math.floor(k*this.g)),
-305Math.max(0,Math.floor(k*this.b)),
-306this.a);
-307};
-308
-309/**
-310 * Constructs a new HSL color with the specified values.
-311 *
-312 * @param {number} h the hue, an integer in [0, 360].
-313 * @param {number} s the saturation, a float in [0, 1].
-314 * @param {number} l the lightness, a float in [0, 1].
-315 * @param {number} [a] the opacity, a float in [0, 1].
-316 * @returns pv.Color.Hsl
-317 */
-318pv.hsl=function(h,s,l,a){
-319returnnewpv.Color.Hsl(h,s,l,(arguments.length==4)?a:1);
-320};
-321
-322/**
-323 * Constructs a new HSL color with the specified values.
-324 *
-325 * @class Represents a color in HSL space.
-326 *
-327 * @param {number} h the hue, an integer in [0, 360].
-328 * @param {number} s the saturation, a float in [0, 1].
-329 * @param {number} l the lightness, a float in [0, 1].
-330 * @param {number} a the opacity, a float in [0, 1].
-331 * @extends pv.Color
-332 */
-333pv.Color.Hsl=function(h,s,l,a){
-334pv.Color.call(this,"hsl("+h+","+(s*100)+"%,"+(l*100)+"%)",a);
-335
-336/**
-337 * The hue, an integer in [0, 360].
-338 *
-339 * @type number
-340 */
-341this.h=h;
-342
-343/**
-344 * The saturation, a float in [0, 1].
-345 *
-346 * @type number
-347 */
-348this.s=s;
-349
-350/**
-351 * The lightness, a float in [0, 1].
-352 *
-353 * @type number
-354 */
-355this.l=l;
-356
-357/**
-358 * The opacity, a float in [0, 1].
-359 *
-360 * @type number
-361 */
-362this.a=a;
-363};
-364pv.Color.Hsl.prototype=pv.extend(pv.Color);
-365
-366/**
-367 * Constructs a new HSL color with the same saturation, lightness and alpha as
-368 * this color, and the specified hue.
-369 *
-370 * @param {number} h the hue, an integer in [0, 360].
-371 */
-372pv.Color.Hsl.prototype.hue=function(h){
-373returnpv.hsl(h,this.s,this.l,this.a);
-374};
-375
-376/**
-377 * Constructs a new HSL color with the same hue, lightness and alpha as this
-378 * color, and the specified saturation.
-379 *
-380 * @param {number} s the saturation, a float in [0, 1].
-381 */
-382pv.Color.Hsl.prototype.saturation=function(s){
-383returnpv.hsl(this.h,s,this.l,this.a);
-384};
-385
-386/**
-387 * Constructs a new HSL color with the same hue, saturation and alpha as this
-388 * color, and the specified lightness.
-389 *
-390 * @param {number} l the lightness, a float in [0, 1].
-391 */
-392pv.Color.Hsl.prototype.lightness=function(l){
-393returnpv.hsl(this.h,this.s,l,this.a);
-394};
-395
-396/**
-397 * Constructs a new HSL color with the same hue, saturation and lightness as
-398 * this color, and the specified alpha.
-399 *
-400 * @param {number} a the opacity, a float in [0, 1].
-401 */
-402pv.Color.Hsl.prototype.alpha=function(a){
-403returnpv.hsl(this.h,this.s,this.l,a);
-404};
-405
-406/**
-407 * Returns the RGB color equivalent to this HSL color.
-408 *
-409 * @returns {pv.Color.Rgb} an RGB color.
-410 */
-411pv.Color.Hsl.prototype.rgb=function(){
-412varh=this.h,s=this.s,l=this.l;
-413
-414/* Some simple corrections for h, s and l. */
-415h=h%360;if(h<0)h+=360;
-416s=Math.max(0,Math.min(s,1));
-417l=Math.max(0,Math.min(l,1));
-418
-419/* From FvD 13.37, CSS Color Module Level 3 */
-420varm2=(l<=.5)?(l*(1+s)):(l+s-l*s);
-421varm1=2*l-m2;
-422functionv(h){
-423if(h>360)h-=360;
-424elseif(h<0)h+=360;
-425if(h<60)returnm1+(m2-m1)*h/60;
-426if(h<180)returnm2;
-427if(h<240)returnm1+(m2-m1)*(240-h)/60;
-428returnm1;
-429}
-430functionvv(h){
-431returnMath.round(v(h)*255);
-432}
-433
-434returnpv.rgb(vv(h+120),vv(h),vv(h-120),this.a);
-435};
-436
-437/**
-438 * @private SVG color keywords, per CSS Color Module Level 3.
-439 *
-440 * @see <a href="http://www.w3.org/TR/SVG/types.html#ColorKeywords">SVG color
-441 * keywords</a>
-442 */
-443pv.Color.names={
-444aliceblue:"#f0f8ff",
-445antiquewhite:"#faebd7",
-446aqua:"#00ffff",
-447aquamarine:"#7fffd4",
-448azure:"#f0ffff",
-449beige:"#f5f5dc",
-450bisque:"#ffe4c4",
-451black:"#000000",
-452blanchedalmond:"#ffebcd",
-453blue:"#0000ff",
-454blueviolet:"#8a2be2",
-455brown:"#a52a2a",
-456burlywood:"#deb887",
-457cadetblue:"#5f9ea0",
-458chartreuse:"#7fff00",
-459chocolate:"#d2691e",
-460coral:"#ff7f50",
-461cornflowerblue:"#6495ed",
-462cornsilk:"#fff8dc",
-463crimson:"#dc143c",
-464cyan:"#00ffff",
-465darkblue:"#00008b",
-466darkcyan:"#008b8b",
-467darkgoldenrod:"#b8860b",
-468darkgray:"#a9a9a9",
-469darkgreen:"#006400",
-470darkgrey:"#a9a9a9",
-471darkkhaki:"#bdb76b",
-472darkmagenta:"#8b008b",
-473darkolivegreen:"#556b2f",
-474darkorange:"#ff8c00",
-475darkorchid:"#9932cc",
-476darkred:"#8b0000",
-477darksalmon:"#e9967a",
-478darkseagreen:"#8fbc8f",
-479darkslateblue:"#483d8b",
-480darkslategray:"#2f4f4f",
-481darkslategrey:"#2f4f4f",
-482darkturquoise:"#00ced1",
-483darkviolet:"#9400d3",
-484deeppink:"#ff1493",
-485deepskyblue:"#00bfff",
-486dimgray:"#696969",
-487dimgrey:"#696969",
-488dodgerblue:"#1e90ff",
-489firebrick:"#b22222",
-490floralwhite:"#fffaf0",
-491forestgreen:"#228b22",
-492fuchsia:"#ff00ff",
-493gainsboro:"#dcdcdc",
-494ghostwhite:"#f8f8ff",
-495gold:"#ffd700",
-496goldenrod:"#daa520",
-497gray:"#808080",
-498green:"#008000",
-499greenyellow:"#adff2f",
-500grey:"#808080",
-501honeydew:"#f0fff0",
-502hotpink:"#ff69b4",
-503indianred:"#cd5c5c",
-504indigo:"#4b0082",
-505ivory:"#fffff0",
-506khaki:"#f0e68c",
-507lavender:"#e6e6fa",
-508lavenderblush:"#fff0f5",
-509lawngreen:"#7cfc00",
-510lemonchiffon:"#fffacd",
-511lightblue:"#add8e6",
-512lightcoral:"#f08080",
-513lightcyan:"#e0ffff",
-514lightgoldenrodyellow:"#fafad2",
-515lightgray:"#d3d3d3",
-516lightgreen:"#90ee90",
-517lightgrey:"#d3d3d3",
-518lightpink:"#ffb6c1",
-519lightsalmon:"#ffa07a",
-520lightseagreen:"#20b2aa",
-521lightskyblue:"#87cefa",
-522lightslategray:"#778899",
-523lightslategrey:"#778899",
-524lightsteelblue:"#b0c4de",
-525lightyellow:"#ffffe0",
-526lime:"#00ff00",
-527limegreen:"#32cd32",
-528linen:"#faf0e6",
-529magenta:"#ff00ff",
-530maroon:"#800000",
-531mediumaquamarine:"#66cdaa",
-532mediumblue:"#0000cd",
-533mediumorchid:"#ba55d3",
-534mediumpurple:"#9370db",
-535mediumseagreen:"#3cb371",
-536mediumslateblue:"#7b68ee",
-537mediumspringgreen:"#00fa9a",
-538mediumturquoise:"#48d1cc",
-539mediumvioletred:"#c71585",
-540midnightblue:"#191970",
-541mintcream:"#f5fffa",
-542mistyrose:"#ffe4e1",
-543moccasin:"#ffe4b5",
-544navajowhite:"#ffdead",
-545navy:"#000080",
-546oldlace:"#fdf5e6",
-547olive:"#808000",
-548olivedrab:"#6b8e23",
-549orange:"#ffa500",
-550orangered:"#ff4500",
-551orchid:"#da70d6",
-552palegoldenrod:"#eee8aa",
-553palegreen:"#98fb98",
-554paleturquoise:"#afeeee",
-555palevioletred:"#db7093",
-556papayawhip:"#ffefd5",
-557peachpuff:"#ffdab9",
-558peru:"#cd853f",
-559pink:"#ffc0cb",
-560plum:"#dda0dd",
-561powderblue:"#b0e0e6",
-562purple:"#800080",
-563red:"#ff0000",
-564rosybrown:"#bc8f8f",
-565royalblue:"#4169e1",
-566saddlebrown:"#8b4513",
-567salmon:"#fa8072",
-568sandybrown:"#f4a460",
-569seagreen:"#2e8b57",
-570seashell:"#fff5ee",
-571sienna:"#a0522d",
-572silver:"#c0c0c0",
-573skyblue:"#87ceeb",
-574slateblue:"#6a5acd",
-575slategray:"#708090",
-576slategrey:"#708090",
-577snow:"#fffafa",
-578springgreen:"#00ff7f",
-579steelblue:"#4682b4",
-580tan:"#d2b48c",
-581teal:"#008080",
-582thistle:"#d8bfd8",
-583tomato:"#ff6347",
-584turquoise:"#40e0d0",
-585violet:"#ee82ee",
-586wheat:"#f5deb3",
-587white:"#ffffff",
-588whitesmoke:"#f5f5f5",
-589yellow:"#ffff00",
-590yellowgreen:"#9acd32",
-591transparent:pv.Color.transparent=pv.rgb(0,0,0,0)
-592};
-593
-594/* Initialized named colors. */
-595(function(){
-596varnames=pv.Color.names;
-597for(varnameinnames)names[name]=pv.color(names[name]);
-598})();
-599
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_color_Colors.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_color_Colors.js.html
deleted file mode 100644
index b3839b09..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_color_Colors.js.html
+++ /dev/null
@@ -1,143 +0,0 @@
-
1/**
- 2 * Returns a new categorical color encoding using the specified colors. The
- 3 * arguments to this method are an array of colors; see {@link pv.color}. For
- 4 * example, to create a categorical color encoding using the <tt>species</tt>
- 5 * attribute:
- 6 *
- 7 * <pre>pv.colors("red", "green", "blue").by(function(d) d.species)</pre>
- 8 *
- 9 * The result of this expression can be used as a fill- or stroke-style
- 10 * property. This assumes that the data's <tt>species</tt> attribute is a
- 11 * string.
- 12 *
- 13 * @param {string} colors... categorical colors.
- 14 * @see pv.Scale.ordinal
- 15 * @returns {pv.Scale.ordinal} an ordinal color scale.
- 16 */
- 17pv.colors=function(){
- 18varscale=pv.Scale.ordinal();
- 19scale.range.apply(scale,arguments);
- 20returnscale;
- 21};
- 22
- 23/**
- 24 * A collection of standard color palettes for categorical encoding.
- 25 *
- 26 * @namespace A collection of standard color palettes for categorical encoding.
- 27 */
- 28pv.Colors={};
- 29
- 30/**
- 31 * Returns a new 10-color scheme. The arguments to this constructor are
- 32 * optional, and equivalent to calling {@link pv.Scale.OrdinalScale#domain}. The
- 33 * following colors are used:
- 34 *
- 35 * <div style="background:#1f77b4;">#1f77b4</div>
- 36 * <div style="background:#ff7f0e;">#ff7f0e</div>
- 37 * <div style="background:#2ca02c;">#2ca02c</div>
- 38 * <div style="background:#d62728;">#d62728</div>
- 39 * <div style="background:#9467bd;">#9467bd</div>
- 40 * <div style="background:#8c564b;">#8c564b</div>
- 41 * <div style="background:#e377c2;">#e377c2</div>
- 42 * <div style="background:#7f7f7f;">#7f7f7f</div>
- 43 * <div style="background:#bcbd22;">#bcbd22</div>
- 44 * <div style="background:#17becf;">#17becf</div>
- 45 *
- 46 * @param {number...} domain... domain values.
- 47 * @returns {pv.Scale.ordinal} a new ordinal color scale.
- 48 * @see pv.color
- 49 */
- 50pv.Colors.category10=function(){
- 51varscale=pv.colors(
- 52"#1f77b4","#ff7f0e","#2ca02c","#d62728","#9467bd",
- 53"#8c564b","#e377c2","#7f7f7f","#bcbd22","#17becf");
- 54scale.domain.apply(scale,arguments);
- 55returnscale;
- 56};
- 57
- 58/**
- 59 * Returns a new 20-color scheme. The arguments to this constructor are
- 60 * optional, and equivalent to calling {@link pv.Scale.OrdinalScale#domain}. The
- 61 * following colors are used:
- 62 *
- 63 * <div style="background:#1f77b4;">#1f77b4</div>
- 64 * <div style="background:#aec7e8;">#aec7e8</div>
- 65 * <div style="background:#ff7f0e;">#ff7f0e</div>
- 66 * <div style="background:#ffbb78;">#ffbb78</div>
- 67 * <div style="background:#2ca02c;">#2ca02c</div>
- 68 * <div style="background:#98df8a;">#98df8a</div>
- 69 * <div style="background:#d62728;">#d62728</div>
- 70 * <div style="background:#ff9896;">#ff9896</div>
- 71 * <div style="background:#9467bd;">#9467bd</div>
- 72 * <div style="background:#c5b0d5;">#c5b0d5</div>
- 73 * <div style="background:#8c564b;">#8c564b</div>
- 74 * <div style="background:#c49c94;">#c49c94</div>
- 75 * <div style="background:#e377c2;">#e377c2</div>
- 76 * <div style="background:#f7b6d2;">#f7b6d2</div>
- 77 * <div style="background:#7f7f7f;">#7f7f7f</div>
- 78 * <div style="background:#c7c7c7;">#c7c7c7</div>
- 79 * <div style="background:#bcbd22;">#bcbd22</div>
- 80 * <div style="background:#dbdb8d;">#dbdb8d</div>
- 81 * <div style="background:#17becf;">#17becf</div>
- 82 * <div style="background:#9edae5;">#9edae5</div>
- 83 *
- 84 * @param {number...} domain... domain values.
- 85 * @returns {pv.Scale.ordinal} a new ordinal color scale.
- 86 * @see pv.color
- 87 */
- 88pv.Colors.category20=function(){
- 89varscale=pv.colors(
- 90"#1f77b4","#aec7e8","#ff7f0e","#ffbb78","#2ca02c",
- 91"#98df8a","#d62728","#ff9896","#9467bd","#c5b0d5",
- 92"#8c564b","#c49c94","#e377c2","#f7b6d2","#7f7f7f",
- 93"#c7c7c7","#bcbd22","#dbdb8d","#17becf","#9edae5");
- 94scale.domain.apply(scale,arguments);
- 95returnscale;
- 96};
- 97
- 98/**
- 99 * Returns a new alternative 19-color scheme. The arguments to this constructor
-100 * are optional, and equivalent to calling
-101 * {@link pv.Scale.OrdinalScale#domain}. The following colors are used:
-102 *
-103 * <div style="background:#9c9ede;">#9c9ede</div>
-104 * <div style="background:#7375b5;">#7375b5</div>
-105 * <div style="background:#4a5584;">#4a5584</div>
-106 * <div style="background:#cedb9c;">#cedb9c</div>
-107 * <div style="background:#b5cf6b;">#b5cf6b</div>
-108 * <div style="background:#8ca252;">#8ca252</div>
-109 * <div style="background:#637939;">#637939</div>
-110 * <div style="background:#e7cb94;">#e7cb94</div>
-111 * <div style="background:#e7ba52;">#e7ba52</div>
-112 * <div style="background:#bd9e39;">#bd9e39</div>
-113 * <div style="background:#8c6d31;">#8c6d31</div>
-114 * <div style="background:#e7969c;">#e7969c</div>
-115 * <div style="background:#d6616b;">#d6616b</div>
-116 * <div style="background:#ad494a;">#ad494a</div>
-117 * <div style="background:#843c39;">#843c39</div>
-118 * <div style="background:#de9ed6;">#de9ed6</div>
-119 * <div style="background:#ce6dbd;">#ce6dbd</div>
-120 * <div style="background:#a55194;">#a55194</div>
-121 * <div style="background:#7b4173;">#7b4173</div>
-122 *
-123 * @param {number...} domain... domain values.
-124 * @returns {pv.Scale.ordinal} a new ordinal color scale.
-125 * @see pv.color
-126 */
-127pv.Colors.category19=function(){
-128varscale=pv.colors(
-129"#9c9ede","#7375b5","#4a5584","#cedb9c","#b5cf6b",
-130"#8ca252","#637939","#e7cb94","#e7ba52","#bd9e39",
-131"#8c6d31","#e7969c","#d6616b","#ad494a","#843c39",
-132"#de9ed6","#ce6dbd","#a55194","#7b4173");
-133scale.domain.apply(scale,arguments);
-134returnscale;
-135};
-136
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_color_Ramp.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_color_Ramp.js.html
deleted file mode 100644
index 0a8ec84b..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_color_Ramp.js.html
+++ /dev/null
@@ -1,25 +0,0 @@
-
1/**
- 2 * Returns a linear color ramp from the specified <tt>start</tt> color to the
- 3 * specified <tt>end</tt> color. The color arguments may be specified either as
- 4 * <tt>string</tt>s or as {@link pv.Color}s. This is equivalent to:
- 5 *
- 6 * <pre> pv.Scale.linear().domain(0, 1).range(...)</pre>
- 7 *
- 8 * @param {string} start the start color; may be a <tt>pv.Color</tt>.
- 9 * @param {string} end the end color; may be a <tt>pv.Color</tt>.
- 10 * @returns {Function} a color ramp from <tt>start</tt> to <tt>end</tt>.
- 11 * @see pv.Scale.linear
- 12 */
- 13pv.ramp=function(start,end){
- 14varscale=pv.Scale.linear();
- 15scale.range.apply(scale,arguments);
- 16returnscale;
- 17};
- 18
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Arrays.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Arrays.js.html
deleted file mode 100644
index f22b864e..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Arrays.js.html
+++ /dev/null
@@ -1,285 +0,0 @@
-
1/**
- 2 * @private A private variant of Array.prototype.map that supports the index
- 3 * property.
- 4 */
- 5pv.map=function(array,f){
- 6varo={};
- 7returnf
- 8?array.map(function(d,i){o.index=i;returnf.call(o,d);})
- 9:array.slice();
- 10};
- 11
- 12/**
- 13 * Concatenates the specified array with itself <i>n</i> times. For example,
- 14 * <tt>pv.repeat([1, 2])</tt> returns [1, 2, 1, 2].
- 15 *
- 16 * @param {array} a an array.
- 17 * @param {number} [n] the number of times to repeat; defaults to two.
- 18 * @returns {array} an array that repeats the specified array.
- 19 */
- 20pv.repeat=function(array,n){
- 21if(arguments.length==1)n=2;
- 22returnpv.blend(pv.range(n).map(function(){returnarray;}));
- 23};
- 24
- 25/**
- 26 * Given two arrays <tt>a</tt> and <tt>b</tt>, <style
- 27 * type="text/css">sub{line-height:0}</style> returns an array of all possible
- 28 * pairs of elements [a<sub>i</sub>, b<sub>j</sub>]. The outer loop is on array
- 29 * <i>a</i>, while the inner loop is on <i>b</i>, such that the order of
- 30 * returned elements is [a<sub>0</sub>, b<sub>0</sub>], [a<sub>0</sub>,
- 31 * b<sub>1</sub>], ... [a<sub>0</sub>, b<sub>m</sub>], [a<sub>1</sub>,
- 32 * b<sub>0</sub>], [a<sub>1</sub>, b<sub>1</sub>], ... [a<sub>1</sub>,
- 33 * b<sub>m</sub>], ... [a<sub>n</sub>, b<sub>m</sub>]. If either array is empty,
- 34 * an empty array is returned.
- 35 *
- 36 * @param {array} a an array.
- 37 * @param {array} b an array.
- 38 * @returns {array} an array of pairs of elements in <tt>a</tt> and <tt>b</tt>.
- 39 */
- 40pv.cross=function(a,b){
- 41vararray=[];
- 42for(vari=0,n=a.length,m=b.length;i<n;i++){
- 43for(varj=0,x=a[i];j<m;j++){
- 44array.push([x,b[j]]);
- 45}
- 46}
- 47returnarray;
- 48};
- 49
- 50/**
- 51 * Given the specified array of arrays, concatenates the arrays into a single
- 52 * array. If the individual arrays are explicitly known, an alternative to blend
- 53 * is to use JavaScript's <tt>concat</tt> method directly. These two equivalent
- 54 * expressions:<ul>
- 55 *
- 56 * <li><tt>pv.blend([[1, 2, 3], ["a", "b", "c"]])</tt>
- 57 * <li><tt>[1, 2, 3].concat(["a", "b", "c"])</tt>
- 58 *
- 59 * </ul>return [1, 2, 3, "a", "b", "c"].
- 60 *
- 61 * @param {array[]} arrays an array of arrays.
- 62 * @returns {array} an array containing all the elements of each array in
- 63 * <tt>arrays</tt>.
- 64 */
- 65pv.blend=function(arrays){
- 66returnArray.prototype.concat.apply([],arrays);
- 67};
- 68
- 69/**
- 70 * Given the specified array of arrays, <style
- 71 * type="text/css">sub{line-height:0}</style> transposes each element
- 72 * array<sub>ij</sub> with array<sub>ji</sub>. If the array has dimensions
- 73 * <i>n</i>×<i>m</i>, it will have dimensions <i>m</i>×<i>n</i>
- 74 * after this method returns. This method transposes the elements of the array
- 75 * in place, mutating the array, and returning a reference to the array.
- 76 *
- 77 * @param {array[]} arrays an array of arrays.
- 78 * @returns {array[]} the passed-in array, after transposing the elements.
- 79 */
- 80pv.transpose=function(arrays){
- 81varn=arrays.length,m=pv.max(arrays,function(d){returnd.length;});
- 82
- 83if(m>n){
- 84arrays.length=m;
- 85for(vari=n;i<m;i++){
- 86arrays[i]=newArray(n);
- 87}
- 88for(vari=0;i<n;i++){
- 89for(varj=i+1;j<m;j++){
- 90vart=arrays[i][j];
- 91arrays[i][j]=arrays[j][i];
- 92arrays[j][i]=t;
- 93}
- 94}
- 95}else{
- 96for(vari=0;i<m;i++){
- 97arrays[i].length=n;
- 98}
- 99for(vari=0;i<n;i++){
-100for(varj=0;j<i;j++){
-101vart=arrays[i][j];
-102arrays[i][j]=arrays[j][i];
-103arrays[j][i]=t;
-104}
-105}
-106}
-107
-108arrays.length=m;
-109for(vari=0;i<m;i++){
-110arrays[i].length=n;
-111}
-112
-113returnarrays;
-114};
-115
-116/**
-117 * Returns a normalized copy of the specified array, such that the sum of the
-118 * returned elements sum to one. If the specified array is not an array of
-119 * numbers, an optional accessor function <tt>f</tt> can be specified to map the
-120 * elements to numbers. For example, if <tt>array</tt> is an array of objects,
-121 * and each object has a numeric property "foo", the expression
-122 *
-123 * <pre>pv.normalize(array, function(d) d.foo)</pre>
-124 *
-125 * returns a normalized array on the "foo" property. If an accessor function is
-126 * not specified, the identity function is used. Accessor functions can refer to
-127 * <tt>this.index</tt>.
-128 *
-129 * @param {array} array an array of objects, or numbers.
-130 * @param {function} [f] an optional accessor function.
-131 * @returns {number[]} an array of numbers that sums to one.
-132 */
-133pv.normalize=function(array,f){
-134varnorm=pv.map(array,f),sum=pv.sum(norm);
-135for(vari=0;i<norm.length;i++)norm[i]/=sum;
-136returnnorm;
-137};
-138
-139/**
-140 * Returns a permutation of the specified array, using the specified array of
-141 * indexes. The returned array contains the corresponding element in
-142 * <tt>array</tt> for each index in <tt>indexes</tt>, in order. For example,
-143 *
-144 * <pre>pv.permute(["a", "b", "c"], [1, 2, 0])</pre>
-145 *
-146 * returns <tt>["b", "c", "a"]</tt>. It is acceptable for the array of indexes
-147 * to be a different length from the array of elements, and for indexes to be
-148 * duplicated or omitted. The optional accessor function <tt>f</tt> can be used
-149 * to perform a simultaneous mapping of the array elements. Accessor functions
-150 * can refer to <tt>this.index</tt>.
-151 *
-152 * @param {array} array an array.
-153 * @param {number[]} indexes an array of indexes into <tt>array</tt>.
-154 * @param {function} [f] an optional accessor function.
-155 * @returns {array} an array of elements from <tt>array</tt>; a permutation.
-156 */
-157pv.permute=function(array,indexes,f){
-158if(!f)f=pv.identity;
-159varp=newArray(indexes.length),o={};
-160indexes.forEach(function(j,i){o.index=j;p[i]=f.call(o,array[j]);});
-161returnp;
-162};
-163
-164/**
-165 * Returns a map from key to index for the specified <tt>keys</tt> array. For
-166 * example,
-167 *
-168 * <pre>pv.numerate(["a", "b", "c"])</pre>
-169 *
-170 * returns <tt>{a: 0, b: 1, c: 2}</tt>. Note that since JavaScript maps only
-171 * support string keys, <tt>keys</tt> must contain strings, or other values that
-172 * naturally map to distinct string values. Alternatively, an optional accessor
-173 * function <tt>f</tt> can be specified to compute the string key for the given
-174 * element. Accessor functions can refer to <tt>this.index</tt>.
-175 *
-176 * @param {array} keys an array, usually of string keys.
-177 * @param {function} [f] an optional key function.
-178 * @returns a map from key to index.
-179 */
-180pv.numerate=function(keys,f){
-181if(!f)f=pv.identity;
-182varmap={},o={};
-183keys.forEach(function(x,i){o.index=i;map[f.call(o,x)]=i;});
-184returnmap;
-185};
-186
-187/**
-188 * Returns the unique elements in the specified array, in the order they appear.
-189 * Note that since JavaScript maps only support string keys, <tt>array</tt> must
-190 * contain strings, or other values that naturally map to distinct string
-191 * values. Alternatively, an optional accessor function <tt>f</tt> can be
-192 * specified to compute the string key for the given element. Accessor functions
-193 * can refer to <tt>this.index</tt>.
-194 *
-195 * @param {array} array an array, usually of string keys.
-196 * @param {function} [f] an optional key function.
-197 * @returns {array} the unique values.
-198 */
-199pv.uniq=function(array,f){
-200if(!f)f=pv.identity;
-201varmap={},keys=[],o={},y;
-202array.forEach(function(x,i){
-203o.index=i;
-204y=f.call(o,x);
-205if(!(yinmap))map[y]=keys.push(y);
-206});
-207returnkeys;
-208};
-209
-210/**
-211 * The comparator function for natural order. This can be used in conjunction with
-212 * the built-in array <tt>sort</tt> method to sort elements by their natural
-213 * order, ascending. Note that if no comparator function is specified to the
-214 * built-in <tt>sort</tt> method, the default order is lexicographic, <i>not</i>
-215 * natural!
-216 *
-217 * @see <a
-218 * href="http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Array/sort">Array.sort</a>.
-219 * @param a an element to compare.
-220 * @param b an element to compare.
-221 * @returns {number} negative if a < b; positive if a > b; otherwise 0.
-222 */
-223pv.naturalOrder=function(a,b){
-224return(a<b)?-1:((a>b)?1:0);
-225};
-226
-227/**
-228 * The comparator function for reverse natural order. This can be used in
-229 * conjunction with the built-in array <tt>sort</tt> method to sort elements by
-230 * their natural order, descending. Note that if no comparator function is
-231 * specified to the built-in <tt>sort</tt> method, the default order is
-232 * lexicographic, <i>not</i> natural!
-233 *
-234 * @see #naturalOrder
-235 * @param a an element to compare.
-236 * @param b an element to compare.
-237 * @returns {number} negative if a < b; positive if a > b; otherwise 0.
-238 */
-239pv.reverseOrder=function(b,a){
-240return(a<b)?-1:((a>b)?1:0);
-241};
-242
-243/**
-244 * Searches the specified array of numbers for the specified value using the
-245 * binary search algorithm. The array must be sorted (as by the <tt>sort</tt>
-246 * method) prior to making this call. If it is not sorted, the results are
-247 * undefined. If the array contains multiple elements with the specified value,
-248 * there is no guarantee which one will be found.
-249 *
-250 * <p>The <i>insertion point</i> is defined as the point at which the value
-251 * would be inserted into the array: the index of the first element greater than
-252 * the value, or <tt>array.length</tt>, if all elements in the array are less
-253 * than the specified value. Note that this guarantees that the return value
-254 * will be nonnegative if and only if the value is found.
-255 *
-256 * @param {number[]} array the array to be searched.
-257 * @param {number} value the value to be searched for.
-258 * @returns the index of the search value, if it is contained in the array;
-259 * otherwise, (-(<i>insertion point</i>) - 1).
-260 * @param {function} [f] an optional key function.
-261 */
-262pv.search=function(array,value,f){
-263if(!f)f=pv.identity;
-264varlow=0,high=array.length-1;
-265while(low<=high){
-266varmid=(low+high)>>1,midValue=f(array[mid]);
-267if(midValue<value)low=mid+1;
-268elseif(midValue>value)high=mid-1;
-269elsereturnmid;
-270}
-271return-low-1;
-272};
-273
-274pv.search.index=function(array,value,f){
-275vari=pv.search(array,value,f);
-276return(i<0)?(-i-1):i;
-277};
-278
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Dom.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Dom.js.html
deleted file mode 100644
index 517374f7..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Dom.js.html
+++ /dev/null
@@ -1,388 +0,0 @@
-
1/**
- 2 * Returns a {@link pv.Dom} operator for the given map. This is a convenience
- 3 * factory method, equivalent to <tt>new pv.Dom(map)</tt>. To apply the operator
- 4 * and retrieve the root node, call {@link pv.Dom#root}; to retrieve all nodes
- 5 * flattened, use {@link pv.Dom#nodes}.
- 6 *
- 7 * @see pv.Dom
- 8 * @param map a map from which to construct a DOM.
- 9 * @returns {pv.Dom} a DOM operator for the specified map.
- 10 */
- 11pv.dom=function(map){
- 12returnnewpv.Dom(map);
- 13};
- 14
- 15/**
- 16 * Constructs a DOM operator for the specified map. This constructor should not
- 17 * be invoked directly; use {@link pv.dom} instead.
- 18 *
- 19 * @class Represets a DOM operator for the specified map. This allows easy
- 20 * transformation of a hierarchical JavaScript object (such as a JSON map) to a
- 21 * W3C Document Object Model hierarchy. For more information on which attributes
- 22 * and methods from the specification are supported, see {@link pv.Dom.Node}.
- 23 *
- 24 * <p>Leaves in the map are determined using an associated <i>leaf</i> function;
- 25 * see {@link #leaf}. By default, leaves are any value whose type is not
- 26 * "object", such as numbers or strings.
- 27 *
- 28 * @param map a map from which to construct a DOM.
- 29 */
- 30pv.Dom=function(map){
- 31this.$map=map;
- 32};
- 33
- 34/** @private The default leaf function. */
- 35pv.Dom.prototype.$leaf=function(n){
- 36returntypeofn!="object";
- 37};
- 38
- 39/**
- 40 * Sets or gets the leaf function for this DOM operator. The leaf function
- 41 * identifies which values in the map are leaves, and which are internal nodes.
- 42 * By default, objects are considered internal nodes, and primitives (such as
- 43 * numbers and strings) are considered leaves.
- 44 *
- 45 * @param {function} f the new leaf function.
- 46 * @returns the current leaf function, or <tt>this</tt>.
- 47 */
- 48pv.Dom.prototype.leaf=function(f){
- 49if(arguments.length){
- 50this.$leaf=f;
- 51returnthis;
- 52}
- 53returnthis.$leaf;
- 54};
- 55
- 56/**
- 57 * Applies the DOM operator, returning the root node.
- 58 *
- 59 * @returns {pv.Dom.Node} the root node.
- 60 * @param {string} [nodeName] optional node name for the root.
- 61 */
- 62pv.Dom.prototype.root=function(nodeName){
- 63varleaf=this.$leaf,root=recurse(this.$map);
- 64
- 65/** @private */
- 66functionrecurse(map){
- 67varn=newpv.Dom.Node();
- 68for(varkinmap){
- 69varv=map[k];
- 70n.appendChild(leaf(v)?newpv.Dom.Node(v):recurse(v)).nodeName=k;
- 71}
- 72returnn;
- 73}
- 74
- 75root.nodeName=nodeName;
- 76returnroot;
- 77};
- 78
- 79/**
- 80 * Applies the DOM operator, returning the array of all nodes in preorder
- 81 * traversal.
- 82 *
- 83 * @returns {array} the array of nodes in preorder traversal.
- 84 */
- 85pv.Dom.prototype.nodes=function(){
- 86returnthis.root().nodes();
- 87};
- 88
- 89/**
- 90 * Constructs a DOM node for the specified value. Instances of this class are
- 91 * not typically created directly; instead they are generated from a JavaScript
- 92 * map using the {@link pv.Dom} operator.
- 93 *
- 94 * @class Represents a <tt>Node</tt> in the W3C Document Object Model.
- 95 */
- 96pv.Dom.Node=function(value){
- 97this.nodeValue=value;
- 98this.childNodes=[];
- 99};
-100
-101/**
-102 * The node name. When generated from a map, the node name corresponds to the
-103 * key at the given level in the map. Note that the root node has no associated
-104 * key, and thus has an undefined node name (and no <tt>parentNode</tt>).
-105 *
-106 * @type string
-107 * @field pv.Dom.Node.prototype.nodeName
-108 */
-109
-110/**
-111 * The node value. When generated from a map, node value corresponds to the leaf
-112 * value for leaf nodes, and is undefined for internal nodes.
-113 *
-114 * @field pv.Dom.Node.prototype.nodeValue
-115 */
-116
-117/**
-118 * The array of child nodes. This array is empty for leaf nodes. An easy way to
-119 * check if child nodes exist is to query <tt>firstChild</tt>.
-120 *
-121 * @type array
-122 * @field pv.Dom.Node.prototype.childNodes
-123 */
-124
-125/**
-126 * The parent node, which is null for root nodes.
-127 *
-128 * @type pv.Dom.Node
-129 */
-130pv.Dom.Node.prototype.parentNode=null;
-131
-132/**
-133 * The first child, which is null for leaf nodes.
-134 *
-135 * @type pv.Dom.Node
-136 */
-137pv.Dom.Node.prototype.firstChild=null;
-138
-139/**
-140 * The last child, which is null for leaf nodes.
-141 *
-142 * @type pv.Dom.Node
-143 */
-144pv.Dom.Node.prototype.lastChild=null;
-145
-146/**
-147 * The previous sibling node, which is null for the first child.
-148 *
-149 * @type pv.Dom.Node
-150 */
-151pv.Dom.Node.prototype.previousSibling=null;
-152
-153/**
-154 * The next sibling node, which is null for the last child.
-155 *
-156 * @type pv.Dom.Node
-157 */
-158pv.Dom.Node.prototype.nextSibling=null;
-159
-160/**
-161 * Removes the specified child node from this node.
-162 *
-163 * @throws Error if the specified child is not a child of this node.
-164 * @returns {pv.Dom.Node} the removed child.
-165 */
-166pv.Dom.Node.prototype.removeChild=function(n){
-167vari=this.childNodes.indexOf(n);
-168if(i==-1)thrownewError("child not found");
-169this.childNodes.splice(i,1);
-170if(n.previousSibling)n.previousSibling.nextSibling=n.nextSibling;
-171elsethis.firstChild=n.nextSibling;
-172if(n.nextSibling)n.nextSibling.previousSibling=n.previousSibling;
-173elsethis.lastChild=n.previousSibling;
-174deleten.nextSibling;
-175deleten.previousSibling;
-176deleten.parentNode;
-177returnn;
-178};
-179
-180/**
-181 * Appends the specified child node to this node. If the specified child is
-182 * already part of the DOM, the child is first removed before being added to
-183 * this node.
-184 *
-185 * @returns {pv.Dom.Node} the appended child.
-186 */
-187pv.Dom.Node.prototype.appendChild=function(n){
-188if(n.parentNode)n.parentNode.removeChild(n);
-189n.parentNode=this;
-190n.previousSibling=this.lastChild;
-191if(this.lastChild)this.lastChild.nextSibling=n;
-192elsethis.firstChild=n;
-193this.lastChild=n;
-194this.childNodes.push(n);
-195returnn;
-196};
-197
-198/**
-199 * Inserts the specified child <i>n</i> before the given reference child
-200 * <i>r</i> of this node. If <i>r</i> is null, this method is equivalent to
-201 * {@link #appendChild}. If <i>n</i> is already part of the DOM, it is first
-202 * removed before being inserted.
-203 *
-204 * @throws Error if <i>r</i> is non-null and not a child of this node.
-205 * @returns {pv.Dom.Node} the inserted child.
-206 */
-207pv.Dom.Node.prototype.insertBefore=function(n,r){
-208if(!r)returnthis.appendChild(n);
-209vari=this.childNodes.indexOf(r);
-210if(i==-1)thrownewError("child not found");
-211if(n.parentNode)n.parentNode.removeChild(n);
-212n.parentNode=this;
-213n.nextSibling=r;
-214n.previousSibling=r.previousSibling;
-215if(r.previousSibling){
-216r.previousSibling.nextSibling=n;
-217}else{
-218if(r==this.lastChild)this.lastChild=n;
-219this.firstChild=n;
-220}
-221this.childNodes.splice(i,0,n);
-222returnn;
-223};
-224
-225/**
-226 * Replaces the specified child <i>r</i> of this node with the node <i>n</i>. If
-227 * <i>n</i> is already part of the DOM, it is first removed before being added.
-228 *
-229 * @throws Error if <i>r</i> is not a child of this node.
-230 */
-231pv.Dom.Node.prototype.replaceChild=function(n,r){
-232vari=this.childNodes.indexOf(r);
-233if(i==-1)thrownewError("child not found");
-234if(n.parentNode)n.parentNode.removeChild(n);
-235n.parentNode=this;
-236n.nextSibling=r.nextSibling;
-237n.previousSibling=r.previousSibling;
-238if(r.previousSibling)r.previousSibling.nextSibling=n;
-239elsethis.firstChild=n;
-240if(r.nextSibling)r.nextSibling.previousSibling=n;
-241elsethis.lastChild=n;
-242this.childNodes[i]=n;
-243returnr;
-244};
-245
-246/**
-247 * Visits each node in the tree in preorder traversal, applying the specified
-248 * function <i>f</i>. The arguments to the function are:<ol>
-249 *
-250 * <li>The current node.
-251 * <li>The current depth, starting at 0 for the root node.</ol>
-252 *
-253 * @param {function} f a function to apply to each node.
-254 */
-255pv.Dom.Node.prototype.visitBefore=function(f){
-256functionvisit(n,i){
-257f(n,i);
-258for(varc=n.firstChild;c;c=c.nextSibling){
-259visit(c,i+1);
-260}
-261}
-262visit(this,0);
-263};
-264
-265/**
-266 * Visits each node in the tree in postorder traversal, applying the specified
-267 * function <i>f</i>. The arguments to the function are:<ol>
-268 *
-269 * <li>The current node.
-270 * <li>The current depth, starting at 0 for the root node.</ol>
-271 *
-272 * @param {function} f a function to apply to each node.
-273 */
-274pv.Dom.Node.prototype.visitAfter=function(f){
-275functionvisit(n,i){
-276for(varc=n.firstChild;c;c=c.nextSibling){
-277visit(c,i+1);
-278}
-279f(n,i);
-280}
-281visit(this,0);
-282};
-283
-284/**
-285 * Sorts child nodes of this node, and all descendent nodes recursively, using
-286 * the specified comparator function <tt>f</tt>. The comparator function is
-287 * passed two nodes to compare.
-288 *
-289 * <p>Note: during the sort operation, the comparator function should not rely
-290 * on the tree being well-formed; the values of <tt>previousSibling</tt> and
-291 * <tt>nextSibling</tt> for the nodes being compared are not defined during the
-292 * sort operation.
-293 *
-294 * @param {function} f a comparator function.
-295 * @returns this.
-296 */
-297pv.Dom.Node.prototype.sort=function(f){
-298if(this.firstChild){
-299this.childNodes.sort(f);
-300varp=this.firstChild=this.childNodes[0],c;
-301deletep.previousSibling;
-302for(vari=1;i<this.childNodes.length;i++){
-303p.sort(f);
-304c=this.childNodes[i];
-305c.previousSibling=p;
-306p=p.nextSibling=c;
-307}
-308this.lastChild=p;
-309deletep.nextSibling;
-310p.sort(f);
-311}
-312returnthis;
-313};
-314
-315/**
-316 * Reverses all sibling nodes.
-317 *
-318 * @returns this.
-319 */
-320pv.Dom.Node.prototype.reverse=function(){
-321varchildNodes=[];
-322this.visitAfter(function(n){
-323while(n.lastChild)childNodes.push(n.removeChild(n.lastChild));
-324for(varc;c=childNodes.pop();)n.insertBefore(c,n.firstChild);
-325});
-326returnthis;
-327};
-328
-329/** Returns all descendants of this node in preorder traversal. */
-330pv.Dom.Node.prototype.nodes=function(){
-331vararray=[];
-332
-333/** @private */
-334functionflatten(node){
-335array.push(node);
-336node.childNodes.forEach(flatten);
-337}
-338
-339flatten(this,array);
-340returnarray;
-341};
-342
-343/**
-344 * Toggles the child nodes of this node. If this node is not yet toggled, this
-345 * method removes all child nodes and appends them to a new <tt>toggled</tt>
-346 * array attribute on this node. Otherwise, if this node is toggled, this method
-347 * re-adds all toggled child nodes and deletes the <tt>toggled</tt> attribute.
-348 *
-349 * <p>This method has no effect if the node has no child nodes.
-350 *
-351 * @param {boolean} [recursive] whether the toggle should apply to descendants.
-352 */
-353pv.Dom.Node.prototype.toggle=function(recursive){
-354if(recursive)returnthis.toggled
-355?this.visitBefore(function(n){if(n.toggled)n.toggle();})
-356:this.visitAfter(function(n){if(!n.toggled)n.toggle();});
-357varn=this;
-358if(n.toggled){
-359for(varc;c=n.toggled.pop();)n.appendChild(c);
-360deleten.toggled;
-361}elseif(n.lastChild){
-362n.toggled=[];
-363while(n.lastChild)n.toggled.push(n.removeChild(n.lastChild));
-364}
-365};
-366
-367/**
-368 * Given a flat array of values, returns a simple DOM with each value wrapped by
-369 * a node that is a child of the root node.
-370 *
-371 * @param {array} values.
-372 * @returns {array} nodes.
-373 */
-374pv.nodes=function(values){
-375varroot=newpv.Dom.Node();
-376for(vari=0;i<values.length;i++){
-377root.appendChild(newpv.Dom.Node(values[i]));
-378}
-379returnroot.nodes();
-380};
-381
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Flatten.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Flatten.js.html
deleted file mode 100644
index 456aa87e..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Flatten.js.html
+++ /dev/null
@@ -1,154 +0,0 @@
-
1/**
- 2 * Returns a {@link pv.Flatten} operator for the specified map. This is a
- 3 * convenience factory method, equivalent to <tt>new pv.Flatten(map)</tt>.
- 4 *
- 5 * @see pv.Flatten
- 6 * @param map a map to flatten.
- 7 * @returns {pv.Flatten} a flatten operator for the specified map.
- 8 */
- 9pv.flatten=function(map){
- 10returnnewpv.Flatten(map);
- 11};
- 12
- 13/**
- 14 * Constructs a flatten operator for the specified map. This constructor should
- 15 * not be invoked directly; use {@link pv.flatten} instead.
- 16 *
- 17 * @class Represents a flatten operator for the specified array. Flattening
- 18 * allows hierarchical maps to be flattened into an array. The levels in the
- 19 * input tree are specified by <i>key</i> functions.
- 20 *
- 21 * <p>For example, consider the following hierarchical data structure of Barley
- 22 * yields, from various sites in Minnesota during 1931-2:
- 23 *
- 24 * <pre>{ 1931: {
- 25 * Manchuria: {
- 26 * "University Farm": 27.00,
- 27 * "Waseca": 48.87,
- 28 * "Morris": 27.43,
- 29 * ... },
- 30 * Glabron: {
- 31 * "University Farm": 43.07,
- 32 * "Waseca": 55.20,
- 33 * ... } },
- 34 * 1932: {
- 35 * ... } }</pre>
- 36 *
- 37 * To facilitate visualization, it may be useful to flatten the tree into a
- 38 * tabular array:
- 39 *
- 40 * <pre>var array = pv.flatten(yields)
- 41 * .key("year")
- 42 * .key("variety")
- 43 * .key("site")
- 44 * .key("yield")
- 45 * .array();</pre>
- 46 *
- 47 * This returns an array of object elements. Each element in the array has
- 48 * attributes corresponding to this flatten operator's keys:
- 49 *
- 50 * <pre>{ site: "University Farm", variety: "Manchuria", year: 1931, yield: 27 },
- 51 * { site: "Waseca", variety: "Manchuria", year: 1931, yield: 48.87 },
- 52 * { site: "Morris", variety: "Manchuria", year: 1931, yield: 27.43 },
- 53 * { site: "University Farm", variety: "Glabron", year: 1931, yield: 43.07 },
- 54 * { site: "Waseca", variety: "Glabron", year: 1931, yield: 55.2 }, ...</pre>
- 55 *
- 56 * <p>The flatten operator is roughly the inverse of the {@link pv.Nest} and
- 57 * {@link pv.Tree} operators.
- 58 *
- 59 * @param map a map to flatten.
- 60 */
- 61pv.Flatten=function(map){
- 62this.map=map;
- 63this.keys=[];
- 64};
- 65
- 66/**
- 67 * Flattens using the specified key function. Multiple keys may be added to the
- 68 * flatten; the tiers of the underlying tree must correspond to the specified
- 69 * keys, in order. The order of the returned array is undefined; however, you
- 70 * can easily sort it.
- 71 *
- 72 * @param {string} key the key name.
- 73 * @param {function} [f] an optional value map function.
- 74 * @returns {pv.Nest} this.
- 75 */
- 76pv.Flatten.prototype.key=function(key,f){
- 77this.keys.push({name:key,value:f});
- 78deletethis.$leaf;
- 79returnthis;
- 80};
- 81
- 82/**
- 83 * Flattens using the specified leaf function. This is an alternative to
- 84 * specifying an explicit set of keys; the tiers of the underlying tree will be
- 85 * determined dynamically by recursing on the values, and the resulting keys
- 86 * will be stored in the entries <tt>keys</tt> attribute. The leaf function must
- 87 * return true for leaves, and false for internal nodes.
- 88 *
- 89 * @param {function} f a leaf function.
- 90 * @returns {pv.Nest} this.
- 91 */
- 92pv.Flatten.prototype.leaf=function(f){
- 93this.keys.length=0;
- 94this.$leaf=f;
- 95returnthis;
- 96};
- 97
- 98/**
- 99 * Returns the flattened array. Each entry in the array is an object; each
-100 * object has attributes corresponding to this flatten operator's keys.
-101 *
-102 * @returns an array of elements from the flattened map.
-103 */
-104pv.Flatten.prototype.array=function(){
-105varentries=[],stack=[],keys=this.keys,leaf=this.$leaf;
-106
-107/* Recursively visit using the leaf function. */
-108if(leaf){
-109functionrecurse(value,i){
-110if(leaf(value)){
-111entries.push({keys:stack.slice(),value:value});
-112}else{
-113for(varkeyinvalue){
-114stack.push(key);
-115recurse(value[key],i+1);
-116stack.pop();
-117}
-118}
-119}
-120recurse(this.map,0);
-121returnentries;
-122}
-123
-124/* Recursively visits the specified value. */
-125functionvisit(value,i){
-126if(i<keys.length-1){
-127for(varkeyinvalue){
-128stack.push(key);
-129visit(value[key],i+1);
-130stack.pop();
-131}
-132}else{
-133entries.push(stack.concat(value));
-134}
-135}
-136
-137visit(this.map,0);
-138returnentries.map(function(stack){
-139varm={};
-140for(vari=0;i<keys.length;i++){
-141vark=keys[i],v=stack[i];
-142m[k.name]=k.value?k.value.call(null,v):v;
-143}
-144returnm;
-145});
-146};
-147
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Histogram.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Histogram.js.html
deleted file mode 100644
index f69f9059..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Histogram.js.html
+++ /dev/null
@@ -1,128 +0,0 @@
-
1/**
- 2 * Returns a histogram operator for the specified data, with an optional
- 3 * accessor function. If the data specified is not an array of numbers, an
- 4 * accessor function must be specified to map the data to numeric values.
- 5 *
- 6 * @class Represents a histogram operator.
- 7 *
- 8 * @param {array} data an array of numbers or objects.
- 9 * @param {function} [f] an optional accessor function.
- 10 */
- 11pv.histogram=function(data,f){
- 12varfrequency=true;
- 13return{
- 14
- 15/**
- 16 * Returns the computed histogram bins. An optional array of numbers,
- 17 * <tt>ticks</tt>, may be specified as the break points. If the ticks are
- 18 * not specified, default ticks will be computed using a linear scale on the
- 19 * data domain.
- 20 *
- 21 * <p>The returned array contains {@link pv.histogram.Bin}s. The <tt>x</tt>
- 22 * attribute corresponds to the bin's start value (inclusive), while the
- 23 * <tt>dx</tt> attribute stores the bin size (end - start). The <tt>y</tt>
- 24 * attribute stores either the frequency count or probability, depending on
- 25 * how the histogram operator has been configured.
- 26 *
- 27 * <p>The {@link pv.histogram.Bin} objects are themselves arrays, containing
- 28 * the data elements present in each bin, i.e., the elements in the
- 29 * <tt>data</tt> array (prior to invoking the accessor function, if any).
- 30 * For example, if the data represented countries, and the accessor function
- 31 * returned the GDP of each country, the returned bins would be arrays of
- 32 * countries (not GDPs).
- 33 *
- 34 * @function
- 35 * @name pv.histogram.prototype.bins
- 36 * @param {array} [ticks]
- 37 * @returns {array}
- 38 *//** @private */
- 39bins:function(ticks){
- 40varx=pv.map(data,f),bins=[];
- 41
- 42/* Initialize default ticks. */
- 43if(!arguments.length)ticks=pv.Scale.linear(x).ticks();
- 44
- 45/* Initialize the bins. */
- 46for(vari=0;i<ticks.length-1;i++){
- 47varbin=bins[i]=[];
- 48bin.x=ticks[i];
- 49bin.dx=ticks[i+1]-ticks[i];
- 50bin.y=0;
- 51}
- 52
- 53/* Count the number of samples per bin. */
- 54for(vari=0;i<x.length;i++){
- 55varj=pv.search.index(ticks,x[i])-1,
- 56bin=bins[Math.max(0,Math.min(bins.length-1,j))];
- 57bin.y++;
- 58bin.push(data[i]);
- 59}
- 60
- 61/* Convert frequencies to probabilities. */
- 62if(!frequency)for(vari=0;i<bins.length;i++){
- 63bins[i].y/=x.length;
- 64}
- 65
- 66returnbins;
- 67},
- 68
- 69/**
- 70 * Sets or gets whether this histogram operator returns frequencies or
- 71 * probabilities.
- 72 *
- 73 * @function
- 74 * @name pv.histogram.prototype.frequency
- 75 * @param {boolean} [x]
- 76 * @returns {pv.histogram} this.
- 77 *//** @private */
- 78frequency:function(x){
- 79if(arguments.length){
- 80frequency=Boolean(x);
- 81returnthis;
- 82}
- 83returnfrequency;
- 84}
- 85};
- 86};
- 87
- 88/**
- 89 * @class Represents a bin returned by the {@link pv.histogram} operator. Bins
- 90 * are themselves arrays containing the data elements present in the given bin
- 91 * (prior to the accessor function being invoked to convert the data object to a
- 92 * numeric value). These bin arrays have additional attributes with meta
- 93 * information about the bin.
- 94 *
- 95 * @name pv.histogram.Bin
- 96 * @extends array
- 97 * @see pv.histogram
- 98 */
- 99
-100/**
-101 * The start value of the bin's range.
-102 *
-103 * @type number
-104 * @name pv.histogram.Bin.prototype.x
-105 */
-106
-107/**
-108 * The magnitude value of the bin's range; end - start.
-109 *
-110 * @type number
-111 * @name pv.histogram.Bin.prototype.dx
-112 */
-113
-114/**
-115 * The frequency or probability of the bin, depending on how the histogram
-116 * operator was configured.
-117 *
-118 * @type number
-119 * @name pv.histogram.Bin.prototype.y
-120 */
-121
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_LinearScale.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_LinearScale.js.html
deleted file mode 100644
index 5965f1b1..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_LinearScale.js.html
+++ /dev/null
@@ -1,62 +0,0 @@
-
1/**
- 2 * Returns a linear scale for the specified domain. The arguments to this
- 3 * constructor are optional, and equivalent to calling {@link #domain}.
- 4 * The default domain and range are [0,1].
- 5 *
- 6 * @class Represents a linear scale; a function that performs a linear
- 7 * transformation. <style type="text/css">sub{line-height:0}</style> Most
- 8 * commonly, a linear scale represents a 1-dimensional linear transformation
- 9 * from a numeric domain of input data [<i>d<sub>0</sub></i>,
- 10 * <i>d<sub>1</sub></i>] to a numeric range of pixels [<i>r<sub>0</sub></i>,
- 11 * <i>r<sub>1</sub></i>]. The equation for such a scale is:
- 12 *
- 13 * <blockquote><i>f(x) = (x - d<sub>0</sub>) / (d<sub>1</sub> - d<sub>0</sub>) *
- 14 * (r<sub>1</sub> - r<sub>0</sub>) + r<sub>0</sub></i></blockquote>
- 15 *
- 16 * For example, a linear scale from the domain [0, 100] to range [0, 640]:
- 17 *
- 18 * <blockquote><i>f(x) = (x - 0) / (100 - 0) * (640 - 0) + 0</i><br>
- 19 * <i>f(x) = x / 100 * 640</i><br>
- 20 * <i>f(x) = x * 6.4</i><br>
- 21 * </blockquote>
- 22 *
- 23 * Thus, saying
- 24 *
- 25 * <pre> .height(function(d) d * 6.4)</pre>
- 26 *
- 27 * is identical to
- 28 *
- 29 * <pre> .height(pv.Scale.linear(0, 100).range(0, 640))</pre>
- 30 *
- 31 * Note that the scale is itself a function, and thus can be used as a property
- 32 * directly, assuming that the data associated with a mark is a number. While
- 33 * this is convenient for single-use scales, frequently it is desirable to
- 34 * define scales globally:
- 35 *
- 36 * <pre>var y = pv.Scale.linear(0, 100).range(0, 640);</pre>
- 37 *
- 38 * The <tt>y</tt> scale can now be equivalently referenced within a property:
- 39 *
- 40 * <pre> .height(function(d) y(d))</pre>
- 41 *
- 42 * Alternatively, if the data are not simple numbers, the appropriate value can
- 43 * be passed to the <tt>y</tt> scale (e.g., <tt>d.foo</tt>). The {@link #by}
- 44 * method similarly allows the data to be mapped to a numeric value before
- 45 * performing the linear transformation.
- 46 *
- 47 * @param {number...} domain... optional domain values.
- 48 * @extends pv.Scale.quantitative
- 49 */
- 50pv.Scale.linear=function(){
- 51varscale=pv.Scale.quantitative();
- 52scale.domain.apply(scale,arguments);
- 53returnscale;
- 54};
- 55
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_LogScale.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_LogScale.js.html
deleted file mode 100644
index 27f62ca5..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_LogScale.js.html
+++ /dev/null
@@ -1,150 +0,0 @@
-
1/**
- 2 * Returns a log scale for the specified domain. The arguments to this
- 3 * constructor are optional, and equivalent to calling {@link #domain}.
- 4 * The default domain is [1,10] and the default range is [0,1].
- 5 *
- 6 * @class Represents a log scale. <style
- 7 * type="text/css">sub{line-height:0}</style> Most commonly, a log scale
- 8 * represents a 1-dimensional log transformation from a numeric domain of input
- 9 * data [<i>d<sub>0</sub></i>, <i>d<sub>1</sub></i>] to a numeric range of
- 10 * pixels [<i>r<sub>0</sub></i>, <i>r<sub>1</sub></i>]. The equation for such a
- 11 * scale is:
- 12 *
- 13 * <blockquote><i>f(x) = (log(x) - log(d<sub>0</sub>)) / (log(d<sub>1</sub>) -
- 14 * log(d<sub>0</sub>)) * (r<sub>1</sub> - r<sub>0</sub>) +
- 15 * r<sub>0</sub></i></blockquote>
- 16 *
- 17 * where <i>log(x)</i> represents the zero-symmetric logarthim of <i>x</i> using
- 18 * the scale's associated base (default: 10, see {@link pv.logSymmetric}). For
- 19 * example, a log scale from the domain [1, 100] to range [0, 640]:
- 20 *
- 21 * <blockquote><i>f(x) = (log(x) - log(1)) / (log(100) - log(1)) * (640 - 0) + 0</i><br>
- 22 * <i>f(x) = log(x) / 2 * 640</i><br>
- 23 * <i>f(x) = log(x) * 320</i><br>
- 24 * </blockquote>
- 25 *
- 26 * Thus, saying
- 27 *
- 28 * <pre> .height(function(d) Math.log(d) * 138.974)</pre>
- 29 *
- 30 * is equivalent to
- 31 *
- 32 * <pre> .height(pv.Scale.log(1, 100).range(0, 640))</pre>
- 33 *
- 34 * Note that the scale is itself a function, and thus can be used as a property
- 35 * directly, assuming that the data associated with a mark is a number. While
- 36 * this is convenient for single-use scales, frequently it is desirable to
- 37 * define scales globally:
- 38 *
- 39 * <pre>var y = pv.Scale.log(1, 100).range(0, 640);</pre>
- 40 *
- 41 * The <tt>y</tt> scale can now be equivalently referenced within a property:
- 42 *
- 43 * <pre> .height(function(d) y(d))</pre>
- 44 *
- 45 * Alternatively, if the data are not simple numbers, the appropriate value can
- 46 * be passed to the <tt>y</tt> scale (e.g., <tt>d.foo</tt>). The {@link #by}
- 47 * method similarly allows the data to be mapped to a numeric value before
- 48 * performing the log transformation.
- 49 *
- 50 * @param {number...} domain... optional domain values.
- 51 * @extends pv.Scale.quantitative
- 52 */
- 53pv.Scale.log=function(){
- 54varscale=pv.Scale.quantitative(1,10),
- 55b,// logarithm base
- 56p,// cached Math.log(b)
- 57/** @ignore */log=function(x){returnMath.log(x)/p;},
- 58/** @ignore */pow=function(y){returnMath.pow(b,y);};
- 59
- 60/**
- 61 * Returns an array of evenly-spaced, suitably-rounded values in the input
- 62 * domain. These values are frequently used in conjunction with
- 63 * {@link pv.Rule} to display tick marks or grid lines.
- 64 *
- 65 * @function
- 66 * @name pv.Scale.log.prototype.ticks
- 67 * @returns {number[]} an array input domain values to use as ticks.
- 68 */
- 69scale.ticks=function(){
- 70// TODO support non-uniform domains
- 71vard=scale.domain(),
- 72n=d[0]<0,
- 73i=Math.floor(n?-log(-d[0]):log(d[0])),
- 74j=Math.ceil(n?-log(-d[1]):log(d[1])),
- 75ticks=[];
- 76if(n){
- 77ticks.push(-pow(-i));
- 78for(;i++<j;)for(vark=b-1;k>0;k--)ticks.push(-pow(-i)*k);
- 79}else{
- 80for(;i<j;i++)for(vark=1;k<b;k++)ticks.push(pow(i)*k);
- 81ticks.push(pow(i));
- 82}
- 83for(i=0;ticks[i]<d[0];i++);// strip small values
- 84for(j=ticks.length;ticks[j-1]>d[1];j--);// strip big values
- 85returnticks.slice(i,j);
- 86};
- 87
- 88/**
- 89 * Formats the specified tick value using the appropriate precision, assuming
- 90 * base 10.
- 91 *
- 92 * @function
- 93 * @name pv.Scale.log.prototype.tickFormat
- 94 * @param {number} t a tick value.
- 95 * @returns {string} a formatted tick value.
- 96 */
- 97scale.tickFormat=function(t){
- 98returnt.toPrecision(1);
- 99};
-100
-101/**
-102 * "Nices" this scale, extending the bounds of the input domain to
-103 * evenly-rounded values. This method uses {@link pv.logFloor} and
-104 * {@link pv.logCeil}. Nicing is useful if the domain is computed dynamically
-105 * from data, and may be irregular. For example, given a domain of
-106 * [0.20147987687960267, 0.996679553296417], a call to <tt>nice()</tt> might
-107 * extend the domain to [0.1, 1].
-108 *
-109 * <p>This method must be invoked each time after setting the domain (and
-110 * base).
-111 *
-112 * @function
-113 * @name pv.Scale.log.prototype.nice
-114 * @returns {pv.Scale.log} <tt>this</tt>.
-115 */
-116scale.nice=function(){
-117// TODO support non-uniform domains
-118vard=scale.domain();
-119returnscale.domain(pv.logFloor(d[0],b),pv.logCeil(d[1],b));
-120};
-121
-122/**
-123 * Sets or gets the logarithm base. Defaults to 10.
-124 *
-125 * @function
-126 * @name pv.Scale.log.prototype.base
-127 * @param {number} [v] the new base.
-128 * @returns {pv.Scale.log} <tt>this</tt>, or the current base.
-129 */
-130scale.base=function(v){
-131if(arguments.length){
-132b=Number(v);
-133p=Math.log(b);
-134scale.transform(log,pow);// update transformed domain
-135returnthis;
-136}
-137returnb;
-138};
-139
-140scale.domain.apply(scale,arguments);
-141returnscale.base(10);
-142};
-143
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Nest.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Nest.js.html
deleted file mode 100644
index 0b73d012..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Nest.js.html
+++ /dev/null
@@ -1,265 +0,0 @@
-
1/**
- 2 * Returns a {@link pv.Nest} operator for the specified array. This is a
- 3 * convenience factory method, equivalent to <tt>new pv.Nest(array)</tt>.
- 4 *
- 5 * @see pv.Nest
- 6 * @param {array} array an array of elements to nest.
- 7 * @returns {pv.Nest} a nest operator for the specified array.
- 8 */
- 9pv.nest=function(array){
- 10returnnewpv.Nest(array);
- 11};
- 12
- 13/**
- 14 * Constructs a nest operator for the specified array. This constructor should
- 15 * not be invoked directly; use {@link pv.nest} instead.
- 16 *
- 17 * @class Represents a {@link Nest} operator for the specified array. Nesting
- 18 * allows elements in an array to be grouped into a hierarchical tree
- 19 * structure. The levels in the tree are specified by <i>key</i> functions. The
- 20 * leaf nodes of the tree can be sorted by value, while the internal nodes can
- 21 * be sorted by key. Finally, the tree can be returned either has a
- 22 * multidimensional array via {@link #entries}, or as a hierarchical map via
- 23 * {@link #map}. The {@link #rollup} routine similarly returns a map, collapsing
- 24 * the elements in each leaf node using a summary function.
- 25 *
- 26 * <p>For example, consider the following tabular data structure of Barley
- 27 * yields, from various sites in Minnesota during 1931-2:
- 28 *
- 29 * <pre>{ yield: 27.00, variety: "Manchuria", year: 1931, site: "University Farm" },
- 30 * { yield: 48.87, variety: "Manchuria", year: 1931, site: "Waseca" },
- 31 * { yield: 27.43, variety: "Manchuria", year: 1931, site: "Morris" }, ...</pre>
- 32 *
- 33 * To facilitate visualization, it may be useful to nest the elements first by
- 34 * year, and then by variety, as follows:
- 35 *
- 36 * <pre>var nest = pv.nest(yields)
- 37 * .key(function(d) d.year)
- 38 * .key(function(d) d.variety)
- 39 * .entries();</pre>
- 40 *
- 41 * This returns a nested array. Each element of the outer array is a key-values
- 42 * pair, listing the values for each distinct key:
- 43 *
- 44 * <pre>{ key: 1931, values: [
- 45 * { key: "Manchuria", values: [
- 46 * { yield: 27.00, variety: "Manchuria", year: 1931, site: "University Farm" },
- 47 * { yield: 48.87, variety: "Manchuria", year: 1931, site: "Waseca" },
- 48 * { yield: 27.43, variety: "Manchuria", year: 1931, site: "Morris" },
- 49 * ...
- 50 * ] },
- 51 * { key: "Glabron", values: [
- 52 * { yield: 43.07, variety: "Glabron", year: 1931, site: "University Farm" },
- 53 * { yield: 55.20, variety: "Glabron", year: 1931, site: "Waseca" },
- 54 * ...
- 55 * ] },
- 56 * ] },
- 57 * { key: 1932, values: ... }</pre>
- 58 *
- 59 * Further details, including sorting and rollup, is provided below on the
- 60 * corresponding methods.
- 61 *
- 62 * @param {array} array an array of elements to nest.
- 63 */
- 64pv.Nest=function(array){
- 65this.array=array;
- 66this.keys=[];
- 67};
- 68
- 69/**
- 70 * Nests using the specified key function. Multiple keys may be added to the
- 71 * nest; the array elements will be nested in the order keys are specified.
- 72 *
- 73 * @param {function} key a key function; must return a string or suitable map
- 74 * key.
- 75 * @returns {pv.Nest} this.
- 76 */
- 77pv.Nest.prototype.key=function(key){
- 78this.keys.push(key);
- 79returnthis;
- 80};
- 81
- 82/**
- 83 * Sorts the previously-added keys. The natural sort order is used by default
- 84 * (see {@link pv.naturalOrder}); if an alternative order is desired,
- 85 * <tt>order</tt> should be a comparator function. If this method is not called
- 86 * (i.e., keys are <i>unsorted</i>), keys will appear in the order they appear
- 87 * in the underlying elements array. For example,
- 88 *
- 89 * <pre>pv.nest(yields)
- 90 * .key(function(d) d.year)
- 91 * .key(function(d) d.variety)
- 92 * .sortKeys()
- 93 * .entries()</pre>
- 94 *
- 95 * groups yield data by year, then variety, and sorts the variety groups
- 96 * lexicographically (since the variety attribute is a string).
- 97 *
- 98 * <p>Key sort order is only used in conjunction with {@link #entries}, which
- 99 * returns an array of key-values pairs. If the nest is used to construct a
-100 * {@link #map} instead, keys are unsorted.
-101 *
-102 * @param {function} [order] an optional comparator function.
-103 * @returns {pv.Nest} this.
-104 */
-105pv.Nest.prototype.sortKeys=function(order){
-106this.keys[this.keys.length-1].order=order||pv.naturalOrder;
-107returnthis;
-108};
-109
-110/**
-111 * Sorts the leaf values. The natural sort order is used by default (see
-112 * {@link pv.naturalOrder}); if an alternative order is desired, <tt>order</tt>
-113 * should be a comparator function. If this method is not called (i.e., values
-114 * are <i>unsorted</i>), values will appear in the order they appear in the
-115 * underlying elements array. For example,
-116 *
-117 * <pre>pv.nest(yields)
-118 * .key(function(d) d.year)
-119 * .key(function(d) d.variety)
-120 * .sortValues(function(a, b) a.yield - b.yield)
-121 * .entries()</pre>
-122 *
-123 * groups yield data by year, then variety, and sorts the values for each
-124 * variety group by yield.
-125 *
-126 * <p>Value sort order, unlike keys, applies to both {@link #entries} and
-127 * {@link #map}. It has no effect on {@link #rollup}.
-128 *
-129 * @param {function} [order] an optional comparator function.
-130 * @returns {pv.Nest} this.
-131 */
-132pv.Nest.prototype.sortValues=function(order){
-133this.order=order||pv.naturalOrder;
-134returnthis;
-135};
-136
-137/**
-138 * Returns a hierarchical map of values. Each key adds one level to the
-139 * hierarchy. With only a single key, the returned map will have a key for each
-140 * distinct value of the key function; the correspond value with be an array of
-141 * elements with that key value. If a second key is added, this will be a nested
-142 * map. For example:
-143 *
-144 * <pre>pv.nest(yields)
-145 * .key(function(d) d.variety)
-146 * .key(function(d) d.site)
-147 * .map()</pre>
-148 *
-149 * returns a map <tt>m</tt> such that <tt>m[variety][site]</tt> is an array, a subset of
-150 * <tt>yields</tt>, with each element having the given variety and site.
-151 *
-152 * @returns a hierarchical map of values.
-153 */
-154pv.Nest.prototype.map=function(){
-155varmap={},values=[];
-156
-157/* Build the map. */
-158for(vari,j=0;j<this.array.length;j++){
-159varx=this.array[j];
-160varm=map;
-161for(i=0;i<this.keys.length-1;i++){
-162vark=this.keys[i](x);
-163if(!m[k])m[k]={};
-164m=m[k];
-165}
-166k=this.keys[i](x);
-167if(!m[k]){
-168vara=[];
-169values.push(a);
-170m[k]=a;
-171}
-172m[k].push(x);
-173}
-174
-175/* Sort each leaf array. */
-176if(this.order){
-177for(vari=0;i<values.length;i++){
-178values[i].sort(this.order);
-179}
-180}
-181
-182returnmap;
-183};
-184
-185/**
-186 * Returns a hierarchical nested array. This method is similar to
-187 * {@link pv.entries}, but works recursively on the entire hierarchy. Rather
-188 * than returning a map like {@link #map}, this method returns a nested
-189 * array. Each element of the array has a <tt>key</tt> and <tt>values</tt>
-190 * field. For leaf nodes, the <tt>values</tt> array will be a subset of the
-191 * underlying elements array; for non-leaf nodes, the <tt>values</tt> array will
-192 * contain more key-values pairs.
-193 *
-194 * <p>For an example usage, see the {@link Nest} constructor.
-195 *
-196 * @returns a hierarchical nested array.
-197 */
-198pv.Nest.prototype.entries=function(){
-199
-200/** Recursively extracts the entries for the given map. */
-201functionentries(map){
-202vararray=[];
-203for(varkinmap){
-204varv=map[k];
-205array.push({key:k,values:(vinstanceofArray)?v:entries(v)});
-206};
-207returnarray;
-208}
-209
-210/** Recursively sorts the values for the given key-values array. */
-211functionsort(array,i){
-212varo=this.keys[i].order;
-213if(o)array.sort(function(a,b){returno(a.key,b.key);});
-214if(++i<this.keys.length){
-215for(varj=0;j<array.length;j++){
-216sort.call(this,array[j].values,i);
-217}
-218}
-219returnarray;
-220}
-221
-222returnsort.call(this,entries(this.map()),0);
-223};
-224
-225/**
-226 * Returns a rollup map. The behavior of this method is the same as
-227 * {@link #map}, except that the leaf values are replaced with the return value
-228 * of the specified rollup function <tt>f</tt>. For example,
-229 *
-230 * <pre>pv.nest(yields)
-231 * .key(function(d) d.site)
-232 * .rollup(function(v) pv.median(v, function(d) d.yield))</pre>
-233 *
-234 * first groups yield data by site, and then returns a map from site to median
-235 * yield for the given site.
-236 *
-237 * @see #map
-238 * @param {function} f a rollup function.
-239 * @returns a hierarchical map, with the leaf values computed by <tt>f</tt>.
-240 */
-241pv.Nest.prototype.rollup=function(f){
-242
-243/** Recursively descends to the leaf nodes (arrays) and does rollup. */
-244functionrollup(map){
-245for(varkeyinmap){
-246varvalue=map[key];
-247if(valueinstanceofArray){
-248map[key]=f(value);
-249}else{
-250rollup(value);
-251}
-252}
-253returnmap;
-254}
-255
-256returnrollup(this.map());
-257};
-258
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Numbers.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Numbers.js.html
deleted file mode 100644
index 8fd8fe17..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Numbers.js.html
+++ /dev/null
@@ -1,320 +0,0 @@
-
1/**
- 2 * Returns an array of numbers, starting at <tt>start</tt>, incrementing by
- 3 * <tt>step</tt>, until <tt>stop</tt> is reached. The stop value is
- 4 * exclusive. If only a single argument is specified, this value is interpeted
- 5 * as the <i>stop</i> value, with the <i>start</i> value as zero. If only two
- 6 * arguments are specified, the step value is implied to be one.
- 7 *
- 8 * <p>The method is modeled after the built-in <tt>range</tt> method from
- 9 * Python. See the Python documentation for more details.
- 10 *
- 11 * @see <a href="http://docs.python.org/library/functions.html#range">Python range</a>
- 12 * @param {number} [start] the start value.
- 13 * @param {number} stop the stop value.
- 14 * @param {number} [step] the step value.
- 15 * @returns {number[]} an array of numbers.
- 16 */
- 17pv.range=function(start,stop,step){
- 18if(arguments.length==1){
- 19stop=start;
- 20start=0;
- 21}
- 22if(step==undefined)step=1;
- 23if((stop-start)/step==Infinity)thrownewError("range must be finite");
- 24vararray=[],i=0,j;
- 25if(step<0){
- 26while((j=start+step*i++)>stop){
- 27array.push(j);
- 28}
- 29}else{
- 30while((j=start+step*i++)<stop){
- 31array.push(j);
- 32}
- 33}
- 34returnarray;
- 35};
- 36
- 37/**
- 38 * Returns a random number in the range [<tt>start</tt>, <tt>stop</tt>) that is
- 39 * a multiple of <tt>step</tt>. More specifically, the returned number is of the
- 40 * form <tt>start</tt> + <i>n</i> * <tt>step</tt>, where <i>n</i> is a
- 41 * nonnegative integer. If <tt>step</tt> is not specified, it defaults to 1,
- 42 * returning a random integer if <tt>start</tt> is also an integer.
- 43 *
- 44 * @param {number} [start] the start value value.
- 45 * @param {number} stop the stop value.
- 46 * @param {number} [step] the step value.
- 47 * @returns {number} a random number between <i>start</i> and <i>stop</i>.
- 48 */
- 49pv.random=function(start,stop,step){
- 50if(arguments.length==1){
- 51stop=start;
- 52start=0;
- 53}
- 54if(step==undefined)step=1;
- 55returnstep
- 56?(Math.floor(Math.random()*(stop-start)/step)*step+start)
- 57:(Math.random()*(stop-start)+start);
- 58};
- 59
- 60/**
- 61 * Returns the sum of the specified array. If the specified array is not an
- 62 * array of numbers, an optional accessor function <tt>f</tt> can be specified
- 63 * to map the elements to numbers. See {@link #normalize} for an example.
- 64 * Accessor functions can refer to <tt>this.index</tt>.
- 65 *
- 66 * @param {array} array an array of objects, or numbers.
- 67 * @param {function} [f] an optional accessor function.
- 68 * @returns {number} the sum of the specified array.
- 69 */
- 70pv.sum=function(array,f){
- 71varo={};
- 72returnarray.reduce(f
- 73?function(p,d,i){o.index=i;returnp+f.call(o,d);}
- 74:function(p,d){returnp+d;},0);
- 75};
- 76
- 77/**
- 78 * Returns the maximum value of the specified array. If the specified array is
- 79 * not an array of numbers, an optional accessor function <tt>f</tt> can be
- 80 * specified to map the elements to numbers. See {@link #normalize} for an
- 81 * example. Accessor functions can refer to <tt>this.index</tt>.
- 82 *
- 83 * @param {array} array an array of objects, or numbers.
- 84 * @param {function} [f] an optional accessor function.
- 85 * @returns {number} the maximum value of the specified array.
- 86 */
- 87pv.max=function(array,f){
- 88if(f==pv.index)returnarray.length-1;
- 89returnMath.max.apply(null,f?pv.map(array,f):array);
- 90};
- 91
- 92/**
- 93 * Returns the index of the maximum value of the specified array. If the
- 94 * specified array is not an array of numbers, an optional accessor function
- 95 * <tt>f</tt> can be specified to map the elements to numbers. See
- 96 * {@link #normalize} for an example. Accessor functions can refer to
- 97 * <tt>this.index</tt>.
- 98 *
- 99 * @param {array} array an array of objects, or numbers.
-100 * @param {function} [f] an optional accessor function.
-101 * @returns {number} the index of the maximum value of the specified array.
-102 */
-103pv.max.index=function(array,f){
-104if(!array.length)return-1;
-105if(f==pv.index)returnarray.length-1;
-106if(!f)f=pv.identity;
-107varmaxi=0,maxx=-Infinity,o={};
-108for(vari=0;i<array.length;i++){
-109o.index=i;
-110varx=f.call(o,array[i]);
-111if(x>maxx){
-112maxx=x;
-113maxi=i;
-114}
-115}
-116returnmaxi;
-117}
-118
-119/**
-120 * Returns the minimum value of the specified array of numbers. If the specified
-121 * array is not an array of numbers, an optional accessor function <tt>f</tt>
-122 * can be specified to map the elements to numbers. See {@link #normalize} for
-123 * an example. Accessor functions can refer to <tt>this.index</tt>.
-124 *
-125 * @param {array} array an array of objects, or numbers.
-126 * @param {function} [f] an optional accessor function.
-127 * @returns {number} the minimum value of the specified array.
-128 */
-129pv.min=function(array,f){
-130if(f==pv.index)return0;
-131returnMath.min.apply(null,f?pv.map(array,f):array);
-132};
-133
-134/**
-135 * Returns the index of the minimum value of the specified array. If the
-136 * specified array is not an array of numbers, an optional accessor function
-137 * <tt>f</tt> can be specified to map the elements to numbers. See
-138 * {@link #normalize} for an example. Accessor functions can refer to
-139 * <tt>this.index</tt>.
-140 *
-141 * @param {array} array an array of objects, or numbers.
-142 * @param {function} [f] an optional accessor function.
-143 * @returns {number} the index of the minimum value of the specified array.
-144 */
-145pv.min.index=function(array,f){
-146if(!array.length)return-1;
-147if(f==pv.index)return0;
-148if(!f)f=pv.identity;
-149varmini=0,minx=Infinity,o={};
-150for(vari=0;i<array.length;i++){
-151o.index=i;
-152varx=f.call(o,array[i]);
-153if(x<minx){
-154minx=x;
-155mini=i;
-156}
-157}
-158returnmini;
-159}
-160
-161/**
-162 * Returns the arithmetic mean, or average, of the specified array. If the
-163 * specified array is not an array of numbers, an optional accessor function
-164 * <tt>f</tt> can be specified to map the elements to numbers. See
-165 * {@link #normalize} for an example. Accessor functions can refer to
-166 * <tt>this.index</tt>.
-167 *
-168 * @param {array} array an array of objects, or numbers.
-169 * @param {function} [f] an optional accessor function.
-170 * @returns {number} the mean of the specified array.
-171 */
-172pv.mean=function(array,f){
-173returnpv.sum(array,f)/array.length;
-174};
-175
-176/**
-177 * Returns the median of the specified array. If the specified array is not an
-178 * array of numbers, an optional accessor function <tt>f</tt> can be specified
-179 * to map the elements to numbers. See {@link #normalize} for an example.
-180 * Accessor functions can refer to <tt>this.index</tt>.
-181 *
-182 * @param {array} array an array of objects, or numbers.
-183 * @param {function} [f] an optional accessor function.
-184 * @returns {number} the median of the specified array.
-185 */
-186pv.median=function(array,f){
-187if(f==pv.index)return(array.length-1)/2;
-188array=pv.map(array,f).sort(pv.naturalOrder);
-189if(array.length%2)returnarray[Math.floor(array.length/2)];
-190vari=array.length/2;
-191return(array[i-1]+array[i])/2;
-192};
-193
-194/**
-195 * Returns the unweighted variance of the specified array. If the specified
-196 * array is not an array of numbers, an optional accessor function <tt>f</tt>
-197 * can be specified to map the elements to numbers. See {@link #normalize} for
-198 * an example. Accessor functions can refer to <tt>this.index</tt>.
-199 *
-200 * @param {array} array an array of objects, or numbers.
-201 * @param {function} [f] an optional accessor function.
-202 * @returns {number} the variance of the specified array.
-203 */
-204pv.variance=function(array,f){
-205if(array.length<1)returnNaN;
-206if(array.length==1)return0;
-207varmean=pv.mean(array,f),sum=0,o={};
-208if(!f)f=pv.identity;
-209for(vari=0;i<array.length;i++){
-210o.index=i;
-211vard=f.call(o,array[i])-mean;
-212sum+=d*d;
-213}
-214returnsum;
-215};
-216
-217/**
-218 * Returns an unbiased estimation of the standard deviation of a population,
-219 * given the specified random sample. If the specified array is not an array of
-220 * numbers, an optional accessor function <tt>f</tt> can be specified to map the
-221 * elements to numbers. See {@link #normalize} for an example. Accessor
-222 * functions can refer to <tt>this.index</tt>.
-223 *
-224 * @param {array} array an array of objects, or numbers.
-225 * @param {function} [f] an optional accessor function.
-226 * @returns {number} the standard deviation of the specified array.
-227 */
-228pv.deviation=function(array,f){
-229returnMath.sqrt(pv.variance(array,f)/(array.length-1));
-230};
-231
-232/**
-233 * Returns the logarithm with a given base value.
-234 *
-235 * @param {number} x the number for which to compute the logarithm.
-236 * @param {number} b the base of the logarithm.
-237 * @returns {number} the logarithm value.
-238 */
-239pv.log=function(x,b){
-240returnMath.log(x)/Math.log(b);
-241};
-242
-243/**
-244 * Computes a zero-symmetric logarithm. Computes the logarithm of the absolute
-245 * value of the input, and determines the sign of the output according to the
-246 * sign of the input value.
-247 *
-248 * @param {number} x the number for which to compute the logarithm.
-249 * @param {number} b the base of the logarithm.
-250 * @returns {number} the symmetric log value.
-251 */
-252pv.logSymmetric=function(x,b){
-253return(x==0)?0:((x<0)?-pv.log(-x,b):pv.log(x,b));
-254};
-255
-256/**
-257 * Computes a zero-symmetric logarithm, with adjustment to values between zero
-258 * and the logarithm base. This adjustment introduces distortion for values less
-259 * than the base number, but enables simultaneous plotting of log-transformed
-260 * data involving both positive and negative numbers.
-261 *
-262 * @param {number} x the number for which to compute the logarithm.
-263 * @param {number} b the base of the logarithm.
-264 * @returns {number} the adjusted, symmetric log value.
-265 */
-266pv.logAdjusted=function(x,b){
-267if(!isFinite(x))returnx;
-268varnegative=x<0;
-269if(x<b)x+=(b-x)/b;
-270returnnegative?-pv.log(x,b):pv.log(x,b);
-271};
-272
-273/**
-274 * Rounds an input value down according to its logarithm. The method takes the
-275 * floor of the logarithm of the value and then uses the resulting value as an
-276 * exponent for the base value.
-277 *
-278 * @param {number} x the number for which to compute the logarithm floor.
-279 * @param {number} b the base of the logarithm.
-280 * @returns {number} the rounded-by-logarithm value.
-281 */
-282pv.logFloor=function(x,b){
-283return(x>0)
-284?Math.pow(b,Math.floor(pv.log(x,b)))
-285:-Math.pow(b,-Math.floor(-pv.log(-x,b)));
-286};
-287
-288/**
-289 * Rounds an input value up according to its logarithm. The method takes the
-290 * ceiling of the logarithm of the value and then uses the resulting value as an
-291 * exponent for the base value.
-292 *
-293 * @param {number} x the number for which to compute the logarithm ceiling.
-294 * @param {number} b the base of the logarithm.
-295 * @returns {number} the rounded-by-logarithm value.
-296 */
-297pv.logCeil=function(x,b){
-298return(x>0)
-299?Math.pow(b,Math.ceil(pv.log(x,b)))
-300:-Math.pow(b,-Math.ceil(-pv.log(-x,b)));
-301};
-302
-303(function(){
-304varradians=Math.PI/180,
-305degrees=180/Math.PI;
-306
-307/** Returns the number of radians corresponding to the specified degrees. */
-308pv.radians=function(degrees){returnradians*degrees;};
-309
-310/** Returns the number of degrees corresponding to the specified radians. */
-311pv.degrees=function(radians){returndegrees*radians;};
-312})();
-313
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Objects.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Objects.js.html
deleted file mode 100644
index ce5b404f..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Objects.js.html
+++ /dev/null
@@ -1,86 +0,0 @@
-
1/**
- 2 * Returns all of the property names (keys) of the specified object (a map). The
- 3 * order of the returned array is not defined.
- 4 *
- 5 * @param map an object.
- 6 * @returns {string[]} an array of strings corresponding to the keys.
- 7 * @see #entries
- 8 */
- 9pv.keys=function(map){
- 10vararray=[];
- 11for(varkeyinmap){
- 12array.push(key);
- 13}
- 14returnarray;
- 15};
- 16
- 17/**
- 18 * Returns all of the entries (key-value pairs) of the specified object (a
- 19 * map). The order of the returned array is not defined. Each key-value pair is
- 20 * represented as an object with <tt>key</tt> and <tt>value</tt> attributes,
- 21 * e.g., <tt>{key: "foo", value: 42}</tt>.
- 22 *
- 23 * @param map an object.
- 24 * @returns {array} an array of key-value pairs corresponding to the keys.
- 25 */
- 26pv.entries=function(map){
- 27vararray=[];
- 28for(varkeyinmap){
- 29array.push({key:key,value:map[key]});
- 30}
- 31returnarray;
- 32};
- 33
- 34/**
- 35 * Returns all of the values (attribute values) of the specified object (a
- 36 * map). The order of the returned array is not defined.
- 37 *
- 38 * @param map an object.
- 39 * @returns {array} an array of objects corresponding to the values.
- 40 * @see #entries
- 41 */
- 42pv.values=function(map){
- 43vararray=[];
- 44for(varkeyinmap){
- 45array.push(map[key]);
- 46}
- 47returnarray;
- 48};
- 49
- 50/**
- 51 * Returns a map constructed from the specified <tt>keys</tt>, using the
- 52 * function <tt>f</tt> to compute the value for each key. The single argument to
- 53 * the value function is the key. The callback is invoked only for indexes of
- 54 * the array which have assigned values; it is not invoked for indexes which
- 55 * have been deleted or which have never been assigned values.
- 56 *
- 57 * <p>For example, this expression creates a map from strings to string length:
- 58 *
- 59 * <pre>pv.dict(["one", "three", "seventeen"], function(s) s.length)</pre>
- 60 *
- 61 * The returned value is <tt>{one: 3, three: 5, seventeen: 9}</tt>. Accessor
- 62 * functions can refer to <tt>this.index</tt>.
- 63 *
- 64 * @param {array} keys an array.
- 65 * @param {function} f a value function.
- 66 * @returns a map from keys to values.
- 67 */
- 68pv.dict=function(keys,f){
- 69varm={},o={};
- 70for(vari=0;i<keys.length;i++){
- 71if(iinkeys){
- 72vark=keys[i];
- 73o.index=i;
- 74m[k]=f.call(o,k);
- 75}
- 76}
- 77returnm;
- 78};
- 79
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_OrdinalScale.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_OrdinalScale.js.html
deleted file mode 100644
index 1be3a61a..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_OrdinalScale.js.html
+++ /dev/null
@@ -1,275 +0,0 @@
-
1/**
- 2 * Returns an ordinal scale for the specified domain. The arguments to this
- 3 * constructor are optional, and equivalent to calling {@link #domain}.
- 4 *
- 5 * @class Represents an ordinal scale. <style
- 6 * type="text/css">sub{line-height:0}</style> An ordinal scale represents a
- 7 * pairwise mapping from <i>n</i> discrete values in the input domain to
- 8 * <i>n</i> discrete values in the output range. For example, an ordinal scale
- 9 * might map a domain of species ["setosa", "versicolor", "virginica"] to colors
- 10 * ["red", "green", "blue"]. Thus, saying
- 11 *
- 12 * <pre> .fillStyle(function(d) {
- 13 * switch (d.species) {
- 14 * case "setosa": return "red";
- 15 * case "versicolor": return "green";
- 16 * case "virginica": return "blue";
- 17 * }
- 18 * })</pre>
- 19 *
- 20 * is equivalent to
- 21 *
- 22 * <pre> .fillStyle(pv.Scale.ordinal("setosa", "versicolor", "virginica")
- 23 * .range("red", "green", "blue")
- 24 * .by(function(d) d.species))</pre>
- 25 *
- 26 * If the mapping from species to color does not need to be specified
- 27 * explicitly, the domain can be omitted. In this case it will be inferred
- 28 * lazily from the data:
- 29 *
- 30 * <pre> .fillStyle(pv.colors("red", "green", "blue")
- 31 * .by(function(d) d.species))</pre>
- 32 *
- 33 * When the domain is inferred, the first time the scale is invoked, the first
- 34 * element from the range will be returned. Subsequent calls with unique values
- 35 * will return subsequent elements from the range. If the inferred domain grows
- 36 * larger than the range, range values will be reused. However, it is strongly
- 37 * recommended that the domain and the range contain the same number of
- 38 * elements.
- 39 *
- 40 * <p>A range can be discretized from a continuous interval (e.g., for pixel
- 41 * positioning) by using {@link #split}, {@link #splitFlush} or
- 42 * {@link #splitBanded} after the domain has been set. For example, if
- 43 * <tt>states</tt> is an array of the fifty U.S. state names, the state name can
- 44 * be encoded in the left position:
- 45 *
- 46 * <pre> .left(pv.Scale.ordinal(states)
- 47 * .split(0, 640)
- 48 * .by(function(d) d.state))</pre>
- 49 *
- 50 * <p>N.B.: ordinal scales are not invertible (at least not yet), since the
- 51 * domain and range and discontinuous. A workaround is to use a linear scale.
- 52 *
- 53 * @param {...} domain... optional domain values.
- 54 * @extends pv.Scale
- 55 * @see pv.colors
- 56 */
- 57pv.Scale.ordinal=function(){
- 58vard=[],i={},r=[],band=0;
- 59
- 60/** @private */
- 61functionscale(x){
- 62if(!(xini))i[x]=d.push(x)-1;
- 63returnr[i[x]%r.length];
- 64}
- 65
- 66/**
- 67 * Sets or gets the input domain. This method can be invoked several ways:
- 68 *
- 69 * <p>1. <tt>domain(values...)</tt>
- 70 *
- 71 * <p>Specifying the domain as a series of values is the most explicit and
- 72 * recommended approach. However, if the domain values are derived from data,
- 73 * you may find the second method more appropriate.
- 74 *
- 75 * <p>2. <tt>domain(array, f)</tt>
- 76 *
- 77 * <p>Rather than enumerating the domain values as explicit arguments to this
- 78 * method, you can specify a single argument of an array. In addition, you can
- 79 * specify an optional accessor function to extract the domain values from the
- 80 * array.
- 81 *
- 82 * <p>3. <tt>domain()</tt>
- 83 *
- 84 * <p>Invoking the <tt>domain</tt> method with no arguments returns the
- 85 * current domain as an array.
- 86 *
- 87 * @function
- 88 * @name pv.Scale.ordinal.prototype.domain
- 89 * @param {...} domain... domain values.
- 90 * @returns {pv.Scale.ordinal} <tt>this</tt>, or the current domain.
- 91 */
- 92scale.domain=function(array,f){
- 93if(arguments.length){
- 94array=(arrayinstanceofArray)
- 95?((arguments.length>1)?pv.map(array,f):array)
- 96:Array.prototype.slice.call(arguments);
- 97
- 98/* Filter the specified ordinals to their unique values. */
- 99d=[];
-100varseen={};
-101for(varj=0;j<array.length;j++){
-102varo=array[j];
-103if(!(oinseen)){
-104seen[o]=true;
-105d.push(o);
-106}
-107}
-108
-109i=pv.numerate(d);
-110returnthis;
-111}
-112returnd;
-113};
-114
-115/**
-116 * Sets or gets the output range. This method can be invoked several ways:
-117 *
-118 * <p>1. <tt>range(values...)</tt>
-119 *
-120 * <p>Specifying the range as a series of values is the most explicit and
-121 * recommended approach. However, if the range values are derived from data,
-122 * you may find the second method more appropriate.
-123 *
-124 * <p>2. <tt>range(array, f)</tt>
-125 *
-126 * <p>Rather than enumerating the range values as explicit arguments to this
-127 * method, you can specify a single argument of an array. In addition, you can
-128 * specify an optional accessor function to extract the range values from the
-129 * array.
-130 *
-131 * <p>3. <tt>range()</tt>
-132 *
-133 * <p>Invoking the <tt>range</tt> method with no arguments returns the
-134 * current range as an array.
-135 *
-136 * @function
-137 * @name pv.Scale.ordinal.prototype.range
-138 * @param {...} range... range values.
-139 * @returns {pv.Scale.ordinal} <tt>this</tt>, or the current range.
-140 */
-141scale.range=function(array,f){
-142if(arguments.length){
-143r=(arrayinstanceofArray)
-144?((arguments.length>1)?pv.map(array,f):array)
-145:Array.prototype.slice.call(arguments);
-146if(typeofr[0]=="string")r=r.map(pv.color);
-147returnthis;
-148}
-149returnr;
-150};
-151
-152/**
-153 * Sets the range from the given continuous interval. The interval
-154 * [<i>min</i>, <i>max</i>] is subdivided into <i>n</i> equispaced points,
-155 * where <i>n</i> is the number of (unique) values in the domain. The first
-156 * and last point are offset from the edge of the range by half the distance
-157 * between points.
-158 *
-159 * <p>This method must be called <i>after</i> the domain is set.
-160 *
-161 * @function
-162 * @name pv.Scale.ordinal.prototype.split
-163 * @param {number} min minimum value of the output range.
-164 * @param {number} max maximum value of the output range.
-165 * @returns {pv.Scale.ordinal} <tt>this</tt>.
-166 * @see #splitFlush
-167 * @see #splitBanded
-168 */
-169scale.split=function(min,max){
-170varstep=(max-min)/this.domain().length;
-171r=pv.range(min+step/2,max,step);
-172returnthis;
-173};
-174
-175/**
-176 * Sets the range from the given continuous interval. The interval
-177 * [<i>min</i>, <i>max</i>] is subdivided into <i>n</i> equispaced points,
-178 * where <i>n</i> is the number of (unique) values in the domain. The first
-179 * and last point are exactly on the edge of the range.
-180 *
-181 * <p>This method must be called <i>after</i> the domain is set.
-182 *
-183 * @function
-184 * @name pv.Scale.ordinal.prototype.splitFlush
-185 * @param {number} min minimum value of the output range.
-186 * @param {number} max maximum value of the output range.
-187 * @returns {pv.Scale.ordinal} <tt>this</tt>.
-188 * @see #split
-189 */
-190scale.splitFlush=function(min,max){
-191varn=this.domain().length,step=(max-min)/(n-1);
-192r=(n==1)?[(min+max)/2]
-193:pv.range(min,max+step/2,step);
-194returnthis;
-195};
-196
-197/**
-198 * Sets the range from the given continuous interval. The interval
-199 * [<i>min</i>, <i>max</i>] is subdivided into <i>n</i> equispaced bands,
-200 * where <i>n</i> is the number of (unique) values in the domain. The first
-201 * and last band are offset from the edge of the range by the distance between
-202 * bands.
-203 *
-204 * <p>The band width argument, <tt>band</tt>, is typically in the range [0, 1]
-205 * and defaults to 1. This fraction corresponds to the amount of space in the
-206 * range to allocate to the bands, as opposed to padding. A value of 0.5 means
-207 * that the band width will be equal to the padding width. The computed
-208 * absolute band width can be retrieved from the range as
-209 * <tt>scale.range().band</tt>.
-210 *
-211 * <p>If the band width argument is negative, this method will allocate bands
-212 * of a <i>fixed</i> width <tt>-band</tt>, rather than a relative fraction of
-213 * the available space.
-214 *
-215 * <p>Tip: to inset the bands by a fixed amount <tt>p</tt>, specify a minimum
-216 * value of <tt>min + p</tt> (or simply <tt>p</tt>, if <tt>min</tt> is
-217 * 0). Then set the mark width to <tt>scale.range().band - p</tt>.
-218 *
-219 * <p>This method must be called <i>after</i> the domain is set.
-220 *
-221 * @function
-222 * @name pv.Scale.ordinal.prototype.splitBanded
-223 * @param {number} min minimum value of the output range.
-224 * @param {number} max maximum value of the output range.
-225 * @param {number} [band] the fractional band width in [0, 1]; defaults to 1.
-226 * @returns {pv.Scale.ordinal} <tt>this</tt>.
-227 * @see #split
-228 */
-229scale.splitBanded=function(min,max,band){
-230if(arguments.length<3)band=1;
-231if(band<0){
-232varn=this.domain().length,
-233total=-band*n,
-234remaining=max-min-total,
-235padding=remaining/(n+1);
-236r=pv.range(min+padding,max,padding-band);
-237r.band=-band;
-238}else{
-239varstep=(max-min)/(this.domain().length+(1-band));
-240r=pv.range(min+step*(1-band),max,step);
-241r.band=step*band;
-242}
-243returnthis;
-244};
-245
-246/**
-247 * Returns a view of this scale by the specified accessor function <tt>f</tt>.
-248 * Given a scale <tt>y</tt>, <tt>y.by(function(d) d.foo)</tt> is equivalent to
-249 * <tt>function(d) y(d.foo)</tt>. This method should be used judiciously; it
-250 * is typically more clear to invoke the scale directly, passing in the value
-251 * to be scaled.
-252 *
-253 * @function
-254 * @name pv.Scale.ordinal.prototype.by
-255 * @param {function} f an accessor function.
-256 * @returns {pv.Scale.ordinal} a view of this scale by the specified accessor
-257 * function.
-258 */
-259scale.by=function(f){
-260functionby(){returnscale(f.apply(this,arguments));}
-261for(varmethodinscale)by[method]=scale[method];
-262returnby;
-263};
-264
-265scale.domain.apply(scale,arguments);
-266returnscale;
-267};
-268
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_QuantileScale.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_QuantileScale.js.html
deleted file mode 100644
index 49655118..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_QuantileScale.js.html
+++ /dev/null
@@ -1,188 +0,0 @@
-
1/**
- 2 * Constructs a default quantile scale. The arguments to this constructor are
- 3 * optional, and equivalent to calling {@link #domain}. The default domain is
- 4 * the empty set, and the default range is [0,1].
- 5 *
- 6 * @class Represents a quantile scale; a function that maps from a value within
- 7 * a sortable domain to a quantized numeric range. Typically, the domain is a
- 8 * set of numbers, but any sortable value (such as strings) can be used as the
- 9 * domain of a quantile scale. The range defaults to [0,1], with 0 corresponding
- 10 * to the smallest value in the domain, 1 the largest, .5 the median, etc.
- 11 *
- 12 * <p>By default, the number of quantiles in the range corresponds to the number
- 13 * of values in the domain. The {@link #quantiles} method can be used to specify
- 14 * an explicit number of quantiles; for example, <tt>quantiles(4)</tt> produces
- 15 * a standard quartile scale. A quartile scale's range is a set of four discrete
- 16 * values, such as [0, 1/3, 2/3, 1]. Calling the {@link #range} method will
- 17 * scale these discrete values accordingly, similar to {@link
- 18 * pv.Scale.ordinal#splitFlush}.
- 19 *
- 20 * <p>For example, given the strings ["c", "a", "b"], a default quantile scale:
- 21 *
- 22 * <pre>pv.Scale.quantile("c", "a", "b")</pre>
- 23 *
- 24 * will return 0 for "a", .5 for "b", and 1 for "c".
- 25 *
- 26 * @extends pv.Scale
- 27 */
- 28pv.Scale.quantile=function(){
- 29varn=-1,// number of quantiles
- 30j=-1,// max quantile index
- 31q=[],// quantile boundaries
- 32d=[],// domain
- 33y=pv.Scale.linear();// range
- 34
- 35/** @private */
- 36functionscale(x){
- 37returny(Math.max(0,Math.min(j,pv.search.index(q,x)-1))/j);
- 38}
- 39
- 40/**
- 41 * Sets or gets the quantile boundaries. By default, each element in the
- 42 * domain is in its own quantile. If the argument to this method is a number,
- 43 * it specifies the number of equal-sized quantiles by which to divide the
- 44 * domain.
- 45 *
- 46 * <p>If no arguments are specified, this method returns the quantile
- 47 * boundaries; the first element is always the minimum value of the domain,
- 48 * and the last element is the maximum value of the domain. Thus, the length
- 49 * of the returned array is always one greater than the number of quantiles.
- 50 *
- 51 * @function
- 52 * @name pv.Scale.quantile.prototype.quantiles
- 53 * @param {number} x the number of quantiles.
- 54 */
- 55scale.quantiles=function(x){
- 56if(arguments.length){
- 57n=Number(x);
- 58if(n<0){
- 59q=[d[0]].concat(d);
- 60j=d.length-1;
- 61}else{
- 62q=[];
- 63q[0]=d[0];
- 64for(vari=1;i<=n;i++){
- 65q[i]=d[~~(i*(d.length-1)/n)];
- 66}
- 67j=n-1;
- 68}
- 69returnthis;
- 70}
- 71returnq;
- 72};
- 73
- 74/**
- 75 * Sets or gets the input domain. This method can be invoked several ways:
- 76 *
- 77 * <p>1. <tt>domain(values...)</tt>
- 78 *
- 79 * <p>Specifying the domain as a series of values is the most explicit and
- 80 * recommended approach. However, if the domain values are derived from data,
- 81 * you may find the second method more appropriate.
- 82 *
- 83 * <p>2. <tt>domain(array, f)</tt>
- 84 *
- 85 * <p>Rather than enumerating the domain values as explicit arguments to this
- 86 * method, you can specify a single argument of an array. In addition, you can
- 87 * specify an optional accessor function to extract the domain values from the
- 88 * array.
- 89 *
- 90 * <p>3. <tt>domain()</tt>
- 91 *
- 92 * <p>Invoking the <tt>domain</tt> method with no arguments returns the
- 93 * current domain as an array.
- 94 *
- 95 * @function
- 96 * @name pv.Scale.quantile.prototype.domain
- 97 * @param {...} domain... domain values.
- 98 * @returns {pv.Scale.quantile} <tt>this</tt>, or the current domain.
- 99 */
-100scale.domain=function(array,f){
-101if(arguments.length){
-102d=(arrayinstanceofArray)
-103?pv.map(array,f)
-104:Array.prototype.slice.call(arguments);
-105d.sort(pv.naturalOrder);
-106scale.quantiles(n);// recompute quantiles
-107returnthis;
-108}
-109returnd;
-110};
-111
-112/**
-113 * Sets or gets the output range. This method can be invoked several ways:
-114 *
-115 * <p>1. <tt>range(min, ..., max)</tt>
-116 *
-117 * <p>The range may be specified as a series of numbers or colors. Most
-118 * commonly, two numbers are specified: the minimum and maximum pixel values.
-119 * For a color scale, values may be specified as {@link pv.Color}s or
-120 * equivalent strings. For a diverging scale, or other subdivided non-uniform
-121 * scales, multiple values can be specified. For example:
-122 *
-123 * <pre> .range("red", "white", "green")</pre>
-124 *
-125 * <p>Currently, only numbers and colors are supported as range values. The
-126 * number of range values must exactly match the number of domain values, or
-127 * the behavior of the scale is undefined.
-128 *
-129 * <p>2. <tt>range()</tt>
-130 *
-131 * <p>Invoking the <tt>range</tt> method with no arguments returns the current
-132 * range as an array of numbers or colors.
-133 *
-134 * @function
-135 * @name pv.Scale.quantile.prototype.range
-136 * @param {...} range... range values.
-137 * @returns {pv.Scale.quantile} <tt>this</tt>, or the current range.
-138 */
-139scale.range=function(){
-140if(arguments.length){
-141y.range.apply(y,arguments);
-142returnthis;
-143}
-144returny.range();
-145};
-146
-147/**
-148 * Returns a view of this scale by the specified accessor function <tt>f</tt>.
-149 * Given a scale <tt>y</tt>, <tt>y.by(function(d) d.foo)</tt> is equivalent to
-150 * <tt>function(d) y(d.foo)</tt>.
-151 *
-152 * <p>This method is provided for convenience, such that scales can be
-153 * succinctly defined inline. For example, given an array of data elements
-154 * that have a <tt>score</tt> attribute with the domain [0, 1], the height
-155 * property could be specified as:
-156 *
-157 * <pre>.height(pv.Scale.linear().range(0, 480).by(function(d) d.score))</pre>
-158 *
-159 * This is equivalent to:
-160 *
-161 * <pre>.height(function(d) d.score * 480)</pre>
-162 *
-163 * This method should be used judiciously; it is typically more clear to
-164 * invoke the scale directly, passing in the value to be scaled.
-165 *
-166 * @function
-167 * @name pv.Scale.quantile.prototype.by
-168 * @param {function} f an accessor function.
-169 * @returns {pv.Scale.quantile} a view of this scale by the specified
-170 * accessor function.
-171 */
-172scale.by=function(f){
-173functionby(){returnscale(f.apply(this,arguments));}
-174for(varmethodinscale)by[method]=scale[method];
-175returnby;
-176};
-177
-178scale.domain.apply(scale,arguments);
-179returnscale;
-180};
-181
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_QuantitativeScale.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_QuantitativeScale.js.html
deleted file mode 100644
index c74cba33..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_QuantitativeScale.js.html
+++ /dev/null
@@ -1,448 +0,0 @@
-
1/**
- 2 * Returns a default quantitative, linear, scale for the specified domain. The
- 3 * arguments to this constructor are optional, and equivalent to calling
- 4 * {@link #domain}. The default domain and range are [0,1].
- 5 *
- 6 * <p>This constructor is typically not used directly; see one of the
- 7 * quantitative scale implementations instead.
- 8 *
- 9 * @class Represents an abstract quantitative scale; a function that performs a
- 10 * numeric transformation. This class is typically not used directly; see one of
- 11 * the quantitative scale implementations (linear, log, root, etc.)
- 12 * instead. <style type="text/css">sub{line-height:0}</style> A quantitative
- 13 * scale represents a 1-dimensional transformation from a numeric domain of
- 14 * input data [<i>d<sub>0</sub></i>, <i>d<sub>1</sub></i>] to a numeric range of
- 15 * pixels [<i>r<sub>0</sub></i>, <i>r<sub>1</sub></i>]. In addition to
- 16 * readability, scales offer several useful features:
- 17 *
- 18 * <p>1. The range can be expressed in colors, rather than pixels. For example:
- 19 *
- 20 * <pre> .fillStyle(pv.Scale.linear(0, 100).range("red", "green"))</pre>
- 21 *
- 22 * will fill the marks "red" on an input value of 0, "green" on an input value
- 23 * of 100, and some color in-between for intermediate values.
- 24 *
- 25 * <p>2. The domain and range can be subdivided for a non-uniform
- 26 * transformation. For example, you may want a diverging color scale that is
- 27 * increasingly red for negative values, and increasingly green for positive
- 28 * values:
- 29 *
- 30 * <pre> .fillStyle(pv.Scale.linear(-1, 0, 1).range("red", "white", "green"))</pre>
- 31 *
- 32 * The domain can be specified as a series of <i>n</i> monotonically-increasing
- 33 * values; the range must also be specified as <i>n</i> values, resulting in
- 34 * <i>n - 1</i> contiguous linear scales.
- 35 *
- 36 * <p>3. Quantitative scales can be inverted for interaction. The
- 37 * {@link #invert} method takes a value in the output range, and returns the
- 38 * corresponding value in the input domain. This is frequently used to convert
- 39 * the mouse location (see {@link pv.Mark#mouse}) to a value in the input
- 40 * domain. Note that inversion is only supported for numeric ranges, and not
- 41 * colors.
- 42 *
- 43 * <p>4. A scale can be queried for reasonable "tick" values. The {@link #ticks}
- 44 * method provides a convenient way to get a series of evenly-spaced rounded
- 45 * values in the input domain. Frequently these are used in conjunction with
- 46 * {@link pv.Rule} to display tick marks or grid lines.
- 47 *
- 48 * <p>5. A scale can be "niced" to extend the domain to suitable rounded
- 49 * numbers. If the minimum and maximum of the domain are messy because they are
- 50 * derived from data, you can use {@link #nice} to round these values down and
- 51 * up to even numbers.
- 52 *
- 53 * @param {number...} domain... optional domain values.
- 54 * @see pv.Scale.linear
- 55 * @see pv.Scale.log
- 56 * @see pv.Scale.root
- 57 * @extends pv.Scale
- 58 */
- 59pv.Scale.quantitative=function(){
- 60vard=[0,1],// default domain
- 61l=[0,1],// default transformed domain
- 62r=[0,1],// default range
- 63i=[pv.identity],// default interpolators
- 64type=Number,// default type
- 65n=false,// whether the domain is negative
- 66f=pv.identity,// default forward transform
- 67g=pv.identity,// default inverse transform
- 68tickFormat=String;// default tick formatting function
- 69
- 70/** @private */
- 71functionnewDate(x){
- 72returnnewDate(x);
- 73}
- 74
- 75/** @private */
- 76functionscale(x){
- 77varj=pv.search(d,x);
- 78if(j<0)j=-j-2;
- 79j=Math.max(0,Math.min(i.length-1,j));
- 80returni[j]((f(x)-l[j])/(l[j+1]-l[j]));
- 81}
- 82
- 83/** @private */
- 84scale.transform=function(forward,inverse){
- 85/** @ignore */f=function(x){returnn?-forward(-x):forward(x);};
- 86/** @ignore */g=function(y){returnn?-inverse(-y):inverse(y);};
- 87l=d.map(f);
- 88returnthis;
- 89};
- 90
- 91/**
- 92 * Sets or gets the input domain. This method can be invoked several ways:
- 93 *
- 94 * <p>1. <tt>domain(min, ..., max)</tt>
- 95 *
- 96 * <p>Specifying the domain as a series of numbers is the most explicit and
- 97 * recommended approach. Most commonly, two numbers are specified: the minimum
- 98 * and maximum value. However, for a diverging scale, or other subdivided
- 99 * non-uniform scales, multiple values can be specified. Values can be derived
-100 * from data using {@link pv.min} and {@link pv.max}. For example:
-101 *
-102 * <pre> .domain(0, pv.max(array))</pre>
-103 *
-104 * An alternative method for deriving minimum and maximum values from data
-105 * follows.
-106 *
-107 * <p>2. <tt>domain(array, minf, maxf)</tt>
-108 *
-109 * <p>When both the minimum and maximum value are derived from data, the
-110 * arguments to the <tt>domain</tt> method can be specified as the array of
-111 * data, followed by zero, one or two accessor functions. For example, if the
-112 * array of data is just an array of numbers:
-113 *
-114 * <pre> .domain(array)</pre>
-115 *
-116 * On the other hand, if the array elements are objects representing stock
-117 * values per day, and the domain should consider the stock's daily low and
-118 * daily high:
-119 *
-120 * <pre> .domain(array, function(d) d.low, function(d) d.high)</pre>
-121 *
-122 * The first method of setting the domain is preferred because it is more
-123 * explicit; setting the domain using this second method should be used only
-124 * if brevity is required.
-125 *
-126 * <p>3. <tt>domain()</tt>
-127 *
-128 * <p>Invoking the <tt>domain</tt> method with no arguments returns the
-129 * current domain as an array of numbers.
-130 *
-131 * @function
-132 * @name pv.Scale.quantitative.prototype.domain
-133 * @param {number...} domain... domain values.
-134 * @returns {pv.Scale.quantitative} <tt>this</tt>, or the current domain.
-135 */
-136scale.domain=function(array,min,max){
-137if(arguments.length){
-138varo;// the object we use to infer the domain type
-139if(arrayinstanceofArray){
-140if(arguments.length<2)min=pv.identity;
-141if(arguments.length<3)max=min;
-142o=array.length&&min(array[0]);
-143d=array.length?[pv.min(array,min),pv.max(array,max)]:[];
-144}else{
-145o=array;
-146d=Array.prototype.slice.call(arguments).map(Number);
-147}
-148if(!d.length)d=[-Infinity,Infinity];
-149elseif(d.length==1)d=[d[0],d[0]];
-150n=(d[0]||d[d.length-1])<0;
-151l=d.map(f);
-152type=(oinstanceofDate)?newDate:Number;
-153returnthis;
-154}
-155returnd.map(type);
-156};
-157
-158/**
-159 * Sets or gets the output range. This method can be invoked several ways:
-160 *
-161 * <p>1. <tt>range(min, ..., max)</tt>
-162 *
-163 * <p>The range may be specified as a series of numbers or colors. Most
-164 * commonly, two numbers are specified: the minimum and maximum pixel values.
-165 * For a color scale, values may be specified as {@link pv.Color}s or
-166 * equivalent strings. For a diverging scale, or other subdivided non-uniform
-167 * scales, multiple values can be specified. For example:
-168 *
-169 * <pre> .range("red", "white", "green")</pre>
-170 *
-171 * <p>Currently, only numbers and colors are supported as range values. The
-172 * number of range values must exactly match the number of domain values, or
-173 * the behavior of the scale is undefined.
-174 *
-175 * <p>2. <tt>range()</tt>
-176 *
-177 * <p>Invoking the <tt>range</tt> method with no arguments returns the current
-178 * range as an array of numbers or colors.
-179 *
-180 * @function
-181 * @name pv.Scale.quantitative.prototype.range
-182 * @param {...} range... range values.
-183 * @returns {pv.Scale.quantitative} <tt>this</tt>, or the current range.
-184 */
-185scale.range=function(){
-186if(arguments.length){
-187r=Array.prototype.slice.call(arguments);
-188if(!r.length)r=[-Infinity,Infinity];
-189elseif(r.length==1)r=[r[0],r[0]];
-190i=[];
-191for(varj=0;j<r.length-1;j++){
-192i.push(pv.Scale.interpolator(r[j],r[j+1]));
-193}
-194returnthis;
-195}
-196returnr;
-197};
-198
-199/**
-200 * Inverts the specified value in the output range, returning the
-201 * corresponding value in the input domain. This is frequently used to convert
-202 * the mouse location (see {@link pv.Mark#mouse}) to a value in the input
-203 * domain. Inversion is only supported for numeric ranges, and not colors.
-204 *
-205 * <p>Note that this method does not do any rounding or bounds checking. If
-206 * the input domain is discrete (e.g., an array index), the returned value
-207 * should be rounded. If the specified <tt>y</tt> value is outside the range,
-208 * the returned value may be equivalently outside the input domain.
-209 *
-210 * @function
-211 * @name pv.Scale.quantitative.prototype.invert
-212 * @param {number} y a value in the output range (a pixel location).
-213 * @returns {number} a value in the input domain.
-214 */
-215scale.invert=function(y){
-216varj=pv.search(r,y);
-217if(j<0)j=-j-2;
-218j=Math.max(0,Math.min(i.length-1,j));
-219returntype(g(l[j]+(y-r[j])/(r[j+1]-r[j])*(l[j+1]-l[j])));
-220};
-221
-222/**
-223 * Returns an array of evenly-spaced, suitably-rounded values in the input
-224 * domain. This method attempts to return between 5 and 10 tick values. These
-225 * values are frequently used in conjunction with {@link pv.Rule} to display
-226 * tick marks or grid lines.
-227 *
-228 * @function
-229 * @name pv.Scale.quantitative.prototype.ticks
-230 * @param {number} [m] optional number of desired ticks.
-231 * @returns {number[]} an array input domain values to use as ticks.
-232 */
-233scale.ticks=function(m){
-234varstart=d[0],
-235end=d[d.length-1],
-236reverse=end<start,
-237min=reverse?end:start,
-238max=reverse?start:end,
-239span=max-min;
-240
-241/* Special case: empty, invalid or infinite span. */
-242if(!span||!isFinite(span)){
-243if(type==newDate)tickFormat=pv.Format.date("%x");
-244return[type(min)];
-245}
-246
-247/* Special case: dates. */
-248if(type==newDate){
-249/* Floor the date d given the precision p. */
-250functionfloor(d,p){
-251switch(p){
-252case31536e6:d.setMonth(0);
-253case2592e6:d.setDate(1);
-254case6048e5:if(p==6048e5)d.setDate(d.getDate()-d.getDay());
-255case864e5:d.setHours(0);
-256case36e5:d.setMinutes(0);
-257case6e4:d.setSeconds(0);
-258case1e3:d.setMilliseconds(0);
-259}
-260}
-261
-262varprecision,format,increment,step=1;
-263if(span>=3*31536e6){
-264precision=31536e6;
-265format="%Y";
-266/** @ignore */increment=function(d){d.setFullYear(d.getFullYear()+step);};
-267}elseif(span>=3*2592e6){
-268precision=2592e6;
-269format="%m/%Y";
-270/** @ignore */increment=function(d){d.setMonth(d.getMonth()+step);};
-271}elseif(span>=3*6048e5){
-272precision=6048e5;
-273format="%m/%d";
-274/** @ignore */increment=function(d){d.setDate(d.getDate()+7*step);};
-275}elseif(span>=3*864e5){
-276precision=864e5;
-277format="%m/%d";
-278/** @ignore */increment=function(d){d.setDate(d.getDate()+step);};
-279}elseif(span>=3*36e5){
-280precision=36e5;
-281format="%I:%M %p";
-282/** @ignore */increment=function(d){d.setHours(d.getHours()+step);};
-283}elseif(span>=3*6e4){
-284precision=6e4;
-285format="%I:%M %p";
-286/** @ignore */increment=function(d){d.setMinutes(d.getMinutes()+step);};
-287}elseif(span>=3*1e3){
-288precision=1e3;
-289format="%I:%M:%S";
-290/** @ignore */increment=function(d){d.setSeconds(d.getSeconds()+step);};
-291}else{
-292precision=1;
-293format="%S.%Qs";
-294/** @ignore */increment=function(d){d.setTime(d.getTime()+step);};
-295}
-296tickFormat=pv.Format.date(format);
-297
-298vardate=newDate(min),dates=[];
-299floor(date,precision);
-300
-301/* If we'd generate too many ticks, skip some!. */
-302varn=span/precision;
-303if(n>10){
-304switch(precision){
-305case36e5:{
-306step=(n>20)?6:3;
-307date.setHours(Math.floor(date.getHours()/step)*step);
-308break;
-309}
-310case2592e6:{
-311step=3;// seasons
-312date.setMonth(Math.floor(date.getMonth()/step)*step);
-313break;
-314}
-315case6e4:{
-316step=(n>30)?15:((n>15)?10:5);
-317date.setMinutes(Math.floor(date.getMinutes()/step)*step);
-318break;
-319}
-320case1e3:{
-321step=(n>90)?15:((n>60)?10:5);
-322date.setSeconds(Math.floor(date.getSeconds()/step)*step);
-323break;
-324}
-325case1:{
-326step=(n>1000)?250:((n>200)?100:((n>100)?50:((n>50)?25:5)));
-327date.setMilliseconds(Math.floor(date.getMilliseconds()/step)*step);
-328break;
-329}
-330default:{
-331step=pv.logCeil(n/15,10);
-332if(n/step<2)step/=5;
-333elseif(n/step<5)step/=2;
-334date.setFullYear(Math.floor(date.getFullYear()/step)*step);
-335break;
-336}
-337}
-338}
-339
-340while(true){
-341increment(date);
-342if(date>max)break;
-343dates.push(newDate(date));
-344}
-345returnreverse?dates.reverse():dates;
-346}
-347
-348/* Normal case: numbers. */
-349if(!arguments.length)m=10;
-350varstep=pv.logFloor(span/m,10),
-351err=m/(span/step);
-352if(err<=.15)step*=10;
-353elseif(err<=.35)step*=5;
-354elseif(err<=.75)step*=2;
-355varstart=Math.ceil(min/step)*step,
-356end=Math.floor(max/step)*step;
-357tickFormat=pv.Format.number()
-358.fractionDigits(Math.max(0,-Math.floor(pv.log(step,10)+.01)));
-359varticks=pv.range(start,end+step,step);
-360returnreverse?ticks.reverse():ticks;
-361};
-362
-363/**
-364 * Formats the specified tick value using the appropriate precision, based on
-365 * the step interval between tick marks. If {@link #ticks} has not been called,
-366 * the argument is converted to a string, but no formatting is applied.
-367 *
-368 * @function
-369 * @name pv.Scale.quantitative.prototype.tickFormat
-370 * @param {number} t a tick value.
-371 * @returns {string} a formatted tick value.
-372 */
-373scale.tickFormat=function(t){returntickFormat(t);};
-374
-375/**
-376 * "Nices" this scale, extending the bounds of the input domain to
-377 * evenly-rounded values. Nicing is useful if the domain is computed
-378 * dynamically from data, and may be irregular. For example, given a domain of
-379 * [0.20147987687960267, 0.996679553296417], a call to <tt>nice()</tt> might
-380 * extend the domain to [0.2, 1].
-381 *
-382 * <p>This method must be invoked each time after setting the domain.
-383 *
-384 * @function
-385 * @name pv.Scale.quantitative.prototype.nice
-386 * @returns {pv.Scale.quantitative} <tt>this</tt>.
-387 */
-388scale.nice=function(){
-389if(d.length!=2)returnthis;// TODO support non-uniform domains
-390varstart=d[0],
-391end=d[d.length-1],
-392reverse=end<start,
-393min=reverse?end:start,
-394max=reverse?start:end,
-395span=max-min;
-396
-397/* Special case: empty, invalid or infinite span. */
-398if(!span||!isFinite(span))returnthis;
-399
-400varstep=Math.pow(10,Math.round(Math.log(span)/Math.log(10))-1);
-401d=[Math.floor(min/step)*step,Math.ceil(max/step)*step];
-402if(reverse)d.reverse();
-403l=d.map(f);
-404returnthis;
-405};
-406
-407/**
-408 * Returns a view of this scale by the specified accessor function <tt>f</tt>.
-409 * Given a scale <tt>y</tt>, <tt>y.by(function(d) d.foo)</tt> is equivalent to
-410 * <tt>function(d) y(d.foo)</tt>.
-411 *
-412 * <p>This method is provided for convenience, such that scales can be
-413 * succinctly defined inline. For example, given an array of data elements
-414 * that have a <tt>score</tt> attribute with the domain [0, 1], the height
-415 * property could be specified as:
-416 *
-417 * <pre> .height(pv.Scale.linear().range(0, 480).by(function(d) d.score))</pre>
-418 *
-419 * This is equivalent to:
-420 *
-421 * <pre> .height(function(d) d.score * 480)</pre>
-422 *
-423 * This method should be used judiciously; it is typically more clear to
-424 * invoke the scale directly, passing in the value to be scaled.
-425 *
-426 * @function
-427 * @name pv.Scale.quantitative.prototype.by
-428 * @param {function} f an accessor function.
-429 * @returns {pv.Scale.quantitative} a view of this scale by the specified
-430 * accessor function.
-431 */
-432scale.by=function(f){
-433functionby(){returnscale(f.apply(this,arguments));}
-434for(varmethodinscale)by[method]=scale[method];
-435returnby;
-436};
-437
-438scale.domain.apply(scale,arguments);
-439returnscale;
-440};
-441
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_RootScale.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_RootScale.js.html
deleted file mode 100644
index b74f9bac..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_RootScale.js.html
+++ /dev/null
@@ -1,63 +0,0 @@
-
1/**
- 2 * Returns a root scale for the specified domain. The arguments to this
- 3 * constructor are optional, and equivalent to calling {@link #domain}.
- 4 * The default domain and range are [0,1].
- 5 *
- 6 * @class Represents a root scale; a function that performs a power
- 7 * transformation. <style type="text/css">sub{line-height:0}</style> Most
- 8 * commonly, a root scale represents a 1-dimensional root transformation from a
- 9 * numeric domain of input data [<i>d<sub>0</sub></i>, <i>d<sub>1</sub></i>] to
- 10 * a numeric range of pixels [<i>r<sub>0</sub></i>, <i>r<sub>1</sub></i>].
- 11 *
- 12 * <p>Note that the scale is itself a function, and thus can be used as a
- 13 * property directly, assuming that the data associated with a mark is a
- 14 * number. While this is convenient for single-use scales, frequently it is
- 15 * desirable to define scales globally:
- 16 *
- 17 * <pre>var y = pv.Scale.root(0, 100).range(0, 640);</pre>
- 18 *
- 19 * The <tt>y</tt> scale can now be equivalently referenced within a property:
- 20 *
- 21 * <pre> .height(function(d) y(d))</pre>
- 22 *
- 23 * Alternatively, if the data are not simple numbers, the appropriate value can
- 24 * be passed to the <tt>y</tt> scale (e.g., <tt>d.foo</tt>). The {@link #by}
- 25 * method similarly allows the data to be mapped to a numeric value before
- 26 * performing the root transformation.
- 27 *
- 28 * @param {number...} domain... optional domain values.
- 29 * @extends pv.Scale.quantitative
- 30 */
- 31pv.Scale.root=function(){
- 32varscale=pv.Scale.quantitative();
- 33
- 34/**
- 35 * Sets or gets the exponent; defaults to 2.
- 36 *
- 37 * @function
- 38 * @name pv.Scale.root.prototype.power
- 39 * @param {number} [v] the new exponent.
- 40 * @returns {pv.Scale.root} <tt>this</tt>, or the current base.
- 41 */
- 42scale.power=function(v){
- 43if(arguments.length){
- 44varb=Number(v),p=1/b;
- 45scale.transform(
- 46function(x){returnMath.pow(x,p);},
- 47function(y){returnMath.pow(y,b);});
- 48returnthis;
- 49}
- 50returnb;
- 51};
- 52
- 53scale.domain.apply(scale,arguments);
- 54returnscale.power(2);
- 55};
- 56
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Scale.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Scale.js.html
deleted file mode 100644
index 232280fa..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Scale.js.html
+++ /dev/null
@@ -1,94 +0,0 @@
-
1/**
- 2 * Abstract; see the various scale implementations.
- 3 *
- 4 * @class Represents a scale; a function that performs a transformation from
- 5 * data domain to visual range. For quantitative and quantile scales, the domain
- 6 * is expressed as numbers; for ordinal scales, the domain is expressed as
- 7 * strings (or equivalently objects with unique string representations). The
- 8 * "visual range" may correspond to pixel space, colors, font sizes, and the
- 9 * like.
- 10 *
- 11 * <p>Note that scales are functions, and thus can be used as properties
- 12 * directly, assuming that the data associated with a mark is a number. While
- 13 * this is convenient for single-use scales, frequently it is desirable to
- 14 * define scales globally:
- 15 *
- 16 * <pre>var y = pv.Scale.linear(0, 100).range(0, 640);</pre>
- 17 *
- 18 * The <tt>y</tt> scale can now be equivalently referenced within a property:
- 19 *
- 20 * <pre> .height(function(d) y(d))</pre>
- 21 *
- 22 * Alternatively, if the data are not simple numbers, the appropriate value can
- 23 * be passed to the <tt>y</tt> scale (e.g., <tt>d.foo</tt>). The {@link #by}
- 24 * method similarly allows the data to be mapped to a numeric value before
- 25 * performing the linear transformation.
- 26 *
- 27 * @see pv.Scale.quantitative
- 28 * @see pv.Scale.quantile
- 29 * @see pv.Scale.ordinal
- 30 * @extends function
- 31 */
- 32pv.Scale=function(){};
- 33
- 34/**
- 35 * @private Returns a function that interpolators from the start value to the
- 36 * end value, given a parameter <i>t</i> in [0, 1].
- 37 *
- 38 * @param start the start value.
- 39 * @param end the end value.
- 40 */
- 41pv.Scale.interpolator=function(start,end){
- 42if(typeofstart=="number"){
- 43returnfunction(t){
- 44returnt*(end-start)+start;
- 45};
- 46}
- 47
- 48/* For now, assume color. */
- 49start=pv.color(start).rgb();
- 50end=pv.color(end).rgb();
- 51returnfunction(t){
- 52vara=start.a*(1-t)+end.a*t;
- 53if(a<1e-5)a=0;// avoid scientific notation
- 54return(start.a==0)?pv.rgb(end.r,end.g,end.b,a)
- 55:((end.a==0)?pv.rgb(start.r,start.g,start.b,a)
- 56:pv.rgb(
- 57Math.round(start.r*(1-t)+end.r*t),
- 58Math.round(start.g*(1-t)+end.g*t),
- 59Math.round(start.b*(1-t)+end.b*t),a));
- 60};
- 61};
- 62
- 63/**
- 64 * Returns a view of this scale by the specified accessor function <tt>f</tt>.
- 65 * Given a scale <tt>y</tt>, <tt>y.by(function(d) d.foo)</tt> is equivalent to
- 66 * <tt>function(d) y(d.foo)</tt>.
- 67 *
- 68 * <p>This method is provided for convenience, such that scales can be
- 69 * succinctly defined inline. For example, given an array of data elements that
- 70 * have a <tt>score</tt> attribute with the domain [0, 1], the height property
- 71 * could be specified as:
- 72 *
- 73 * <pre> .height(pv.Scale.linear().range(0, 480).by(function(d) d.score))</pre>
- 74 *
- 75 * This is equivalent to:
- 76 *
- 77 * <pre> .height(function(d) d.score * 480)</pre>
- 78 *
- 79 * This method should be used judiciously; it is typically more clear to invoke
- 80 * the scale directly, passing in the value to be scaled.
- 81 *
- 82 * @function
- 83 * @name pv.Scale.prototype.by
- 84 * @param {function} f an accessor function.
- 85 * @returns {pv.Scale} a view of this scale by the specified accessor function.
- 86 */
- 87
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Transform.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Transform.js.html
deleted file mode 100644
index add4eb0b..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Transform.js.html
+++ /dev/null
@@ -1,117 +0,0 @@
-
1/**
- 2 * Returns a new identity transform.
- 3 *
- 4 * @class Represents a transformation matrix. The transformation matrix is
- 5 * limited to expressing translate and uniform scale transforms only; shearing,
- 6 * rotation, general affine, and other transforms are not supported.
- 7 *
- 8 * <p>The methods on this class treat the transform as immutable, returning a
- 9 * copy of the transformation matrix with the specified transform applied. Note,
- 10 * alternatively, that the matrix fields can be get and set directly.
- 11 */
- 12pv.Transform=function(){};
- 13pv.Transform.prototype={k:1,x:0,y:0};
- 14
- 15/**
- 16 * The scale magnitude; defaults to 1.
- 17 *
- 18 * @type number
- 19 * @name pv.Transform.prototype.k
- 20 */
- 21
- 22/**
- 23 * The x-offset; defaults to 0.
- 24 *
- 25 * @type number
- 26 * @name pv.Transform.prototype.x
- 27 */
- 28
- 29/**
- 30 * The y-offset; defaults to 0.
- 31 *
- 32 * @type number
- 33 * @name pv.Transform.prototype.y
- 34 */
- 35
- 36/**
- 37 * @private The identity transform.
- 38 *
- 39 * @type pv.Transform
- 40 */
- 41pv.Transform.identity=newpv.Transform();
- 42
- 43// k 0 x 1 0 a k 0 ka+x
- 44// 0 k y * 0 1 b = 0 k kb+y
- 45// 0 0 1 0 0 1 0 0 1
- 46
- 47/**
- 48 * Returns a translated copy of this transformation matrix.
- 49 *
- 50 * @param {number} x the x-offset.
- 51 * @param {number} y the y-offset.
- 52 * @returns {pv.Transform} the translated transformation matrix.
- 53 */
- 54pv.Transform.prototype.translate=function(x,y){
- 55varv=newpv.Transform();
- 56v.k=this.k;
- 57v.x=this.k*x+this.x;
- 58v.y=this.k*y+this.y;
- 59returnv;
- 60};
- 61
- 62// k 0 x d 0 0 kd 0 x
- 63// 0 k y * 0 d 0 = 0 kd y
- 64// 0 0 1 0 0 1 0 0 1
- 65
- 66/**
- 67 * Returns a scaled copy of this transformation matrix.
- 68 *
- 69 * @param {number} k
- 70 * @returns {pv.Transform} the scaled transformation matrix.
- 71 */
- 72pv.Transform.prototype.scale=function(k){
- 73varv=newpv.Transform();
- 74v.k=this.k*k;
- 75v.x=this.x;
- 76v.y=this.y;
- 77returnv;
- 78};
- 79
- 80/**
- 81 * Returns the inverse of this transformation matrix.
- 82 *
- 83 * @returns {pv.Transform} the inverted transformation matrix.
- 84 */
- 85pv.Transform.prototype.invert=function(){
- 86varv=newpv.Transform(),k=1/this.k;
- 87v.k=k;
- 88v.x=-this.x*k;
- 89v.y=-this.y*k;
- 90returnv;
- 91};
- 92
- 93// k 0 x d 0 a kd 0 ka+x
- 94// 0 k y * 0 d b = 0 kd kb+y
- 95// 0 0 1 0 0 1 0 0 1
- 96
- 97/**
- 98 * Returns this matrix post-multiplied by the specified matrix <i>m</i>.
- 99 *
-100 * @param {pv.Transform} m
-101 * @returns {pv.Transform} the post-multiplied transformation matrix.
-102 */
-103pv.Transform.prototype.times=function(m){
-104varv=newpv.Transform();
-105v.k=this.k*m.k;
-106v.x=this.k*m.x+this.x;
-107v.y=this.k*m.y+this.y;
-108returnv;
-109};
-110
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Tree.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Tree.js.html
deleted file mode 100644
index 31c7a91c..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Tree.js.html
+++ /dev/null
@@ -1,132 +0,0 @@
-
1/**
- 2 * Returns a {@link pv.Tree} operator for the specified array. This is a
- 3 * convenience factory method, equivalent to <tt>new pv.Tree(array)</tt>.
- 4 *
- 5 * @see pv.Tree
- 6 * @param {array} array an array from which to construct a tree.
- 7 * @returns {pv.Tree} a tree operator for the specified array.
- 8 */
- 9pv.tree=function(array){
- 10returnnewpv.Tree(array);
- 11};
- 12
- 13/**
- 14 * Constructs a tree operator for the specified array. This constructor should
- 15 * not be invoked directly; use {@link pv.tree} instead.
- 16 *
- 17 * @class Represents a tree operator for the specified array. The tree operator
- 18 * allows a hierarchical map to be constructed from an array; it is similar to
- 19 * the {@link pv.Nest} operator, except the hierarchy is derived dynamically
- 20 * from the array elements.
- 21 *
- 22 * <p>For example, given an array of size information for ActionScript classes:
- 23 *
- 24 * <pre>{ name: "flare.flex.FlareVis", size: 4116 },
- 25 * { name: "flare.physics.DragForce", size: 1082 },
- 26 * { name: "flare.physics.GravityForce", size: 1336 }, ...</pre>
- 27 *
- 28 * To facilitate visualization, it may be useful to nest the elements by their
- 29 * package hierarchy:
- 30 *
- 31 * <pre>var tree = pv.tree(classes)
- 32 * .keys(function(d) d.name.split("."))
- 33 * .map();</pre>
- 34 *
- 35 * The resulting tree is:
- 36 *
- 37 * <pre>{ flare: {
- 38 * flex: {
- 39 * FlareVis: {
- 40 * name: "flare.flex.FlareVis",
- 41 * size: 4116 } },
- 42 * physics: {
- 43 * DragForce: {
- 44 * name: "flare.physics.DragForce",
- 45 * size: 1082 },
- 46 * GravityForce: {
- 47 * name: "flare.physics.GravityForce",
- 48 * size: 1336 } },
- 49 * ... } }</pre>
- 50 *
- 51 * By specifying a value function,
- 52 *
- 53 * <pre>var tree = pv.tree(classes)
- 54 * .keys(function(d) d.name.split("."))
- 55 * .value(function(d) d.size)
- 56 * .map();</pre>
- 57 *
- 58 * we can further eliminate redundant data:
- 59 *
- 60 * <pre>{ flare: {
- 61 * flex: {
- 62 * FlareVis: 4116 },
- 63 * physics: {
- 64 * DragForce: 1082,
- 65 * GravityForce: 1336 },
- 66 * ... } }</pre>
- 67 *
- 68 * For visualizations with large data sets, performance improvements may be seen
- 69 * by storing the data in a tree format, and then flattening it into an array at
- 70 * runtime with {@link pv.Flatten}.
- 71 *
- 72 * @param {array} array an array from which to construct a tree.
- 73 */
- 74pv.Tree=function(array){
- 75this.array=array;
- 76};
- 77
- 78/**
- 79 * Assigns a <i>keys</i> function to this operator; required. The keys function
- 80 * returns an array of <tt>string</tt>s for each element in the associated
- 81 * array; these keys determine how the elements are nested in the tree. The
- 82 * returned keys should be unique for each element in the array; otherwise, the
- 83 * behavior of this operator is undefined.
- 84 *
- 85 * @param {function} k the keys function.
- 86 * @returns {pv.Tree} this.
- 87 */
- 88pv.Tree.prototype.keys=function(k){
- 89this.k=k;
- 90returnthis;
- 91};
- 92
- 93/**
- 94 * Assigns a <i>value</i> function to this operator; optional. The value
- 95 * function specifies an optional transformation of the element in the array
- 96 * before it is inserted into the map. If no value function is specified, it is
- 97 * equivalent to using the identity function.
- 98 *
- 99 * @param {function} k the value function.
-100 * @returns {pv.Tree} this.
-101 */
-102pv.Tree.prototype.value=function(v){
-103this.v=v;
-104returnthis;
-105};
-106
-107/**
-108 * Returns a hierarchical map of values. The hierarchy is determined by the keys
-109 * function; the values in the map are determined by the value function.
-110 *
-111 * @returns a hierarchical map of values.
-112 */
-113pv.Tree.prototype.map=function(){
-114varmap={},o={};
-115for(vari=0;i<this.array.length;i++){
-116o.index=i;
-117varvalue=this.array[i],keys=this.k.call(o,value),node=map;
-118for(varj=0;j<keys.length-1;j++){
-119node=node[keys[j]]||(node[keys[j]]={});
-120}
-121node[keys[j]]=this.v?this.v.call(o,value):value;
-122}
-123returnmap;
-124};
-125
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Vector.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Vector.js.html
deleted file mode 100644
index 6051d92d..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_data_Vector.js.html
+++ /dev/null
@@ -1,126 +0,0 @@
-
1/**
- 2 * Returns a {@link pv.Vector} for the specified <i>x</i> and <i>y</i>
- 3 * coordinate. This is a convenience factory method, equivalent to <tt>new
- 4 * pv.Vector(x, y)</tt>.
- 5 *
- 6 * @see pv.Vector
- 7 * @param {number} x the <i>x</i> coordinate.
- 8 * @param {number} y the <i>y</i> coordinate.
- 9 * @returns {pv.Vector} a vector for the specified coordinates.
- 10 */
- 11pv.vector=function(x,y){
- 12returnnewpv.Vector(x,y);
- 13};
- 14
- 15/**
- 16 * Constructs a {@link pv.Vector} for the specified <i>x</i> and <i>y</i>
- 17 * coordinate. This constructor should not be invoked directly; use
- 18 * {@link pv.vector} instead.
- 19 *
- 20 * @class Represents a two-dimensional vector; a 2-tuple <i>⟨x,
- 21 * y⟩</i>. The intent of this class is to simplify vector math. Note that
- 22 * in performance-sensitive cases it may be more efficient to represent 2D
- 23 * vectors as simple objects with <tt>x</tt> and <tt>y</tt> attributes, rather
- 24 * than using instances of this class.
- 25 *
- 26 * @param {number} x the <i>x</i> coordinate.
- 27 * @param {number} y the <i>y</i> coordinate.
- 28 */
- 29pv.Vector=function(x,y){
- 30this.x=x;
- 31this.y=y;
- 32};
- 33
- 34/**
- 35 * Returns a vector perpendicular to this vector: <i>⟨-y, x⟩</i>.
- 36 *
- 37 * @returns {pv.Vector} a perpendicular vector.
- 38 */
- 39pv.Vector.prototype.perp=function(){
- 40returnnewpv.Vector(-this.y,this.x);
- 41};
- 42
- 43/**
- 44 * Returns a normalized copy of this vector: a vector with the same direction,
- 45 * but unit length. If this vector has zero length this method returns a copy of
- 46 * this vector.
- 47 *
- 48 * @returns {pv.Vector} a unit vector.
- 49 */
- 50pv.Vector.prototype.norm=function(){
- 51varl=this.length();
- 52returnthis.times(l?(1/l):1);
- 53};
- 54
- 55/**
- 56 * Returns the magnitude of this vector, defined as <i>sqrt(x * x + y * y)</i>.
- 57 *
- 58 * @returns {number} a length.
- 59 */
- 60pv.Vector.prototype.length=function(){
- 61returnMath.sqrt(this.x*this.x+this.y*this.y);
- 62};
- 63
- 64/**
- 65 * Returns a scaled copy of this vector: <i>⟨x * k, y * k⟩</i>.
- 66 * To perform the equivalent divide operation, use <i>1 / k</i>.
- 67 *
- 68 * @param {number} k the scale factor.
- 69 * @returns {pv.Vector} a scaled vector.
- 70 */
- 71pv.Vector.prototype.times=function(k){
- 72returnnewpv.Vector(this.x*k,this.y*k);
- 73};
- 74
- 75/**
- 76 * Returns this vector plus the vector <i>v</i>: <i>⟨x + v.x, y +
- 77 * v.y⟩</i>. If only one argument is specified, it is interpreted as the
- 78 * vector <i>v</i>.
- 79 *
- 80 * @param {number} x the <i>x</i> coordinate to add.
- 81 * @param {number} y the <i>y</i> coordinate to add.
- 82 * @returns {pv.Vector} a new vector.
- 83 */
- 84pv.Vector.prototype.plus=function(x,y){
- 85return(arguments.length==1)
- 86?newpv.Vector(this.x+x.x,this.y+x.y)
- 87:newpv.Vector(this.x+x,this.y+y);
- 88};
- 89
- 90/**
- 91 * Returns this vector minus the vector <i>v</i>: <i>⟨x - v.x, y -
- 92 * v.y⟩</i>. If only one argument is specified, it is interpreted as the
- 93 * vector <i>v</i>.
- 94 *
- 95 * @param {number} x the <i>x</i> coordinate to subtract.
- 96 * @param {number} y the <i>y</i> coordinate to subtract.
- 97 * @returns {pv.Vector} a new vector.
- 98 */
- 99pv.Vector.prototype.minus=function(x,y){
-100return(arguments.length==1)
-101?newpv.Vector(this.x-x.x,this.y-x.y)
-102:newpv.Vector(this.x-x,this.y-y);
-103};
-104
-105/**
-106 * Returns the dot product of this vector and the vector <i>v</i>: <i>x * v.x +
-107 * y * v.y</i>. If only one argument is specified, it is interpreted as the
-108 * vector <i>v</i>.
-109 *
-110 * @param {number} x the <i>x</i> coordinate to dot.
-111 * @param {number} y the <i>y</i> coordinate to dot.
-112 * @returns {number} a dot product.
-113 */
-114pv.Vector.prototype.dot=function(x,y){
-115return(arguments.length==1)
-116?this.x*x.x+this.y*x.y
-117:this.x*x+this.y*y;
-118};
-119
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_geo_Geo.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_geo_Geo.js.html
deleted file mode 100644
index 4f482b29..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_geo_Geo.js.html
+++ /dev/null
@@ -1,13 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_geo_GeoScale.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_geo_GeoScale.js.html
deleted file mode 100644
index 5a6a38ed..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_geo_GeoScale.js.html
+++ /dev/null
@@ -1,315 +0,0 @@
-
1/**
- 2 * Returns a geographic scale. The arguments to this constructor are optional,
- 3 * and equivalent to calling {@link #projection}.
- 4 *
- 5 * @class Represents a geographic scale; a mapping between latitude-longitude
- 6 * coordinates and screen pixel coordinates. By default, the domain is inferred
- 7 * from the geographic coordinates, so that the domain fills the output range.
- 8 *
- 9 * <p>Note that geographic scales are two-dimensional transformations, rather
- 10 * than the one-dimensional bidrectional mapping typical of other scales.
- 11 * Rather than mapping (for example) between a numeric domain and a numeric
- 12 * range, geographic scales map between two coordinate objects: {@link
- 13 * pv.Geo.LatLng} and {@link pv.Vector}.
- 14 *
- 15 * @param {pv.Geo.Projection} [p] optional projection.
- 16 * @see pv.Geo.scale#ticks
- 17 */
- 18pv.Geo.scale=function(p){
- 19varrmin={x:0,y:0},// default range minimum
- 20rmax={x:1,y:1},// default range maximum
- 21d=[],// default domain
- 22j=pv.Geo.projections.identity,// domain <-> normalized range
- 23x=pv.Scale.linear(-1,1).range(0,1),// normalized <-> range
- 24y=pv.Scale.linear(-1,1).range(1,0),// normalized <-> range
- 25c={lng:0,lat:0},// Center Point
- 26lastLatLng,// cached latlng
- 27lastPoint;// cached point
- 28
- 29/** @private */
- 30functionscale(latlng){
- 31if(!lastLatLng
- 32||(latlng.lng!=lastLatLng.lng)
- 33||(latlng.lat!=lastLatLng.lat)){
- 34lastLatLng=latlng;
- 35varp=project(latlng);
- 36lastPoint={x:x(p.x),y:y(p.y)};
- 37}
- 38returnlastPoint;
- 39}
- 40
- 41/** @private */
- 42functionproject(latlng){
- 43varoffset={lng:latlng.lng-c.lng,lat:latlng.lat};
- 44returnj.project(offset);
- 45}
- 46
- 47/** @private */
- 48functioninvert(xy){
- 49varlatlng=j.invert(xy);
- 50latlng.lng+=c.lng;
- 51returnlatlng;
- 52}
- 53
- 54/** Returns the projected x-coordinate. */
- 55scale.x=function(latlng){
- 56returnscale(latlng).x;
- 57};
- 58
- 59/** Returns the projected y-coordinate. */
- 60scale.y=function(latlng){
- 61returnscale(latlng).y;
- 62};
- 63
- 64/**
- 65 * Abstract; this is a local namespace on a given geographic scale.
- 66 *
- 67 * @namespace Tick functions for geographic scales. Because geographic scales
- 68 * represent two-dimensional transformations (as opposed to one-dimensional
- 69 * transformations typical of other scales), the tick values are similarly
- 70 * represented as two-dimensional coordinates in the input domain, i.e.,
- 71 * {@link pv.Geo.LatLng} objects.
- 72 *
- 73 * <p>Also, note that non-rectilinear projections, such as sinsuoidal and
- 74 * aitoff, may not produce straight lines for constant longitude or constant
- 75 * latitude. Therefore the returned array of ticks is a two-dimensional array,
- 76 * sampling various latitudes as constant longitude, and vice versa.
- 77 *
- 78 * <p>The tick lines can therefore be approximated as polylines, either with
- 79 * "linear" or "cardinal" interpolation. This is not as accurate as drawing
- 80 * the true curve through the projection space, but is usually sufficient.
- 81 *
- 82 * @name pv.Geo.scale.prototype.ticks
- 83 * @see pv.Geo.scale
- 84 * @see pv.Geo.LatLng
- 85 * @see pv.Line#interpolate
- 86 */
- 87scale.ticks={
- 88
- 89/**
- 90 * Returns longitude ticks.
- 91 *
- 92 * @function
- 93 * @param {number} [m] the desired number of ticks.
- 94 * @returns {array} a nested array of <tt>pv.Geo.LatLng</tt> ticks.
- 95 * @name pv.Geo.scale.prototype.ticks.prototype.lng
- 96 */
- 97lng:function(m){
- 98varlat,lng;
- 99if(d.length>1){
-100vars=pv.Scale.linear();
-101if(m==undefined)m=10;
-102lat=s.domain(d,function(d){returnd.lat;}).ticks(m);
-103lng=s.domain(d,function(d){returnd.lng;}).ticks(m);
-104}else{
-105lat=pv.range(-80,81,10);
-106lng=pv.range(-180,181,10);
-107}
-108returnlng.map(function(lng){
-109returnlat.map(function(lat){
-110return{lat:lat,lng:lng};
-111});
-112});
-113},
-114
-115/**
-116 * Returns latitude ticks.
-117 *
-118 * @function
-119 * @param {number} [m] the desired number of ticks.
-120 * @returns {array} a nested array of <tt>pv.Geo.LatLng</tt> ticks.
-121 * @name pv.Geo.scale.prototype.ticks.prototype.lat
-122 */
-123lat:function(m){
-124returnpv.transpose(scale.ticks.lng(m));
-125}
-126};
-127
-128/**
-129 * Inverts the specified value in the output range, returning the
-130 * corresponding value in the input domain. This is frequently used to convert
-131 * the mouse location (see {@link pv.Mark#mouse}) to a value in the input
-132 * domain. Inversion is only supported for numeric ranges, and not colors.
-133 *
-134 * <p>Note that this method does not do any rounding or bounds checking. If
-135 * the input domain is discrete (e.g., an array index), the returned value
-136 * should be rounded. If the specified <tt>y</tt> value is outside the range,
-137 * the returned value may be equivalently outside the input domain.
-138 *
-139 * @function
-140 * @name pv.Geo.scale.prototype.invert
-141 * @param {number} y a value in the output range (a pixel location).
-142 * @returns {number} a value in the input domain.
-143 */
-144scale.invert=function(p){
-145returninvert({x:x.invert(p.x),y:y.invert(p.y)});
-146};
-147
-148/**
-149 * Sets or gets the input domain. Note that unlike quantitative scales, the
-150 * domain cannot be reduced to a simple rectangle (i.e., minimum and maximum
-151 * values for latitude and longitude). Instead, the domain values must be
-152 * projected to normalized space, effectively finding the domain in normalized
-153 * space rather than in terms of latitude and longitude. Thus, changing the
-154 * projection requires recomputing the normalized domain.
-155 *
-156 * <p>This method can be invoked several ways:
-157 *
-158 * <p>1. <tt>domain(values...)</tt>
-159 *
-160 * <p>Specifying the domain as a series of {@link pv.Geo.LatLng}s is the most
-161 * explicit and recommended approach. However, if the domain values are
-162 * derived from data, you may find the second method more appropriate.
-163 *
-164 * <p>2. <tt>domain(array, f)</tt>
-165 *
-166 * <p>Rather than enumerating the domain explicitly, you can specify a single
-167 * argument of an array. In addition, you can specify an optional accessor
-168 * function to extract the domain values (as {@link pv.Geo.LatLng}s) from the
-169 * array. If the specified array has fewer than two elements, this scale will
-170 * default to the full normalized domain.
-171 *
-172 * <p>2. <tt>domain()</tt>
-173 *
-174 * <p>Invoking the <tt>domain</tt> method with no arguments returns the
-175 * current domain as an array.
-176 *
-177 * @function
-178 * @name pv.Geo.scale.prototype.domain
-179 * @param {...} domain... domain values.
-180 * @returns {pv.Geo.scale} <tt>this</tt>, or the current domain.
-181 */
-182scale.domain=function(array,f){
-183if(arguments.length){
-184d=(arrayinstanceofArray)
-185?((arguments.length>1)?pv.map(array,f):array)
-186:Array.prototype.slice.call(arguments);
-187if(d.length>1){
-188varlngs=d.map(function(c){returnc.lng;});
-189varlats=d.map(function(c){returnc.lat;});
-190c={
-191lng:(pv.max(lngs)+pv.min(lngs))/2,
-192lat:(pv.max(lats)+pv.min(lats))/2
-193};
-194varn=d.map(project);// normalized domain
-195x.domain(n,function(p){returnp.x;});
-196y.domain(n,function(p){returnp.y;});
-197}else{
-198c={lng:0,lat:0};
-199x.domain(-1,1);
-200y.domain(-1,1);
-201}
-202lastLatLng=null;// invalidate the cache
-203returnthis;
-204}
-205returnd;
-206};
-207
-208/**
-209 * Sets or gets the output range. This method can be invoked several ways:
-210 *
-211 * <p>1. <tt>range(min, max)</tt>
-212 *
-213 * <p>If two objects are specified, the arguments should be {@link pv.Vector}s
-214 * which specify the minimum and maximum values of the x- and y-coordinates
-215 * explicitly.
-216 *
-217 * <p>2. <tt>range(width, height)</tt>
-218 *
-219 * <p>If two numbers are specified, the arguments specify the maximum values
-220 * of the x- and y-coordinates explicitly; the minimum values are implicitly
-221 * zero.
-222 *
-223 * <p>3. <tt>range()</tt>
-224 *
-225 * <p>Invoking the <tt>range</tt> method with no arguments returns the current
-226 * range as an array of two {@link pv.Vector}s: the minimum (top-left) and
-227 * maximum (bottom-right) values.
-228 *
-229 * @function
-230 * @name pv.Geo.scale.prototype.range
-231 * @param {...} range... range values.
-232 * @returns {pv.Geo.scale} <tt>this</tt>, or the current range.
-233 */
-234scale.range=function(min,max){
-235if(arguments.length){
-236if(typeofmin=="object"){
-237rmin={x:Number(min.x),y:Number(min.y)};
-238rmax={x:Number(max.x),y:Number(max.y)};
-239}else{
-240rmin={x:0,y:0};
-241rmax={x:Number(min),y:Number(max)};
-242}
-243x.range(rmin.x,rmax.x);
-244y.range(rmax.y,rmin.y);// XXX flipped?
-245lastLatLng=null;// invalidate the cache
-246returnthis;
-247}
-248return[rmin,rmax];
-249};
-250
-251/**
-252 * Sets or gets the projection. This method can be invoked several ways:
-253 *
-254 * <p>1. <tt>projection(string)</tt>
-255 *
-256 * <p>Specifying a string sets the projection to the given named projection in
-257 * {@link pv.Geo.projections}. If no such projection is found, the identity
-258 * projection is used.
-259 *
-260 * <p>2. <tt>projection(object)</tt>
-261 *
-262 * <p>Specifying an object sets the projection to the given custom projection,
-263 * which must implement the <i>forward</i> and <i>inverse</i> methods per the
-264 * {@link pv.Geo.Projection} interface.
-265 *
-266 * <p>3. <tt>projection()</tt>
-267 *
-268 * <p>Invoking the <tt>projection</tt> method with no arguments returns the
-269 * current object that defined the projection.
-270 *
-271 * @function
-272 * @name pv.Scale.geo.prototype.projection
-273 * @param {...} range... range values.
-274 * @returns {pv.Scale.geo} <tt>this</tt>, or the current range.
-275 */
-276scale.projection=function(p){
-277if(arguments.length){
-278j=typeofp=="string"
-279?pv.Geo.projections[p]||pv.Geo.projections.identity
-280:p;
-281returnthis.domain(d);// recompute normalized domain
-282}
-283returnp;
-284};
-285
-286/**
-287 * Returns a view of this scale by the specified accessor function <tt>f</tt>.
-288 * Given a scale <tt>g</tt>, <tt>g.by(function(d) d.foo)</tt> is equivalent to
-289 * <tt>function(d) g(d.foo)</tt>. This method should be used judiciously; it
-290 * is typically more clear to invoke the scale directly, passing in the value
-291 * to be scaled.
-292 *
-293 * @function
-294 * @name pv.Geo.scale.prototype.by
-295 * @param {function} f an accessor function.
-296 * @returns {pv.Geo.scale} a view of this scale by the specified accessor
-297 * function.
-298 */
-299scale.by=function(f){
-300functionby(){returnscale(f.apply(this,arguments));}
-301for(varmethodinscale)by[method]=scale[method];
-302returnby;
-303};
-304
-305if(arguments.length)scale.projection(p);
-306returnscale;
-307};
-308
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_geo_LatLng.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_geo_LatLng.js.html
deleted file mode 100644
index 429e721c..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_geo_LatLng.js.html
+++ /dev/null
@@ -1,31 +0,0 @@
-
1/**
- 2 * Abstract; not implemented. There is no explicit constructor; this class
- 3 * merely serves to document the representation used by {@link pv.Geo.scale}.
- 4 *
- 5 * @class Represents a pair of geographic coordinates.
- 6 *
- 7 * @name pv.Geo.LatLng
- 8 * @see pv.Geo.scale
- 9 */
- 10
- 11/**
- 12 * The <i>latitude</i> coordinate in degrees; positive is North.
- 13 *
- 14 * @type number
- 15 * @name pv.Geo.LatLng.prototype.lat
- 16 */
- 17
- 18/**
- 19 * The <i>longitude</i> coordinate in degrees; positive is East.
- 20 *
- 21 * @type number
- 22 * @name pv.Geo.LatLng.prototype.lng
- 23 */
- 24
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_geo_Projection.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_geo_Projection.js.html
deleted file mode 100644
index 8e08747a..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_geo_Projection.js.html
+++ /dev/null
@@ -1,51 +0,0 @@
-
1/**
- 2 * Abstract; not implemented. There is no explicit constructor; this class
- 3 * merely serves to document the representation used by {@link pv.Geo.scale}.
- 4 *
- 5 * @class Represents a geographic projection. This class provides the core
- 6 * implementation for {@link pv.Geo.scale}s, mapping between geographic
- 7 * coordinates (latitude and longitude) and normalized screen space in the range
- 8 * [-1,1]. The remaining mapping between normalized screen space and actual
- 9 * pixels is performed by <tt>pv.Geo.scale</tt>.
- 10 *
- 11 * <p>Many geographic projections have a point around which the projection is
- 12 * centered. Rather than have each implementation add support for a
- 13 * user-specified center point, the <tt>pv.Geo.scale</tt> translates the
- 14 * geographic coordinates relative to the center point for both the forward and
- 15 * inverse projection.
- 16 *
- 17 * <p>In general, this class should not be used directly, unless the desire is
- 18 * to implement a new geographic projection. Instead, use <tt>pv.Geo.scale</tt>.
- 19 * Implementations are not required to implement inverse projections, but are
- 20 * needed for some forms of interactivity. Also note that some inverse
- 21 * projections are ambiguous, such as the connecting points in Dymaxian maps.
- 22 *
- 23 * @name pv.Geo.Projection
- 24 * @see pv.Geo.scale
- 25 */
- 26
- 27/**
- 28 * The <i>forward</i> projection.
- 29 *
- 30 * @function
- 31 * @name pv.Geo.Projection.prototype.project
- 32 * @param {pv.Geo.LatLng} latlng the latitude and longitude to project.
- 33 * @returns {pv.Vector} the xy-coordinates of the given point.
- 34 */
- 35
- 36/**
- 37 * The <i>inverse</i> projection; optional.
- 38 *
- 39 * @function
- 40 * @name pv.Geo.Projection.prototype.invert
- 41 * @param {pv.Vector} xy the x- and y-coordinates to invert.
- 42 * @returns {pv.Geo.LatLng} the latitude and longitude of the given point.
- 43 */
- 44
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_geo_Projections.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_geo_Projections.js.html
deleted file mode 100644
index 5bb12791..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_geo_Projections.js.html
+++ /dev/null
@@ -1,125 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_lang_Array.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_lang_Array.js.html
deleted file mode 100644
index ad68f3d0..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_lang_Array.js.html
+++ /dev/null
@@ -1,120 +0,0 @@
-
1/**
- 2 * @class The built-in Array class.
- 3 * @name Array
- 4 */
- 5
- 6/**
- 7 * Creates a new array with the results of calling a provided function on every
- 8 * element in this array. Implemented in Javascript 1.6.
- 9 *
- 10 * @function
- 11 * @name Array.prototype.map
- 12 * @see <a
- 13 * href="https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array/Map">map</a>
- 14 * documentation.
- 15 * @param {function} f function that produces an element of the new Array from
- 16 * an element of the current one.
- 17 * @param [o] object to use as <tt>this</tt> when executing <tt>f</tt>.
- 18 */
- 19if(!Array.prototype.map)Array.prototype.map=function(f,o){
- 20varn=this.length;
- 21varresult=newArray(n);
- 22for(vari=0;i<n;i++){
- 23if(iinthis){
- 24result[i]=f.call(o,this[i],i,this);
- 25}
- 26}
- 27returnresult;
- 28};
- 29
- 30/**
- 31 * Creates a new array with all elements that pass the test implemented by the
- 32 * provided function. Implemented in Javascript 1.6.
- 33 *
- 34 * @function
- 35 * @name Array.prototype.filter
- 36 * @see <a
- 37 * href="https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array/filter">filter</a>
- 38 * documentation.
- 39 * @param {function} f function to test each element of the array.
- 40 * @param [o] object to use as <tt>this</tt> when executing <tt>f</tt>.
- 41 */
- 42if(!Array.prototype.filter)Array.prototype.filter=function(f,o){
- 43varn=this.length;
- 44varresult=newArray();
- 45for(vari=0;i<n;i++){
- 46if(iinthis){
- 47varv=this[i];
- 48if(f.call(o,v,i,this))result.push(v);
- 49}
- 50}
- 51returnresult;
- 52};
- 53
- 54/**
- 55 * Executes a provided function once per array element. Implemented in
- 56 * Javascript 1.6.
- 57 *
- 58 * @function
- 59 * @name Array.prototype.forEach
- 60 * @see <a
- 61 * href="https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array/ForEach">forEach</a>
- 62 * documentation.
- 63 * @param {function} f function to execute for each element.
- 64 * @param [o] object to use as <tt>this</tt> when executing <tt>f</tt>.
- 65 */
- 66if(!Array.prototype.forEach)Array.prototype.forEach=function(f,o){
- 67varn=this.length>>>0;
- 68for(vari=0;i<n;i++){
- 69if(iinthis)f.call(o,this[i],i,this);
- 70}
- 71};
- 72
- 73/**
- 74 * Apply a function against an accumulator and each value of the array (from
- 75 * left-to-right) as to reduce it to a single value. Implemented in Javascript
- 76 * 1.8.
- 77 *
- 78 * @function
- 79 * @name Array.prototype.reduce
- 80 * @see <a
- 81 * href="https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array/Reduce">reduce</a>
- 82 * documentation.
- 83 * @param {function} f function to execute on each value in the array.
- 84 * @param [v] object to use as the first argument to the first call of
- 85 * <tt>t</tt>.
- 86 */
- 87if(!Array.prototype.reduce)Array.prototype.reduce=function(f,v){
- 88varlen=this.length;
- 89if(!len&&(arguments.length==1)){
- 90thrownewError("reduce: empty array, no initial value");
- 91}
- 92
- 93vari=0;
- 94if(arguments.length<2){
- 95while(true){
- 96if(iinthis){
- 97v=this[i++];
- 98break;
- 99}
-100if(++i>=len){
-101thrownewError("reduce: no values, no initial value");
-102}
-103}
-104}
-105
-106for(;i<len;i++){
-107if(iinthis){
-108v=f(v,this[i],i,this);
-109}
-110}
-111returnv;
-112};
-113
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_lang_init.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_lang_init.js.html
deleted file mode 100644
index 5e04a868..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_lang_init.js.html
+++ /dev/null
@@ -1,34 +0,0 @@
-
1/*
- 2 * Parses the Protovis specifications on load, allowing the use of JavaScript
- 3 * 1.8 function expressions on browsers that only support JavaScript 1.6.
- 4 *
- 5 * @see pv.parse
- 6 */
- 7pv.listen(window,"load",function(){
- 8/*
- 9 * Note: in Firefox any variables declared here are visible to the eval'd
- 10 * script below. Even worse, any global variables declared by the script
- 11 * could overwrite local variables here (such as the index, `i`)! To protect
- 12 * against this, all variables are explicitly scoped on a pv.$ object.
- 13 */
- 14pv.$={i:0,x:document.getElementsByTagName("script")};
- 15for(;pv.$.i<pv.$.x.length;pv.$.i++){
- 16pv.$.s=pv.$.x[pv.$.i];
- 17if(pv.$.s.type=="text/javascript+protovis"){
- 18try{
- 19window.eval(pv.parse(pv.$.s.text));
- 20}catch(e){
- 21pv.error(e);
- 22}
- 23}
- 24}
- 25deletepv.$;
- 26});
- 27
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Arc.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Arc.js.html
deleted file mode 100644
index 7054173c..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Arc.js.html
+++ /dev/null
@@ -1,186 +0,0 @@
-
1/**
- 2 * Constructs a new, empty arc layout. Layouts are not typically constructed
- 3 * directly; instead, they are added to an existing panel via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Implements a layout for arc diagrams. An arc diagram is a network
- 7 * visualization with a one-dimensional layout of nodes, using circular arcs to
- 8 * render links between nodes. For undirected networks, arcs are rendering on a
- 9 * single side; this makes arc diagrams useful as annotations to other
- 10 * two-dimensional network layouts, such as rollup, matrix or table layouts. For
- 11 * directed networks, links in opposite directions can be rendered on opposite
- 12 * sides using <tt>directed(true)</tt>.
- 13 *
- 14 * <p>Arc layouts are particularly sensitive to node ordering; for best results,
- 15 * order the nodes such that related nodes are close to each other. A poor
- 16 * (e.g., random) order may result in large arcs with crossovers that impede
- 17 * visual processing. A future improvement to this layout may include automatic
- 18 * reordering using, e.g., spectral graph layout or simulated annealing.
- 19 *
- 20 * <p>This visualization technique is related to that developed by
- 21 * M. Wattenberg, <a
- 22 * href="http://www.research.ibm.com/visual/papers/arc-diagrams.pdf">"Arc
- 23 * Diagrams: Visualizing Structure in Strings"</a> in <i>IEEE InfoVis</i>, 2002.
- 24 * However, this implementation is limited to simple node-link networks, as
- 25 * opposed to structures with hierarchical self-similarity (such as strings).
- 26 *
- 27 * <p>As with other network layouts, three mark prototypes are provided:<ul>
- 28 *
- 29 * <li><tt>node</tt> - for rendering nodes; typically a {@link pv.Dot}.
- 30 * <li><tt>link</tt> - for rendering links; typically a {@link pv.Line}.
- 31 * <li><tt>label</tt> - for rendering node labels; typically a {@link pv.Label}.
- 32 *
- 33 * </ul>For more details on how this layout is structured and can be customized,
- 34 * see {@link pv.Layout.Network}.
- 35 *
- 36 * @extends pv.Layout.Network
- 37 **/
- 38pv.Layout.Arc=function(){
- 39pv.Layout.Network.call(this);
- 40varinterpolate,// cached interpolate
- 41directed,// cached directed
- 42reverse,// cached reverse
- 43buildImplied=this.buildImplied;
- 44
- 45/** @private Cache layout state to optimize properties. */
- 46this.buildImplied=function(s){
- 47buildImplied.call(this,s);
- 48directed=s.directed;
- 49interpolate=s.orient=="radial"?"linear":"polar";
- 50reverse=s.orient=="right"||s.orient=="top";
- 51};
- 52
- 53/* Override link properties to handle directedness and orientation. */
- 54this.link
- 55.data(function(p){
- 56vars=p.sourceNode,t=p.targetNode;
- 57returnreverse!=(directed||(s.breadth<t.breadth))?[s,t]:[t,s];
- 58})
- 59.interpolate(function(){returninterpolate;});
- 60};
- 61
- 62pv.Layout.Arc.prototype=pv.extend(pv.Layout.Network)
- 63.property("orient",String)
- 64.property("directed",Boolean);
- 65
- 66/**
- 67 * Default properties for arc layouts. By default, the orientation is "bottom".
- 68 *
- 69 * @type pv.Layout.Arc
- 70 */
- 71pv.Layout.Arc.prototype.defaults=newpv.Layout.Arc()
- 72.extend(pv.Layout.Network.prototype.defaults)
- 73.orient("bottom");
- 74
- 75/**
- 76 * Specifies an optional sort function. The sort function follows the same
- 77 * comparator contract required by {@link pv.Dom.Node#sort}. Specifying a sort
- 78 * function provides an alternative to sort the nodes as they are specified by
- 79 * the <tt>nodes</tt> property; the main advantage of doing this is that the
- 80 * comparator function can access implicit fields populated by the network
- 81 * layout, such as the <tt>linkDegree</tt>.
- 82 *
- 83 * <p>Note that arc diagrams are particularly sensitive to order. This is
- 84 * referred to as the seriation problem, and many different techniques exist to
- 85 * find good node orders that emphasize clusters, such as spectral layout and
- 86 * simulated annealing.
- 87 *
- 88 * @param {function} f comparator function for nodes.
- 89 * @returns {pv.Layout.Arc} this.
- 90 */
- 91pv.Layout.Arc.prototype.sort=function(f){
- 92this.$sort=f;
- 93returnthis;
- 94};
- 95
- 96/** @private Populates the x, y and angle attributes on the nodes. */
- 97pv.Layout.Arc.prototype.buildImplied=function(s){
- 98if(pv.Layout.Network.prototype.buildImplied.call(this,s))return;
- 99
-100varnodes=s.nodes,
-101orient=s.orient,
-102sort=this.$sort,
-103index=pv.range(nodes.length),
-104w=s.width,
-105h=s.height,
-106r=Math.min(w,h)/2;
-107
-108/* Sort the nodes. */
-109if(sort)index.sort(function(a,b){returnsort(nodes[a],nodes[b]);});
-110
-111/** @private Returns the mid-angle, given the breadth. */
-112functionmidAngle(b){
-113switch(orient){
-114case"top":return-Math.PI/2;
-115case"bottom":returnMath.PI/2;
-116case"left":returnMath.PI;
-117case"right":return0;
-118case"radial":return(b-.25)*2*Math.PI;
-119}
-120}
-121
-122/** @private Returns the x-position, given the breadth. */
-123functionx(b){
-124switch(orient){
-125case"top":
-126case"bottom":returnb*w;
-127case"left":return0;
-128case"right":returnw;
-129case"radial":returnw/2+r*Math.cos(midAngle(b));
-130}
-131}
-132
-133/** @private Returns the y-position, given the breadth. */
-134functiony(b){
-135switch(orient){
-136case"top":return0;
-137case"bottom":returnh;
-138case"left":
-139case"right":returnb*h;
-140case"radial":returnh/2+r*Math.sin(midAngle(b));
-141}
-142}
-143
-144/* Populate the x, y and mid-angle attributes. */
-145for(vari=0;i<nodes.length;i++){
-146varn=nodes[index[i]],b=n.breadth=(i+.5)/nodes.length;
-147n.x=x(b);
-148n.y=y(b);
-149n.midAngle=midAngle(b);
-150}
-151};
-152
-153/**
-154 * The orientation. The default orientation is "left", which means that nodes
-155 * will be positioned from left-to-right in the order they are specified in the
-156 * <tt>nodes</tt> property. The following orientations are supported:<ul>
-157 *
-158 * <li>left - left-to-right.
-159 * <li>right - right-to-left.
-160 * <li>top - top-to-bottom.
-161 * <li>bottom - bottom-to-top.
-162 * <li>radial - radially, starting at 12 o'clock and proceeding clockwise.</ul>
-163 *
-164 * @type string
-165 * @name pv.Layout.Arc.prototype.orient
-166 */
-167
-168/**
-169 * Whether this arc digram is directed (bidirectional); only applies to
-170 * non-radial orientations. By default, arc digrams are undirected, such that
-171 * all arcs appear on one side. If the arc digram is directed, then forward
-172 * links are drawn on the conventional side (the same as as undirected
-173 * links--right, left, bottom and top for left, right, top and bottom,
-174 * respectively), while reverse links are drawn on the opposite side.
-175 *
-176 * @type boolean
-177 * @name pv.Layout.Arc.prototype.directed
-178 */
-179
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Bullet.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Bullet.js.html
deleted file mode 100644
index 6b312db8..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Bullet.js.html
+++ /dev/null
@@ -1,172 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Cluster.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Cluster.js.html
deleted file mode 100644
index 5425330c..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Cluster.js.html
+++ /dev/null
@@ -1,213 +0,0 @@
-
1/**
- 2 * Constructs a new, empty cluster layout. Layouts are not typically
- 3 * constructed directly; instead, they are added to an existing panel via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Implements a hierarchical layout using the cluster (or dendrogram)
- 7 * algorithm. This layout provides both node-link and space-filling
- 8 * implementations of cluster diagrams. In many ways it is similar to
- 9 * {@link pv.Layout.Partition}, except that leaf nodes are positioned at maximum
- 10 * depth, and the depth of internal nodes is based on their distance from their
- 11 * deepest descendant, rather than their distance from the root.
- 12 *
- 13 * <p>The cluster layout supports a "group" property, which if true causes
- 14 * siblings to be positioned closer together than unrelated nodes at the same
- 15 * depth. Unlike the partition layout, this layout does not support dynamic
- 16 * sizing for leaf nodes; all leaf nodes are the same size.
- 17 *
- 18 * <p>For more details on how to use this layout, see
- 19 * {@link pv.Layout.Hierarchy}.
- 20 *
- 21 * @see pv.Layout.Cluster.Fill
- 22 * @extends pv.Layout.Hierarchy
- 23 */
- 24pv.Layout.Cluster=function(){
- 25pv.Layout.Hierarchy.call(this);
- 26varinterpolate,// cached interpolate
- 27buildImplied=this.buildImplied;
- 28
- 29/** @private Cache layout state to optimize properties. */
- 30this.buildImplied=function(s){
- 31buildImplied.call(this,s);
- 32interpolate
- 33=/^(top|bottom)$/.test(s.orient)?"step-before"
- 34:/^(left|right)$/.test(s.orient)?"step-after"
- 35:"linear";
- 36};
- 37
- 38this.link.interpolate(function(){returninterpolate;});
- 39};
- 40
- 41pv.Layout.Cluster.prototype=pv.extend(pv.Layout.Hierarchy)
- 42.property("group",Number)
- 43.property("orient",String)
- 44.property("innerRadius",Number)
- 45.property("outerRadius",Number);
- 46
- 47/**
- 48 * The group parameter; defaults to 0, disabling grouping of siblings. If this
- 49 * parameter is set to a positive number (or true, which is equivalent to 1),
- 50 * then additional space will be allotted between sibling groups. In other
- 51 * words, siblings (nodes that share the same parent) will be positioned more
- 52 * closely than nodes at the same depth that do not share a parent.
- 53 *
- 54 * @type number
- 55 * @name pv.Layout.Cluster.prototype.group
- 56 */
- 57
- 58/**
- 59 * The orientation. The default orientation is "top", which means that the root
- 60 * node is placed on the top edge, leaf nodes appear on the bottom edge, and
- 61 * internal nodes are in-between. The following orientations are supported:<ul>
- 62 *
- 63 * <li>left - left-to-right.
- 64 * <li>right - right-to-left.
- 65 * <li>top - top-to-bottom.
- 66 * <li>bottom - bottom-to-top.
- 67 * <li>radial - radially, with the root at the center.</ul>
- 68 *
- 69 * @type string
- 70 * @name pv.Layout.Cluster.prototype.orient
- 71 */
- 72
- 73/**
- 74 * The inner radius; defaults to 0. This property applies only to radial
- 75 * orientations, and can be used to compress the layout radially. Note that for
- 76 * the node-link implementation, the root node is always at the center,
- 77 * regardless of the value of this property; this property only affects internal
- 78 * and leaf nodes. For the space-filling implementation, a non-zero value of
- 79 * this property will result in the root node represented as a ring rather than
- 80 * a circle.
- 81 *
- 82 * @type number
- 83 * @name pv.Layout.Cluster.prototype.innerRadius
- 84 */
- 85
- 86/**
- 87 * The outer radius; defaults to fill the containing panel, based on the height
- 88 * and width of the layout. If the layout has no height and width specified, it
- 89 * will extend to fill the enclosing panel.
- 90 *
- 91 * @type number
- 92 * @name pv.Layout.Cluster.prototype.outerRadius
- 93 */
- 94
- 95/**
- 96 * Defaults for cluster layouts. The default group parameter is 0 and the
- 97 * default orientation is "top".
- 98 *
- 99 * @type pv.Layout.Cluster
-100 */
-101pv.Layout.Cluster.prototype.defaults=newpv.Layout.Cluster()
-102.extend(pv.Layout.Hierarchy.prototype.defaults)
-103.group(0)
-104.orient("top");
-105
-106/** @private */
-107pv.Layout.Cluster.prototype.buildImplied=function(s){
-108if(pv.Layout.Hierarchy.prototype.buildImplied.call(this,s))return;
-109
-110varroot=s.nodes[0],
-111group=s.group,
-112breadth,
-113depth,
-114leafCount=0,
-115leafIndex=.5-group/2;
-116
-117/* Count the leaf nodes and compute the depth of descendants. */
-118varp=undefined;
-119root.visitAfter(function(n){
-120if(n.firstChild){
-121n.depth=1+pv.max(n.childNodes,function(n){returnn.depth;});
-122}else{
-123if(group&&(p!=n.parentNode)){
-124p=n.parentNode;
-125leafCount+=group;
-126}
-127leafCount++;
-128n.depth=0;
-129}
-130});
-131breadth=1/leafCount;
-132depth=1/root.depth;
-133
-134/* Compute the unit breadth and depth of each node. */
-135varp=undefined;
-136root.visitAfter(function(n){
-137if(n.firstChild){
-138n.breadth=pv.mean(n.childNodes,function(n){returnn.breadth;});
-139}else{
-140if(group&&(p!=n.parentNode)){
-141p=n.parentNode;
-142leafIndex+=group;
-143}
-144n.breadth=breadth*leafIndex++;
-145}
-146n.depth=1-n.depth*depth;
-147});
-148
-149/* Compute breadth and depth ranges for space-filling layouts. */
-150root.visitAfter(function(n){
-151n.minBreadth=n.firstChild
-152?n.firstChild.minBreadth
-153:(n.breadth-breadth/2);
-154n.maxBreadth=n.firstChild
-155?n.lastChild.maxBreadth
-156:(n.breadth+breadth/2);
-157});
-158root.visitBefore(function(n){
-159n.minDepth=n.parentNode
-160?n.parentNode.maxDepth
-161:0;
-162n.maxDepth=n.parentNode
-163?(n.depth+root.depth)
-164:(n.minDepth+2*root.depth);
-165});
-166root.minDepth=-depth;
-167
-168pv.Layout.Hierarchy.NodeLink.buildImplied.call(this,s);
-169};
-170
-171/**
-172 * Constructs a new, empty space-filling cluster layout. Layouts are not
-173 * typically constructed directly; instead, they are added to an existing panel
-174 * via {@link pv.Mark#add}.
-175 *
-176 * @class A variant of cluster layout that is space-filling. The meaning of the
-177 * exported mark prototypes changes slightly in the space-filling
-178 * implementation:<ul>
-179 *
-180 * <li><tt>node</tt> - for rendering nodes; typically a {@link pv.Bar} for
-181 * non-radial orientations, and a {@link pv.Wedge} for radial orientations.
-182 *
-183 * <p><li><tt>link</tt> - unsupported; undefined. Links are encoded implicitly
-184 * in the arrangement of the space-filling nodes.
-185 *
-186 * <p><li><tt>label</tt> - for rendering node labels; typically a
-187 * {@link pv.Label}.
-188 *
-189 * </ul>For more details on how to use this layout, see
-190 * {@link pv.Layout.Cluster}.
-191 *
-192 * @extends pv.Layout.Cluster
-193 */
-194pv.Layout.Cluster.Fill=function(){
-195pv.Layout.Cluster.call(this);
-196pv.Layout.Hierarchy.Fill.constructor.call(this);
-197};
-198
-199pv.Layout.Cluster.Fill.prototype=pv.extend(pv.Layout.Cluster);
-200
-201/** @private */
-202pv.Layout.Cluster.Fill.prototype.buildImplied=function(s){
-203if(pv.Layout.Cluster.prototype.buildImplied.call(this,s))return;
-204pv.Layout.Hierarchy.Fill.buildImplied.call(this,s);
-205};
-206
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Force.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Force.js.html
deleted file mode 100644
index 4245982f..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Force.js.html
+++ /dev/null
@@ -1,317 +0,0 @@
-
1/**
- 2 * Constructs a new, empty force-directed layout. Layouts are not typically
- 3 * constructed directly; instead, they are added to an existing panel via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Implements force-directed network layout as a node-link diagram. This
- 7 * layout uses the Fruchterman-Reingold algorithm, which applies an attractive
- 8 * spring force between neighboring nodes, and a repulsive electrical charge
- 9 * force between all nodes. An additional drag force improves stability of the
- 10 * simulation. See {@link pv.Force.spring}, {@link pv.Force.drag} and {@link
- 11 * pv.Force.charge} for more details; note that the n-body charge force is
- 12 * approximated using the Barnes-Hut algorithm.
- 13 *
- 14 * <p>This layout is implemented on top of {@link pv.Simulation}, which can be
- 15 * used directly for more control over simulation parameters. The simulation
- 16 * uses Position Verlet integration, which does not compute velocities
- 17 * explicitly, but allows for easy geometric constraints, such as bounding the
- 18 * nodes within the layout panel. Many of the configuration properties supported
- 19 * by this layout are simply passed through to the underlying forces and
- 20 * constraints of the simulation.
- 21 *
- 22 * <p>Force layouts are typically interactive. The gradual movement of the nodes
- 23 * as they stabilize to a local stress minimum can help reveal the structure of
- 24 * the network, as can {@link pv.Behavior.drag}, which allows the user to pick
- 25 * up nodes and reposition them while the physics simulation continues. This
- 26 * layout can also be used with pan & zoom behaviors for interaction.
- 27 *
- 28 * <p>To facilitate interaction, this layout by default automatically re-renders
- 29 * using a <tt>setInterval</tt> every 42 milliseconds. This can be disabled via
- 30 * the <tt>iterations</tt> property, which if non-null specifies the number of
- 31 * simulation iterations to run before the force-directed layout is finalized.
- 32 * Be careful not to use too high an iteration count, as this can lead to an
- 33 * annoying delay on page load.
- 34 *
- 35 * <p>As with other network layouts, the network data can be updated
- 36 * dynamically, provided the property cache is reset. See
- 37 * {@link pv.Layout.Network} for details. New nodes are initialized with random
- 38 * positions near the center. Alternatively, positions can be specified manually
- 39 * by setting the <tt>x</tt> and <tt>y</tt> attributes on nodes.
- 40 *
- 41 * @extends pv.Layout.Network
- 42 * @see <a href="http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.13.8444&rep=rep1&type=pdf"
- 43 * >"Graph Drawing by Force-directed Placement"</a> by T. Fruchterman &
- 44 * E. Reingold, Software--Practice & Experience, November 1991.
- 45 */
- 46pv.Layout.Force=function(){
- 47pv.Layout.Network.call(this);
- 48
- 49/* Force-directed graphs can be messy, so reduce the link width. */
- 50this.link.lineWidth(function(d,p){returnMath.sqrt(p.linkValue)*1.5;});
- 51this.label.textAlign("center");
- 52};
- 53
- 54pv.Layout.Force.prototype=pv.extend(pv.Layout.Network)
- 55.property("bound",Boolean)
- 56.property("iterations",Number)
- 57.property("dragConstant",Number)
- 58.property("chargeConstant",Number)
- 59.property("chargeMinDistance",Number)
- 60.property("chargeMaxDistance",Number)
- 61.property("chargeTheta",Number)
- 62.property("springConstant",Number)
- 63.property("springDamping",Number)
- 64.property("springLength",Number);
- 65
- 66/**
- 67 * The bound parameter; true if nodes should be constrained within the layout
- 68 * panel. Bounding is disabled by default. Currently the layout does not observe
- 69 * the radius of the nodes; strictly speaking, only the center of the node is
- 70 * constrained to be within the panel, with an additional 6-pixel offset for
- 71 * padding. A future enhancement could extend the bound constraint to observe
- 72 * the node's radius, which would also support bounding for variable-size nodes.
- 73 *
- 74 * <p>Note that if this layout is used in conjunction with pan & zoom
- 75 * behaviors, those behaviors should have their bound parameter set to the same
- 76 * value.
- 77 *
- 78 * @type boolean
- 79 * @name pv.Layout.Force.prototype.bound
- 80 */
- 81
- 82/**
- 83 * The number of simulation iterations to run, or null if this layout is
- 84 * interactive. Force-directed layouts are interactive by default, using a
- 85 * <tt>setInterval</tt> to advance the physics simulation and re-render
- 86 * automatically.
- 87 *
- 88 * @type number
- 89 * @name pv.Layout.Force.prototype.iterations
- 90 */
- 91
- 92/**
- 93 * The drag constant, in the range [0,1]. A value of 0 means no drag (a
- 94 * perfectly frictionless environment), while a value of 1 means friction
- 95 * immediately cancels all momentum. The default value is 0.1, which provides a
- 96 * minimum amount of drag that helps stabilize bouncy springs; lower values may
- 97 * result in excessive bounciness, while higher values cause the simulation to
- 98 * take longer to converge.
- 99 *
-100 * @type number
-101 * @name pv.Layout.Force.prototype.dragConstant
-102 * @see pv.Force.drag#constant
-103 */
-104
-105/**
-106 * The charge constant, which should be a negative number. The default value is
-107 * -40; more negative values will result in a stronger repulsive force, which
-108 * may lead to faster convergence at the risk of instability. Too strong
-109 * repulsive charge forces can cause comparatively weak springs to be stretched
-110 * well beyond their rest length, emphasizing global structure over local
-111 * structure. A nonnegative value will break the Fruchterman-Reingold algorithm,
-112 * and is for entertainment purposes only.
-113 *
-114 * @type number
-115 * @name pv.Layout.Force.prototype.chargeConstant
-116 * @see pv.Force.charge#constant
-117 */
-118
-119/**
-120 * The minimum distance at which charge forces are applied. The default minimum
-121 * distance of 2 avoids applying forces that are two strong; because the physics
-122 * simulation is run at discrete time intervals, it is possible for two same-
-123 * charged particles to become very close or even a singularity! Since the
-124 * charge force is inversely proportional to the square of the distance, very
-125 * small distances can break the simulation.
-126 *
-127 * <p>In rare cases, two particles can become stuck on top of each other, as a
-128 * minimum distance threshold will prevent the charge force from repelling them.
-129 * However, this occurs very rarely because other forces and momentum typically
-130 * cause the particles to become separated again, at which point the repulsive
-131 * charge force kicks in.
-132 *
-133 * @type number
-134 * @name pv.Layout.Force.prototype.chargeMinDistance
-135 * @see pv.Force.charge#domain
-136 */
-137
-138/**
-139 * The maximum distance at which charge forces are applied. This improves
-140 * performance by ignoring weak charge forces at great distances. Note that this
-141 * parameter is partly redundant, as the Barnes-Hut algorithm for n-body forces
-142 * already improves performance for far-away particles through approximation.
-143 *
-144 * @type number
-145 * @name pv.Layout.Force.prototype.chargeMaxDistance
-146 * @see pv.Force.charge#domain
-147 */
-148
-149/**
-150 * The Barnes-Hut approximation factor. The Barnes-Hut approximation criterion
-151 * is the ratio of the size of the quadtree node to the distance from the point
-152 * to the node's center of mass is beneath some threshold. The default value is
-153 * 0.9.
-154 *
-155 * @type number
-156 * @name pv.Layout.Force.prototype.chargeTheta
-157 * @see pv.Force.charge#theta
-158 */
-159
-160/**
-161 * The spring constant, which should be a positive number. The default value is
-162 * 0.1; greater values will result in a stronger attractive force, which may
-163 * lead to faster convergence at the risk of instability. Too strong spring
-164 * forces can cause comparatively weak charge forces to be ignored, emphasizing
-165 * local structure over global structure. A nonpositive value will break the
-166 * Fruchterman-Reingold algorithm, and is for entertainment purposes only.
-167 *
-168 * <p>The spring tension is automatically normalized using the inverse square
-169 * root of the maximum link degree of attached nodes.
-170 *
-171 * @type number
-172 * @name pv.Layout.Force.prototype.springConstant
-173 * @see pv.Force.spring#constant
-174 */
-175
-176/**
-177 * The spring damping factor, in the range [0,1]. Damping functions identically
-178 * to drag forces, damping spring bounciness by applying a force in the opposite
-179 * direction of attached nodes' velocities. The default value is 0.3.
-180 *
-181 * <p>The spring damping is automatically normalized using the inverse square
-182 * root of the maximum link degree of attached nodes.
-183 *
-184 * @type number
-185 * @name pv.Layout.Force.prototype.springDamping
-186 * @see pv.Force.spring#damping
-187 */
-188
-189/**
-190 * The spring rest length. The default value is 20 pixels. Larger values may be
-191 * appropriate if the layout panel is larger, or if the nodes are rendered
-192 * larger than the default dot size of 20.
-193 *
-194 * @type number
-195 * @name pv.Layout.Force.prototype.springLength
-196 * @see pv.Force.spring#length
-197 */
-198
-199/**
-200 * Default properties for force-directed layouts. The default drag constant is
-201 * 0.1, the default charge constant is -40 (with a domain of [2, 500] and theta
-202 * of 0.9), and the default spring constant is 0.1 (with a damping of 0.3 and a
-203 * rest length of 20).
-204 *
-205 * @type pv.Layout.Force
-206 */
-207pv.Layout.Force.prototype.defaults=newpv.Layout.Force()
-208.extend(pv.Layout.Network.prototype.defaults)
-209.dragConstant(.1)
-210.chargeConstant(-40)
-211.chargeMinDistance(2)
-212.chargeMaxDistance(500)
-213.chargeTheta(.9)
-214.springConstant(.1)
-215.springDamping(.3)
-216.springLength(20);
-217
-218/** @private Initialize the physics simulation. */
-219pv.Layout.Force.prototype.buildImplied=function(s){
-220
-221/* Any cached interactive layouts need to be rebound for the timer. */
-222if(pv.Layout.Network.prototype.buildImplied.call(this,s)){
-223varf=s.$force;
-224if(f){
-225f.next=this.binds.$force;
-226this.binds.$force=f;
-227}
-228return;
-229}
-230
-231varthat=this,
-232nodes=s.nodes,
-233links=s.links,
-234k=s.iterations,
-235w=s.width,
-236h=s.height;
-237
-238/* Initialize positions randomly near the center. */
-239for(vari=0,n;i<nodes.length;i++){
-240n=nodes[i];
-241if(isNaN(n.x))n.x=w/2+40*Math.random()-20;
-242if(isNaN(n.y))n.y=h/2+40*Math.random()-20;
-243}
-244
-245/* Initialize the simulation. */
-246varsim=pv.simulation(nodes);
-247
-248/* Drag force. */
-249sim.force(pv.Force.drag(s.dragConstant));
-250
-251/* Charge (repelling) force. */
-252sim.force(pv.Force.charge(s.chargeConstant)
-253.domain(s.chargeMinDistance,s.chargeMaxDistance)
-254.theta(s.chargeTheta));
-255
-256/* Spring (attracting) force. */
-257sim.force(pv.Force.spring(s.springConstant)
-258.damping(s.springDamping)
-259.length(s.springLength)
-260.links(links));
-261
-262/* Position constraint (for interactive dragging). */
-263sim.constraint(pv.Constraint.position());
-264
-265/* Optionally add bound constraint. TODO: better padding. */
-266if(s.bound){
-267sim.constraint(pv.Constraint.bound().x(6,w-6).y(6,h-6));
-268}
-269
-270/** @private Returns the speed of the given node, to determine cooling. */
-271functionspeed(n){
-272returnn.fix?1:n.vx*n.vx+n.vy*n.vy;
-273}
-274
-275/*
-276 * If the iterations property is null (the default), the layout is
-277 * interactive. The simulation is run until the fastest particle drops below
-278 * an arbitrary minimum speed. Although the timer keeps firing, this speed
-279 * calculation is fast so there is minimal CPU overhead. Note: if a particle
-280 * is fixed for interactivity, treat this as a high speed and resume
-281 * simulation.
-282 */
-283if(k==null){
-284sim.step();// compute initial previous velocities
-285sim.step();// compute initial velocities
-286
-287/* Add the simulation state to the bound list. */
-288varforce=s.$force=this.binds.$force={
-289next:this.binds.$force,
-290nodes:nodes,
-291min:1e-4*(links.length+1),
-292sim:sim
-293};
-294
-295/* Start the timer, if not already started. */
-296if(!this.$timer)this.$timer=setInterval(function(){
-297varrender=false;
-298for(varf=that.binds.$force;f;f=f.next){
-299if(pv.max(f.nodes,speed)>f.min){
-300f.sim.step();
-301render=true;
-302}
-303}
-304if(render)that.render();
-305},42);
-306}elsefor(vari=0;i<k;i++){
-307sim.step();
-308}
-309};
-310
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Grid.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Grid.js.html
deleted file mode 100644
index bdc13a4b..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Grid.js.html
+++ /dev/null
@@ -1,127 +0,0 @@
-
1/**
- 2 * Constructs a new, empty grid layout. Layouts are not typically constructed
- 3 * directly; instead, they are added to an existing panel via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Implements a grid layout with regularly-sized rows and columns. The
- 7 * number of rows and columns are determined from their respective
- 8 * properties. For example, the 2×3 array:
- 9 *
- 10 * <pre>1 2 3
- 11 * 4 5 6</pre>
- 12 *
- 13 * can be represented using the <tt>rows</tt> property as:
- 14 *
- 15 * <pre>[[1, 2, 3], [4, 5, 6]]</pre>
- 16 *
- 17 * If your data is in column-major order, you can equivalently use the
- 18 * <tt>columns</tt> property. If the <tt>rows</tt> property is an array, it
- 19 * takes priority over the <tt>columns</tt> property. The data is implicitly
- 20 * transposed, as if the {@link pv.transpose} operator were applied.
- 21 *
- 22 * <p>This layout exports a single <tt>cell</tt> mark prototype, which is
- 23 * intended to be used with a bar, panel, layout, or subclass thereof. The data
- 24 * property of the cell prototype is defined as the elements in the array. For
- 25 * example, if the array is a two-dimensional array of values in the range
- 26 * [0,1], a simple heatmap can be generated as:
- 27 *
- 28 * <pre>vis.add(pv.Layout.Grid)
- 29 * .rows(arrays)
- 30 * .cell.add(pv.Bar)
- 31 * .fillStyle(pv.ramp("white", "black"))</pre>
- 32 *
- 33 * The grid subdivides the full width and height of the parent panel into equal
- 34 * rectangles. Note, however, that for large, interactive, or animated heatmaps,
- 35 * you may see significantly better performance through dynamic {@link pv.Image}
- 36 * generation.
- 37 *
- 38 * <p>For irregular grids using value-based spatial partitioning, see {@link
- 39 * pv.Layout.Treemap}.
- 40 *
- 41 * @extends pv.Layout
- 42 */
- 43pv.Layout.Grid=function(){
- 44pv.Layout.call(this);
- 45varthat=this;
- 46
- 47/**
- 48 * The cell prototype. This prototype is intended to be used with a bar,
- 49 * panel, or layout (or subclass thereof) to render the grid cells.
- 50 *
- 51 * @type pv.Mark
- 52 * @name pv.Layout.Grid.prototype.cell
- 53 */
- 54(this.cell=newpv.Mark()
- 55.data(function(){
- 56returnthat.scene[that.index].$grid;
- 57})
- 58.width(function(){
- 59returnthat.width()/that.cols();
- 60})
- 61.height(function(){
- 62returnthat.height()/that.rows();
- 63})
- 64.left(function(){
- 65returnthis.width()*(this.index%that.cols());
- 66})
- 67.top(function(){
- 68returnthis.height()*Math.floor(this.index/that.cols());
- 69})).parent=this;
- 70};
- 71
- 72pv.Layout.Grid.prototype=pv.extend(pv.Layout)
- 73.property("rows")
- 74.property("cols");
- 75
- 76/**
- 77 * Default properties for grid layouts. By default, there is one row and one
- 78 * column, and the data is the propagated to the child cell.
- 79 *
- 80 * @type pv.Layout.Grid
- 81 */
- 82pv.Layout.Grid.prototype.defaults=newpv.Layout.Grid()
- 83.extend(pv.Layout.prototype.defaults)
- 84.rows(1)
- 85.cols(1);
- 86
- 87/** @private */
- 88pv.Layout.Grid.prototype.buildImplied=function(s){
- 89pv.Layout.prototype.buildImplied.call(this,s);
- 90varr=s.rows,c=s.cols;
- 91if(typeofc=="object")r=pv.transpose(c);
- 92if(typeofr=="object"){
- 93s.$grid=pv.blend(r);
- 94s.rows=r.length;
- 95s.cols=r[0]?r[0].length:0;
- 96}else{
- 97s.$grid=pv.repeat([s.data],r*c);
- 98}
- 99};
-100
-101/**
-102 * The number of rows. This property can also be specified as the data in
-103 * row-major order; in this case, the rows property is implicitly set to the
-104 * length of the array, and the cols property is set to the length of the first
-105 * element in the array.
-106 *
-107 * @type number
-108 * @name pv.Layout.Grid.prototype.rows
-109 */
-110
-111/**
-112 * The number of columns. This property can also be specified as the data in
-113 * column-major order; in this case, the cols property is implicitly set to the
-114 * length of the array, and the rows property is set to the length of the first
-115 * element in the array.
-116 *
-117 * @type number
-118 * @name pv.Layout.Grid.prototype.cols
-119 */
-120
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Hierarchy.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Hierarchy.js.html
deleted file mode 100644
index 269ee49d..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Hierarchy.js.html
+++ /dev/null
@@ -1,257 +0,0 @@
-
1/**
- 2 * Constructs a new, empty hierarchy layout. Layouts are not typically
- 3 * constructed directly; instead, they are added to an existing panel via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Represents an abstract layout for hierarchy diagrams. This class is a
- 7 * specialization of {@link pv.Layout.Network}, providing the basic structure
- 8 * for both hierarchical node-link diagrams (such as Reingold-Tilford trees) and
- 9 * space-filling hierarchy diagrams (such as sunbursts and treemaps).
- 10 *
- 11 * <p>Unlike general network layouts, the <tt>links</tt> property need not be
- 12 * defined explicitly. Instead, the links are computed implicitly from the
- 13 * <tt>parentNode</tt> attribute of the node objects, as defined by the
- 14 * <tt>nodes</tt> property. This implementation is also available as
- 15 * {@link #links}, for reuse with non-hierarchical layouts; for example, to
- 16 * render a tree using force-directed layout.
- 17 *
- 18 * <p>Correspondingly, the <tt>nodes</tt> property is represented as a union of
- 19 * {@link pv.Layout.Network.Node} and {@link pv.Dom.Node}. To construct a node
- 20 * hierarchy from a simple JSON map, use the {@link pv.Dom} operator; this
- 21 * operator also provides an easy way to sort nodes before passing them to the
- 22 * layout.
- 23 *
- 24 * <p>For more details on how to use this layout, see
- 25 * {@link pv.Layout.Network}.
- 26 *
- 27 * @see pv.Layout.Cluster
- 28 * @see pv.Layout.Partition
- 29 * @see pv.Layout.Tree
- 30 * @see pv.Layout.Treemap
- 31 * @see pv.Layout.Indent
- 32 * @see pv.Layout.Pack
- 33 * @extends pv.Layout.Network
- 34 */
- 35pv.Layout.Hierarchy=function(){
- 36pv.Layout.Network.call(this);
- 37this.link.strokeStyle("#ccc");
- 38};
- 39
- 40pv.Layout.Hierarchy.prototype=pv.extend(pv.Layout.Network);
- 41
- 42/** @private Compute the implied links. (Links are null by default.) */
- 43pv.Layout.Hierarchy.prototype.buildImplied=function(s){
- 44if(!s.links)s.links=pv.Layout.Hierarchy.links.call(this);
- 45pv.Layout.Network.prototype.buildImplied.call(this,s);
- 46};
- 47
- 48/** The implied links; computes links using the <tt>parentNode</tt> attribute. */
- 49pv.Layout.Hierarchy.links=function(){
- 50returnthis.nodes()
- 51.filter(function(n){returnn.parentNode;})
- 52.map(function(n){
- 53return{
- 54sourceNode:n,
- 55targetNode:n.parentNode,
- 56linkValue:1
- 57};
- 58});
- 59};
- 60
- 61/** @private Provides standard node-link layout based on breadth & depth. */
- 62pv.Layout.Hierarchy.NodeLink={
- 63
- 64/** @private */
- 65buildImplied:function(s){
- 66varnodes=s.nodes,
- 67orient=s.orient,
- 68horizontal=/^(top|bottom)$/.test(orient),
- 69w=s.width,
- 70h=s.height;
- 71
- 72/* Compute default inner and outer radius. */
- 73if(orient=="radial"){
- 74varir=s.innerRadius,or=s.outerRadius;
- 75if(ir==null)ir=0;
- 76if(or==null)or=Math.min(w,h)/2;
- 77}
- 78
- 79/** @private Returns the radius of the given node. */
- 80functionradius(n){
- 81returnn.parentNode?(n.depth*(or-ir)+ir):0;
- 82}
- 83
- 84/** @private Returns the angle of the given node. */
- 85functionmidAngle(n){
- 86return(n.parentNode?(n.breadth-.25)*2*Math.PI:0);
- 87}
- 88
- 89/** @private */
- 90functionx(n){
- 91switch(orient){
- 92case"left":returnn.depth*w;
- 93case"right":returnw-n.depth*w;
- 94case"top":returnn.breadth*w;
- 95case"bottom":returnw-n.breadth*w;
- 96case"radial":returnw/2+radius(n)*Math.cos(n.midAngle);
- 97}
- 98}
- 99
-100/** @private */
-101functiony(n){
-102switch(orient){
-103case"left":returnn.breadth*h;
-104case"right":returnh-n.breadth*h;
-105case"top":returnn.depth*h;
-106case"bottom":returnh-n.depth*h;
-107case"radial":returnh/2+radius(n)*Math.sin(n.midAngle);
-108}
-109}
-110
-111for(vari=0;i<nodes.length;i++){
-112varn=nodes[i];
-113n.midAngle=orient=="radial"?midAngle(n)
-114:horizontal?Math.PI/2:0;
-115n.x=x(n);
-116n.y=y(n);
-117if(n.firstChild)n.midAngle+=Math.PI;
-118}
-119}
-120};
-121
-122/** @private Provides standard space-filling layout based on breadth & depth. */
-123pv.Layout.Hierarchy.Fill={
-124
-125/** @private */
-126constructor:function(){
-127this.node
-128.strokeStyle("#fff")
-129.fillStyle("#ccc")
-130.width(function(n){returnn.dx;})
-131.height(function(n){returnn.dy;})
-132.innerRadius(function(n){returnn.innerRadius;})
-133.outerRadius(function(n){returnn.outerRadius;})
-134.startAngle(function(n){returnn.startAngle;})
-135.angle(function(n){returnn.angle;});
-136
-137this.label
-138.textAlign("center")
-139.left(function(n){returnn.x+(n.dx/2);})
-140.top(function(n){returnn.y+(n.dy/2);});
-141
-142/* Hide unsupported link. */
-143deletethis.link;
-144},
-145
-146/** @private */
-147buildImplied:function(s){
-148varnodes=s.nodes,
-149orient=s.orient,
-150horizontal=/^(top|bottom)$/.test(orient),
-151w=s.width,
-152h=s.height,
-153depth=-nodes[0].minDepth;
-154
-155/* Compute default inner and outer radius. */
-156if(orient=="radial"){
-157varir=s.innerRadius,or=s.outerRadius;
-158if(ir==null)ir=0;
-159if(ir)depth*=2;// use full depth step for root
-160if(or==null)or=Math.min(w,h)/2;
-161}
-162
-163/** @private Scales the specified depth for a space-filling layout. */
-164functionscale(d,depth){
-165return(d+depth)/(1+depth);
-166}
-167
-168/** @private */
-169functionx(n){
-170switch(orient){
-171case"left":returnscale(n.minDepth,depth)*w;
-172case"right":return(1-scale(n.maxDepth,depth))*w;
-173case"top":returnn.minBreadth*w;
-174case"bottom":return(1-n.maxBreadth)*w;
-175case"radial":returnw/2;
-176}
-177}
-178
-179/** @private */
-180functiony(n){
-181switch(orient){
-182case"left":returnn.minBreadth*h;
-183case"right":return(1-n.maxBreadth)*h;
-184case"top":returnscale(n.minDepth,depth)*h;
-185case"bottom":return(1-scale(n.maxDepth,depth))*h;
-186case"radial":returnh/2;
-187}
-188}
-189
-190/** @private */
-191functiondx(n){
-192switch(orient){
-193case"left":
-194case"right":return(n.maxDepth-n.minDepth)/(1+depth)*w;
-195case"top":
-196case"bottom":return(n.maxBreadth-n.minBreadth)*w;
-197case"radial":returnn.parentNode?(n.innerRadius+n.outerRadius)*Math.cos(n.midAngle):0;
-198}
-199}
-200
-201/** @private */
-202functiondy(n){
-203switch(orient){
-204case"left":
-205case"right":return(n.maxBreadth-n.minBreadth)*h;
-206case"top":
-207case"bottom":return(n.maxDepth-n.minDepth)/(1+depth)*h;
-208case"radial":returnn.parentNode?(n.innerRadius+n.outerRadius)*Math.sin(n.midAngle):0;
-209}
-210}
-211
-212/** @private */
-213functioninnerRadius(n){
-214returnMath.max(0,scale(n.minDepth,depth/2))*(or-ir)+ir;
-215}
-216
-217/** @private */
-218functionouterRadius(n){
-219returnscale(n.maxDepth,depth/2)*(or-ir)+ir;
-220}
-221
-222/** @private */
-223functionstartAngle(n){
-224return(n.parentNode?n.minBreadth-.25:0)*2*Math.PI;
-225}
-226
-227/** @private */
-228functionangle(n){
-229return(n.parentNode?n.maxBreadth-n.minBreadth:1)*2*Math.PI;
-230}
-231
-232for(vari=0;i<nodes.length;i++){
-233varn=nodes[i];
-234n.x=x(n);
-235n.y=y(n);
-236if(orient=="radial"){
-237n.innerRadius=innerRadius(n);
-238n.outerRadius=outerRadius(n);
-239n.startAngle=startAngle(n);
-240n.angle=angle(n);
-241n.midAngle=n.startAngle+n.angle/2;
-242}else{
-243n.midAngle=horizontal?-Math.PI/2:0;
-244}
-245n.dx=dx(n);
-246n.dy=dy(n);
-247}
-248}
-249};
-250
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Horizon.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Horizon.js.html
deleted file mode 100644
index 0dcd31b9..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Horizon.js.html
+++ /dev/null
@@ -1,167 +0,0 @@
-
1/**
- 2 * Constructs a new, empty horizon layout. Layouts are not typically constructed
- 3 * directly; instead, they are added to an existing panel via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Implements a horizon layout, which is a variation of a single-series
- 7 * area chart where the area is folded into multiple bands. Color is used to
- 8 * encode band, allowing the size of the chart to be reduced significantly
- 9 * without impeding readability. This layout algorithm is based on the work of
- 10 * J. Heer, N. Kong and M. Agrawala in <a
- 11 * href="http://hci.stanford.edu/publications/2009/heer-horizon-chi09.pdf">"Sizing
- 12 * the Horizon: The Effects of Chart Size and Layering on the Graphical
- 13 * Perception of Time Series Visualizations"</a>, CHI 2009.
- 14 *
- 15 * <p>This layout exports a single <tt>band</tt> mark prototype, which is
- 16 * intended to be used with an area mark. The band mark is contained in a panel
- 17 * which is replicated per band (and for negative/positive bands). For example,
- 18 * to create a simple horizon graph given an array of numbers:
- 19 *
- 20 * <pre>vis.add(pv.Layout.Horizon)
- 21 * .bands(n)
- 22 * .band.add(pv.Area)
- 23 * .data(data)
- 24 * .left(function() this.index * 35)
- 25 * .height(function(d) d * 40);</pre>
- 26 *
- 27 * The layout can be further customized by changing the number of bands, and
- 28 * toggling whether the negative bands are mirrored or offset. (See the
- 29 * above-referenced paper for guidance.)
- 30 *
- 31 * <p>The <tt>fillStyle</tt> of the area can be overridden, though typically it
- 32 * is easier to customize the layout's behavior through the custom
- 33 * <tt>backgroundStyle</tt>, <tt>positiveStyle</tt> and <tt>negativeStyle</tt>
- 34 * properties. By default, the background is white, positive bands are blue, and
- 35 * negative bands are red. For the most accurate presentation, use fully-opaque
- 36 * colors of equal intensity for the negative and positive bands.
- 37 *
- 38 * @extends pv.Layout
- 39 */
- 40pv.Layout.Horizon=function(){
- 41pv.Layout.call(this);
- 42varthat=this,
- 43bands,// cached bands
- 44mode,// cached mode
- 45size,// cached height
- 46fill,// cached background style
- 47red,// cached negative color (ramp)
- 48blue,// cached positive color (ramp)
- 49buildImplied=this.buildImplied;
- 50
- 51/** @private Cache the layout state to optimize properties. */
- 52this.buildImplied=function(s){
- 53buildImplied.call(this,s);
- 54bands=s.bands;
- 55mode=s.mode;
- 56size=Math.round((mode=="color"?.5:1)*s.height);
- 57fill=s.backgroundStyle;
- 58red=pv.ramp(fill,s.negativeStyle).domain(0,bands);
- 59blue=pv.ramp(fill,s.positiveStyle).domain(0,bands);
- 60};
- 61
- 62varbands=newpv.Panel()
- 63.data(function(){returnpv.range(bands*2);})
- 64.overflow("hidden")
- 65.height(function(){returnsize;})
- 66.top(function(i){returnmode=="color"?(i&1)*size:0;})
- 67.fillStyle(function(i){returni?null:fill;});
- 68
- 69/**
- 70 * The band prototype. This prototype is intended to be used with an Area
- 71 * mark to render the horizon bands.
- 72 *
- 73 * @type pv.Mark
- 74 * @name pv.Layout.Horizon.prototype.band
- 75 */
- 76this.band=newpv.Mark()
- 77.top(function(d,i){
- 78returnmode=="mirror"&&i&1
- 79?(i+1>>1)*size
- 80:null;
- 81})
- 82.bottom(function(d,i){
- 83returnmode=="mirror"
- 84?(i&1?null:(i+1>>1)*-size)
- 85:((i&1||-1)*(i+1>>1)*size);
- 86})
- 87.fillStyle(function(d,i){
- 88return(i&1?red:blue)((i>>1)+1);
- 89});
- 90
- 91this.band.add=function(type){
- 92returnthat.add(pv.Panel).extend(bands).add(type).extend(this);
- 93};
- 94};
- 95
- 96pv.Layout.Horizon.prototype=pv.extend(pv.Layout)
- 97.property("bands",Number)
- 98.property("mode",String)
- 99.property("backgroundStyle",pv.color)
-100.property("positiveStyle",pv.color)
-101.property("negativeStyle",pv.color);
-102
-103/**
-104 * Default properties for horizon layouts. By default, there are two bands, the
-105 * mode is "offset", the background style is "white", the positive style is
-106 * blue, negative style is red.
-107 *
-108 * @type pv.Layout.Horizon
-109 */
-110pv.Layout.Horizon.prototype.defaults=newpv.Layout.Horizon()
-111.extend(pv.Layout.prototype.defaults)
-112.bands(2)
-113.mode("offset")
-114.backgroundStyle("white")
-115.positiveStyle("#1f77b4")
-116.negativeStyle("#d62728");
-117
-118/**
-119 * The horizon mode: offset, mirror, or color. The default is "offset".
-120 *
-121 * @type string
-122 * @name pv.Layout.Horizon.prototype.mode
-123 */
-124
-125/**
-126 * The number of bands. Must be at least one. The default value is two.
-127 *
-128 * @type number
-129 * @name pv.Layout.Horizon.prototype.bands
-130 */
-131
-132/**
-133 * The positive band color; if non-null, the interior of positive bands are
-134 * filled with the specified color. The default value of this property is blue.
-135 * For accurate blending, this color should be fully opaque.
-136 *
-137 * @type pv.Color
-138 * @name pv.Layout.Horizon.prototype.positiveStyle
-139 */
-140
-141/**
-142 * The negative band color; if non-null, the interior of negative bands are
-143 * filled with the specified color. The default value of this property is red.
-144 * For accurate blending, this color should be fully opaque.
-145 *
-146 * @type pv.Color
-147 * @name pv.Layout.Horizon.prototype.negativeStyle
-148 */
-149
-150/**
-151 * The background color. The panel background is filled with the specified
-152 * color, and the negative and positive bands are filled with an interpolated
-153 * color between this color and the respective band color. The default value of
-154 * this property is white. For accurate blending, this color should be fully
-155 * opaque.
-156 *
-157 * @type pv.Color
-158 * @name pv.Layout.Horizon.prototype.backgroundStyle
-159 */
-160
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Indent.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Indent.js.html
deleted file mode 100644
index 1f8ded48..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Indent.js.html
+++ /dev/null
@@ -1,91 +0,0 @@
-
1/**
- 2 * Constructs a new, empty indent layout. Layouts are not typically constructed
- 3 * directly; instead, they are added to an existing panel via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Implements a hierarchical layout using the indent algorithm. This
- 7 * layout implements a node-link diagram where the nodes are presented in
- 8 * preorder traversal, and nodes are indented based on their depth from the
- 9 * root. This technique is used ubiquitously by operating systems to represent
- 10 * file directories; although it requires much vertical space, indented trees
- 11 * allow efficient <i>interactive</i> exploration of trees to find a specific
- 12 * node. In addition they allow rapid scanning of node labels, and multivariate
- 13 * data such as file sizes can be displayed adjacent to the hierarchy.
- 14 *
- 15 * <p>The indent layout can be configured using the <tt>depth</tt> and
- 16 * <tt>breadth</tt> properties, which control the increments in pixel space for
- 17 * each indent and row in the layout. This layout does not support multiple
- 18 * orientations; the root node is rendered in the top-left, while
- 19 * <tt>breadth</tt> is a vertical offset from the top, and <tt>depth</tt> is a
- 20 * horizontal offset from the left.
- 21 *
- 22 * <p>For more details on how to use this layout, see
- 23 * {@link pv.Layout.Hierarchy}.
- 24 *
- 25 * @extends pv.Layout.Hierarchy
- 26 */
- 27pv.Layout.Indent=function(){
- 28pv.Layout.Hierarchy.call(this);
- 29this.link.interpolate("step-after");
- 30};
- 31
- 32pv.Layout.Indent.prototype=pv.extend(pv.Layout.Hierarchy)
- 33.property("depth",Number)
- 34.property("breadth",Number);
- 35
- 36/**
- 37 * The horizontal offset between different levels of the tree; defaults to 15.
- 38 *
- 39 * @type number
- 40 * @name pv.Layout.Indent.prototype.depth
- 41 */
- 42
- 43/**
- 44 * The vertical offset between nodes; defaults to 15.
- 45 *
- 46 * @type number
- 47 * @name pv.Layout.Indent.prototype.breadth
- 48 */
- 49
- 50/**
- 51 * Default properties for indent layouts. By default the depth and breadth
- 52 * offsets are 15 pixels.
- 53 *
- 54 * @type pv.Layout.Indent
- 55 */
- 56pv.Layout.Indent.prototype.defaults=newpv.Layout.Indent()
- 57.extend(pv.Layout.Hierarchy.prototype.defaults)
- 58.depth(15)
- 59.breadth(15);
- 60
- 61/** @private */
- 62pv.Layout.Indent.prototype.buildImplied=function(s){
- 63if(pv.Layout.Hierarchy.prototype.buildImplied.call(this,s))return;
- 64
- 65varnodes=s.nodes,
- 66bspace=s.breadth,
- 67dspace=s.depth,
- 68ax=0,
- 69ay=0;
- 70
- 71/** @private */
- 72functionposition(n,breadth,depth){
- 73n.x=ax+depth++*dspace;
- 74n.y=ay+breadth++*bspace;
- 75n.midAngle=0;
- 76for(varc=n.firstChild;c;c=c.nextSibling){
- 77breadth=position(c,breadth,depth);
- 78}
- 79returnbreadth;
- 80}
- 81
- 82position(nodes[0],1,1);
- 83};
- 84
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Layout.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Layout.js.html
deleted file mode 100644
index 30d538b6..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Layout.js.html
+++ /dev/null
@@ -1,64 +0,0 @@
-
1/**
- 2 * Constructs a new, empty layout with default properties. Layouts are not
- 3 * typically constructed directly; instead, a concrete subclass is added to an
- 4 * existing panel via {@link pv.Mark#add}.
- 5 *
- 6 * @class Represents an abstract layout, encapsulating a visualization technique
- 7 * such as a streamgraph or treemap. Layouts are themselves containers,
- 8 * extending from {@link pv.Panel}, and defining a set of mark prototypes as
- 9 * children. These mark prototypes provide default properties that together
- 10 * implement the given visualization technique.
- 11 *
- 12 * <p>Layouts do not initially contain any marks; any exported marks (such as a
- 13 * network layout's <tt>link</tt> and <tt>node</tt>) are intended to be used as
- 14 * prototypes. By adding a concrete mark, such as a {@link pv.Bar}, to the
- 15 * appropriate mark prototype, the mark is added to the layout and inherits the
- 16 * given properties. This approach allows further customization of the layout,
- 17 * either by choosing a different mark type to add, or more simply by overriding
- 18 * some of the layout's defined properties.
- 19 *
- 20 * <p>Each concrete layout, such as treemap or circle-packing, has different
- 21 * behavior and may export different mark prototypes, depending on what marks
- 22 * are typically needed to render the desired visualization. Therefore it is
- 23 * important to understand how each layout is structured, such that the provided
- 24 * mark prototypes are used appropriately.
- 25 *
- 26 * <p>In addition to the mark prototypes, layouts may define custom properties
- 27 * that affect the overall behavior of the layout. For example, a treemap layout
- 28 * might use a property to specify which layout algorithm to use. These
- 29 * properties are just like other mark properties, and can be defined as
- 30 * constants or as functions. As with panels, the data property can be used to
- 31 * replicate layouts, and properties can be defined to in terms of layout data.
- 32 *
- 33 * @extends pv.Panel
- 34 */
- 35pv.Layout=function(){
- 36pv.Panel.call(this);
- 37};
- 38
- 39pv.Layout.prototype=pv.extend(pv.Panel);
- 40
- 41/**
- 42 * @private Defines a local property with the specified name and cast. Note that
- 43 * although the property method is only defined locally, the cast function is
- 44 * global, which is necessary since properties are inherited!
- 45 *
- 46 * @param {string} name the property name.
- 47 * @param {function} [cast] the cast function for this property.
- 48 */
- 49pv.Layout.prototype.property=function(name,cast){
- 50if(!this.hasOwnProperty("properties")){
- 51this.properties=pv.extend(this.properties);
- 52}
- 53this.properties[name]=true;
- 54this.propertyMethod(name,false,pv.Mark.cast[name]=cast);
- 55returnthis;
- 56};
- 57
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Matrix.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Matrix.js.html
deleted file mode 100644
index 90a87bba..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Matrix.js.html
+++ /dev/null
@@ -1,185 +0,0 @@
-
1/**
- 2 * Constructs a new, empty matrix network layout. Layouts are not typically
- 3 * constructed directly; instead, they are added to an existing panel via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Implements a network visualization using a matrix view. This is, in
- 7 * effect, a visualization of the graph's <i>adjacency matrix</i>: the cell at
- 8 * row <i>i</i>, column <i>j</i>, corresponds to the link from node <i>i</i> to
- 9 * node <i>j</i>. The fill color of each cell is binary by default, and
- 10 * corresponds to whether a link exists between the two nodes. If the underlying
- 11 * graph has links with variable values, the <tt>fillStyle</tt> property can be
- 12 * substited to use an appropriate color function, such as {@link pv.ramp}.
- 13 *
- 14 * <p>For undirected networks, the matrix is symmetric around the diagonal. For
- 15 * directed networks, links in opposite directions can be rendered on opposite
- 16 * sides of the diagonal using <tt>directed(true)</tt>. The graph is assumed to
- 17 * be undirected by default.
- 18 *
- 19 * <p>The mark prototypes for this network layout are slightly different than
- 20 * other implementations:<ul>
- 21 *
- 22 * <li><tt>node</tt> - unsupported; undefined. No mark is needed to visualize
- 23 * nodes directly, as the nodes are implicit in the location (rows and columns)
- 24 * of the links.
- 25 *
- 26 * <p><li><tt>link</tt> - for rendering links; typically a {@link pv.Bar}. The
- 27 * link mark is added directly to the layout, with the data property defined as
- 28 * all possible pairs of nodes. Each pair is represented as a
- 29 * {@link pv.Network.Layout.Link}, though the <tt>linkValue</tt> attribute may
- 30 * be 0 if no link exists in the graph.
- 31 *
- 32 * <p><li><tt>label</tt> - for rendering node labels; typically a
- 33 * {@link pv.Label}. The label mark is added directly to the layout, with the
- 34 * data property defined via the layout's <tt>nodes</tt> property; note,
- 35 * however, that the nodes are duplicated so as to provide a label across the
- 36 * top and down the side. Properties such as <tt>strokeStyle</tt> and
- 37 * <tt>fillStyle</tt> can be overridden to compute properties from node data
- 38 * dynamically.
- 39 *
- 40 * </ul>For more details on how to use this layout, see
- 41 * {@link pv.Layout.Network}.
- 42 *
- 43 * @extends pv.Layout.Network
- 44 */
- 45pv.Layout.Matrix=function(){
- 46pv.Layout.Network.call(this);
- 47varthat=this,
- 48n,// cached matrix size
- 49dx,// cached cell width
- 50dy,// cached cell height
- 51labels,// cached labels (array of strings)
- 52pairs,// cached pairs (array of links)
- 53buildImplied=that.buildImplied;
- 54
- 55/** @private Cache layout state to optimize properties. */
- 56this.buildImplied=function(s){
- 57buildImplied.call(this,s);
- 58n=s.nodes.length;
- 59dx=s.width/n;
- 60dy=s.height/n;
- 61labels=s.$matrix.labels;
- 62pairs=s.$matrix.pairs;
- 63};
- 64
- 65/* Links are all pairs of nodes. */
- 66this.link
- 67.data(function(){returnpairs;})
- 68.left(function(){returndx*(this.index%n);})
- 69.top(function(){returndy*Math.floor(this.index/n);})
- 70.width(function(){returndx;})
- 71.height(function(){returndy;})
- 72.lineWidth(1.5)
- 73.strokeStyle("#fff")
- 74.fillStyle(function(l){returnl.linkValue?"#555":"#eee";})
- 75.parent=this;
- 76
- 77/* No special add for links! */
- 78deletethis.link.add;
- 79
- 80/* Labels are duplicated for top & left. */
- 81this.label
- 82.data(function(){returnlabels;})
- 83.left(function(){returnthis.index&1?dx*((this.index>>1)+.5):null;})
- 84.top(function(){returnthis.index&1?null:dy*((this.index>>1)+.5);})
- 85.textMargin(4)
- 86.textAlign(function(){returnthis.index&1?"left":"right";})
- 87.textAngle(function(){returnthis.index&1?-Math.PI/2:0;});
- 88
- 89/* The node mark is unused. */
- 90deletethis.node;
- 91};
- 92
- 93pv.Layout.Matrix.prototype=pv.extend(pv.Layout.Network)
- 94.property("directed",Boolean);
- 95
- 96/**
- 97 * Whether this matrix visualization is directed (bidirectional). By default,
- 98 * the graph is assumed to be undirected, such that the visualization is
- 99 * symmetric across the matrix diagonal. If the network is directed, then
-100 * forward links are drawn above the diagonal, while reverse links are drawn
-101 * below.
-102 *
-103 * @type boolean
-104 * @name pv.Layout.Matrix.prototype.directed
-105 */
-106
-107/**
-108 * Specifies an optional sort function. The sort function follows the same
-109 * comparator contract required by {@link pv.Dom.Node#sort}. Specifying a sort
-110 * function provides an alternative to sort the nodes as they are specified by
-111 * the <tt>nodes</tt> property; the main advantage of doing this is that the
-112 * comparator function can access implicit fields populated by the network
-113 * layout, such as the <tt>linkDegree</tt>.
-114 *
-115 * <p>Note that matrix visualizations are particularly sensitive to order. This
-116 * is referred to as the seriation problem, and many different techniques exist
-117 * to find good node orders that emphasize clusters, such as spectral layout and
-118 * simulated annealing.
-119 *
-120 * @param {function} f comparator function for nodes.
-121 * @returns {pv.Layout.Matrix} this.
-122 */
-123pv.Layout.Matrix.prototype.sort=function(f){
-124this.$sort=f;
-125returnthis;
-126};
-127
-128/** @private */
-129pv.Layout.Matrix.prototype.buildImplied=function(s){
-130if(pv.Layout.Network.prototype.buildImplied.call(this,s))return;
-131
-132varnodes=s.nodes,
-133links=s.links,
-134sort=this.$sort,
-135n=nodes.length,
-136index=pv.range(n),
-137labels=[],
-138pairs=[],
-139map={};
-140
-141s.$matrix={labels:labels,pairs:pairs};
-142
-143/* Sort the nodes. */
-144if(sort)index.sort(function(a,b){returnsort(nodes[a],nodes[b]);});
-145
-146/* Create pairs. */
-147for(vari=0;i<n;i++){
-148for(varj=0;j<n;j++){
-149vara=index[i],
-150b=index[j],
-151p={
-152row:i,
-153col:j,
-154sourceNode:nodes[a],
-155targetNode:nodes[b],
-156linkValue:0
-157};
-158pairs.push(map[a+"."+b]=p);
-159}
-160}
-161
-162/* Create labels. */
-163for(vari=0;i<n;i++){
-164vara=index[i];
-165labels.push(nodes[a],nodes[a]);
-166}
-167
-168/* Accumulate link values. */
-169for(vari=0;i<links.length;i++){
-170varl=links[i],
-171source=l.sourceNode.index,
-172target=l.targetNode.index,
-173value=l.linkValue;
-174map[source+"."+target].linkValue+=value;
-175if(!s.directed)map[target+"."+source].linkValue+=value;
-176}
-177};
-178
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Network.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Network.js.html
deleted file mode 100644
index 4d8f43c0..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Network.js.html
+++ /dev/null
@@ -1,308 +0,0 @@
-
1/**
- 2 * Constructs a new, empty network layout. Layouts are not typically constructed
- 3 * directly; instead, they are added to an existing panel via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Represents an abstract layout for network diagrams. This class
- 7 * provides the basic structure for both node-link diagrams (such as
- 8 * force-directed graph layout) and space-filling network diagrams (such as
- 9 * sunbursts and treemaps). Note that "network" here is a general term that
- 10 * includes hierarchical structures; a tree is represented using links from
- 11 * child to parent.
- 12 *
- 13 * <p>Network layouts require the graph data structure to be defined using two
- 14 * properties:<ul>
- 15 *
- 16 * <li><tt>nodes</tt> - an array of objects representing nodes. Objects in this
- 17 * array must conform to the {@link pv.Layout.Network.Node} interface; which is
- 18 * to say, be careful to avoid naming collisions with automatic attributes such
- 19 * as <tt>index</tt> and <tt>linkDegree</tt>. If the nodes property is defined
- 20 * as an array of primitives, such as numbers or strings, these primitives are
- 21 * automatically wrapped in an object; the resulting object's <tt>nodeValue</tt>
- 22 * attribute points to the original primitive value.
- 23 *
- 24 * <p><li><tt>links</tt> - an array of objects representing links. Objects in
- 25 * this array must conform to the {@link pv.Layout.Network.Link} interface; at a
- 26 * minimum, either <tt>source</tt> and <tt>target</tt> indexes or
- 27 * <tt>sourceNode</tt> and <tt>targetNode</tt> references must be set. Note that
- 28 * if the links property is defined after the nodes property, the links can be
- 29 * defined in terms of <tt>this.nodes()</tt>.
- 30 *
- 31 * </ul>
- 32 *
- 33 * <p>Three standard mark prototypes are provided:<ul>
- 34 *
- 35 * <li><tt>node</tt> - for rendering nodes; typically a {@link pv.Dot}. The node
- 36 * mark is added directly to the layout, with the data property defined via the
- 37 * layout's <tt>nodes</tt> property. Properties such as <tt>strokeStyle</tt> and
- 38 * <tt>fillStyle</tt> can be overridden to compute properties from node data
- 39 * dynamically.
- 40 *
- 41 * <p><li><tt>link</tt> - for rendering links; typically a {@link pv.Line}. The
- 42 * link mark is added to a child panel, whose data property is defined as
- 43 * layout's <tt>links</tt> property. The link's data property is then a
- 44 * two-element array of the source node and target node. Thus, poperties such as
- 45 * <tt>strokeStyle</tt> and <tt>fillStyle</tt> can be overridden to compute
- 46 * properties from either the node data (the first argument) or the link data
- 47 * (the second argument; the parent panel data) dynamically.
- 48 *
- 49 * <p><li><tt>label</tt> - for rendering node labels; typically a
- 50 * {@link pv.Label}. The label mark is added directly to the layout, with the
- 51 * data property defined via the layout's <tt>nodes</tt> property. Properties
- 52 * such as <tt>strokeStyle</tt> and <tt>fillStyle</tt> can be overridden to
- 53 * compute properties from node data dynamically.
- 54 *
- 55 * </ul>Note that some network implementations may not support all three
- 56 * standard mark prototypes; for example, space-filling hierarchical layouts
- 57 * typically do not use a <tt>link</tt> prototype, as the parent-child links are
- 58 * implied by the structure of the space-filling <tt>node</tt> marks. Check the
- 59 * specific network layout for implementation details.
- 60 *
- 61 * <p>Network layout properties, including <tt>nodes</tt> and <tt>links</tt>,
- 62 * are typically cached rather than re-evaluated with every call to render. This
- 63 * is a performance optimization, as network layout algorithms can be
- 64 * expensive. If the network structure changes, call {@link #reset} to clear the
- 65 * cache before rendering. Note that although the network layout properties are
- 66 * cached, child mark properties, such as the marks used to render the nodes and
- 67 * links, <i>are not</i>. Therefore, non-structural changes to the network
- 68 * layout, such as changing the color of a mark on mouseover, do not need to
- 69 * reset the layout.
- 70 *
- 71 * @see pv.Layout.Hierarchy
- 72 * @see pv.Layout.Force
- 73 * @see pv.Layout.Matrix
- 74 * @see pv.Layout.Arc
- 75 * @see pv.Layout.Rollup
- 76 * @extends pv.Layout
- 77 */
- 78pv.Layout.Network=function(){
- 79pv.Layout.call(this);
- 80varthat=this;
- 81
- 82/* @private Version tracking to cache layout state, improving performance. */
- 83this.$id=pv.id();
- 84
- 85/**
- 86 * The node prototype. This prototype is intended to be used with a Dot mark
- 87 * in conjunction with the link prototype.
- 88 *
- 89 * @type pv.Mark
- 90 * @name pv.Layout.Network.prototype.node
- 91 */
- 92(this.node=newpv.Mark()
- 93.data(function(){returnthat.nodes();})
- 94.strokeStyle("#1f77b4")
- 95.fillStyle("#fff")
- 96.left(function(n){returnn.x;})
- 97.top(function(n){returnn.y;})).parent=this;
- 98
- 99/**
-100 * The link prototype, which renders edges between source nodes and target
-101 * nodes. This prototype is intended to be used with a Line mark in
-102 * conjunction with the node prototype.
-103 *
-104 * @type pv.Mark
-105 * @name pv.Layout.Network.prototype.link
-106 */
-107this.link=newpv.Mark()
-108.extend(this.node)
-109.data(function(p){return[p.sourceNode,p.targetNode];})
-110.fillStyle(null)
-111.lineWidth(function(d,p){returnp.linkValue*1.5;})
-112.strokeStyle("rgba(0,0,0,.2)");
-113
-114this.link.add=function(type){
-115returnthat.add(pv.Panel)
-116.data(function(){returnthat.links();})
-117.add(type)
-118.extend(this);
-119};
-120
-121/**
-122 * The node label prototype, which renders the node name adjacent to the node.
-123 * This prototype is provided as an alternative to using the anchor on the
-124 * node mark; it is primarily intended to be used with radial node-link
-125 * layouts, since it provides a convenient mechanism to set the text angle.
-126 *
-127 * @type pv.Mark
-128 * @name pv.Layout.Network.prototype.label
-129 */
-130(this.label=newpv.Mark()
-131.extend(this.node)
-132.textMargin(7)
-133.textBaseline("middle")
-134.text(function(n){returnn.nodeName||n.nodeValue;})
-135.textAngle(function(n){
-136vara=n.midAngle;
-137returnpv.Wedge.upright(a)?a:(a+Math.PI);
-138})
-139.textAlign(function(n){
-140returnpv.Wedge.upright(n.midAngle)?"left":"right";
-141})).parent=this;
-142};
-143
-144/**
-145 * @class Represents a node in a network layout. There is no explicit
-146 * constructor; this class merely serves to document the attributes that are
-147 * used on nodes in network layouts. (Note that hierarchical nodes place
-148 * additional requirements on node representation, vis {@link pv.Dom.Node}.)
-149 *
-150 * @see pv.Layout.Network
-151 * @name pv.Layout.Network.Node
-152 */
-153
-154/**
-155 * The node index, zero-based. This attribute is populated automatically based
-156 * on the index in the array returned by the <tt>nodes</tt> property.
-157 *
-158 * @type number
-159 * @name pv.Layout.Network.Node.prototype.index
-160 */
-161
-162/**
-163 * The link degree; the sum of link values for all incoming and outgoing links.
-164 * This attribute is populated automatically.
-165 *
-166 * @type number
-167 * @name pv.Layout.Network.Node.prototype.linkDegree
-168 */
-169
-170/**
-171 * The node name; optional. If present, this attribute will be used to provide
-172 * the text for node labels. If not present, the label text will fallback to the
-173 * <tt>nodeValue</tt> attribute.
-174 *
-175 * @type string
-176 * @name pv.Layout.Network.Node.prototype.nodeName
-177 */
-178
-179/**
-180 * The node value; optional. If present, and no <tt>nodeName</tt> attribute is
-181 * present, the node value will be used as the label text. This attribute is
-182 * also automatically populated if the nodes are specified as an array of
-183 * primitives, such as strings or numbers.
-184 *
-185 * @type object
-186 * @name pv.Layout.Network.Node.prototype.nodeValue
-187 */
-188
-189/**
-190 * @class Represents a link in a network layout. There is no explicit
-191 * constructor; this class merely serves to document the attributes that are
-192 * used on links in network layouts. For hierarchical layouts, this class is
-193 * used to represent the parent-child links.
-194 *
-195 * @see pv.Layout.Network
-196 * @name pv.Layout.Network.Link
-197 */
-198
-199/**
-200 * The link value, or weight; optional. If not specified (or not a number), the
-201 * default value of 1 is used.
-202 *
-203 * @type number
-204 * @name pv.Layout.Network.Link.prototype.linkValue
-205 */
-206
-207/**
-208 * The link's source node. If not set, this value will be derived from the
-209 * <tt>source</tt> attribute index.
-210 *
-211 * @type pv.Layout.Network.Node
-212 * @name pv.Layout.Network.Link.prototype.sourceNode
-213 */
-214
-215/**
-216 * The link's target node. If not set, this value will be derived from the
-217 * <tt>target</tt> attribute index.
-218 *
-219 * @type pv.Layout.Network.Node
-220 * @name pv.Layout.Network.Link.prototype.targetNode
-221 */
-222
-223/**
-224 * Alias for <tt>sourceNode</tt>, as expressed by the index of the source node.
-225 * This attribute is not populated automatically, but may be used as a more
-226 * convenient identification of the link's source, for example in a static JSON
-227 * representation.
-228 *
-229 * @type number
-230 * @name pv.Layout.Network.Link.prototype.source
-231 */
-232
-233/**
-234 * Alias for <tt>targetNode</tt>, as expressed by the index of the target node.
-235 * This attribute is not populated automatically, but may be used as a more
-236 * convenient identification of the link's target, for example in a static JSON
-237 * representation.
-238 *
-239 * @type number
-240 * @name pv.Layout.Network.Link.prototype.target
-241 */
-242
-243/**
-244 * Alias for <tt>linkValue</tt>. This attribute is not populated automatically,
-245 * but may be used instead of the <tt>linkValue</tt> attribute when specifying
-246 * links.
-247 *
-248 * @type number
-249 * @name pv.Layout.Network.Link.prototype.value
-250 */
-251
-252/** @private Transform nodes and links on cast. */
-253pv.Layout.Network.prototype=pv.extend(pv.Layout)
-254.property("nodes",function(v){
-255returnv.map(function(d,i){
-256if(typeofd!="object")d={nodeValue:d};
-257d.index=i;
-258d.linkDegree=0;
-259returnd;
-260});
-261})
-262.property("links",function(v){
-263returnv.map(function(d){
-264if(isNaN(d.linkValue))d.linkValue=isNaN(d.value)?1:d.value;
-265returnd;
-266});
-267});
-268
-269/**
-270 * Resets the cache, such that changes to layout property definitions will be
-271 * visible on subsequent render. Unlike normal marks (and normal layouts),
-272 * properties associated with network layouts are not automatically re-evaluated
-273 * on render; the properties are cached, and any expensive layout algorithms are
-274 * only run after the layout is explicitly reset.
-275 *
-276 * @returns {pv.Layout.Network} this.
-277 */
-278pv.Layout.Network.prototype.reset=function(){
-279this.$id=pv.id();
-280returnthis;
-281};
-282
-283/** @private Skip evaluating properties if cached. */
-284pv.Layout.Network.prototype.buildProperties=function(s,properties){
-285if((s.$id||0)<this.$id){
-286pv.Layout.prototype.buildProperties.call(this,s,properties);
-287}
-288};
-289
-290/** @private Compute link degrees; map source and target indexes to nodes. */
-291pv.Layout.Network.prototype.buildImplied=function(s){
-292pv.Layout.prototype.buildImplied.call(this,s);
-293if(s.$id>=this.$id)returntrue;
-294s.$id=this.$id;
-295s.links.forEach(function(d){
-296varv=d.linkValue;
-297(d.sourceNode||(d.sourceNode=s.nodes[d.source])).linkDegree+=v;
-298(d.targetNode||(d.targetNode=s.nodes[d.target])).linkDegree+=v;
-299});
-300};
-301
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Pack.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Pack.js.html
deleted file mode 100644
index af21a318..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Pack.js.html
+++ /dev/null
@@ -1,331 +0,0 @@
-
1/**
- 2 * Constructs a new, empty circle-packing layout. Layouts are not typically
- 3 * constructed directly; instead, they are added to an existing panel via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Implements a hierarchical layout using circle-packing. The meaning of
- 7 * the exported mark prototypes changes slightly in the space-filling
- 8 * implementation:<ul>
- 9 *
- 10 * <li><tt>node</tt> - for rendering nodes; typically a {@link pv.Dot}.
- 11 *
- 12 * <p><li><tt>link</tt> - unsupported; undefined. Links are encoded implicitly
- 13 * in the arrangement of the space-filling nodes.
- 14 *
- 15 * <p><li><tt>label</tt> - for rendering node labels; typically a
- 16 * {@link pv.Label}.
- 17 *
- 18 * </ul>The pack layout support dynamic sizing for leaf nodes, if a
- 19 * {@link #size} psuedo-property is specified. The default size function returns
- 20 * 1, causing all leaf nodes to be sized equally, and all internal nodes to be
- 21 * sized by the number of leaf nodes they have as descendants.
- 22 *
- 23 * <p>The size function can be used in conjunction with the order property,
- 24 * which allows the nodes to the sorted by the computed size. Note: for sorting
- 25 * based on other data attributes, simply use the default <tt>null</tt> for the
- 26 * order property, and sort the nodes beforehand using the {@link pv.Dom}
- 27 * operator.
- 28 *
- 29 * <p>For more details on how to use this layout, see
- 30 * {@link pv.Layout.Hierarchy}.
- 31 *
- 32 * @extends pv.Layout.Hierarchy
- 33 * @see <a href="http://portal.acm.org/citation.cfm?id=1124772.1124851"
- 34 * >"Visualization of large hierarchical data by circle packing"</a> by W. Wang,
- 35 * H. Wang, G. Dai, and H. Wang, ACM CHI 2006.
- 36 */
- 37pv.Layout.Pack=function(){
- 38pv.Layout.Hierarchy.call(this);
- 39
- 40this.node
- 41.radius(function(n){returnn.radius;})
- 42.strokeStyle("rgb(31, 119, 180)")
- 43.fillStyle("rgba(31, 119, 180, .25)");
- 44
- 45this.label
- 46.textAlign("center");
- 47
- 48/* Hide unsupported link. */
- 49deletethis.link;
- 50};
- 51
- 52pv.Layout.Pack.prototype=pv.extend(pv.Layout.Hierarchy)
- 53.property("spacing",Number)
- 54.property("order",String);// ascending, descending, reverse, null
- 55
- 56/**
- 57 * Default properties for circle-packing layouts. The default spacing parameter
- 58 * is 1 and the default order is "ascending".
- 59 *
- 60 * @type pv.Layout.Pack
- 61 */
- 62pv.Layout.Pack.prototype.defaults=newpv.Layout.Pack()
- 63.extend(pv.Layout.Hierarchy.prototype.defaults)
- 64.spacing(1)
- 65.order("ascending");
- 66
- 67/**
- 68 * The spacing parameter; defaults to 1, which provides a little bit of padding
- 69 * between sibling nodes and the enclosing circle. Larger values increase the
- 70 * spacing, by making the sibling nodes smaller; a value of zero makes the leaf
- 71 * nodes as large as possible, with no padding on enclosing circles.
- 72 *
- 73 * @type number
- 74 * @name pv.Layout.Pack.prototype.spacing
- 75 */
- 76
- 77/**
- 78 * The sibling node order. The default order is <tt>null</tt>, which means to
- 79 * use the sibling order specified by the nodes property as-is. A value of
- 80 * "ascending" will sort siblings in ascending order of size, while "descending"
- 81 * will do the reverse. For sorting based on data attributes other than size,
- 82 * use the default <tt>null</tt> for the order property, and sort the nodes
- 83 * beforehand using the {@link pv.Dom} operator.
- 84 *
- 85 * @see pv.Dom.Node#sort
- 86 * @type string
- 87 * @name pv.Layout.Pack.prototype.order
- 88 */
- 89
- 90/** @private The default size function. */
- 91pv.Layout.Pack.prototype.$radius=function(){return1;};
- 92
- 93// TODO is it possible for spacing to operate in pixel space?
- 94// Right now it appears to be multiples of the smallest radius.
- 95
- 96/**
- 97 * Specifies the sizing function. By default, a sizing function is disabled and
- 98 * all nodes are given constant size. The sizing function is invoked for each
- 99 * leaf node in the tree (passed to the constructor).
-100 *
-101 * <p>For example, if the tree data structure represents a file system, with
-102 * files as leaf nodes, and each file has a <tt>bytes</tt> attribute, you can
-103 * specify a size function as:
-104 *
-105 * <pre> .size(function(d) d.bytes)</pre>
-106 *
-107 * As with other properties, a size function may specify additional arguments to
-108 * access the data associated with the layout and any enclosing panels.
-109 *
-110 * @param {function} f the new sizing function.
-111 * @returns {pv.Layout.Pack} this.
-112 */
-113pv.Layout.Pack.prototype.size=function(f){
-114this.$radius=typeoff=="function"
-115?function(){returnMath.sqrt(f.apply(this,arguments));}
-116:(f=Math.sqrt(f),function(){returnf;});
-117returnthis;
-118};
-119
-120/** @private */
-121pv.Layout.Pack.prototype.buildImplied=function(s){
-122if(pv.Layout.Hierarchy.prototype.buildImplied.call(this,s))return;
-123
-124varthat=this,
-125nodes=s.nodes,
-126root=nodes[0];
-127
-128/** @private Compute the radii of the leaf nodes. */
-129functionradii(nodes){
-130varstack=pv.Mark.stack;
-131stack.unshift(null);
-132for(vari=0,n=nodes.length;i<n;i++){
-133varc=nodes[i];
-134if(!c.firstChild){
-135c.radius=that.$radius.apply(that,(stack[0]=c,stack));
-136}
-137}
-138stack.shift();
-139}
-140
-141/** @private */
-142functionpackTree(n){
-143varnodes=[];
-144for(varc=n.firstChild;c;c=c.nextSibling){
-145if(c.firstChild)c.radius=packTree(c);
-146c.n=c.p=c;
-147nodes.push(c);
-148}
-149
-150/* Sort. */
-151switch(s.order){
-152case"ascending":{
-153nodes.sort(function(a,b){returna.radius-b.radius;});
-154break;
-155}
-156case"descending":{
-157nodes.sort(function(a,b){returnb.radius-a.radius;});
-158break;
-159}
-160case"reverse":nodes.reverse();break;
-161}
-162
-163returnpackCircle(nodes);
-164}
-165
-166/** @private */
-167functionpackCircle(nodes){
-168varxMin=Infinity,
-169xMax=-Infinity,
-170yMin=Infinity,
-171yMax=-Infinity,
-172a,b,c,j,k;
-173
-174/** @private */
-175functionbound(n){
-176xMin=Math.min(n.x-n.radius,xMin);
-177xMax=Math.max(n.x+n.radius,xMax);
-178yMin=Math.min(n.y-n.radius,yMin);
-179yMax=Math.max(n.y+n.radius,yMax);
-180}
-181
-182/** @private */
-183functioninsert(a,b){
-184varc=a.n;
-185a.n=b;
-186b.p=a;
-187b.n=c;
-188c.p=b;
-189}
-190
-191/** @private */
-192functionsplice(a,b){
-193a.n=b;
-194b.p=a;
-195}
-196
-197/** @private */
-198functionintersects(a,b){
-199vardx=b.x-a.x,
-200dy=b.y-a.y,
-201dr=a.radius+b.radius;
-202return(dr*dr-dx*dx-dy*dy)>.001;// within epsilon
-203}
-204
-205/* Create first node. */
-206a=nodes[0];
-207a.x=-a.radius;
-208a.y=0;
-209bound(a);
-210
-211/* Create second node. */
-212if(nodes.length>1){
-213b=nodes[1];
-214b.x=b.radius;
-215b.y=0;
-216bound(b);
-217
-218/* Create third node and build chain. */
-219if(nodes.length>2){
-220c=nodes[2];
-221place(a,b,c);
-222bound(c);
-223insert(a,c);
-224a.p=c;
-225insert(c,b);
-226b=a.n;
-227
-228/* Now iterate through the rest. */
-229for(vari=3;i<nodes.length;i++){
-230place(a,b,c=nodes[i]);
-231
-232/* Search for the closest intersection. */
-233varisect=0,s1=1,s2=1;
-234for(j=b.n;j!=b;j=j.n,s1++){
-235if(intersects(j,c)){
-236isect=1;
-237break;
-238}
-239}
-240if(isect==1){
-241for(k=a.p;k!=j.p;k=k.p,s2++){
-242if(intersects(k,c)){
-243if(s2<s1){
-244isect=-1;
-245j=k;
-246}
-247break;
-248}
-249}
-250}
-251
-252/* Update node chain. */
-253if(isect==0){
-254insert(a,c);
-255b=c;
-256bound(c);
-257}elseif(isect>0){
-258splice(a,j);
-259b=j;
-260i--;
-261}elseif(isect<0){
-262splice(j,b);
-263a=j;
-264i--;
-265}
-266}
-267}
-268}
-269
-270/* Re-center the circles and return the encompassing radius. */
-271varcx=(xMin+xMax)/2,
-272cy=(yMin+yMax)/2,
-273cr=0;
-274for(vari=0;i<nodes.length;i++){
-275varn=nodes[i];
-276n.x-=cx;
-277n.y-=cy;
-278cr=Math.max(cr,n.radius+Math.sqrt(n.x*n.x+n.y*n.y));
-279}
-280returncr+s.spacing;
-281}
-282
-283/** @private */
-284functionplace(a,b,c){
-285varda=b.radius+c.radius,
-286db=a.radius+c.radius,
-287dx=b.x-a.x,
-288dy=b.y-a.y,
-289dc=Math.sqrt(dx*dx+dy*dy),
-290cos=(db*db+dc*dc-da*da)/(2*db*dc),
-291theta=Math.acos(cos),
-292x=cos*db,
-293h=Math.sin(theta)*db;
-294dx/=dc;
-295dy/=dc;
-296c.x=a.x+x*dx+h*dy;
-297c.y=a.y+x*dy-h*dx;
-298}
-299
-300/** @private */
-301functiontransform(n,x,y,k){
-302for(varc=n.firstChild;c;c=c.nextSibling){
-303c.x+=n.x;
-304c.y+=n.y;
-305transform(c,x,y,k);
-306}
-307n.x=x+k*n.x;
-308n.y=y+k*n.y;
-309n.radius*=k;
-310}
-311
-312radii(nodes);
-313
-314/* Recursively compute the layout. */
-315root.x=0;
-316root.y=0;
-317root.radius=packTree(root);
-318
-319varw=this.width(),
-320h=this.height(),
-321k=1/Math.max(2*root.radius/w,2*root.radius/h);
-322transform(root,w/2,h/2,k);
-323};
-324
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Partition.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Partition.js.html
deleted file mode 100644
index 5b41067c..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Partition.js.html
+++ /dev/null
@@ -1,211 +0,0 @@
-
1/**
- 2 * Constructs a new, empty partition layout. Layouts are not typically
- 3 * constructed directly; instead, they are added to an existing panel via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Implemeents a hierarchical layout using the partition (or sunburst,
- 7 * icicle) algorithm. This layout provides both node-link and space-filling
- 8 * implementations of partition diagrams. In many ways it is similar to
- 9 * {@link pv.Layout.Cluster}, except that leaf nodes are positioned based on
- 10 * their distance from the root.
- 11 *
- 12 * <p>The partition layout support dynamic sizing for leaf nodes, if a
- 13 * {@link #size} psuedo-property is specified. The default size function returns
- 14 * 1, causing all leaf nodes to be sized equally, and all internal nodes to be
- 15 * sized by the number of leaf nodes they have as descendants.
- 16 *
- 17 * <p>The size function can be used in conjunction with the order property,
- 18 * which allows the nodes to the sorted by the computed size. Note: for sorting
- 19 * based on other data attributes, simply use the default <tt>null</tt> for the
- 20 * order property, and sort the nodes beforehand using the {@link pv.Dom}
- 21 * operator.
- 22 *
- 23 * <p>For more details on how to use this layout, see
- 24 * {@link pv.Layout.Hierarchy}.
- 25 *
- 26 * @see pv.Layout.Partition.Fill
- 27 * @extends pv.Layout.Hierarchy
- 28 */
- 29pv.Layout.Partition=function(){
- 30pv.Layout.Hierarchy.call(this);
- 31};
- 32
- 33pv.Layout.Partition.prototype=pv.extend(pv.Layout.Hierarchy)
- 34.property("order",String)// null, ascending, descending?
- 35.property("orient",String)// top, left, right, bottom, radial
- 36.property("innerRadius",Number)
- 37.property("outerRadius",Number);
- 38
- 39/**
- 40 * The sibling node order. The default order is <tt>null</tt>, which means to
- 41 * use the sibling order specified by the nodes property as-is. A value of
- 42 * "ascending" will sort siblings in ascending order of size, while "descending"
- 43 * will do the reverse. For sorting based on data attributes other than size,
- 44 * use the default <tt>null</tt> for the order property, and sort the nodes
- 45 * beforehand using the {@link pv.Dom} operator.
- 46 *
- 47 * @see pv.Dom.Node#sort
- 48 * @type string
- 49 * @name pv.Layout.Partition.prototype.order
- 50 */
- 51
- 52/**
- 53 * The orientation. The default orientation is "top", which means that the root
- 54 * node is placed on the top edge, leaf nodes appear at the bottom, and internal
- 55 * nodes are in-between. The following orientations are supported:<ul>
- 56 *
- 57 * <li>left - left-to-right.
- 58 * <li>right - right-to-left.
- 59 * <li>top - top-to-bottom.
- 60 * <li>bottom - bottom-to-top.
- 61 * <li>radial - radially, with the root at the center.</ul>
- 62 *
- 63 * @type string
- 64 * @name pv.Layout.Partition.prototype.orient
- 65 */
- 66
- 67/**
- 68 * The inner radius; defaults to 0. This property applies only to radial
- 69 * orientations, and can be used to compress the layout radially. Note that for
- 70 * the node-link implementation, the root node is always at the center,
- 71 * regardless of the value of this property; this property only affects internal
- 72 * and leaf nodes. For the space-filling implementation, a non-zero value of
- 73 * this property will result in the root node represented as a ring rather than
- 74 * a circle.
- 75 *
- 76 * @type number
- 77 * @name pv.Layout.Partition.prototype.innerRadius
- 78 */
- 79
- 80/**
- 81 * The outer radius; defaults to fill the containing panel, based on the height
- 82 * and width of the layout. If the layout has no height and width specified, it
- 83 * will extend to fill the enclosing panel.
- 84 *
- 85 * @type number
- 86 * @name pv.Layout.Partition.prototype.outerRadius
- 87 */
- 88
- 89/**
- 90 * Default properties for partition layouts. The default orientation is "top".
- 91 *
- 92 * @type pv.Layout.Partition
- 93 */
- 94pv.Layout.Partition.prototype.defaults=newpv.Layout.Partition()
- 95.extend(pv.Layout.Hierarchy.prototype.defaults)
- 96.orient("top");
- 97
- 98/** @private */
- 99pv.Layout.Partition.prototype.$size=function(){return1;};
-100
-101/**
-102 * Specifies the sizing function. By default, a sizing function is disabled and
-103 * all nodes are given constant size. The sizing function is invoked for each
-104 * leaf node in the tree (passed to the constructor).
-105 *
-106 * <p>For example, if the tree data structure represents a file system, with
-107 * files as leaf nodes, and each file has a <tt>bytes</tt> attribute, you can
-108 * specify a size function as:
-109 *
-110 * <pre> .size(function(d) d.bytes)</pre>
-111 *
-112 * As with other properties, a size function may specify additional arguments to
-113 * access the data associated with the layout and any enclosing panels.
-114 *
-115 * @param {function} f the new sizing function.
-116 * @returns {pv.Layout.Partition} this.
-117 */
-118pv.Layout.Partition.prototype.size=function(f){
-119this.$size=f;
-120returnthis;
-121};
-122
-123/** @private */
-124pv.Layout.Partition.prototype.buildImplied=function(s){
-125if(pv.Layout.Hierarchy.prototype.buildImplied.call(this,s))return;
-126
-127varthat=this,
-128root=s.nodes[0],
-129stack=pv.Mark.stack,
-130maxDepth=0;
-131
-132/* Recursively compute the tree depth and node size. */
-133stack.unshift(null);
-134root.visitAfter(function(n,i){
-135if(i>maxDepth)maxDepth=i;
-136n.size=n.firstChild
-137?pv.sum(n.childNodes,function(n){returnn.size;})
-138:that.$size.apply(that,(stack[0]=n,stack));
-139});
-140stack.shift();
-141
-142/* Order */
-143switch(s.order){
-144case"ascending":root.sort(function(a,b){returna.size-b.size;});break;
-145case"descending":root.sort(function(b,a){returna.size-b.size;});break;
-146}
-147
-148/* Compute the unit breadth and depth of each node. */
-149vards=1/maxDepth;
-150root.minBreadth=0;
-151root.breadth=.5;
-152root.maxBreadth=1;
-153root.visitBefore(function(n){
-154varb=n.minBreadth,s=n.maxBreadth-b;
-155for(varc=n.firstChild;c;c=c.nextSibling){
-156c.minBreadth=b;
-157c.maxBreadth=b+=(c.size/n.size)*s;
-158c.breadth=(b+c.minBreadth)/2;
-159}
-160});
-161root.visitAfter(function(n,i){
-162n.minDepth=(i-1)*ds;
-163n.maxDepth=n.depth=i*ds;
-164});
-165
-166pv.Layout.Hierarchy.NodeLink.buildImplied.call(this,s);
-167};
-168
-169/**
-170 * Constructs a new, empty space-filling partition layout. Layouts are not
-171 * typically constructed directly; instead, they are added to an existing panel
-172 * via {@link pv.Mark#add}.
-173 *
-174 * @class A variant of partition layout that is space-filling. The meaning of
-175 * the exported mark prototypes changes slightly in the space-filling
-176 * implementation:<ul>
-177 *
-178 * <li><tt>node</tt> - for rendering nodes; typically a {@link pv.Bar} for
-179 * non-radial orientations, and a {@link pv.Wedge} for radial orientations.
-180 *
-181 * <p><li><tt>link</tt> - unsupported; undefined. Links are encoded implicitly
-182 * in the arrangement of the space-filling nodes.
-183 *
-184 * <p><li><tt>label</tt> - for rendering node labels; typically a
-185 * {@link pv.Label}.
-186 *
-187 * </ul>For more details on how to use this layout, see
-188 * {@link pv.Layout.Partition}.
-189 *
-190 * @extends pv.Layout.Partition
-191 */
-192pv.Layout.Partition.Fill=function(){
-193pv.Layout.Partition.call(this);
-194pv.Layout.Hierarchy.Fill.constructor.call(this);
-195};
-196
-197pv.Layout.Partition.Fill.prototype=pv.extend(pv.Layout.Partition);
-198
-199/** @private */
-200pv.Layout.Partition.Fill.prototype.buildImplied=function(s){
-201if(pv.Layout.Partition.prototype.buildImplied.call(this,s))return;
-202pv.Layout.Hierarchy.Fill.buildImplied.call(this,s);
-203};
-204
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Rollup.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Rollup.js.html
deleted file mode 100644
index 0b602fed..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Rollup.js.html
+++ /dev/null
@@ -1,211 +0,0 @@
-
1/**
- 2 * Constructs a new, empty rollup network layout. Layouts are not typically
- 3 * constructed directly; instead, they are added to an existing panel via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Implements a network visualization using a node-link diagram where
- 7 * nodes are rolled up along two dimensions. This implementation is based on the
- 8 * "PivotGraph" designed by Martin Wattenberg:
- 9 *
- 10 * <blockquote>The method is designed for graphs that are "multivariate", i.e.,
- 11 * where each node is associated with several attributes. Unlike visualizations
- 12 * which emphasize global graph topology, PivotGraph uses a simple grid-based
- 13 * approach to focus on the relationship between node attributes &
- 14 * connections.</blockquote>
- 15 *
- 16 * This layout requires two psuedo-properties to be specified, which assign node
- 17 * positions along the two dimensions {@link #x} and {@link #y}, corresponding
- 18 * to the left and top properties, respectively. Typically, these functions are
- 19 * specified using an {@link pv.Scale.ordinal}. Nodes that share the same
- 20 * position in <i>x</i> and <i>y</i> are "rolled up" into a meta-node, and
- 21 * similarly links are aggregated between meta-nodes. For example, to construct
- 22 * a rollup to analyze links by gender and affiliation, first define two ordinal
- 23 * scales:
- 24 *
- 25 * <pre>var x = pv.Scale.ordinal(nodes, function(d) d.gender).split(0, w),
- 26 * y = pv.Scale.ordinal(nodes, function(d) d.aff).split(0, h);</pre>
- 27 *
- 28 * Next, define the position psuedo-properties:
- 29 *
- 30 * <pre> .x(function(d) x(d.gender))
- 31 * .y(function(d) y(d.aff))</pre>
- 32 *
- 33 * Linear and other quantitative scales can alternatively be used to position
- 34 * the nodes along either dimension. Note, however, that the rollup requires
- 35 * that the positions match exactly, and thus ordinal scales are recommended to
- 36 * avoid precision errors.
- 37 *
- 38 * <p>Note that because this layout provides a visualization of the rolled up
- 39 * graph, the data properties for the mark prototypes (<tt>node</tt>,
- 40 * <tt>link</tt> and <tt>label</tt>) are different from most other network
- 41 * layouts: they reference the rolled-up nodes and links, rather than the nodes
- 42 * and links of the full network. The underlying nodes and links for each
- 43 * rolled-up node and link can be accessed via the <tt>nodes</tt> and
- 44 * <tt>links</tt> attributes, respectively. The aggregated link values for
- 45 * rolled-up links can similarly be accessed via the <tt>linkValue</tt>
- 46 * attribute.
- 47 *
- 48 * <p>For undirected networks, links are duplicated in both directions. For
- 49 * directed networks, use <tt>directed(true)</tt>. The graph is assumed to be
- 50 * undirected by default.
- 51 *
- 52 * @extends pv.Layout.Network
- 53 * @see <a href="http://www.research.ibm.com/visual/papers/pivotgraph.pdf"
- 54 * >"Visual Exploration of Multivariate Graphs"</a> by M. Wattenberg, CHI 2006.
- 55 */
- 56pv.Layout.Rollup=function(){
- 57pv.Layout.Network.call(this);
- 58varthat=this,
- 59nodes,// cached rollup nodes
- 60links,// cached rollup links
- 61buildImplied=that.buildImplied;
- 62
- 63/** @private Cache layout state to optimize properties. */
- 64this.buildImplied=function(s){
- 65buildImplied.call(this,s);
- 66nodes=s.$rollup.nodes;
- 67links=s.$rollup.links;
- 68};
- 69
- 70/* Render rollup nodes. */
- 71this.node
- 72.data(function(){returnnodes;})
- 73.size(function(d){returnd.nodes.length*20;});
- 74
- 75/* Render rollup links. */
- 76this.link
- 77.interpolate("polar")
- 78.eccentricity(.8);
- 79
- 80this.link.add=function(type){
- 81returnthat.add(pv.Panel)
- 82.data(function(){returnlinks;})
- 83.add(type)
- 84.extend(this);
- 85};
- 86};
- 87
- 88pv.Layout.Rollup.prototype=pv.extend(pv.Layout.Network)
- 89.property("directed",Boolean);
- 90
- 91/**
- 92 * Whether the underlying network is directed. By default, the graph is assumed
- 93 * to be undirected, and links are rendered in both directions. If the network
- 94 * is directed, then forward links are drawn above the diagonal, while reverse
- 95 * links are drawn below.
- 96 *
- 97 * @type boolean
- 98 * @name pv.Layout.Rollup.prototype.directed
- 99 */
-100
-101/**
-102 * Specifies the <i>x</i>-position function used to rollup nodes. The rolled up
-103 * nodes are positioned horizontally using the return values from the given
-104 * function. Typically the function is specified as an ordinal scale. For
-105 * single-dimension rollups, a constant value can be specified.
-106 *
-107 * @param {function} f the <i>x</i>-position function.
-108 * @returns {pv.Layout.Rollup} this.
-109 * @see pv.Scale.ordinal
-110 */
-111pv.Layout.Rollup.prototype.x=function(f){
-112this.$x=pv.functor(f);
-113returnthis;
-114};
-115
-116/**
-117 * Specifies the <i>y</i>-position function used to rollup nodes. The rolled up
-118 * nodes are positioned vertically using the return values from the given
-119 * function. Typically the function is specified as an ordinal scale. For
-120 * single-dimension rollups, a constant value can be specified.
-121 *
-122 * @param {function} f the <i>y</i>-position function.
-123 * @returns {pv.Layout.Rollup} this.
-124 * @see pv.Scale.ordinal
-125 */
-126pv.Layout.Rollup.prototype.y=function(f){
-127this.$y=pv.functor(f);
-128returnthis;
-129};
-130
-131/** @private */
-132pv.Layout.Rollup.prototype.buildImplied=function(s){
-133if(pv.Layout.Network.prototype.buildImplied.call(this,s))return;
-134
-135varnodes=s.nodes,
-136links=s.links,
-137directed=s.directed,
-138n=nodes.length,
-139x=[],
-140y=[],
-141rnindex=0,
-142rnodes={},
-143rlinks={};
-144
-145/** @private */
-146functionid(i){
-147returnx[i]+","+y[i];
-148}
-149
-150/* Iterate over the data, evaluating the x and y functions. */
-151varstack=pv.Mark.stack,o={parent:this};
-152stack.unshift(null);
-153for(vari=0;i<n;i++){
-154o.index=i;
-155stack[0]=nodes[i];
-156x[i]=this.$x.apply(o,stack);
-157y[i]=this.$y.apply(o,stack);
-158}
-159stack.shift();
-160
-161/* Compute rollup nodes. */
-162for(vari=0;i<nodes.length;i++){
-163varnodeId=id(i),
-164rn=rnodes[nodeId];
-165if(!rn){
-166rn=rnodes[nodeId]=pv.extend(nodes[i]);
-167rn.index=rnindex++;
-168rn.x=x[i];
-169rn.y=y[i];
-170rn.nodes=[];
-171}
-172rn.nodes.push(nodes[i]);
-173}
-174
-175/* Compute rollup links. */
-176for(vari=0;i<links.length;i++){
-177varsource=links[i].sourceNode,
-178target=links[i].targetNode,
-179rsource=rnodes[id(source.index)],
-180rtarget=rnodes[id(target.index)],
-181reverse=!directed&&rsource.index>rtarget.index,
-182linkId=reverse
-183?rtarget.index+","+rsource.index
-184:rsource.index+","+rtarget.index,
-185rl=rlinks[linkId];
-186if(!rl){
-187rl=rlinks[linkId]={
-188sourceNode:rsource,
-189targetNode:rtarget,
-190linkValue:0,
-191links:[]
-192};
-193}
-194rl.links.push(links[i]);
-195rl.linkValue+=links[i].linkValue;
-196}
-197
-198/* Export the rolled up nodes and links to the scene. */
-199s.$rollup={
-200nodes:pv.values(rnodes),
-201links:pv.values(rlinks)
-202};
-203};
-204
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Stack.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Stack.js.html
deleted file mode 100644
index 70d20eb5..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Stack.js.html
+++ /dev/null
@@ -1,399 +0,0 @@
-
1/**
- 2 * Constructs a new, empty stack layout. Layouts are not typically constructed
- 3 * directly; instead, they are added to an existing panel via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Implements a layout for stacked visualizations, ranging from simple
- 7 * stacked bar charts to more elaborate "streamgraphs" composed of stacked
- 8 * areas. Stack layouts uses length as a visual encoding, as opposed to
- 9 * position, as the layers do not share an aligned axis.
- 10 *
- 11 * <p>Marks can be stacked vertically or horizontally. For example,
- 12 *
- 13 * <pre>vis.add(pv.Layout.Stack)
- 14 * .layers([[1, 1.2, 1.7, 1.5, 1.7],
- 15 * [.5, 1, .8, 1.1, 1.3],
- 16 * [.2, .5, .8, .9, 1]])
- 17 * .x(function() this.index * 35)
- 18 * .y(function(d) d * 40)
- 19 * .layer.add(pv.Area);</pre>
- 20 *
- 21 * specifies a vertically-stacked area chart, using the default "bottom-left"
- 22 * orientation with "zero" offset. This visualization can be easily changed into
- 23 * a streamgraph using the "wiggle" offset, which attempts to minimize change in
- 24 * slope weighted by layer thickness. See the {@link #offset} property for more
- 25 * supported streamgraph algorithms.
- 26 *
- 27 * <p>In the simplest case, the layer data can be specified as a two-dimensional
- 28 * array of numbers. The <tt>x</tt> and <tt>y</tt> psuedo-properties are used to
- 29 * define the thickness of each layer at the given position, respectively; in
- 30 * the above example of the "bottom-left" orientation, the <tt>x</tt> and
- 31 * <tt>y</tt> psuedo-properties are equivalent to the <tt>left</tt> and
- 32 * <tt>height</tt> properties that you might use if you implemented a stacked
- 33 * area by hand.
- 34 *
- 35 * <p>The advantage of using the stack layout is that the baseline, i.e., the
- 36 * <tt>bottom</tt> property is computed automatically using the specified offset
- 37 * algorithm. In addition, the order of layers can be computed using a built-in
- 38 * algorithm via the <tt>order</tt> property.
- 39 *
- 40 * <p>With the exception of the "expand" <tt>offset</tt>, the stack layout does
- 41 * not perform any automatic scaling of data; the values returned from
- 42 * <tt>x</tt> and <tt>y</tt> specify pixel sizes. To simplify scaling math, use
- 43 * this layout in conjunction with {@link pv.Scale.linear} or similar.
- 44 *
- 45 * <p>In other cases, the <tt>values</tt> psuedo-property can be used to define
- 46 * the data more flexibly. As with a typical panel & area, the
- 47 * <tt>layers</tt> property corresponds to the data in the enclosing panel,
- 48 * while the <tt>values</tt> psuedo-property corresponds to the data for the
- 49 * area within the panel. For example, given an array of data values:
- 50 *
- 51 * <pre>var crimea = [
- 52 * { date: "4/1854", wounds: 0, other: 110, disease: 110 },
- 53 * { date: "5/1854", wounds: 0, other: 95, disease: 105 },
- 54 * { date: "6/1854", wounds: 0, other: 40, disease: 95 },
- 55 * ...</pre>
- 56 *
- 57 * and a corresponding array of series names:
- 58 *
- 59 * <pre>var causes = ["wounds", "other", "disease"];</pre>
- 60 *
- 61 * Separate layers can be defined for each cause like so:
- 62 *
- 63 * <pre>vis.add(pv.Layout.Stack)
- 64 * .layers(causes)
- 65 * .values(crimea)
- 66 * .x(function(d) x(d.date))
- 67 * .y(function(d, p) y(d[p]))
- 68 * .layer.add(pv.Area)
- 69 * ...</pre>
- 70 *
- 71 * As with the panel & area case, the datum that is passed to the
- 72 * psuedo-properties <tt>x</tt> and <tt>y</tt> are the values (an element in
- 73 * <tt>crimea</tt>); the second argument is the layer data (a string in
- 74 * <tt>causes</tt>). Additional arguments specify the data of enclosing panels,
- 75 * if any.
- 76 *
- 77 * @extends pv.Layout
- 78 */
- 79pv.Layout.Stack=function(){
- 80pv.Layout.call(this);
- 81varthat=this,
- 82/** @ignore */none=function(){returnnull;},
- 83prop={t:none,l:none,r:none,b:none,w:none,h:none},
- 84values,
- 85buildImplied=that.buildImplied;
- 86
- 87/** @private Proxy the given property on the layer. */
- 88functionproxy(name){
- 89returnfunction(){
- 90returnprop[name](this.parent.index,this.index);
- 91};
- 92}
- 93
- 94/** @private Compute the layout! */
- 95this.buildImplied=function(s){
- 96buildImplied.call(this,s);
- 97
- 98vardata=s.layers,
- 99n=data.length,
-100m,
-101orient=s.orient,
-102horizontal=/^(top|bottom)\b/.test(orient),
-103h=this.parent[horizontal?"height":"width"](),
-104x=[],
-105y=[],
-106dy=[];
-107
-108/*
-109 * Iterate over the data, evaluating the values, x and y functions. The
-110 * context in which the x and y psuedo-properties are evaluated is a
-111 * pseudo-mark that is a grandchild of this layout.
-112 */
-113varstack=pv.Mark.stack,o={parent:{parent:this}};
-114stack.unshift(null);
-115values=[];
-116for(vari=0;i<n;i++){
-117dy[i]=[];
-118y[i]=[];
-119o.parent.index=i;
-120stack[0]=data[i];
-121values[i]=this.$values.apply(o.parent,stack);
-122if(!i)m=values[i].length;
-123stack.unshift(null);
-124for(varj=0;j<m;j++){
-125stack[0]=values[i][j];
-126o.index=j;
-127if(!i)x[j]=this.$x.apply(o,stack);
-128dy[i][j]=this.$y.apply(o,stack);
-129}
-130stack.shift();
-131}
-132stack.shift();
-133
-134/* order */
-135varindex;
-136switch(s.order){
-137case"inside-out":{
-138varmax=dy.map(function(v){returnpv.max.index(v);}),
-139map=pv.range(n).sort(function(a,b){returnmax[a]-max[b];}),
-140sums=dy.map(function(v){returnpv.sum(v);}),
-141top=0,
-142bottom=0,
-143tops=[],
-144bottoms=[];
-145for(vari=0;i<n;i++){
-146varj=map[i];
-147if(top<bottom){
-148top+=sums[j];
-149tops.push(j);
-150}else{
-151bottom+=sums[j];
-152bottoms.push(j);
-153}
-154}
-155index=bottoms.reverse().concat(tops);
-156break;
-157}
-158case"reverse":index=pv.range(n-1,-1,-1);break;
-159default:index=pv.range(n);break;
-160}
-161
-162/* offset */
-163switch(s.offset){
-164case"silohouette":{
-165for(varj=0;j<m;j++){
-166varo=0;
-167for(vari=0;i<n;i++)o+=dy[i][j];
-168y[index[0]][j]=(h-o)/2;
-169}
-170break;
-171}
-172case"wiggle":{
-173varo=0;
-174for(vari=0;i<n;i++)o+=dy[i][0];
-175y[index[0]][0]=o=(h-o)/2;
-176for(varj=1;j<m;j++){
-177vars1=0,s2=0,dx=x[j]-x[j-1];
-178for(vari=0;i<n;i++)s1+=dy[i][j];
-179for(vari=0;i<n;i++){
-180vars3=(dy[index[i]][j]-dy[index[i]][j-1])/(2*dx);
-181for(vark=0;k<i;k++){
-182s3+=(dy[index[k]][j]-dy[index[k]][j-1])/dx;
-183}
-184s2+=s3*dy[index[i]][j];
-185}
-186y[index[0]][j]=o-=s1?s2/s1*dx:0;
-187}
-188break;
-189}
-190case"expand":{
-191for(varj=0;j<m;j++){
-192y[index[0]][j]=0;
-193vark=0;
-194for(vari=0;i<n;i++)k+=dy[i][j];
-195if(k){
-196k=h/k;
-197for(vari=0;i<n;i++)dy[i][j]*=k;
-198}else{
-199k=h/n;
-200for(vari=0;i<n;i++)dy[i][j]=k;
-201}
-202}
-203break;
-204}
-205default:{
-206for(varj=0;j<m;j++)y[index[0]][j]=0;
-207break;
-208}
-209}
-210
-211/* Propagate the offset to the other series. */
-212for(varj=0;j<m;j++){
-213varo=y[index[0]][j];
-214for(vari=1;i<n;i++){
-215o+=dy[index[i-1]][j];
-216y[index[i]][j]=o;
-217}
-218}
-219
-220/* Find the property definitions for dynamic substitution. */
-221vari=orient.indexOf("-"),
-222pdy=horizontal?"h":"w",
-223px=i<0?(horizontal?"l":"b"):orient.charAt(i+1),
-224py=orient.charAt(0);
-225for(varpinprop)prop[p]=none;
-226prop[px]=function(i,j){returnx[j];};
-227prop[py]=function(i,j){returny[i][j];};
-228prop[pdy]=function(i,j){returndy[i][j];};
-229};
-230
-231/**
-232 * The layer prototype. This prototype is intended to be used with an area,
-233 * bar or panel mark (or subclass thereof). Other mark types may be possible,
-234 * though note that the stack layout is not currently designed to support
-235 * radial stacked visualizations using wedges.
-236 *
-237 * <p>The layer is not a direct child of the stack layout; a hidden panel is
-238 * used to replicate layers.
-239 *
-240 * @type pv.Mark
-241 * @name pv.Layout.Stack.prototype.layer
-242 */
-243this.layer=newpv.Mark()
-244.data(function(){returnvalues[this.parent.index];})
-245.top(proxy("t"))
-246.left(proxy("l"))
-247.right(proxy("r"))
-248.bottom(proxy("b"))
-249.width(proxy("w"))
-250.height(proxy("h"));
-251
-252this.layer.add=function(type){
-253returnthat.add(pv.Panel)
-254.data(function(){returnthat.layers();})
-255.add(type)
-256.extend(this);
-257};
-258};
-259
-260pv.Layout.Stack.prototype=pv.extend(pv.Layout)
-261.property("orient",String)
-262.property("offset",String)
-263.property("order",String)
-264.property("layers");
-265
-266/**
-267 * Default properties for stack layouts. The default orientation is
-268 * "bottom-left", the default offset is "zero", and the default layers is
-269 * <tt>[[]]</tt>.
-270 *
-271 * @type pv.Layout.Stack
-272 */
-273pv.Layout.Stack.prototype.defaults=newpv.Layout.Stack()
-274.extend(pv.Layout.prototype.defaults)
-275.orient("bottom-left")
-276.offset("zero")
-277.layers([[]]);
-278
-279/** @private */
-280pv.Layout.Stack.prototype.$x
-281=/** @private */pv.Layout.Stack.prototype.$y
-282=function(){return0;};
-283
-284/**
-285 * The x psuedo-property; determines the position of the value within the layer.
-286 * This typically corresponds to the independent variable. For example, with the
-287 * default "bottom-left" orientation, this function defines the "left" property.
-288 *
-289 * @param {function} f the x function.
-290 * @returns {pv.Layout.Stack} this.
-291 */
-292pv.Layout.Stack.prototype.x=function(f){
-293/** @private */this.$x=pv.functor(f);
-294returnthis;
-295};
-296
-297/**
-298 * The y psuedo-property; determines the thickness of the layer at the given
-299 * value. This typically corresponds to the dependent variable. For example,
-300 * with the default "bottom-left" orientation, this function defines the
-301 * "height" property.
-302 *
-303 * @param {function} f the y function.
-304 * @returns {pv.Layout.Stack} this.
-305 */
-306pv.Layout.Stack.prototype.y=function(f){
-307/** @private */this.$y=pv.functor(f);
-308returnthis;
-309};
-310
-311/** @private The default value function; identity. */
-312pv.Layout.Stack.prototype.$values=pv.identity;
-313
-314/**
-315 * The values function; determines the values for a given layer. The default
-316 * value is the identity function, which assumes that the layers property is
-317 * specified as a two-dimensional (i.e., nested) array.
-318 *
-319 * @param {function} f the values function.
-320 * @returns {pv.Layout.Stack} this.
-321 */
-322pv.Layout.Stack.prototype.values=function(f){
-323this.$values=pv.functor(f);
-324returnthis;
-325};
-326
-327/**
-328 * The layer data in row-major order. The value of this property is typically a
-329 * two-dimensional (i.e., nested) array, but any array can be used, provided the
-330 * values psuedo-property is defined accordingly.
-331 *
-332 * @type array[]
-333 * @name pv.Layout.Stack.prototype.layers
-334 */
-335
-336/**
-337 * The layer orientation. The following values are supported:<ul>
-338 *
-339 * <li>bottom-left == bottom
-340 * <li>bottom-right
-341 * <li>top-left == top
-342 * <li>top-right
-343 * <li>left-top
-344 * <li>left-bottom == left
-345 * <li>right-top
-346 * <li>right-bottom == right
-347 *
-348 * </ul>. The default value is "bottom-left", which means that the layers will
-349 * be built from the bottom-up, and the values within layers will be laid out
-350 * from left-to-right.
-351 *
-352 * <p>Note that with non-zero baselines, some orientations may give similar
-353 * results. For example, offset("silohouette") centers the layers, resulting in
-354 * a streamgraph. Thus, the orientations "bottom-left" and "top-left" will
-355 * produce similar results, differing only in the layer order.
-356 *
-357 * @type string
-358 * @name pv.Layout.Stack.prototype.orient
-359 */
-360
-361/**
-362 * The layer order. The following values are supported:<ul>
-363 *
-364 * <li><i>null</i> - use given layer order.
-365 * <li>inside-out - sort by maximum value, with balanced order.
-366 * <li>reverse - use reverse of given layer order.
-367 *
-368 * </ul>For details on the inside-out order algorithm, refer to "Stacked Graphs
-369 * -- Geometry & Aesthetics" by L. Byron and M. Wattenberg, IEEE TVCG
-370 * November/December 2008.
-371 *
-372 * @type string
-373 * @name pv.Layout.Stack.prototype.order
-374 */
-375
-376/**
-377 * The layer offset; the y-position of the bottom of the lowest layer. The
-378 * following values are supported:<ul>
-379 *
-380 * <li>zero - use a zero baseline, i.e., the y-axis.
-381 * <li>silohouette - center the stream, i.e., ThemeRiver.
-382 * <li>wiggle - minimize weighted change in slope.
-383 * <li>expand - expand layers to fill the enclosing layout dimensions.
-384 *
-385 * </ul>For details on these offset algorithms, refer to "Stacked Graphs --
-386 * Geometry & Aesthetics" by L. Byron and M. Wattenberg, IEEE TVCG
-387 * November/December 2008.
-388 *
-389 * @type string
-390 * @name pv.Layout.Stack.prototype.offset
-391 */
-392
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Tree.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Tree.js.html
deleted file mode 100644
index b58f4206..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Tree.js.html
+++ /dev/null
@@ -1,290 +0,0 @@
-
1/**
- 2 * Constructs a new, empty tree layout. Layouts are not typically constructed
- 3 * directly; instead, they are added to an existing panel via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Implements a node-link tree diagram using the Reingold-Tilford "tidy"
- 7 * tree layout algorithm. The specific algorithm used by this layout is based on
- 8 * <a href="http://citeseer.ist.psu.edu/buchheim02improving.html">"Improving
- 9 * Walker's Algorithm to Run in Linear Time"</A> by C. Buchheim, M. Jünger
- 10 * & S. Leipert, Graph Drawing 2002. This layout supports both cartesian and
- 11 * radial orientations orientations for node-link diagrams.
- 12 *
- 13 * <p>The tree layout supports a "group" property, which if true causes siblings
- 14 * to be positioned closer together than unrelated nodes at the same depth. The
- 15 * layout can be configured using the <tt>depth</tt> and <tt>breadth</tt>
- 16 * properties, which control the increments in pixel space between nodes in both
- 17 * dimensions, similar to the indent layout.
- 18 *
- 19 * <p>For more details on how to use this layout, see
- 20 * {@link pv.Layout.Hierarchy}.
- 21 *
- 22 * @extends pv.Layout.Hierarchy
- 23 */
- 24pv.Layout.Tree=function(){
- 25pv.Layout.Hierarchy.call(this);
- 26};
- 27
- 28pv.Layout.Tree.prototype=pv.extend(pv.Layout.Hierarchy)
- 29.property("group",Number)
- 30.property("breadth",Number)
- 31.property("depth",Number)
- 32.property("orient",String);
- 33
- 34/**
- 35 * Default properties for tree layouts. The default orientation is "top", the
- 36 * default group parameter is 1, and the default breadth and depth offsets are
- 37 * 15 and 60 respectively.
- 38 *
- 39 * @type pv.Layout.Tree
- 40 */
- 41pv.Layout.Tree.prototype.defaults=newpv.Layout.Tree()
- 42.extend(pv.Layout.Hierarchy.prototype.defaults)
- 43.group(1)
- 44.breadth(15)
- 45.depth(60)
- 46.orient("top");
- 47
- 48/** @private */
- 49pv.Layout.Tree.prototype.buildImplied=function(s){
- 50if(pv.Layout.Hierarchy.prototype.buildImplied.call(this,s))return;
- 51
- 52varnodes=s.nodes,
- 53orient=s.orient,
- 54depth=s.depth,
- 55breadth=s.breadth,
- 56group=s.group,
- 57w=s.width,
- 58h=s.height;
- 59
- 60/** @private */
- 61functionfirstWalk(v){
- 62varl,r,a;
- 63if(!v.firstChild){
- 64if(l=v.previousSibling){
- 65v.prelim=l.prelim+distance(v.depth,true);
- 66}
- 67}else{
- 68l=v.firstChild;
- 69r=v.lastChild;
- 70a=l;// default ancestor
- 71for(varc=l;c;c=c.nextSibling){
- 72firstWalk(c);
- 73a=apportion(c,a);
- 74}
- 75executeShifts(v);
- 76varmidpoint=.5*(l.prelim+r.prelim);
- 77if(l=v.previousSibling){
- 78v.prelim=l.prelim+distance(v.depth,true);
- 79v.mod=v.prelim-midpoint;
- 80}else{
- 81v.prelim=midpoint;
- 82}
- 83}
- 84}
- 85
- 86/** @private */
- 87functionsecondWalk(v,m,depth){
- 88v.breadth=v.prelim+m;
- 89m+=v.mod;
- 90for(varc=v.firstChild;c;c=c.nextSibling){
- 91secondWalk(c,m,depth);
- 92}
- 93}
- 94
- 95/** @private */
- 96functionapportion(v,a){
- 97varw=v.previousSibling;
- 98if(w){
- 99varvip=v,
-100vop=v,
-101vim=w,
-102vom=v.parentNode.firstChild,
-103sip=vip.mod,
-104sop=vop.mod,
-105sim=vim.mod,
-106som=vom.mod,
-107nr=nextRight(vim),
-108nl=nextLeft(vip);
-109while(nr&&nl){
-110vim=nr;
-111vip=nl;
-112vom=nextLeft(vom);
-113vop=nextRight(vop);
-114vop.ancestor=v;
-115varshift=(vim.prelim+sim)-(vip.prelim+sip)+distance(vim.depth,false);
-116if(shift>0){
-117moveSubtree(ancestor(vim,v,a),v,shift);
-118sip+=shift;
-119sop+=shift;
-120}
-121sim+=vim.mod;
-122sip+=vip.mod;
-123som+=vom.mod;
-124sop+=vop.mod;
-125nr=nextRight(vim);
-126nl=nextLeft(vip);
-127}
-128if(nr&&!nextRight(vop)){
-129vop.thread=nr;
-130vop.mod+=sim-sop;
-131}
-132if(nl&&!nextLeft(vom)){
-133vom.thread=nl;
-134vom.mod+=sip-som;
-135a=v;
-136}
-137}
-138returna;
-139}
-140
-141/** @private */
-142functionnextLeft(v){
-143returnv.firstChild||v.thread;
-144}
-145
-146/** @private */
-147functionnextRight(v){
-148returnv.lastChild||v.thread;
-149}
-150
-151/** @private */
-152functionmoveSubtree(wm,wp,shift){
-153varsubtrees=wp.number-wm.number;
-154wp.change-=shift/subtrees;
-155wp.shift+=shift;
-156wm.change+=shift/subtrees;
-157wp.prelim+=shift;
-158wp.mod+=shift;
-159}
-160
-161/** @private */
-162functionexecuteShifts(v){
-163varshift=0,change=0;
-164for(varc=v.lastChild;c;c=c.previousSibling){
-165c.prelim+=shift;
-166c.mod+=shift;
-167change+=c.change;
-168shift+=c.shift+change;
-169}
-170}
-171
-172/** @private */
-173functionancestor(vim,v,a){
-174return(vim.ancestor.parentNode==v.parentNode)?vim.ancestor:a;
-175}
-176
-177/** @private */
-178functiondistance(depth,siblings){
-179return(siblings?1:(group+1))/((orient=="radial")?depth:1);
-180}
-181
-182/* Initialize temporary layout variables. TODO: store separately. */
-183varroot=nodes[0];
-184root.visitAfter(function(v,i){
-185v.ancestor=v;
-186v.prelim=0;
-187v.mod=0;
-188v.change=0;
-189v.shift=0;
-190v.number=v.previousSibling?(v.previousSibling.number+1):0;
-191v.depth=i;
-192});
-193
-194/* Compute the layout using Buchheim et al.'s algorithm. */
-195firstWalk(root);
-196secondWalk(root,-root.prelim,0);
-197
-198/** @private Returns the angle of the given node. */
-199functionmidAngle(n){
-200return(orient=="radial")?n.breadth/depth:0;
-201}
-202
-203/** @private */
-204functionx(n){
-205switch(orient){
-206case"left":returnn.depth;
-207case"right":returnw-n.depth;
-208case"top":
-209case"bottom":returnn.breadth+w/2;
-210case"radial":returnw/2+n.depth*Math.cos(midAngle(n));
-211}
-212}
-213
-214/** @private */
-215functiony(n){
-216switch(orient){
-217case"left":
-218case"right":returnn.breadth+h/2;
-219case"top":returnn.depth;
-220case"bottom":returnh-n.depth;
-221case"radial":returnh/2+n.depth*Math.sin(midAngle(n));
-222}
-223}
-224
-225/* Clear temporary layout variables; transform depth and breadth. */
-226root.visitAfter(function(v){
-227v.breadth*=breadth;
-228v.depth*=depth;
-229v.midAngle=midAngle(v);
-230v.x=x(v);
-231v.y=y(v);
-232if(v.firstChild)v.midAngle+=Math.PI;
-233deletev.breadth;
-234deletev.depth;
-235deletev.ancestor;
-236deletev.prelim;
-237deletev.mod;
-238deletev.change;
-239deletev.shift;
-240deletev.number;
-241deletev.thread;
-242});
-243};
-244
-245/**
-246 * The offset between siblings nodes; defaults to 15.
-247 *
-248 * @type number
-249 * @name pv.Layout.Tree.prototype.breadth
-250 */
-251
-252/**
-253 * The offset between parent and child nodes; defaults to 60.
-254 *
-255 * @type number
-256 * @name pv.Layout.Tree.prototype.depth
-257 */
-258
-259/**
-260 * The orientation. The default orientation is "top", which means that the root
-261 * node is placed on the top edge, leaf nodes appear at the bottom, and internal
-262 * nodes are in-between. The following orientations are supported:<ul>
-263 *
-264 * <li>left - left-to-right.
-265 * <li>right - right-to-left.
-266 * <li>top - top-to-bottom.
-267 * <li>bottom - bottom-to-top.
-268 * <li>radial - radially, with the root at the center.</ul>
-269 *
-270 * @type string
-271 * @name pv.Layout.Tree.prototype.orient
-272 */
-273
-274/**
-275 * The sibling grouping, i.e., whether differentiating space is placed between
-276 * sibling groups. The default is 1 (or true), causing sibling leaves to be
-277 * separated by one breadth offset. Setting this to false (or 0) causes
-278 * non-siblings to be adjacent.
-279 *
-280 * @type number
-281 * @name pv.Layout.Tree.prototype.group
-282 */
-283
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Treemap.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Treemap.js.html
deleted file mode 100644
index 85ba0585..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_layout_Treemap.js.html
+++ /dev/null
@@ -1,355 +0,0 @@
-
1/**
- 2 * Constructs a new, empty treemap layout. Layouts are not typically
- 3 * constructed directly; instead, they are added to an existing panel via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Implements a space-filling rectangular layout, with the hierarchy
- 7 * represented via containment. Treemaps represent nodes as boxes, with child
- 8 * nodes placed within parent boxes. The size of each box is proportional to the
- 9 * size of the node in the tree. This particular algorithm is taken from Bruls,
- 10 * D.M., C. Huizing, and J.J. van Wijk, <a
- 11 * href="http://www.win.tue.nl/~vanwijk/stm.pdf">"Squarified Treemaps"</a> in
- 12 * <i>Data Visualization 2000, Proceedings of the Joint Eurographics and IEEE
- 13 * TCVG Sumposium on Visualization</i>, 2000, pp. 33-42.
- 14 *
- 15 * <p>The meaning of the exported mark prototypes changes slightly in the
- 16 * space-filling implementation:<ul>
- 17 *
- 18 * <li><tt>node</tt> - for rendering nodes; typically a {@link pv.Bar}. The node
- 19 * data is populated with <tt>dx</tt> and <tt>dy</tt> attributes, in addition to
- 20 * the standard <tt>x</tt> and <tt>y</tt> position attributes.
- 21 *
- 22 * <p><li><tt>leaf</tt> - for rendering leaf nodes only, with no fill or stroke
- 23 * style by default; typically a {@link pv.Panel} or another layout!
- 24 *
- 25 * <p><li><tt>link</tt> - unsupported; undefined. Links are encoded implicitly
- 26 * in the arrangement of the space-filling nodes.
- 27 *
- 28 * <p><li><tt>label</tt> - for rendering node labels; typically a
- 29 * {@link pv.Label}.
- 30 *
- 31 * </ul>For more details on how to use this layout, see
- 32 * {@link pv.Layout.Hierarchy}.
- 33 *
- 34 * @extends pv.Layout.Hierarchy
- 35 */
- 36pv.Layout.Treemap=function(){
- 37pv.Layout.Hierarchy.call(this);
- 38
- 39this.node
- 40.strokeStyle("#fff")
- 41.fillStyle("rgba(31, 119, 180, .25)")
- 42.width(function(n){returnn.dx;})
- 43.height(function(n){returnn.dy;});
- 44
- 45this.label
- 46.visible(function(n){return!n.firstChild;})
- 47.left(function(n){returnn.x+(n.dx/2);})
- 48.top(function(n){returnn.y+(n.dy/2);})
- 49.textAlign("center")
- 50.textAngle(function(n){returnn.dx>n.dy?0:-Math.PI/2;});
- 51
- 52(this.leaf=newpv.Mark()
- 53.extend(this.node)
- 54.fillStyle(null)
- 55.strokeStyle(null)
- 56.visible(function(n){return!n.firstChild;})).parent=this;
- 57
- 58/* Hide unsupported link. */
- 59deletethis.link;
- 60};
- 61
- 62pv.Layout.Treemap.prototype=pv.extend(pv.Layout.Hierarchy)
- 63.property("round",Boolean)
- 64.property("paddingLeft",Number)
- 65.property("paddingRight",Number)
- 66.property("paddingTop",Number)
- 67.property("paddingBottom",Number)
- 68.property("mode",String)
- 69.property("order",String);
- 70
- 71/**
- 72 * Default propertiess for treemap layouts. The default mode is "squarify" and
- 73 * the default order is "ascending".
- 74 *
- 75 * @type pv.Layout.Treemap
- 76 */
- 77pv.Layout.Treemap.prototype.defaults=newpv.Layout.Treemap()
- 78.extend(pv.Layout.Hierarchy.prototype.defaults)
- 79.mode("squarify")// squarify, slice-and-dice, slice, dice
- 80.order("ascending");// ascending, descending, reverse, null
- 81
- 82/**
- 83 * Whether node sizes should be rounded to integer values. This has a similar
- 84 * effect to setting <tt>antialias(false)</tt> for node values, but allows the
- 85 * treemap algorithm to accumulate error related to pixel rounding.
- 86 *
- 87 * @type boolean
- 88 * @name pv.Layout.Treemap.prototype.round
- 89 */
- 90
- 91/**
- 92 * The left inset between parent add child in pixels. Defaults to 0.
- 93 *
- 94 * @type number
- 95 * @name pv.Layout.Treemap.prototype.paddingLeft
- 96 * @see #padding
- 97 */
- 98
- 99/**
-100 * The right inset between parent add child in pixels. Defaults to 0.
-101 *
-102 * @type number
-103 * @name pv.Layout.Treemap.prototype.paddingRight
-104 * @see #padding
-105 */
-106
-107/**
-108 * The top inset between parent and child in pixels. Defaults to 0.
-109 *
-110 * @type number
-111 * @name pv.Layout.Treemap.prototype.paddingTop
-112 * @see #padding
-113 */
-114
-115/**
-116 * The bottom inset between parent and child in pixels. Defaults to 0.
-117 *
-118 * @type number
-119 * @name pv.Layout.Treemap.prototype.paddingBottom
-120 * @see #padding
-121 */
-122
-123/**
-124 * The treemap algorithm. The default value is "squarify". The "slice-and-dice"
-125 * algorithm may also be used, which alternates between horizontal and vertical
-126 * slices for different depths. In addition, the "slice" and "dice" algorithms
-127 * may be specified explicitly to control whether horizontal or vertical slices
-128 * are used, which may be useful for nested treemap layouts.
-129 *
-130 * @type string
-131 * @name pv.Layout.Treemap.prototype.mode
-132 * @see <a
-133 * href="ftp://ftp.cs.umd.edu/pub/hcil/Reports-Abstracts-Bibliography/2001-06html/2001-06.pdf"
-134 * >"Ordered Treemap Layouts"</a> by B. Shneiderman & M. Wattenberg, IEEE
-135 * InfoVis 2001.
-136 */
-137
-138/**
-139 * The sibling node order. A <tt>null</tt> value means to use the sibling order
-140 * specified by the nodes property as-is; "reverse" will reverse the given
-141 * order. The default value "ascending" will sort siblings in ascending order of
-142 * size, while "descending" will do the reverse. For sorting based on data
-143 * attributes other than size, use the default <tt>null</tt> for the order
-144 * property, and sort the nodes beforehand using the {@link pv.Dom} operator.
-145 *
-146 * @type string
-147 * @name pv.Layout.Treemap.prototype.order
-148 */
-149
-150/**
-151 * Alias for setting the left, right, top and bottom padding properties
-152 * simultaneously.
-153 *
-154 * @see #paddingLeft
-155 * @see #paddingRight
-156 * @see #paddingTop
-157 * @see #paddingBottom
-158 * @returns {pv.Layout.Treemap} this.
-159 */
-160pv.Layout.Treemap.prototype.padding=function(n){
-161returnthis.paddingLeft(n).paddingRight(n).paddingTop(n).paddingBottom(n);
-162};
-163
-164/** @private The default size function. */
-165pv.Layout.Treemap.prototype.$size=function(d){
-166returnNumber(d.nodeValue);
-167};
-168
-169/**
-170 * Specifies the sizing function. By default, the size function uses the
-171 * <tt>nodeValue</tt> attribute of nodes as a numeric value: <tt>function(d)
-172 * Number(d.nodeValue)</tt>.
-173 *
-174 * <p>The sizing function is invoked for each leaf node in the tree, per the
-175 * <tt>nodes</tt> property. For example, if the tree data structure represents a
-176 * file system, with files as leaf nodes, and each file has a <tt>bytes</tt>
-177 * attribute, you can specify a size function as:
-178 *
-179 * <pre> .size(function(d) d.bytes)</pre>
-180 *
-181 * @param {function} f the new sizing function.
-182 * @returns {pv.Layout.Treemap} this.
-183 */
-184pv.Layout.Treemap.prototype.size=function(f){
-185this.$size=pv.functor(f);
-186returnthis;
-187};
-188
-189/** @private */
-190pv.Layout.Treemap.prototype.buildImplied=function(s){
-191if(pv.Layout.Hierarchy.prototype.buildImplied.call(this,s))return;
-192
-193varthat=this,
-194nodes=s.nodes,
-195root=nodes[0],
-196stack=pv.Mark.stack,
-197left=s.paddingLeft,
-198right=s.paddingRight,
-199top=s.paddingTop,
-200bottom=s.paddingBottom,
-201/** @ignore */size=function(n){returnn.size;},
-202round=s.round?Math.round:Number,
-203mode=s.mode;
-204
-205/** @private */
-206functionslice(row,sum,horizontal,x,y,w,h){
-207for(vari=0,d=0;i<row.length;i++){
-208varn=row[i];
-209if(horizontal){
-210n.x=x+d;
-211n.y=y;
-212d+=n.dx=round(w*n.size/sum);
-213n.dy=h;
-214}else{
-215n.x=x;
-216n.y=y+d;
-217n.dx=w;
-218d+=n.dy=round(h*n.size/sum);
-219}
-220}
-221if(n){// correct on-axis rounding error
-222if(horizontal){
-223n.dx+=w-d;
-224}else{
-225n.dy+=h-d;
-226}
-227}
-228}
-229
-230/** @private */
-231functionratio(row,l){
-232varrmax=-Infinity,rmin=Infinity,s=0;
-233for(vari=0;i<row.length;i++){
-234varr=row[i].size;
-235if(r<rmin)rmin=r;
-236if(r>rmax)rmax=r;
-237s+=r;
-238}
-239s=s*s;
-240l=l*l;
-241returnMath.max(l*rmax/s,s/(l*rmin));
-242}
-243
-244/** @private */
-245functionlayout(n,i){
-246varx=n.x+left,
-247y=n.y+top,
-248w=n.dx-left-right,
-249h=n.dy-top-bottom;
-250
-251/* Assume squarify by default. */
-252if(mode!="squarify"){
-253slice(n.childNodes,n.size,
-254mode=="slice"?true
-255:mode=="dice"?false
-256:i&1,x,y,w,h);
-257return;
-258}
-259
-260varrow=[],
-261mink=Infinity,
-262l=Math.min(w,h),
-263k=w*h/n.size;
-264
-265/* Abort if the size is nonpositive. */
-266if(n.size<=0)return;
-267
-268/* Scale the sizes to fill the current subregion. */
-269n.visitBefore(function(n){n.size*=k;});
-270
-271/** @private Position the specified nodes along one dimension. */
-272functionposition(row){
-273varhorizontal=w==l,
-274sum=pv.sum(row,size),
-275r=l?round(sum/l):0;
-276slice(row,sum,horizontal,x,y,horizontal?w:r,horizontal?r:h);
-277if(horizontal){
-278y+=r;
-279h-=r;
-280}else{
-281x+=r;
-282w-=r;
-283}
-284l=Math.min(w,h);
-285returnhorizontal;
-286}
-287
-288varchildren=n.childNodes.slice();// copy
-289while(children.length){
-290varchild=children[children.length-1];
-291if(!child.size){
-292children.pop();
-293continue;
-294}
-295row.push(child);
-296
-297vark=ratio(row,l);
-298if(k<=mink){
-299children.pop();
-300mink=k;
-301}else{
-302row.pop();
-303position(row);
-304row.length=0;
-305mink=Infinity;
-306}
-307}
-308
-309/* correct off-axis rounding error */
-310if(position(row))for(vari=0;i<row.length;i++){
-311row[i].dy+=h;
-312}elsefor(vari=0;i<row.length;i++){
-313row[i].dx+=w;
-314}
-315}
-316
-317/* Recursively compute the node depth and size. */
-318stack.unshift(null);
-319root.visitAfter(function(n,i){
-320n.depth=i;
-321n.x=n.y=n.dx=n.dy=0;
-322n.size=n.firstChild
-323?pv.sum(n.childNodes,function(n){returnn.size;})
-324:that.$size.apply(that,(stack[0]=n,stack));
-325});
-326stack.shift();
-327
-328/* Sort. */
-329switch(s.order){
-330case"ascending":{
-331root.sort(function(a,b){returna.size-b.size;});
-332break;
-333}
-334case"descending":{
-335root.sort(function(a,b){returnb.size-a.size;});
-336break;
-337}
-338case"reverse":root.reverse();break;
-339}
-340
-341/* Recursively compute the layout. */
-342root.x=0;
-343root.y=0;
-344root.dx=s.width;
-345root.dy=s.height;
-346root.visitBefore(layout);
-347};
-348
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Anchor.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Anchor.js.html
deleted file mode 100644
index 0327bd51..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Anchor.js.html
+++ /dev/null
@@ -1,86 +0,0 @@
-
1/**
- 2 * Constructs a new mark anchor with default properties.
- 3 *
- 4 * @class Represents an anchor on a given mark. An anchor is itself a mark, but
- 5 * without a visual representation. It serves only to provide useful default
- 6 * properties that can be inherited by other marks. Each type of mark can define
- 7 * any number of named anchors for convenience. If the concrete mark type does
- 8 * not define an anchor implementation specifically, one will be inherited from
- 9 * the mark's parent class.
- 10 *
- 11 * <p>For example, the bar mark provides anchors for its four sides: left,
- 12 * right, top and bottom. Adding a label to the top anchor of a bar,
- 13 *
- 14 * <pre>bar.anchor("top").add(pv.Label);</pre>
- 15 *
- 16 * will render a text label on the top edge of the bar; the top anchor defines
- 17 * the appropriate position properties (top and left), as well as text-rendering
- 18 * properties for convenience (textAlign and textBaseline).
- 19 *
- 20 * <p>Note that anchors do not <i>inherit</i> from their targets; the positional
- 21 * properties are copied from the scene graph, which guarantees that the anchors
- 22 * are positioned correctly, even if the positional properties are not defined
- 23 * deterministically. (In addition, it also improves performance by avoiding
- 24 * re-evaluating expensive properties.) If you want the anchor to inherit from
- 25 * the target, use {@link pv.Mark#extend} before adding. For example:
- 26 *
- 27 * <pre>bar.anchor("top").extend(bar).add(pv.Label);</pre>
- 28 *
- 29 * The anchor defines it's own positional properties, but other properties (such
- 30 * as the title property, say) can be inherited using the above idiom. Also note
- 31 * that you can override positional properties in the anchor for custom
- 32 * behavior.
- 33 *
- 34 * @extends pv.Mark
- 35 * @param {pv.Mark} target the anchor target.
- 36 */
- 37pv.Anchor=function(target){
- 38pv.Mark.call(this);
- 39this.target=target;
- 40this.parent=target.parent;
- 41};
- 42
- 43pv.Anchor.prototype=pv.extend(pv.Mark)
- 44.property("name",String);
- 45
- 46/**
- 47 * The anchor name. The set of supported anchor names is dependent on the
- 48 * concrete mark type; see the mark type for details. For example, bars support
- 49 * left, right, top and bottom anchors.
- 50 *
- 51 * <p>While anchor names are typically constants, the anchor name is a true
- 52 * property, which means you can specify a function to compute the anchor name
- 53 * dynamically. For instance, if you wanted to alternate top and bottom anchors,
- 54 * saying
- 55 *
- 56 * <pre>m.anchor(function() (this.index % 2) ? "top" : "bottom").add(pv.Dot);</pre>
- 57 *
- 58 * would have the desired effect.
- 59 *
- 60 * @type string
- 61 * @name pv.Anchor.prototype.name
- 62 */
- 63
- 64/**
- 65 * Returns the anchor target of this mark, if it is derived from an anchor;
- 66 * otherwise returns null. For example, if a label is derived from a bar anchor,
- 67 *
- 68 * <pre>bar.anchor("top").add(pv.Label);</pre>
- 69 *
- 70 * then property functions on the label can refer to the bar via the
- 71 * <tt>anchorTarget</tt> method. This method is also useful for mark types
- 72 * defining properties on custom anchors.
- 73 *
- 74 * @returns {pv.Mark} the anchor target of this mark; possibly null.
- 75 */
- 76pv.Anchor.prototype.anchorTarget=function(){
- 77returnthis.target;
- 78};
- 79
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Area.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Area.js.html
deleted file mode 100644
index df3971c2..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Area.js.html
+++ /dev/null
@@ -1,279 +0,0 @@
-
1/**
- 2 * Constructs a new area mark with default properties. Areas are not typically
- 3 * constructed directly, but by adding to a panel or an existing mark via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Represents an area mark: the solid area between two series of
- 7 * connected line segments. Unsurprisingly, areas are used most frequently for
- 8 * area charts.
- 9 *
- 10 * <p>Just as a line represents a polyline, the <tt>Area</tt> mark type
- 11 * represents a <i>polygon</i>. However, an area is not an arbitrary polygon;
- 12 * vertices are paired either horizontally or vertically into parallel
- 13 * <i>spans</i>, and each span corresponds to an associated datum. Either the
- 14 * width or the height must be specified, but not both; this determines whether
- 15 * the area is horizontally-oriented or vertically-oriented. Like lines, areas
- 16 * can be stroked and filled with arbitrary colors.
- 17 *
- 18 * <p>See also the <a href="../../api/Area.html">Area guide</a>.
- 19 *
- 20 * @extends pv.Mark
- 21 */
- 22pv.Area=function(){
- 23pv.Mark.call(this);
- 24};
- 25
- 26pv.Area.prototype=pv.extend(pv.Mark)
- 27.property("width",Number)
- 28.property("height",Number)
- 29.property("lineWidth",Number)
- 30.property("strokeStyle",pv.color)
- 31.property("fillStyle",pv.color)
- 32.property("segmented",Boolean)
- 33.property("interpolate",String)
- 34.property("tension",Number);
- 35
- 36pv.Area.prototype.type="area";
- 37
- 38/**
- 39 * The width of a given span, in pixels; used for horizontal spans. If the width
- 40 * is specified, the height property should be 0 (the default). Either the top
- 41 * or bottom property should be used to space the spans vertically, typically as
- 42 * a multiple of the index.
- 43 *
- 44 * @type number
- 45 * @name pv.Area.prototype.width
- 46 */
- 47
- 48/**
- 49 * The height of a given span, in pixels; used for vertical spans. If the height
- 50 * is specified, the width property should be 0 (the default). Either the left
- 51 * or right property should be used to space the spans horizontally, typically
- 52 * as a multiple of the index.
- 53 *
- 54 * @type number
- 55 * @name pv.Area.prototype.height
- 56 */
- 57
- 58/**
- 59 * The width of stroked lines, in pixels; used in conjunction with
- 60 * <tt>strokeStyle</tt> to stroke the perimeter of the area. Unlike the
- 61 * {@link Line} mark type, the entire perimeter is stroked, rather than just one
- 62 * edge. The default value of this property is 1.5, but since the default stroke
- 63 * style is null, area marks are not stroked by default.
- 64 *
- 65 * <p>This property is <i>fixed</i> for non-segmented areas. See
- 66 * {@link pv.Mark}.
- 67 *
- 68 * @type number
- 69 * @name pv.Area.prototype.lineWidth
- 70 */
- 71
- 72/**
- 73 * The style of stroked lines; used in conjunction with <tt>lineWidth</tt> to
- 74 * stroke the perimeter of the area. Unlike the {@link Line} mark type, the
- 75 * entire perimeter is stroked, rather than just one edge. The default value of
- 76 * this property is null, meaning areas are not stroked by default.
- 77 *
- 78 * <p>This property is <i>fixed</i> for non-segmented areas. See
- 79 * {@link pv.Mark}.
- 80 *
- 81 * @type string
- 82 * @name pv.Area.prototype.strokeStyle
- 83 * @see pv.color
- 84 */
- 85
- 86/**
- 87 * The area fill style; if non-null, the interior of the polygon forming the
- 88 * area is filled with the specified color. The default value of this property
- 89 * is a categorical color.
- 90 *
- 91 * <p>This property is <i>fixed</i> for non-segmented areas. See
- 92 * {@link pv.Mark}.
- 93 *
- 94 * @type string
- 95 * @name pv.Area.prototype.fillStyle
- 96 * @see pv.color
- 97 */
- 98
- 99/**
-100 * Whether the area is segmented; whether variations in fill style, stroke
-101 * style, and the other properties are treated as fixed. Rendering segmented
-102 * areas is noticeably slower than non-segmented areas.
-103 *
-104 * <p>This property is <i>fixed</i>. See {@link pv.Mark}.
-105 *
-106 * @type boolean
-107 * @name pv.Area.prototype.segmented
-108 */
-109
-110/**
-111 * How to interpolate between values. Linear interpolation ("linear") is the
-112 * default, producing a straight line between points. For piecewise constant
-113 * functions (i.e., step functions), either "step-before" or "step-after" can be
-114 * specified. To draw open uniform b-splines, specify "basis". To draw cardinal
-115 * splines, specify "cardinal"; see also {@link #tension}.
-116 *
-117 * <p>This property is <i>fixed</i>. See {@link pv.Mark}.
-118 *
-119 * @type string
-120 * @name pv.Area.prototype.interpolate
-121 */
-122
-123/**
-124 * The tension of cardinal splines; used in conjunction with
-125 * interpolate("cardinal"). A value between 0 and 1 draws cardinal splines with
-126 * the given tension. In some sense, the tension can be interpreted as the
-127 * "length" of the tangent; a tension of 1 will yield all zero tangents (i.e.,
-128 * linear interpolation), and a tension of 0 yields a Catmull-Rom spline. The
-129 * default value is 0.7.
-130 *
-131 * <p>This property is <i>fixed</i>. See {@link pv.Mark}.
-132 *
-133 * @type number
-134 * @name pv.Area.prototype.tension
-135 */
-136
-137/**
-138 * Default properties for areas. By default, there is no stroke and the fill
-139 * style is a categorical color.
-140 *
-141 * @type pv.Area
-142 */
-143pv.Area.prototype.defaults=newpv.Area()
-144.extend(pv.Mark.prototype.defaults)
-145.lineWidth(1.5)
-146.fillStyle(pv.Colors.category20().by(pv.parent))
-147.interpolate("linear")
-148.tension(.7);
-149
-150/** @private Sets width and height to zero if null. */
-151pv.Area.prototype.buildImplied=function(s){
-152if(s.height==null)s.height=0;
-153if(s.width==null)s.width=0;
-154pv.Mark.prototype.buildImplied.call(this,s);
-155};
-156
-157/** @private Records which properties may be fixed. */
-158pv.Area.fixed={
-159lineWidth:1,
-160lineJoin:1,
-161strokeStyle:1,
-162fillStyle:1,
-163segmented:1,
-164interpolate:1,
-165tension:1
-166};
-167
-168/**
-169 * @private Make segmented required, such that this fixed property is always
-170 * evaluated, even if the first segment is not visible. Also cache which
-171 * properties are normally fixed.
-172 */
-173pv.Area.prototype.bind=function(){
-174pv.Mark.prototype.bind.call(this);
-175varbinds=this.binds,
-176required=binds.required,
-177optional=binds.optional;
-178for(vari=0,n=optional.length;i<n;i++){
-179varp=optional[i];
-180p.fixed=p.nameinpv.Area.fixed;
-181if(p.name=="segmented"){
-182required.push(p);
-183optional.splice(i,1);
-184i--;
-185n--;
-186}
-187}
-188
-189/* Cache the original arrays so they can be restored on build. */
-190this.binds.$required=required;
-191this.binds.$optional=optional;
-192};
-193
-194/**
-195 * @private Override the default build behavior such that fixed properties are
-196 * determined dynamically, based on the value of the (always) fixed segmented
-197 * property. Any fixed properties are only evaluated on the first instance,
-198 * although their values are propagated to subsequent instances, so that they
-199 * are available for property chaining and the like.
-200 */
-201pv.Area.prototype.buildInstance=function(s){
-202varbinds=this.binds;
-203
-204/* Handle fixed properties on secondary instances. */
-205if(this.index){
-206varfixed=binds.fixed;
-207
-208/* Determine which properties are fixed. */
-209if(!fixed){
-210fixed=binds.fixed=[];
-211functionf(p){return!p.fixed||(fixed.push(p),false);}
-212binds.required=binds.required.filter(f);
-213if(!this.scene[0].segmented)binds.optional=binds.optional.filter(f);
-214}
-215
-216/* Copy fixed property values from the first instance. */
-217for(vari=0,n=fixed.length;i<n;i++){
-218varp=fixed[i].name;
-219s[p]=this.scene[0][p];
-220}
-221}
-222
-223/* Evaluate all properties on the first instance. */
-224else{
-225binds.required=binds.$required;
-226binds.optional=binds.$optional;
-227binds.fixed=null;
-228}
-229
-230pv.Mark.prototype.buildInstance.call(this,s);
-231};
-232
-233/**
-234 * Constructs a new area anchor with default properties. Areas support five
-235 * different anchors:<ul>
-236 *
-237 * <li>top
-238 * <li>left
-239 * <li>center
-240 * <li>bottom
-241 * <li>right
-242 *
-243 * </ul>In addition to positioning properties (left, right, top bottom), the
-244 * anchors support text rendering properties (text-align, text-baseline). Text
-245 * is rendered to appear inside the area. The area anchor also propagates the
-246 * interpolate, eccentricity, and tension properties such that an anchored area
-247 * or line will match positions between control points.
-248 *
-249 * <p>For consistency with the other mark types, the anchor positions are
-250 * defined in terms of their opposite edge. For example, the top anchor defines
-251 * the bottom property, such that an area added to the top anchor grows upward.
-252 *
-253 * @param {string} name the anchor name; either a string or a property function.
-254 * @returns {pv.Anchor}
-255 */
-256pv.Area.prototype.anchor=function(name){
-257varscene;
-258returnpv.Mark.prototype.anchor.call(this,name)
-259.def("$area.anchor",function(){
-260scene=this.scene.target;
-261})
-262.interpolate(function(){
-263returnscene[this.index].interpolate;
-264})
-265.eccentricity(function(){
-266returnscene[this.index].eccentricity;
-267})
-268.tension(function(){
-269returnscene[this.index].tension;
-270});
-271};
-272
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Bar.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Bar.js.html
deleted file mode 100644
index 5a2a3627..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Bar.js.html
+++ /dev/null
@@ -1,101 +0,0 @@
-
1/**
- 2 * Constructs a new bar mark with default properties. Bars are not typically
- 3 * constructed directly, but by adding to a panel or an existing mark via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Represents a bar: an axis-aligned rectangle that can be stroked and
- 7 * filled. Bars are used for many chart types, including bar charts, histograms
- 8 * and Gantt charts. Bars can also be used as decorations, for example to draw a
- 9 * frame border around a panel; in fact, a panel is a special type (a subclass)
- 10 * of bar.
- 11 *
- 12 * <p>Bars can be positioned in several ways. Most commonly, one of the four
- 13 * corners is fixed using two margins, and then the width and height properties
- 14 * determine the extent of the bar relative to this fixed location. For example,
- 15 * using the bottom and left properties fixes the bottom-left corner; the width
- 16 * then extends to the right, while the height extends to the top. As an
- 17 * alternative to the four corners, a bar can be positioned exclusively using
- 18 * margins; this is convenient as an inset from the containing panel, for
- 19 * example. See {@link pv.Mark} for details on the prioritization of redundant
- 20 * positioning properties.
- 21 *
- 22 * <p>See also the <a href="../../api/Bar.html">Bar guide</a>.
- 23 *
- 24 * @extends pv.Mark
- 25 */
- 26pv.Bar=function(){
- 27pv.Mark.call(this);
- 28};
- 29
- 30pv.Bar.prototype=pv.extend(pv.Mark)
- 31.property("width",Number)
- 32.property("height",Number)
- 33.property("lineWidth",Number)
- 34.property("strokeStyle",pv.color)
- 35.property("fillStyle",pv.color);
- 36
- 37pv.Bar.prototype.type="bar";
- 38
- 39/**
- 40 * The width of the bar, in pixels. If the left position is specified, the bar
- 41 * extends rightward from the left edge; if the right position is specified, the
- 42 * bar extends leftward from the right edge.
- 43 *
- 44 * @type number
- 45 * @name pv.Bar.prototype.width
- 46 */
- 47
- 48/**
- 49 * The height of the bar, in pixels. If the bottom position is specified, the
- 50 * bar extends upward from the bottom edge; if the top position is specified,
- 51 * the bar extends downward from the top edge.
- 52 *
- 53 * @type number
- 54 * @name pv.Bar.prototype.height
- 55 */
- 56
- 57/**
- 58 * The width of stroked lines, in pixels; used in conjunction with
- 59 * <tt>strokeStyle</tt> to stroke the bar's border.
- 60 *
- 61 * @type number
- 62 * @name pv.Bar.prototype.lineWidth
- 63 */
- 64
- 65/**
- 66 * The style of stroked lines; used in conjunction with <tt>lineWidth</tt> to
- 67 * stroke the bar's border. The default value of this property is null, meaning
- 68 * bars are not stroked by default.
- 69 *
- 70 * @type string
- 71 * @name pv.Bar.prototype.strokeStyle
- 72 * @see pv.color
- 73 */
- 74
- 75/**
- 76 * The bar fill style; if non-null, the interior of the bar is filled with the
- 77 * specified color. The default value of this property is a categorical color.
- 78 *
- 79 * @type string
- 80 * @name pv.Bar.prototype.fillStyle
- 81 * @see pv.color
- 82 */
- 83
- 84/**
- 85 * Default properties for bars. By default, there is no stroke and the fill
- 86 * style is a categorical color.
- 87 *
- 88 * @type pv.Bar
- 89 */
- 90pv.Bar.prototype.defaults=newpv.Bar()
- 91.extend(pv.Mark.prototype.defaults)
- 92.lineWidth(1.5)
- 93.fillStyle(pv.Colors.category20().by(pv.parent));
- 94
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Dot.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Dot.js.html
deleted file mode 100644
index 09e7503f..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Dot.js.html
+++ /dev/null
@@ -1,214 +0,0 @@
-
1/**
- 2 * Constructs a new dot mark with default properties. Dots are not typically
- 3 * constructed directly, but by adding to a panel or an existing mark via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Represents a dot; a dot is simply a sized glyph centered at a given
- 7 * point that can also be stroked and filled. The <tt>size</tt> property is
- 8 * proportional to the area of the rendered glyph to encourage meaningful visual
- 9 * encodings. Dots can visually encode up to eight dimensions of data, though
- 10 * this may be unwise due to integrality. See {@link pv.Mark} for details on the
- 11 * prioritization of redundant positioning properties.
- 12 *
- 13 * <p>See also the <a href="../../api/Dot.html">Dot guide</a>.
- 14 *
- 15 * @extends pv.Mark
- 16 */
- 17pv.Dot=function(){
- 18pv.Mark.call(this);
- 19};
- 20
- 21pv.Dot.prototype=pv.extend(pv.Mark)
- 22.property("size",Number)
- 23.property("radius",Number)
- 24.property("shape",String)
- 25.property("angle",Number)
- 26.property("lineWidth",Number)
- 27.property("strokeStyle",pv.color)
- 28.property("fillStyle",pv.color);
- 29
- 30pv.Dot.prototype.type="dot";
- 31
- 32/**
- 33 * The size of the dot, in square pixels. Square pixels are used such that the
- 34 * area of the dot is linearly proportional to the value of the size property,
- 35 * facilitating representative encodings.
- 36 *
- 37 * @see #radius
- 38 * @type number
- 39 * @name pv.Dot.prototype.size
- 40 */
- 41
- 42/**
- 43 * The radius of the dot, in pixels. This is an alternative to using
- 44 * {@link #size}.
- 45 *
- 46 * @see #size
- 47 * @type number
- 48 * @name pv.Dot.prototype.radius
- 49 */
- 50
- 51/**
- 52 * The shape name. Several shapes are supported:<ul>
- 53 *
- 54 * <li>cross
- 55 * <li>triangle
- 56 * <li>diamond
- 57 * <li>square
- 58 * <li>circle
- 59 * <li>tick
- 60 * <li>bar
- 61 *
- 62 * </ul>These shapes can be further changed using the {@link #angle} property;
- 63 * for instance, a cross can be turned into a plus by rotating. Similarly, the
- 64 * tick, which is vertical by default, can be rotated horizontally. Note that
- 65 * some shapes (cross and tick) do not have interior areas, and thus do not
- 66 * support fill style meaningfully.
- 67 *
- 68 * <p>Note: it may be more natural to use the {@link pv.Rule} mark for
- 69 * horizontal and vertical ticks. The tick shape is only necessary if angled
- 70 * ticks are needed.
- 71 *
- 72 * @type string
- 73 * @name pv.Dot.prototype.shape
- 74 */
- 75
- 76/**
- 77 * The rotation angle, in radians. Used to rotate shapes, such as to turn a
- 78 * cross into a plus.
- 79 *
- 80 * @type number
- 81 * @name pv.Dot.prototype.angle
- 82 */
- 83
- 84/**
- 85 * The width of stroked lines, in pixels; used in conjunction with
- 86 * <tt>strokeStyle</tt> to stroke the dot's shape.
- 87 *
- 88 * @type number
- 89 * @name pv.Dot.prototype.lineWidth
- 90 */
- 91
- 92/**
- 93 * The style of stroked lines; used in conjunction with <tt>lineWidth</tt> to
- 94 * stroke the dot's shape. The default value of this property is a categorical
- 95 * color.
- 96 *
- 97 * @type string
- 98 * @name pv.Dot.prototype.strokeStyle
- 99 * @see pv.color
-100 */
-101
-102/**
-103 * The fill style; if non-null, the interior of the dot is filled with the
-104 * specified color. The default value of this property is null, meaning dots are
-105 * not filled by default.
-106 *
-107 * @type string
-108 * @name pv.Dot.prototype.fillStyle
-109 * @see pv.color
-110 */
-111
-112/**
-113 * Default properties for dots. By default, there is no fill and the stroke
-114 * style is a categorical color. The default shape is "circle" with size 20.
-115 *
-116 * @type pv.Dot
-117 */
-118pv.Dot.prototype.defaults=newpv.Dot()
-119.extend(pv.Mark.prototype.defaults)
-120.size(20)
-121.shape("circle")
-122.lineWidth(1.5)
-123.strokeStyle(pv.Colors.category10().by(pv.parent));
-124
-125/**
-126 * Constructs a new dot anchor with default properties. Dots support five
-127 * different anchors:<ul>
-128 *
-129 * <li>top
-130 * <li>left
-131 * <li>center
-132 * <li>bottom
-133 * <li>right
-134 *
-135 * </ul>In addition to positioning properties (left, right, top bottom), the
-136 * anchors support text rendering properties (text-align, text-baseline). Text is
-137 * rendered to appear outside the dot. Note that this behavior is different from
-138 * other mark anchors, which default to rendering text <i>inside</i> the mark.
-139 *
-140 * <p>For consistency with the other mark types, the anchor positions are
-141 * defined in terms of their opposite edge. For example, the top anchor defines
-142 * the bottom property, such that a bar added to the top anchor grows upward.
-143 *
-144 * @param {string} name the anchor name; either a string or a property function.
-145 * @returns {pv.Anchor}
-146 */
-147pv.Dot.prototype.anchor=function(name){
-148varscene;
-149returnpv.Mark.prototype.anchor.call(this,name)
-150.def("$wedge.anchor",function(){
-151scene=this.scene.target;
-152})
-153.left(function(){
-154vars=scene[this.index];
-155switch(this.name()){
-156case"bottom":
-157case"top":
-158case"center":returns.left;
-159case"left":returnnull;
-160}
-161returns.left+s.radius;
-162})
-163.right(function(){
-164vars=scene[this.index];
-165returnthis.name()=="left"?s.right+s.radius:null;
-166})
-167.top(function(){
-168vars=scene[this.index];
-169switch(this.name()){
-170case"left":
-171case"right":
-172case"center":returns.top;
-173case"top":returnnull;
-174}
-175returns.top+s.radius;
-176})
-177.bottom(function(){
-178vars=scene[this.index];
-179returnthis.name()=="top"?s.bottom+s.radius:null;
-180})
-181.textAlign(function(){
-182switch(this.name()){
-183case"left":return"right";
-184case"bottom":
-185case"top":
-186case"center":return"center";
-187}
-188return"left";
-189})
-190.textBaseline(function(){
-191switch(this.name()){
-192case"right":
-193case"left":
-194case"center":return"middle";
-195case"bottom":return"top";
-196}
-197return"bottom";
-198});
-199};
-200
-201/** @private Sets radius based on size or vice versa. */
-202pv.Dot.prototype.buildImplied=function(s){
-203if(s.radius==null)s.radius=Math.sqrt(s.size);
-204elseif(s.size==null)s.size=s.radius*s.radius;
-205pv.Mark.prototype.buildImplied.call(this,s);
-206};
-207
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Image.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Image.js.html
deleted file mode 100644
index 587eed53..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Image.js.html
+++ /dev/null
@@ -1,162 +0,0 @@
-
1/**
- 2 * Constructs a new image with default properties. Images are not typically
- 3 * constructed directly, but by adding to a panel or an existing mark via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Represents an image, either a static resource or a dynamically-
- 7 * generated pixel buffer. Images share the same layout and style properties as
- 8 * bars. The external image resource is specified via the {@link #url}
- 9 * property. The optional fill, if specified, appears beneath the image, while
- 10 * the optional stroke appears above the image.
- 11 *
- 12 * <p>Dynamic images such as heatmaps are supported using the {@link #image}
- 13 * psuedo-property. This function is passed the <i>x</i> and <i>y</i> index, in
- 14 * addition to the current data stack. The return value is a {@link pv.Color},
- 15 * or null for transparent. A string can also be returned, which will be parsed
- 16 * into a color; however, it is typically much faster to return an object with
- 17 * <tt>r</tt>, <tt>g</tt>, <tt>b</tt> and <tt>a</tt> attributes, to avoid the
- 18 * cost of parsing and object instantiation.
- 19 *
- 20 * <p>See {@link pv.Bar} for details on positioning properties.
- 21 *
- 22 * @extends pv.Bar
- 23 */
- 24pv.Image=function(){
- 25pv.Bar.call(this);
- 26};
- 27
- 28pv.Image.prototype=pv.extend(pv.Bar)
- 29.property("url",String)
- 30.property("imageWidth",Number)
- 31.property("imageHeight",Number);
- 32
- 33pv.Image.prototype.type="image";
- 34
- 35/**
- 36 * The URL of the image to display. The set of supported image types is
- 37 * browser-dependent; PNG and JPEG are recommended.
- 38 *
- 39 * @type string
- 40 * @name pv.Image.prototype.url
- 41 */
- 42
- 43/**
- 44 * The width of the image in pixels. For static images, this property is
- 45 * computed implicitly from the loaded image resources. For dynamic images, this
- 46 * property can be used to specify the width of the pixel buffer; otherwise, the
- 47 * value is derived from the <tt>width</tt> property.
- 48 *
- 49 * @type number
- 50 * @name pv.Image.prototype.imageWidth
- 51 */
- 52
- 53/**
- 54 * The height of the image in pixels. For static images, this property is
- 55 * computed implicitly from the loaded image resources. For dynamic images, this
- 56 * property can be used to specify the height of the pixel buffer; otherwise, the
- 57 * value is derived from the <tt>height</tt> property.
- 58 *
- 59 * @type number
- 60 * @name pv.Image.prototype.imageHeight
- 61 */
- 62
- 63/**
- 64 * Default properties for images. By default, there is no stroke or fill style.
- 65 *
- 66 * @type pv.Image
- 67 */
- 68pv.Image.prototype.defaults=newpv.Image()
- 69.extend(pv.Bar.prototype.defaults)
- 70.fillStyle(null);
- 71
- 72/**
- 73 * Specifies the dynamic image function. By default, no image function is
- 74 * specified and the <tt>url</tt> property is used to load a static image
- 75 * resource. If an image function is specified, it will be invoked for each
- 76 * pixel in the image, based on the related <tt>imageWidth</tt> and
- 77 * <tt>imageHeight</tt> properties.
- 78 *
- 79 * <p>For example, given a two-dimensional array <tt>heatmap</tt>, containing
- 80 * numbers in the range [0, 1] in row-major order, a simple monochrome heatmap
- 81 * image can be specified as:
- 82 *
- 83 * <pre>vis.add(pv.Image)
- 84 * .imageWidth(heatmap[0].length)
- 85 * .imageHeight(heatmap.length)
- 86 * .image(pv.ramp("white", "black").by(function(x, y) heatmap[y][x]));</pre>
- 87 *
- 88 * For fastest performance, use an ordinal scale which caches the fixed color
- 89 * palette, or return an object literal with <tt>r</tt>, <tt>g</tt>, <tt>b</tt>
- 90 * and <tt>a</tt> attributes. A {@link pv.Color} or string can also be returned,
- 91 * though this typically results in slower performance.
- 92 *
- 93 * @param {function} f the new sizing function.
- 94 * @returns {pv.Layout.Pack} this.
- 95 */
- 96pv.Image.prototype.image=function(f){
- 97/** @private */
- 98this.$image=function(){
- 99varc=f.apply(this,arguments);
-100returnc==null?pv.Color.transparent
-101:typeofc=="string"?pv.color(c)
-102:c;
-103};
-104returnthis;
-105};
-106
-107/** @private Scan the proto chain for an image function. */
-108pv.Image.prototype.bind=function(){
-109pv.Bar.prototype.bind.call(this);
-110varbinds=this.binds,mark=this;
-111do{
-112binds.image=mark.$image;
-113}while(!binds.image&&(mark=mark.proto));
-114};
-115
-116/** @private */
-117pv.Image.prototype.buildImplied=function(s){
-118pv.Bar.prototype.buildImplied.call(this,s);
-119if(!s.visible)return;
-120
-121/* Compute the implied image dimensions. */
-122if(s.imageWidth==null)s.imageWidth=s.width;
-123if(s.imageHeight==null)s.imageHeight=s.height;
-124
-125/* Compute the pixel values. */
-126if((s.url==null)&&this.binds.image){
-127
-128/* Cache the canvas element to reuse across renders. */
-129varcanvas=this.$canvas||(this.$canvas=document.createElement("canvas")),
-130context=canvas.getContext("2d"),
-131w=s.imageWidth,
-132h=s.imageHeight,
-133stack=pv.Mark.stack,
-134data;
-135
-136/* Evaluate the image function, storing into a CanvasPixelArray. */
-137canvas.width=w;
-138canvas.height=h;
-139data=(s.image=context.createImageData(w,h)).data;
-140stack.unshift(null,null);
-141for(vary=0,p=0;y<h;y++){
-142stack[1]=y;
-143for(varx=0;x<w;x++){
-144stack[0]=x;
-145varcolor=this.binds.image.apply(this,stack);
-146data[p++]=color.r;
-147data[p++]=color.g;
-148data[p++]=color.b;
-149data[p++]=255*color.a;
-150}
-151}
-152stack.splice(0,2);
-153}
-154};
-155
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Label.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Label.js.html
deleted file mode 100644
index 90373fe3..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Label.js.html
+++ /dev/null
@@ -1,163 +0,0 @@
-
1/**
- 2 * Constructs a new label mark with default properties. Labels are not typically
- 3 * constructed directly, but by adding to a panel or an existing mark via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Represents a text label, allowing textual annotation of other marks or
- 7 * arbitrary text within the visualization. The character data must be plain
- 8 * text (unicode), though the text can be styled using the {@link #font}
- 9 * property. If rich text is needed, external HTML elements can be overlaid on
- 10 * the canvas by hand.
- 11 *
- 12 * <p>Labels are positioned using the box model, similarly to {@link Dot}. Thus,
- 13 * a label has no width or height, but merely a text anchor location. The text
- 14 * is positioned relative to this anchor location based on the
- 15 * {@link #textAlign}, {@link #textBaseline} and {@link #textMargin} properties.
- 16 * Furthermore, the text may be rotated using {@link #textAngle}.
- 17 *
- 18 * <p>Labels ignore events, so as to not interfere with event handlers on
- 19 * underlying marks, such as bars. In the future, we may support event handlers
- 20 * on labels.
- 21 *
- 22 * <p>See also the <a href="../../api/Label.html">Label guide</a>.
- 23 *
- 24 * @extends pv.Mark
- 25 */
- 26pv.Label=function(){
- 27pv.Mark.call(this);
- 28};
- 29
- 30pv.Label.prototype=pv.extend(pv.Mark)
- 31.property("text",String)
- 32.property("font",String)
- 33.property("textAngle",Number)
- 34.property("textStyle",pv.color)
- 35.property("textAlign",String)
- 36.property("textBaseline",String)
- 37.property("textMargin",Number)
- 38.property("textDecoration",String)
- 39.property("textShadow",String);
- 40
- 41pv.Label.prototype.type="label";
- 42
- 43/**
- 44 * The character data to render; a string. The default value of the text
- 45 * property is the identity function, meaning the label's associated datum will
- 46 * be rendered using its <tt>toString</tt>.
- 47 *
- 48 * @type string
- 49 * @name pv.Label.prototype.text
- 50 */
- 51
- 52/**
- 53 * The font format, per the CSS Level 2 specification. The default font is "10px
- 54 * sans-serif", for consistency with the HTML 5 canvas element specification.
- 55 * Note that since text is not wrapped, any line-height property will be
- 56 * ignored. The other font-style, font-variant, font-weight, font-size and
- 57 * font-family properties are supported.
- 58 *
- 59 * @see <a href="http://www.w3.org/TR/CSS2/fonts.html#font-shorthand">CSS2 fonts</a>
- 60 * @type string
- 61 * @name pv.Label.prototype.font
- 62 */
- 63
- 64/**
- 65 * The rotation angle, in radians. Text is rotated clockwise relative to the
- 66 * anchor location. For example, with the default left alignment, an angle of
- 67 * Math.PI / 2 causes text to proceed downwards. The default angle is zero.
- 68 *
- 69 * @type number
- 70 * @name pv.Label.prototype.textAngle
- 71 */
- 72
- 73/**
- 74 * The text color. The name "textStyle" is used for consistency with "fillStyle"
- 75 * and "strokeStyle", although it might be better to rename this property (and
- 76 * perhaps use the same name as "strokeStyle"). The default color is black.
- 77 *
- 78 * @type string
- 79 * @name pv.Label.prototype.textStyle
- 80 * @see pv.color
- 81 */
- 82
- 83/**
- 84 * The horizontal text alignment. One of:<ul>
- 85 *
- 86 * <li>left
- 87 * <li>center
- 88 * <li>right
- 89 *
- 90 * </ul>The default horizontal alignment is left.
- 91 *
- 92 * @type string
- 93 * @name pv.Label.prototype.textAlign
- 94 */
- 95
- 96/**
- 97 * The vertical text alignment. One of:<ul>
- 98 *
- 99 * <li>top
-100 * <li>middle
-101 * <li>bottom
-102 *
-103 * </ul>The default vertical alignment is bottom.
-104 *
-105 * @type string
-106 * @name pv.Label.prototype.textBaseline
-107 */
-108
-109/**
-110 * The text margin; may be specified in pixels, or in font-dependent units (such
-111 * as ".1ex"). The margin can be used to pad text away from its anchor location,
-112 * in a direction dependent on the horizontal and vertical alignment
-113 * properties. For example, if the text is left- and middle-aligned, the margin
-114 * shifts the text to the right. The default margin is 3 pixels.
-115 *
-116 * @type number
-117 * @name pv.Label.prototype.textMargin
-118 */
-119
-120/**
-121 * A list of shadow effects to be applied to text, per the CSS Text Level 3
-122 * text-shadow property. An example specification is "0.1em 0.1em 0.1em
-123 * rgba(0,0,0,.5)"; the first length is the horizontal offset, the second the
-124 * vertical offset, and the third the blur radius.
-125 *
-126 * @see <a href="http://www.w3.org/TR/css3-text/#text-shadow">CSS3 text</a>
-127 * @type string
-128 * @name pv.Label.prototype.textShadow
-129 */
-130
-131/**
-132 * A list of decoration to be applied to text, per the CSS Text Level 3
-133 * text-decoration property. An example specification is "underline".
-134 *
-135 * @see <a href="http://www.w3.org/TR/css3-text/#text-decoration">CSS3 text</a>
-136 * @type string
-137 * @name pv.Label.prototype.textDecoration
-138 */
-139
-140/**
-141 * Default properties for labels. See the individual properties for the default
-142 * values.
-143 *
-144 * @type pv.Label
-145 */
-146pv.Label.prototype.defaults=newpv.Label()
-147.extend(pv.Mark.prototype.defaults)
-148.events("none")
-149.text(pv.identity)
-150.font("10px sans-serif")
-151.textAngle(0)
-152.textStyle("black")
-153.textAlign("left")
-154.textBaseline("bottom")
-155.textMargin(3);
-156
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Line.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Line.js.html
deleted file mode 100644
index 899aba7a..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Line.js.html
+++ /dev/null
@@ -1,203 +0,0 @@
-
1/**
- 2 * Constructs a new line mark with default properties. Lines are not typically
- 3 * constructed directly, but by adding to a panel or an existing mark via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Represents a series of connected line segments, or <i>polyline</i>,
- 7 * that can be stroked with a configurable color and thickness. Each
- 8 * articulation point in the line corresponds to a datum; for <i>n</i> points,
- 9 * <i>n</i>-1 connected line segments are drawn. The point is positioned using
- 10 * the box model. Arbitrary paths are also possible, allowing radar plots and
- 11 * other custom visualizations.
- 12 *
- 13 * <p>Like areas, lines can be stroked and filled with arbitrary colors. In most
- 14 * cases, lines are only stroked, but the fill style can be used to construct
- 15 * arbitrary polygons.
- 16 *
- 17 * <p>See also the <a href="../../api/Line.html">Line guide</a>.
- 18 *
- 19 * @extends pv.Mark
- 20 */
- 21pv.Line=function(){
- 22pv.Mark.call(this);
- 23};
- 24
- 25pv.Line.prototype=pv.extend(pv.Mark)
- 26.property("lineWidth",Number)
- 27.property("lineJoin",String)
- 28.property("strokeStyle",pv.color)
- 29.property("fillStyle",pv.color)
- 30.property("segmented",Boolean)
- 31.property("interpolate",String)
- 32.property("eccentricity",Number)
- 33.property("tension",Number);
- 34
- 35pv.Line.prototype.type="line";
- 36
- 37/**
- 38 * The width of stroked lines, in pixels; used in conjunction with
- 39 * <tt>strokeStyle</tt> to stroke the line.
- 40 *
- 41 * @type number
- 42 * @name pv.Line.prototype.lineWidth
- 43 */
- 44
- 45/**
- 46 * The style of stroked lines; used in conjunction with <tt>lineWidth</tt> to
- 47 * stroke the line. The default value of this property is a categorical color.
- 48 *
- 49 * @type string
- 50 * @name pv.Line.prototype.strokeStyle
- 51 * @see pv.color
- 52 */
- 53
- 54/**
- 55 * The type of corners where two lines meet. Accepted values are "bevel",
- 56 * "round" and "miter". The default value is "miter".
- 57 *
- 58 * <p>For segmented lines, only "miter" joins and "linear" interpolation are
- 59 * currently supported. Any other value, including null, will disable joins,
- 60 * producing disjoint line segments. Note that the miter joins must be computed
- 61 * manually (at least in the current SVG renderer); since this calculation may
- 62 * be expensive and unnecessary for small lines, specifying null can improve
- 63 * performance significantly.
- 64 *
- 65 * <p>This property is <i>fixed</i>. See {@link pv.Mark}.
- 66 *
- 67 * @type string
- 68 * @name pv.Line.prototype.lineJoin
- 69 */
- 70
- 71/**
- 72 * The line fill style; if non-null, the interior of the line is closed and
- 73 * filled with the specified color. The default value of this property is a
- 74 * null, meaning that lines are not filled by default.
- 75 *
- 76 * <p>This property is <i>fixed</i>. See {@link pv.Mark}.
- 77 *
- 78 * @type string
- 79 * @name pv.Line.prototype.fillStyle
- 80 * @see pv.color
- 81 */
- 82
- 83/**
- 84 * Whether the line is segmented; whether variations in stroke style, line width
- 85 * and the other properties are treated as fixed. Rendering segmented lines is
- 86 * noticeably slower than non-segmented lines.
- 87 *
- 88 * <p>This property is <i>fixed</i>. See {@link pv.Mark}.
- 89 *
- 90 * @type boolean
- 91 * @name pv.Line.prototype.segmented
- 92 */
- 93
- 94/**
- 95 * How to interpolate between values. Linear interpolation ("linear") is the
- 96 * default, producing a straight line between points. For piecewise constant
- 97 * functions (i.e., step functions), either "step-before" or "step-after" can be
- 98 * specified. To draw a clockwise circular arc between points, specify "polar";
- 99 * to draw a counterclockwise circular arc between points, specify
-100 * "polar-reverse". To draw open uniform b-splines, specify "basis". To draw
-101 * cardinal splines, specify "cardinal"; see also {@link #tension}.
-102 *
-103 * <p>This property is <i>fixed</i>. See {@link pv.Mark}.
-104 *
-105 * @type string
-106 * @name pv.Line.prototype.interpolate
-107 */
-108
-109/**
-110 * The eccentricity of polar line segments; used in conjunction with
-111 * interpolate("polar"). The default value of 0 means that line segments are
-112 * drawn as circular arcs. A value of 1 draws a straight line. A value between 0
-113 * and 1 draws an elliptical arc with the given eccentricity.
-114 *
-115 * @type number
-116 * @name pv.Line.prototype.eccentricity
-117 */
-118
-119/**
-120 * The tension of cardinal splines; used in conjunction with
-121 * interpolate("cardinal"). A value between 0 and 1 draws cardinal splines with
-122 * the given tension. In some sense, the tension can be interpreted as the
-123 * "length" of the tangent; a tension of 1 will yield all zero tangents (i.e.,
-124 * linear interpolation), and a tension of 0 yields a Catmull-Rom spline. The
-125 * default value is 0.7.
-126 *
-127 * <p>This property is <i>fixed</i>. See {@link pv.Mark}.
-128 *
-129 * @type number
-130 * @name pv.Line.prototype.tension
-131 */
-132
-133/**
-134 * Default properties for lines. By default, there is no fill and the stroke
-135 * style is a categorical color. The default interpolation is linear.
-136 *
-137 * @type pv.Line
-138 */
-139pv.Line.prototype.defaults=newpv.Line()
-140.extend(pv.Mark.prototype.defaults)
-141.lineJoin("miter")
-142.lineWidth(1.5)
-143.strokeStyle(pv.Colors.category10().by(pv.parent))
-144.interpolate("linear")
-145.eccentricity(0)
-146.tension(.7);
-147
-148/** @private Reuse Area's implementation for segmented bind & build. */
-149pv.Line.prototype.bind=pv.Area.prototype.bind;
-150pv.Line.prototype.buildInstance=pv.Area.prototype.buildInstance;
-151
-152/**
-153 * Constructs a new line anchor with default properties. Lines support five
-154 * different anchors:<ul>
-155 *
-156 * <li>top
-157 * <li>left
-158 * <li>center
-159 * <li>bottom
-160 * <li>right
-161 *
-162 * </ul>In addition to positioning properties (left, right, top bottom), the
-163 * anchors support text rendering properties (text-align, text-baseline). Text is
-164 * rendered to appear outside the line. Note that this behavior is different
-165 * from other mark anchors, which default to rendering text <i>inside</i> the
-166 * mark.
-167 *
-168 * <p>For consistency with the other mark types, the anchor positions are
-169 * defined in terms of their opposite edge. For example, the top anchor defines
-170 * the bottom property, such that a bar added to the top anchor grows upward.
-171 *
-172 * @param {string} name the anchor name; either a string or a property function.
-173 * @returns {pv.Anchor}
-174 */
-175pv.Line.prototype.anchor=function(name){
-176returnpv.Area.prototype.anchor.call(this,name)
-177.textAlign(function(d){
-178switch(this.name()){
-179case"left":return"right";
-180case"bottom":
-181case"top":
-182case"center":return"center";
-183case"right":return"left";
-184}
-185})
-186.textBaseline(function(d){
-187switch(this.name()){
-188case"right":
-189case"left":
-190case"center":return"middle";
-191case"top":return"bottom";
-192case"bottom":return"top";
-193}
-194});
-195};
-196
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Mark.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Mark.js.html
deleted file mode 100644
index f3b014e8..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Mark.js.html
+++ /dev/null
@@ -1,1219 +0,0 @@
-
1/**
- 2 * Constructs a new mark with default properties. Marks, with the exception of
- 3 * the root panel, are not typically constructed directly; instead, they are
- 4 * added to a panel or an existing mark via {@link pv.Mark#add}.
- 5 *
- 6 * @class Represents a data-driven graphical mark. The <tt>Mark</tt> class is
- 7 * the base class for all graphical marks in Protovis; it does not provide any
- 8 * specific rendering functionality, but together with {@link Panel} establishes
- 9 * the core framework.
- 10 *
- 11 * <p>Concrete mark types include familiar visual elements such as bars, lines
- 12 * and labels. Although a bar mark may be used to construct a bar chart, marks
- 13 * know nothing about charts; it is only through their specification and
- 14 * composition that charts are produced. These building blocks permit many
- 15 * combinatorial possibilities.
- 16 *
- 17 * <p>Marks are associated with <b>data</b>: a mark is generated once per
- 18 * associated datum, mapping the datum to visual <b>properties</b> such as
- 19 * position and color. Thus, a single mark specification represents a set of
- 20 * visual elements that share the same data and visual encoding. The type of
- 21 * mark defines the names of properties and their meaning. A property may be
- 22 * static, ignoring the associated datum and returning a constant; or, it may be
- 23 * dynamic, derived from the associated datum or index. Such dynamic encodings
- 24 * can be specified succinctly using anonymous functions. Special properties
- 25 * called event handlers can be registered to add interactivity.
- 26 *
- 27 * <p>Protovis uses <b>inheritance</b> to simplify the specification of related
- 28 * marks: a new mark can be derived from an existing mark, inheriting its
- 29 * properties. The new mark can then override properties to specify new
- 30 * behavior, potentially in terms of the old behavior. In this way, the old mark
- 31 * serves as the <b>prototype</b> for the new mark. Most mark types share the
- 32 * same basic properties for consistency and to facilitate inheritance.
- 33 *
- 34 * <p>The prioritization of redundant properties is as follows:<ol>
- 35 *
- 36 * <li>If the <tt>width</tt> property is not specified (i.e., null), its value
- 37 * is the width of the parent panel, minus this mark's left and right margins;
- 38 * the left and right margins are zero if not specified.
- 39 *
- 40 * <li>Otherwise, if the <tt>right</tt> margin is not specified, its value is
- 41 * the width of the parent panel, minus this mark's width and left margin; the
- 42 * left margin is zero if not specified.
- 43 *
- 44 * <li>Otherwise, if the <tt>left</tt> property is not specified, its value is
- 45 * the width of the parent panel, minus this mark's width and the right margin.
- 46 *
- 47 * </ol>This prioritization is then duplicated for the <tt>height</tt>,
- 48 * <tt>bottom</tt> and <tt>top</tt> properties, respectively.
- 49 *
- 50 * <p>While most properties are <i>variable</i>, some mark types, such as lines
- 51 * and areas, generate a single visual element rather than a distinct visual
- 52 * element per datum. With these marks, some properties may be <b>fixed</b>.
- 53 * Fixed properties can vary per mark, but not <i>per datum</i>! These
- 54 * properties are evaluated solely for the first (0-index) datum, and typically
- 55 * are specified as a constant. However, it is valid to use a function if the
- 56 * property varies between panels or is dynamically generated.
- 57 *
- 58 * <p>See also the <a href="../../api/">Protovis guide</a>.
- 59 */
- 60pv.Mark=function(){
- 61/*
- 62 * TYPE 0 constant defs
- 63 * TYPE 1 function defs
- 64 * TYPE 2 constant properties
- 65 * TYPE 3 function properties
- 66 * in order of evaluation!
- 67 */
- 68this.$properties=[];
- 69this.$handlers={};
- 70};
- 71
- 72/** @private Records which properties are defined on this mark type. */
- 73pv.Mark.prototype.properties={};
- 74
- 75/** @private Records the cast function for each property. */
- 76pv.Mark.cast={};
- 77
- 78/**
- 79 * @private Defines and registers a property method for the property with the
- 80 * given name. This method should be called on a mark class prototype to define
- 81 * each exposed property. (Note this refers to the JavaScript
- 82 * <tt>prototype</tt>, not the Protovis mark prototype, which is the {@link
- 83 * #proto} field.)
- 84 *
- 85 * <p>The created property method supports several modes of invocation: <ol>
- 86 *
- 87 * <li>If invoked with a <tt>Function</tt> argument, this function is evaluated
- 88 * for each associated datum. The return value of the function is used as the
- 89 * computed property value. The context of the function (<tt>this</tt>) is this
- 90 * mark. The arguments to the function are the associated data of this mark and
- 91 * any enclosing panels. For example, a linear encoding of numerical data to
- 92 * height is specified as
- 93 *
- 94 * <pre>m.height(function(d) d * 100);</pre>
- 95 *
- 96 * The expression <tt>d * 100</tt> will be evaluated for the height property of
- 97 * each mark instance. The return value of the property method (e.g.,
- 98 * <tt>m.height</tt>) is this mark (<tt>m</tt>)).<p>
- 99 *
-100 * <li>If invoked with a non-function argument, the property is treated as a
-101 * constant. The return value of the property method (e.g., <tt>m.height</tt>)
-102 * is this mark.<p>
-103 *
-104 * <li>If invoked with no arguments, the computed property value for the current
-105 * mark instance in the scene graph is returned. This facilitates <i>property
-106 * chaining</i>, where one mark's properties are defined in terms of another's.
-107 * For example, to offset a mark's location from its prototype, you might say
-108 *
-109 * <pre>m.top(function() this.proto.top() + 10);</pre>
-110 *
-111 * Note that the index of the mark being evaluated (in the above example,
-112 * <tt>this.proto</tt>) is inherited from the <tt>Mark</tt> class and set by
-113 * this mark. So, if the fifth element's top property is being evaluated, the
-114 * fifth instance of <tt>this.proto</tt> will similarly be queried for the value
-115 * of its top property. If the mark being evaluated has a different number of
-116 * instances, or its data is unrelated, the behavior of this method is
-117 * undefined. In these cases it may be better to index the <tt>scene</tt>
-118 * explicitly to specify the exact instance.
-119 *
-120 * </ol><p>Property names should follow standard JavaScript method naming
-121 * conventions, using lowerCamel-style capitalization.
-122 *
-123 * <p>In addition to creating the property method, every property is registered
-124 * in the {@link #properties} map on the <tt>prototype</tt>. Although this is an
-125 * instance field, it is considered immutable and shared by all instances of a
-126 * given mark type. The <tt>properties</tt> map can be queried to see if a mark
-127 * type defines a particular property, such as width or height.
-128 *
-129 * @param {string} name the property name.
-130 * @param {function} [cast] the cast function for this property.
-131 */
-132pv.Mark.prototype.property=function(name,cast){
-133if(!this.hasOwnProperty("properties")){
-134this.properties=pv.extend(this.properties);
-135}
-136this.properties[name]=true;
-137
-138/*
-139 * Define the setter-getter globally, since the default behavior should be the
-140 * same for all properties, and since the Protovis inheritance chain is
-141 * independent of the JavaScript inheritance chain. For example, anchors
-142 * define a "name" property that is evaluated on derived marks, even though
-143 * those marks don't normally have a name.
-144 */
-145pv.Mark.prototype.propertyMethod(name,false,pv.Mark.cast[name]=cast);
-146returnthis;
-147};
-148
-149/**
-150 * @private Defines a setter-getter for the specified property.
-151 *
-152 * <p>If a cast function has been assigned to the specified property name, the
-153 * property function is wrapped by the cast function, or, if a constant is
-154 * specified, the constant is immediately cast. Note, however, that if the
-155 * property value is null, the cast function is not invoked.
-156 *
-157 * @param {string} name the property name.
-158 * @param {boolean} [def] whether is a property or a def.
-159 * @param {function} [cast] the cast function for this property.
-160 */
-161pv.Mark.prototype.propertyMethod=function(name,def,cast){
-162if(!cast)cast=pv.Mark.cast[name];
-163this[name]=function(v){
-164
-165/* If this is a def, use it rather than property. */
-166if(def&&this.scene){
-167vardefs=this.scene.defs;
-168if(arguments.length){
-169defs[name]={
-170id:(v==null)?0:pv.id(),
-171value:((v!=null)&&cast)?cast(v):v
-172};
-173returnthis;
-174}
-175returndefs[name]?defs[name].value:null;
-176}
-177
-178/* If arguments are specified, set the property value. */
-179if(arguments.length){
-180vartype=!def<<1|(typeofv=="function");
-181this.propertyValue(name,(type&1&&cast)?function(){
-182varx=v.apply(this,arguments);
-183return(x!=null)?cast(x):null;
-184}:(((v!=null)&&cast)?cast(v):v)).type=type;
-185returnthis;
-186}
-187
-188returnthis.instance()[name];
-189};
-190};
-191
-192/** @private Sets the value of the property <i>name</i> to <i>v</i>. */
-193pv.Mark.prototype.propertyValue=function(name,v){
-194varproperties=this.$properties,p={name:name,id:pv.id(),value:v};
-195for(vari=0;i<properties.length;i++){
-196if(properties[i].name==name){
-197properties.splice(i,1);
-198break;
-199}
-200}
-201properties.push(p);
-202returnp;
-203};
-204
-205/* Define all global properties. */
-206pv.Mark.prototype
-207.property("data")
-208.property("visible",Boolean)
-209.property("left",Number)
-210.property("right",Number)
-211.property("top",Number)
-212.property("bottom",Number)
-213.property("cursor",String)
-214.property("title",String)
-215.property("reverse",Boolean)
-216.property("antialias",Boolean)
-217.property("events",String);
-218
-219/**
-220 * The mark type; a lower camelCase name. The type name controls rendering
-221 * behavior, and unless the rendering engine is extended, must be one of the
-222 * built-in concrete mark types: area, bar, dot, image, label, line, panel,
-223 * rule, or wedge.
-224 *
-225 * @type string
-226 * @name pv.Mark.prototype.type
-227 */
-228
-229/**
-230 * The mark prototype, possibly undefined, from which to inherit property
-231 * functions. The mark prototype is not necessarily of the same type as this
-232 * mark. Any properties defined on this mark will override properties inherited
-233 * either from the prototype or from the type-specific defaults.
-234 *
-235 * @type pv.Mark
-236 * @name pv.Mark.prototype.proto
-237 */
-238
-239/**
-240 * The enclosing parent panel. The parent panel is generally undefined only for
-241 * the root panel; however, it is possible to create "offscreen" marks that are
-242 * used only for inheritance purposes.
-243 *
-244 * @type pv.Panel
-245 * @name pv.Mark.prototype.parent
-246 */
-247
-248/**
-249 * The child index. -1 if the enclosing parent panel is null; otherwise, the
-250 * zero-based index of this mark into the parent panel's <tt>children</tt> array.
-251 *
-252 * @type number
-253 */
-254pv.Mark.prototype.childIndex=-1;
-255
-256/**
-257 * The mark index. The value of this field depends on which instance (i.e.,
-258 * which element of the data array) is currently being evaluated. During the
-259 * build phase, the index is incremented over each datum; when handling events,
-260 * the index is set to the instance that triggered the event.
-261 *
-262 * @type number
-263 */
-264pv.Mark.prototype.index=-1;
-265
-266/**
-267 * The current scale factor, based on any enclosing transforms. The current
-268 * scale can be used to create scale-independent graphics. For example, to
-269 * define a dot that has a radius of 10 irrespective of any zooming, say:
-270 *
-271 * <pre>dot.radius(function() 10 / this.scale)</pre>
-272 *
-273 * Note that the stroke width and font size are defined irrespective of scale
-274 * (i.e., in screen space) already. Also note that when a transform is applied
-275 * to a panel, the scale affects only the child marks, not the panel itself.
-276 *
-277 * @type number
-278 * @see pv.Panel#transform
-279 */
-280pv.Mark.prototype.scale=1;
-281
-282/**
-283 * @private The scene graph. The scene graph is an array of objects; each object
-284 * (or "node") corresponds to an instance of this mark and an element in the
-285 * data array. The scene graph can be traversed to lookup previously-evaluated
-286 * properties.
-287 *
-288 * @name pv.Mark.prototype.scene
-289 */
-290
-291/**
-292 * The root parent panel. This may be undefined for "offscreen" marks that are
-293 * created for inheritance purposes only.
-294 *
-295 * @type pv.Panel
-296 * @name pv.Mark.prototype.root
-297 */
-298
-299/**
-300 * The data property; an array of objects. The size of the array determines the
-301 * number of marks that will be instantiated; each element in the array will be
-302 * passed to property functions to compute the property values. Typically, the
-303 * data property is specified as a constant array, such as
-304 *
-305 * <pre>m.data([1, 2, 3, 4, 5]);</pre>
-306 *
-307 * However, it is perfectly acceptable to define the data property as a
-308 * function. This function might compute the data dynamically, allowing
-309 * different data to be used per enclosing panel. For instance, in the stacked
-310 * area graph example (see {@link #scene}), the data function on the area mark
-311 * dereferences each series.
-312 *
-313 * @type array
-314 * @name pv.Mark.prototype.data
-315 */
-316
-317/**
-318 * The visible property; a boolean determining whether or not the mark instance
-319 * is visible. If a mark instance is not visible, its other properties will not
-320 * be evaluated. Similarly, for panels no child marks will be rendered.
-321 *
-322 * @type boolean
-323 * @name pv.Mark.prototype.visible
-324 */
-325
-326/**
-327 * The left margin; the distance, in pixels, between the left edge of the
-328 * enclosing panel and the left edge of this mark. Note that in some cases this
-329 * property may be redundant with the right property, or with the conjunction of
-330 * right and width.
-331 *
-332 * @type number
-333 * @name pv.Mark.prototype.left
-334 */
-335
-336/**
-337 * The right margin; the distance, in pixels, between the right edge of the
-338 * enclosing panel and the right edge of this mark. Note that in some cases this
-339 * property may be redundant with the left property, or with the conjunction of
-340 * left and width.
-341 *
-342 * @type number
-343 * @name pv.Mark.prototype.right
-344 */
-345
-346/**
-347 * The top margin; the distance, in pixels, between the top edge of the
-348 * enclosing panel and the top edge of this mark. Note that in some cases this
-349 * property may be redundant with the bottom property, or with the conjunction
-350 * of bottom and height.
-351 *
-352 * @type number
-353 * @name pv.Mark.prototype.top
-354 */
-355
-356/**
-357 * The bottom margin; the distance, in pixels, between the bottom edge of the
-358 * enclosing panel and the bottom edge of this mark. Note that in some cases
-359 * this property may be redundant with the top property, or with the conjunction
-360 * of top and height.
-361 *
-362 * @type number
-363 * @name pv.Mark.prototype.bottom
-364 */
-365
-366/**
-367 * The cursor property; corresponds to the CSS cursor property. This is
-368 * typically used in conjunction with event handlers to indicate interactivity.
-369 *
-370 * @type string
-371 * @name pv.Mark.prototype.cursor
-372 * @see <a href="http://www.w3.org/TR/CSS2/ui.html#propdef-cursor">CSS2 cursor</a>
-373 */
-374
-375/**
-376 * The title property; corresponds to the HTML/SVG title property, allowing the
-377 * general of simple plain text tooltips.
-378 *
-379 * @type string
-380 * @name pv.Mark.prototype.title
-381 */
-382
-383/**
-384 * The events property; corresponds to the SVG pointer-events property,
-385 * specifying how the mark should participate in mouse events. The default value
-386 * is "painted". Supported values are:
-387 *
-388 * <p>"painted": The given mark may receive events when the mouse is over a
-389 * "painted" area. The painted areas are the interior (i.e., fill) of the mark
-390 * if a 'fillStyle' is specified, and the perimeter (i.e., stroke) of the mark
-391 * if a 'strokeStyle' is specified.
-392 *
-393 * <p>"all": The given mark may receive events when the mouse is over either the
-394 * interior (i.e., fill) or the perimeter (i.e., stroke) of the mark, regardless
-395 * of the specified fillStyle and strokeStyle.
-396 *
-397 * <p>"none": The given mark may not receive events.
-398 *
-399 * @type string
-400 * @name pv.Mark.prototype.events
-401 */
-402
-403/**
-404 * The reverse property; a boolean determining whether marks are ordered from
-405 * front-to-back or back-to-front. SVG does not support explicit z-ordering;
-406 * shapes are rendered in the order they appear. Thus, by default, marks are
-407 * rendered in data order. Setting the reverse property to false reverses the
-408 * order in which they are rendered; however, the properties are still evaluated
-409 * (i.e., built) in forward order.
-410 *
-411 * @type boolean
-412 * @name pv.Mark.prototype.reverse
-413 */
-414
-415/**
-416 * Default properties for all mark types. By default, the data array is the
-417 * parent data as a single-element array; if the data property is not specified,
-418 * this causes each mark to be instantiated as a singleton with the parents
-419 * datum. The visible property is true by default, and the reverse property is
-420 * false.
-421 *
-422 * @type pv.Mark
-423 */
-424pv.Mark.prototype.defaults=newpv.Mark()
-425.data(function(d){return[d];})
-426.visible(true)
-427.antialias(true)
-428.events("painted");
-429
-430/**
-431 * Sets the prototype of this mark to the specified mark. Any properties not
-432 * defined on this mark may be inherited from the specified prototype mark, or
-433 * its prototype, and so on. The prototype mark need not be the same type of
-434 * mark as this mark. (Note that for inheritance to be useful, properties with
-435 * the same name on different mark types should have equivalent meaning.)
-436 *
-437 * @param {pv.Mark} proto the new prototype.
-438 * @returns {pv.Mark} this mark.
-439 * @see #add
-440 */
-441pv.Mark.prototype.extend=function(proto){
-442this.proto=proto;
-443returnthis;
-444};
-445
-446/**
-447 * Adds a new mark of the specified type to the enclosing parent panel, whilst
-448 * simultaneously setting the prototype of the new mark to be this mark.
-449 *
-450 * @param {function} type the type of mark to add; a constructor, such as
-451 * <tt>pv.Bar</tt>.
-452 * @returns {pv.Mark} the new mark.
-453 * @see #extend
-454 */
-455pv.Mark.prototype.add=function(type){
-456returnthis.parent.add(type).extend(this);
-457};
-458
-459/**
-460 * Defines a custom property on this mark. Custom properties are currently
-461 * fixed, in that they are initialized once per mark set (i.e., per parent panel
-462 * instance). Custom properties can be used to store local state for the mark,
-463 * such as data needed by other properties (e.g., a custom scale) or interaction
-464 * state.
-465 *
-466 * <p>WARNING We plan on changing this feature in a future release to define
-467 * standard properties, as opposed to <i>fixed</i> properties that behave
-468 * idiosyncratically within event handlers. Furthermore, we recommend storing
-469 * state in an external data structure, rather than tying it to the
-470 * visualization specification as with defs.
-471 *
-472 * @param {string} name the name of the local variable.
-473 * @param {function} [v] an optional initializer; may be a constant or a
-474 * function.
-475 */
-476pv.Mark.prototype.def=function(name,v){
-477this.propertyMethod(name,true);
-478returnthis[name](arguments.length>1?v:null);
-479};
-480
-481/**
-482 * Returns an anchor with the specified name. All marks support the five
-483 * standard anchor names:<ul>
-484 *
-485 * <li>top
-486 * <li>left
-487 * <li>center
-488 * <li>bottom
-489 * <li>right
-490 *
-491 * </ul>In addition to positioning properties (left, right, top bottom), the
-492 * anchors support text rendering properties (text-align, text-baseline). Text is
-493 * rendered to appear inside the mark by default.
-494 *
-495 * <p>To facilitate stacking, anchors are defined in terms of their opposite
-496 * edge. For example, the top anchor defines the bottom property, such that the
-497 * mark extends upwards; the bottom anchor instead defines the top property,
-498 * such that the mark extends downwards. See also {@link pv.Layout.Stack}.
-499 *
-500 * <p>While anchor names are typically constants, the anchor name is a true
-501 * property, which means you can specify a function to compute the anchor name
-502 * dynamically. See the {@link pv.Anchor#name} property for details.
-503 *
-504 * @param {string} name the anchor name; either a string or a property function.
-505 * @returns {pv.Anchor} the new anchor.
-506 */
-507pv.Mark.prototype.anchor=function(name){
-508vartarget=this,scene;
-509
-510/* Default anchor name. */
-511if(!name)name="center";
-512
-513/** @private Find the instances of target that match source. */
-514functioninstances(source){
-515varmark=target,index=[];
-516
-517/* Mirrored descent. */
-518while(!(scene=mark.scene)){
-519source=source.parent;
-520index.push({index:source.index,childIndex:mark.childIndex});
-521mark=mark.parent;
-522}
-523while(index.length){
-524vari=index.pop();
-525scene=scene[i.index].children[i.childIndex];
-526}
-527
-528/*
-529 * When the anchor target is also an ancestor, as in the case of adding
-530 * to a panel anchor, only generate one instance per panel. Also, set
-531 * the margins to zero, since they are offset by the enclosing panel.
-532 */
-533if(target.hasOwnProperty("index")){
-534vars=pv.extend(scene[target.index]);
-535s.right=s.top=s.left=s.bottom=0;
-536return[s];
-537}
-538returnscene;
-539}
-540
-541returnnewpv.Anchor(this)
-542.name(name)
-543.def("$mark.anchor",function(){
-544scene=this.scene.target=instances(this);
-545})
-546.data(function(){
-547returnscene.map(function(s){returns.data;});
-548})
-549.visible(function(){
-550returnscene[this.index].visible;
-551})
-552.left(function(){
-553vars=scene[this.index],w=s.width||0;
-554switch(this.name()){
-555case"bottom":
-556case"top":
-557case"center":returns.left+w/2;
-558case"left":returnnull;
-559}
-560returns.left+w;
-561})
-562.top(function(){
-563vars=scene[this.index],h=s.height||0;
-564switch(this.name()){
-565case"left":
-566case"right":
-567case"center":returns.top+h/2;
-568case"top":returnnull;
-569}
-570returns.top+h;
-571})
-572.right(function(){
-573vars=scene[this.index];
-574returnthis.name()=="left"?s.right+(s.width||0):null;
-575})
-576.bottom(function(){
-577vars=scene[this.index];
-578returnthis.name()=="top"?s.bottom+(s.height||0):null;
-579})
-580.textAlign(function(){
-581switch(this.name()){
-582case"bottom":
-583case"top":
-584case"center":return"center";
-585case"right":return"right";
-586}
-587return"left";
-588})
-589.textBaseline(function(){
-590switch(this.name()){
-591case"right":
-592case"left":
-593case"center":return"middle";
-594case"top":return"top";
-595}
-596return"bottom";
-597});
-598};
-599
-600/**
-601 * Returns the anchor target of this mark, if it is derived from an anchor;
-602 * otherwise returns null. For example, if a label is derived from a bar anchor,
-603 *
-604 * <pre>bar.anchor("top").add(pv.Label);</pre>
-605 *
-606 * then property functions on the label can refer to the bar via the
-607 * <tt>anchorTarget</tt> method. This method is also useful for mark types
-608 * defining properties on custom anchors.
-609 *
-610 * @returns {pv.Mark} the anchor target of this mark; possibly null.
-611 */
-612pv.Mark.prototype.anchorTarget=function(){
-613returnthis.proto.anchorTarget();
-614};
-615
-616/**
-617 * Alias for setting the left, right, top and bottom properties simultaneously.
-618 *
-619 * @see #left
-620 * @see #right
-621 * @see #top
-622 * @see #bottom
-623 * @returns {pv.Mark} this.
-624 */
-625pv.Mark.prototype.margin=function(n){
-626returnthis.left(n).right(n).top(n).bottom(n);
-627};
-628
-629/**
-630 * @private Returns the current instance of this mark in the scene graph. This
-631 * is typically equivalent to <tt>this.scene[this.index]</tt>, however if the
-632 * scene or index is unset, the default instance of the mark is returned. If no
-633 * default is set, the default is the last instance. Similarly, if the scene or
-634 * index of the parent panel is unset, the default instance of this mark in the
-635 * last instance of the enclosing panel is returned, and so on.
-636 *
-637 * @returns a node in the scene graph.
-638 */
-639pv.Mark.prototype.instance=function(defaultIndex){
-640varscene=this.scene||this.parent.instance(-1).children[this.childIndex],
-641index=!arguments.length||this.hasOwnProperty("index")?this.index:defaultIndex;
-642returnscene[index<0?scene.length-1:index];
-643};
-644
-645/**
-646 * @private Returns the first instance of this mark in the scene graph. This
-647 * method can only be called when the mark is bound to the scene graph (for
-648 * example, from an event handler, or within a property function).
-649 *
-650 * @returns a node in the scene graph.
-651 */
-652pv.Mark.prototype.first=function(){
-653returnthis.scene[0];
-654};
-655
-656/**
-657 * @private Returns the last instance of this mark in the scene graph. This
-658 * method can only be called when the mark is bound to the scene graph (for
-659 * example, from an event handler, or within a property function). In addition,
-660 * note that mark instances are built sequentially, so the last instance of this
-661 * mark may not yet be constructed.
-662 *
-663 * @returns a node in the scene graph.
-664 */
-665pv.Mark.prototype.last=function(){
-666returnthis.scene[this.scene.length-1];
-667};
-668
-669/**
-670 * @private Returns the previous instance of this mark in the scene graph, or
-671 * null if this is the first instance.
-672 *
-673 * @returns a node in the scene graph, or null.
-674 */
-675pv.Mark.prototype.sibling=function(){
-676return(this.index==0)?null:this.scene[this.index-1];
-677};
-678
-679/**
-680 * @private Returns the current instance in the scene graph of this mark, in the
-681 * previous instance of the enclosing parent panel. May return null if this
-682 * instance could not be found.
-683 *
-684 * @returns a node in the scene graph, or null.
-685 */
-686pv.Mark.prototype.cousin=function(){
-687varp=this.parent,s=p&&p.sibling();
-688return(s&&s.children)?s.children[this.childIndex][this.index]:null;
-689};
-690
-691/**
-692 * Renders this mark, including recursively rendering all child marks if this is
-693 * a panel. This method finds all instances of this mark and renders them. This
-694 * method descends recursively to the level of the mark to be rendered, finding
-695 * all visible instances of the mark. After the marks are rendered, the scene
-696 * and index attributes are removed from the mark to restore them to a clean
-697 * state.
-698 *
-699 * <p>If an enclosing panel has an index property set (as is the case inside in
-700 * an event handler), then only instances of this mark inside the given instance
-701 * of the panel will be rendered; otherwise, all visible instances of the mark
-702 * will be rendered.
-703 */
-704pv.Mark.prototype.render=function(){
-705varparent=this.parent,
-706stack=pv.Mark.stack;
-707
-708/* For the first render, take it from the top. */
-709if(parent&&!this.root.scene){
-710this.root.render();
-711return;
-712}
-713
-714/* Record the path to this mark. */
-715varindexes=[];
-716for(varmark=this;mark.parent;mark=mark.parent){
-717indexes.unshift(mark.childIndex);
-718}
-719
-720/** @private */
-721functionrender(mark,depth,scale){
-722mark.scale=scale;
-723if(depth<indexes.length){
-724stack.unshift(null);
-725if(mark.hasOwnProperty("index")){
-726renderInstance(mark,depth,scale);
-727}else{
-728for(vari=0,n=mark.scene.length;i<n;i++){
-729mark.index=i;
-730renderInstance(mark,depth,scale);
-731}
-732deletemark.index;
-733}
-734stack.shift();
-735}else{
-736mark.build();
-737
-738/*
-739 * In the update phase, the scene is rendered by creating and updating
-740 * elements and attributes in the SVG image. No properties are evaluated
-741 * during the update phase; instead the values computed previously in the
-742 * build phase are simply translated into SVG. The update phase is
-743 * decoupled (see pv.Scene) to allow different rendering engines.
-744 */
-745pv.Scene.scale=scale;
-746pv.Scene.updateAll(mark.scene);
-747}
-748deletemark.scale;
-749}
-750
-751/**
-752 * @private Recursively renders the current instance of the specified mark.
-753 * This is slightly tricky because `index` and `scene` properties may or may
-754 * not already be set; if they are set, it means we are rendering only a
-755 * specific instance; if they are unset, we are rendering all instances.
-756 * Furthermore, we must preserve the original context of these properties when
-757 * rendering completes.
-758 *
-759 * <p>Another tricky aspect is that the `scene` attribute should be set for
-760 * any preceding children, so as to allow property chaining. This is
-761 * consistent with first-pass rendering.
-762 */
-763functionrenderInstance(mark,depth,scale){
-764vars=mark.scene[mark.index],i;
-765if(s.visible){
-766varchildIndex=indexes[depth],
-767child=mark.children[childIndex];
-768
-769/* Set preceding child scenes. */
-770for(i=0;i<childIndex;i++){
-771mark.children[i].scene=s.children[i];
-772}
-773
-774/* Set current child scene, if necessary. */
-775stack[0]=s.data;
-776if(child.scene){
-777render(child,depth+1,scale*s.transform.k);
-778}else{
-779child.scene=s.children[childIndex];
-780render(child,depth+1,scale*s.transform.k);
-781deletechild.scene;
-782}
-783
-784/* Clear preceding child scenes. */
-785for(i=0;i<childIndex;i++){
-786deletemark.children[i].scene;
-787}
-788}
-789}
-790
-791/* Bind this mark's property definitions. */
-792this.bind();
-793
-794/* The render context is the first ancestor with an explicit index. */
-795while(parent&&!parent.hasOwnProperty("index"))parent=parent.parent;
-796
-797/* Recursively render all instances of this mark. */
-798this.context(
-799parent?parent.scene:undefined,
-800parent?parent.index:-1,
-801function(){render(this.root,0,1);});
-802};
-803
-804/** @private Stores the current data stack. */
-805pv.Mark.stack=[];
-806
-807/**
-808 * @private In the bind phase, inherited property definitions are cached so they
-809 * do not need to be queried during build.
-810 */
-811pv.Mark.prototype.bind=function(){
-812varseen={},types=[[],[],[],[]],data,visible;
-813
-814/** Scans the proto chain for the specified mark. */
-815functionbind(mark){
-816do{
-817varproperties=mark.$properties;
-818for(vari=properties.length-1;i>=0;i--){
-819varp=properties[i];
-820if(!(p.nameinseen)){
-821seen[p.name]=p;
-822switch(p.name){
-823case"data":data=p;break;
-824case"visible":visible=p;break;
-825default:types[p.type].push(p);break;
-826}
-827}
-828}
-829}while(mark=mark.proto);
-830}
-831
-832/* Scan the proto chain for all defined properties. */
-833bind(this);
-834bind(this.defaults);
-835types[1].reverse();
-836types[3].reverse();
-837
-838/* Any undefined properties are null. */
-839varmark=this;
-840dofor(varnameinmark.properties){
-841if(!(nameinseen)){
-842types[2].push(seen[name]={name:name,type:2,value:null});
-843}
-844}while(mark=mark.proto);
-845
-846/* Define setter-getter for inherited defs. */
-847vardefs=types[0].concat(types[1]);
-848for(vari=0;i<defs.length;i++){
-849this.propertyMethod(defs[i].name,true);
-850}
-851
-852/* Setup binds to evaluate constants before functions. */
-853this.binds={
-854properties:seen,
-855data:data,
-856defs:defs,
-857required:[visible],
-858optional:pv.blend(types)
-859};
-860};
-861
-862/**
-863 * @private Evaluates properties and computes implied properties. Properties are
-864 * stored in the {@link #scene} array for each instance of this mark.
-865 *
-866 * <p>As marks are built recursively, the {@link #index} property is updated to
-867 * match the current index into the data array for each mark. Note that the
-868 * index property is only set for the mark currently being built and its
-869 * enclosing parent panels. The index property for other marks is unset, but is
-870 * inherited from the global <tt>Mark</tt> class prototype. This allows mark
-871 * properties to refer to properties on other marks <i>in the same panel</i>
-872 * conveniently; however, in general it is better to reference mark instances
-873 * specifically through the scene graph rather than depending on the magical
-874 * behavior of {@link #index}.
-875 *
-876 * <p>The root scene array has a special property, <tt>data</tt>, which stores
-877 * the current data stack. The first element in this stack is the current datum,
-878 * followed by the datum of the enclosing parent panel, and so on. The data
-879 * stack should not be accessed directly; instead, property functions are passed
-880 * the current data stack as arguments.
-881 *
-882 * <p>The evaluation of the <tt>data</tt> and <tt>visible</tt> properties is
-883 * special. The <tt>data</tt> property is evaluated first; unlike the other
-884 * properties, the data stack is from the parent panel, rather than the current
-885 * mark, since the data is not defined until the data property is evaluated.
-886 * The <tt>visisble</tt> property is subsequently evaluated for each instance;
-887 * only if true will the {@link #buildInstance} method be called, evaluating
-888 * other properties and recursively building the scene graph.
-889 *
-890 * <p>If this mark is being re-built, any old instances of this mark that no
-891 * longer exist (because the new data array contains fewer elements) will be
-892 * cleared using {@link #clearInstance}.
-893 *
-894 * @param parent the instance of the parent panel from the scene graph.
-895 */
-896pv.Mark.prototype.build=function(){
-897varscene=this.scene,stack=pv.Mark.stack;
-898if(!scene){
-899scene=this.scene=[];
-900scene.mark=this;
-901scene.type=this.type;
-902scene.childIndex=this.childIndex;
-903if(this.parent){
-904scene.parent=this.parent.scene;
-905scene.parentIndex=this.parent.index;
-906}
-907}
-908
-909/* Evaluate defs. */
-910if(this.binds.defs.length){
-911vardefs=scene.defs;
-912if(!defs)scene.defs=defs={};
-913for(vari=0;i<this.binds.defs.length;i++){
-914varp=this.binds.defs[i],d=defs[p.name];
-915if(!d||(p.id>d.id)){
-916defs[p.name]={
-917id:0,// this def will be re-evaluated on next build
-918value:(p.type&1)?p.value.apply(this,stack):p.value
-919};
-920}
-921}
-922}
-923
-924/* Evaluate special data property. */
-925vardata=this.binds.data;
-926data=data.type&1?data.value.apply(this,stack):data.value;
-927
-928/* Create, update and delete scene nodes. */
-929stack.unshift(null);
-930scene.length=data.length;
-931for(vari=0;i<data.length;i++){
-932pv.Mark.prototype.index=this.index=i;
-933vars=scene[i];
-934if(!s)scene[i]=s={};
-935s.data=stack[0]=data[i];
-936this.buildInstance(s);
-937}
-938pv.Mark.prototype.index=-1;
-939deletethis.index;
-940stack.shift();
-941
-942returnthis;
-943};
-944
-945/**
-946 * @private Evaluates the specified array of properties for the specified
-947 * instance <tt>s</tt> in the scene graph.
-948 *
-949 * @param s a node in the scene graph; the instance of the mark to build.
-950 * @param properties an array of properties.
-951 */
-952pv.Mark.prototype.buildProperties=function(s,properties){
-953for(vari=0,n=properties.length;i<n;i++){
-954varp=properties[i],v=p.value;// assume case 2 (constant)
-955switch(p.type){
-956case0:
-957case1:v=this.scene.defs[p.name].value;break;
-958case3:v=v.apply(this,pv.Mark.stack);break;
-959}
-960s[p.name]=v;
-961}
-962};
-963
-964/**
-965 * @private Evaluates all of the properties for this mark for the specified
-966 * instance <tt>s</tt> in the scene graph. The set of properties to evaluate is
-967 * retrieved from the {@link #properties} array for this mark type (see {@link
-968 * #type}). After these properties are evaluated, any <b>implied</b> properties
-969 * may be computed by the mark and set on the scene graph; see
-970 * {@link #buildImplied}.
-971 *
-972 * <p>For panels, this method recursively builds the scene graph for all child
-973 * marks as well. In general, this method should not need to be overridden by
-974 * concrete mark types.
-975 *
-976 * @param s a node in the scene graph; the instance of the mark to build.
-977 */
-978pv.Mark.prototype.buildInstance=function(s){
-979this.buildProperties(s,this.binds.required);
-980if(s.visible){
-981this.buildProperties(s,this.binds.optional);
-982this.buildImplied(s);
-983}
-984};
-985
-986/**
-987 * @private Computes the implied properties for this mark for the specified
-988 * instance <tt>s</tt> in the scene graph. Implied properties are those with
-989 * dependencies on multiple other properties; for example, the width property
-990 * may be implied if the left and right properties are set. This method can be
-991 * overridden by concrete mark types to define new implied properties, if
-992 * necessary.
-993 *
-994 * @param s a node in the scene graph; the instance of the mark to build.
-995 */
-996pv.Mark.prototype.buildImplied=function(s){
-997varl=s.left;
-998varr=s.right;
-999vart=s.top;
-1000varb=s.bottom;
-1001
-1002/* Assume width and height are zero if not supported by this mark type. */
-1003varp=this.properties;
-1004varw=p.width?s.width:0;
-1005varh=p.height?s.height:0;
-1006
-1007/* Compute implied width, right and left. */
-1008varwidth=this.parent?this.parent.width():(w+l+r);
-1009if(w==null){
-1010w=width-(r=r||0)-(l=l||0);
-1011}elseif(r==null){
-1012r=width-w-(l=l||0);
-1013}elseif(l==null){
-1014l=width-w-(r=r||0);
-1015}
-1016
-1017/* Compute implied height, bottom and top. */
-1018varheight=this.parent?this.parent.height():(h+t+b);
-1019if(h==null){
-1020h=height-(t=t||0)-(b=b||0);
-1021}elseif(b==null){
-1022b=height-h-(t=t||0);
-1023}elseif(t==null){
-1024t=height-h-(b=b||0);
-1025}
-1026
-1027s.left=l;
-1028s.right=r;
-1029s.top=t;
-1030s.bottom=b;
-1031
-1032/* Only set width and height if they are supported by this mark type. */
-1033if(p.width)s.width=w;
-1034if(p.height)s.height=h;
-1035
-1036/* Set any null colors to pv.Color.transparent. */
-1037if(p.textStyle&&!s.textStyle)s.textStyle=pv.Color.transparent;
-1038if(p.fillStyle&&!s.fillStyle)s.fillStyle=pv.Color.transparent;
-1039if(p.strokeStyle&&!s.strokeStyle)s.strokeStyle=pv.Color.transparent;
-1040};
-1041
-1042/**
-1043 * Returns the current location of the mouse (cursor) relative to this mark's
-1044 * parent. The <i>x</i> coordinate corresponds to the left margin, while the
-1045 * <i>y</i> coordinate corresponds to the top margin.
-1046 *
-1047 * @returns {pv.Vector} the mouse location.
-1048 */
-1049pv.Mark.prototype.mouse=function(){
-1050
-1051/* Compute xy-coordinates relative to the panel. */
-1052varx=pv.event.pageX||0,
-1053y=pv.event.pageY||0,
-1054n=this.root.canvas();
-1055do{
-1056x-=n.offsetLeft;
-1057y-=n.offsetTop;
-1058}while(n=n.offsetParent);
-1059
-1060/* Compute the inverse transform of all enclosing panels. */
-1061vart=pv.Transform.identity,
-1062p=this.properties.transform?this:this.parent,
-1063pz=[];
-1064do{pz.push(p);}while(p=p.parent);
-1065while(p=pz.pop())t=t.translate(p.left(),p.top()).times(p.transform());
-1066t=t.invert();
-1067
-1068returnpv.vector(x*t.k+t.x,y*t.k+t.y);
-1069};
-1070
-1071/**
-1072 * Registers an event handler for the specified event type with this mark. When
-1073 * an event of the specified type is triggered, the specified handler will be
-1074 * invoked. The handler is invoked in a similar method to property functions:
-1075 * the context is <tt>this</tt> mark instance, and the arguments are the full
-1076 * data stack. Event handlers can use property methods to manipulate the display
-1077 * properties of the mark:
-1078 *
-1079 * <pre>m.event("click", function() this.fillStyle("red"));</pre>
-1080 *
-1081 * Alternatively, the external data can be manipulated and the visualization
-1082 * redrawn:
-1083 *
-1084 * <pre>m.event("click", function(d) {
-1085 * data = all.filter(function(k) k.name == d);
-1086 * vis.render();
-1087 * });</pre>
-1088 *
-1089 * The return value of the event handler determines which mark gets re-rendered.
-1090 * Use defs ({@link #def}) to set temporary state from event handlers.
-1091 *
-1092 * <p>The complete set of event types is defined by SVG; see the reference
-1093 * below. The set of supported event types is:<ul>
-1094 *
-1095 * <li>click
-1096 * <li>mousedown
-1097 * <li>mouseup
-1098 * <li>mouseover
-1099 * <li>mousemove
-1100 * <li>mouseout
-1101 *
-1102 * </ul>Since Protovis does not specify any concept of focus, it does not
-1103 * support key events; these should be handled outside the visualization using
-1104 * standard JavaScript. In the future, support for interaction may be extended
-1105 * to support additional event types, particularly those most relevant to
-1106 * interactive visualization, such as selection.
-1107 *
-1108 * <p>TODO In the current implementation, event handlers are not inherited from
-1109 * prototype marks. They must be defined explicitly on each interactive mark. In
-1110 * addition, only one event handler for a given event type can be defined; when
-1111 * specifying multiple event handlers for the same type, only the last one will
-1112 * be used.
-1113 *
-1114 * @see <a href="http://www.w3.org/TR/SVGTiny12/interact.html#SVGEvents">SVG events</a>
-1115 * @param {string} type the event type.
-1116 * @param {function} handler the event handler.
-1117 * @returns {pv.Mark} this.
-1118 */
-1119pv.Mark.prototype.event=function(type,handler){
-1120this.$handlers[type]=pv.functor(handler);
-1121returnthis;
-1122};
-1123
-1124/** @private Evaluates the function <i>f</i> with the specified context. */
-1125pv.Mark.prototype.context=function(scene,index,f){
-1126varproto=pv.Mark.prototype,
-1127stack=pv.Mark.stack,
-1128oscene=pv.Mark.scene,
-1129oindex=proto.index;
-1130
-1131/** @private Sets the context. */
-1132functionapply(scene,index){
-1133pv.Mark.scene=scene;
-1134proto.index=index;
-1135if(!scene)return;
-1136
-1137varthat=scene.mark,
-1138mark=that,
-1139ancestors=[];
-1140
-1141/* Set ancestors' scene and index; populate data stack. */
-1142do{
-1143ancestors.push(mark);
-1144stack.push(scene[index].data);
-1145mark.index=index;
-1146mark.scene=scene;
-1147index=scene.parentIndex;
-1148scene=scene.parent;
-1149}while(mark=mark.parent);
-1150
-1151/* Set ancestors' scale; requires top-down. */
-1152for(vari=ancestors.length-1,k=1;i>0;i--){
-1153mark=ancestors[i];
-1154mark.scale=k;
-1155k*=mark.scene[mark.index].transform.k;
-1156}
-1157
-1158/* Set children's scene and scale. */
-1159if(that.children)for(vari=0,n=that.children.length;i<n;i++){
-1160mark=that.children[i];
-1161mark.scene=that.scene[that.index].children[i];
-1162mark.scale=k;
-1163}
-1164}
-1165
-1166/** @private Clears the context. */
-1167functionclear(scene,index){
-1168if(!scene)return;
-1169varthat=scene.mark,
-1170mark;
-1171
-1172/* Reset children. */
-1173if(that.children)for(vari=0,n=that.children.length;i<n;i++){
-1174mark=that.children[i];
-1175deletemark.scene;
-1176deletemark.scale;
-1177}
-1178
-1179/* Reset ancestors. */
-1180mark=that;
-1181do{
-1182stack.pop();
-1183if(mark.parent){
-1184deletemark.scene;
-1185deletemark.scale;
-1186}
-1187deletemark.index;
-1188}while(mark=mark.parent);
-1189}
-1190
-1191/* Context switch, invoke the function, then switch back. */
-1192clear(oscene,oindex);
-1193apply(scene,index);
-1194try{
-1195f.apply(this,stack);
-1196}finally{
-1197clear(scene,index);
-1198apply(oscene,oindex);
-1199}
-1200};
-1201
-1202/** @private Execute the event listener, then re-render. */
-1203pv.Mark.dispatch=function(type,scene,index){
-1204varm=scene.mark,p=scene.parent,l=m.$handlers[type];
-1205if(!l)returnp&&pv.Mark.dispatch(type,p,scene.parentIndex);
-1206m.context(scene,index,function(){
-1207m=l.apply(m,pv.Mark.stack);
-1208if(m&&m.render)m.render();
-1209});
-1210returntrue;
-1211};
-1212
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Panel.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Panel.js.html
deleted file mode 100644
index 3b0a4899..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Panel.js.html
+++ /dev/null
@@ -1,281 +0,0 @@
-
1/**
- 2 * Constructs a new, empty panel with default properties. Panels, with the
- 3 * exception of the root panel, are not typically constructed directly; instead,
- 4 * they are added to an existing panel or mark via {@link pv.Mark#add}.
- 5 *
- 6 * @class Represents a container mark. Panels allow repeated or nested
- 7 * structures, commonly used in small multiple displays where a small
- 8 * visualization is tiled to facilitate comparison across one or more
- 9 * dimensions. Other types of visualizations may benefit from repeated and
- 10 * possibly overlapping structure as well, such as stacked area charts. Panels
- 11 * can also offset the position of marks to provide padding from surrounding
- 12 * content.
- 13 *
- 14 * <p>All Protovis displays have at least one panel; this is the root panel to
- 15 * which marks are rendered. The box model properties (four margins, width and
- 16 * height) are used to offset the positions of contained marks. The data
- 17 * property determines the panel count: a panel is generated once per associated
- 18 * datum. When nested panels are used, property functions can declare additional
- 19 * arguments to access the data associated with enclosing panels.
- 20 *
- 21 * <p>Panels can be rendered inline, facilitating the creation of sparklines.
- 22 * This allows designers to reuse browser layout features, such as text flow and
- 23 * tables; designers can also overlay HTML elements such as rich text and
- 24 * images.
- 25 *
- 26 * <p>All panels have a <tt>children</tt> array (possibly empty) containing the
- 27 * child marks in the order they were added. Panels also have a <tt>root</tt>
- 28 * field which points to the root (outermost) panel; the root panel's root field
- 29 * points to itself.
- 30 *
- 31 * <p>See also the <a href="../../api/">Protovis guide</a>.
- 32 *
- 33 * @extends pv.Bar
- 34 */
- 35pv.Panel=function(){
- 36pv.Bar.call(this);
- 37
- 38/**
- 39 * The child marks; zero or more {@link pv.Mark}s in the order they were
- 40 * added.
- 41 *
- 42 * @see #add
- 43 * @type pv.Mark[]
- 44 */
- 45this.children=[];
- 46this.root=this;
- 47
- 48/**
- 49 * The internal $dom field is set by the Protovis loader; see lang/init.js. It
- 50 * refers to the script element that contains the Protovis specification, so
- 51 * that the panel knows where in the DOM to insert the generated SVG element.
- 52 *
- 53 * @private
- 54 */
- 55this.$dom=pv.$&&pv.$.s;
- 56};
- 57
- 58pv.Panel.prototype=pv.extend(pv.Bar)
- 59.property("transform")
- 60.property("overflow",String)
- 61.property("canvas",function(c){
- 62return(typeofc=="string")
- 63?document.getElementById(c)
- 64:c;// assume that c is the passed-in element
- 65});
- 66
- 67pv.Panel.prototype.type="panel";
- 68
- 69/**
- 70 * The canvas element; either the string ID of the canvas element in the current
- 71 * document, or a reference to the canvas element itself. If null, a canvas
- 72 * element will be created and inserted into the document at the location of the
- 73 * script element containing the current Protovis specification. This property
- 74 * only applies to root panels and is ignored on nested panels.
- 75 *
- 76 * <p>Note: the "canvas" element here refers to a <tt>div</tt> (or other suitable
- 77 * HTML container element), <i>not</i> a <tt>canvas</tt> element. The name of
- 78 * this property is a historical anachronism from the first implementation that
- 79 * used HTML 5 canvas, rather than SVG.
- 80 *
- 81 * @type string
- 82 * @name pv.Panel.prototype.canvas
- 83 */
- 84
- 85/**
- 86 * Specifies whether child marks are clipped when they overflow this panel.
- 87 * This affects the clipping of all this panel's descendant marks.
- 88 *
- 89 * @type string
- 90 * @name pv.Panel.prototype.overflow
- 91 * @see <a href="http://www.w3.org/TR/CSS2/visufx.html#overflow">CSS2</a>
- 92 */
- 93
- 94/**
- 95 * The transform to be applied to child marks. The default transform is
- 96 * identity, which has no effect. Note that the panel's own fill and stroke are
- 97 * not affected by the transform, and panel's transform only affects the
- 98 * <tt>scale</tt> of child marks, not the panel itself.
- 99 *
-100 * @type pv.Transform
-101 * @name pv.Panel.prototype.transform
-102 * @see pv.Mark#scale
-103 */
-104
-105/**
-106 * Default properties for panels. By default, the margins are zero, the fill
-107 * style is transparent.
-108 *
-109 * @type pv.Panel
-110 */
-111pv.Panel.prototype.defaults=newpv.Panel()
-112.extend(pv.Bar.prototype.defaults)
-113.fillStyle(null)// override Bar default
-114.overflow("visible");
-115
-116/**
-117 * Returns an anchor with the specified name. This method is overridden such
-118 * that adding to a panel's anchor adds to the panel, rather than to the panel's
-119 * parent.
-120 *
-121 * @param {string} name the anchor name; either a string or a property function.
-122 * @returns {pv.Anchor} the new anchor.
-123 */
-124pv.Panel.prototype.anchor=function(name){
-125varanchor=pv.Bar.prototype.anchor.call(this,name);
-126anchor.parent=this;
-127returnanchor;
-128};
-129
-130/**
-131 * Adds a new mark of the specified type to this panel. Unlike the normal
-132 * {@link Mark#add} behavior, adding a mark to a panel does not cause the mark
-133 * to inherit from the panel. Since the contained marks are offset by the panel
-134 * margins already, inheriting properties is generally undesirable; of course,
-135 * it is always possible to change this behavior by calling {@link Mark#extend}
-136 * explicitly.
-137 *
-138 * @param {function} type the type of the new mark to add.
-139 * @returns {pv.Mark} the new mark.
-140 */
-141pv.Panel.prototype.add=function(type){
-142varchild=newtype();
-143child.parent=this;
-144child.root=this.root;
-145child.childIndex=this.children.length;
-146this.children.push(child);
-147returnchild;
-148};
-149
-150/** @private Bind this panel, then any child marks recursively. */
-151pv.Panel.prototype.bind=function(){
-152pv.Mark.prototype.bind.call(this);
-153for(vari=0;i<this.children.length;i++){
-154this.children[i].bind();
-155}
-156};
-157
-158/**
-159 * @private Evaluates all of the properties for this panel for the specified
-160 * instance <tt>s</tt> in the scene graph, including recursively building the
-161 * scene graph for child marks.
-162 *
-163 * @param s a node in the scene graph; the instance of the panel to build.
-164 * @see Mark#scene
-165 */
-166pv.Panel.prototype.buildInstance=function(s){
-167pv.Bar.prototype.buildInstance.call(this,s);
-168if(!s.visible)return;
-169if(!s.children)s.children=[];
-170
-171/*
-172 * Multiply the current scale factor by this panel's transform. Also clear the
-173 * default index as we recurse into child marks; it will be reset to the
-174 * current index when the next panel instance is built.
-175 */
-176varscale=this.scale*s.transform.k,child,n=this.children.length;
-177pv.Mark.prototype.index=-1;
-178
-179/*
-180 * Build each child, passing in the parent (this panel) scene graph node. The
-181 * child mark's scene is initialized from the corresponding entry in the
-182 * existing scene graph, such that properties from the previous build can be
-183 * reused; this is largely to facilitate the recycling of SVG elements.
-184 */
-185for(vari=0;i<n;i++){
-186child=this.children[i];
-187child.scene=s.children[i];// possibly undefined
-188child.scale=scale;
-189child.build();
-190}
-191
-192/*
-193 * Once the child marks have been built, the new scene graph nodes are removed
-194 * from the child marks and placed into the scene graph. The nodes cannot
-195 * remain on the child nodes because this panel (or a parent panel) may be
-196 * instantiated multiple times!
-197 */
-198for(vari=0;i<n;i++){
-199child=this.children[i];
-200s.children[i]=child.scene;
-201deletechild.scene;
-202deletechild.scale;
-203}
-204
-205/* Delete any expired child scenes. */
-206s.children.length=n;
-207};
-208
-209/**
-210 * @private Computes the implied properties for this panel for the specified
-211 * instance <tt>s</tt> in the scene graph. Panels have two implied
-212 * properties:<ul>
-213 *
-214 * <li>The <tt>canvas</tt> property references the DOM element, typically a DIV,
-215 * that contains the SVG element that is used to display the visualization. This
-216 * property may be specified as a string, referring to the unique ID of the
-217 * element in the DOM. The string is converted to a reference to the DOM
-218 * element. The width and height of the SVG element is inferred from this DOM
-219 * element. If no canvas property is specified, a new SVG element is created and
-220 * inserted into the document, using the panel dimensions; see
-221 * {@link #createCanvas}.
-222 *
-223 * <li>The <tt>children</tt> array, while not a property per se, contains the
-224 * scene graph for each child mark. This array is initialized to be empty, and
-225 * is populated above in {@link #buildInstance}.
-226 *
-227 * </ul>The current implementation creates the SVG element, if necessary, during
-228 * the build phase; in the future, it may be preferrable to move this to the
-229 * update phase, although then the canvas property would be undefined. In
-230 * addition, DOM inspection is necessary to define the implied width and height
-231 * properties that may be inferred from the DOM.
-232 *
-233 * @param s a node in the scene graph; the instance of the panel to build.
-234 */
-235pv.Panel.prototype.buildImplied=function(s){
-236if(!this.parent){
-237varc=s.canvas;
-238if(c){
-239/* Clear the container if it's not associated with this panel. */
-240if(c.$panel!=this){
-241c.$panel=this;
-242while(c.lastChild)c.removeChild(c.lastChild);
-243}
-244
-245/* If width and height weren't specified, inspect the container. */
-246varw,h;
-247if(s.width==null){
-248w=parseFloat(pv.css(c,"width"));
-249s.width=w-s.left-s.right;
-250}
-251if(s.height==null){
-252h=parseFloat(pv.css(c,"height"));
-253s.height=h-s.top-s.bottom;
-254}
-255}else{
-256varcache=this.$canvas||(this.$canvas=[]);
-257if(!(c=cache[this.index])){
-258c=cache[this.index]=document.createElement("span");
-259if(this.$dom){// script element for text/javascript+protovis
-260this.$dom.parentNode.insertBefore(c,this.$dom);
-261}else{// find the last element in the body
-262varn=document.body;
-263while(n.lastChild&&n.lastChild.tagName)n=n.lastChild;
-264if(n!=document.body)n=n.parentNode;
-265n.appendChild(c);
-266}
-267}
-268}
-269s.canvas=c;
-270}
-271if(!s.transform)s.transform=pv.Transform.identity;
-272pv.Mark.prototype.buildImplied.call(this,s);
-273};
-274
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Rule.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Rule.js.html
deleted file mode 100644
index 628cb1ba..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Rule.js.html
+++ /dev/null
@@ -1,151 +0,0 @@
-
1/**
- 2 * Constructs a new rule with default properties. Rules are not typically
- 3 * constructed directly, but by adding to a panel or an existing mark via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Represents a horizontal or vertical rule. Rules are frequently used
- 7 * for axes and grid lines. For example, specifying only the bottom property
- 8 * draws horizontal rules, while specifying only the left draws vertical
- 9 * rules. Rules can also be used as thin bars. The visual style is controlled in
- 10 * the same manner as lines.
- 11 *
- 12 * <p>Rules are positioned exclusively the standard box model properties. The
- 13 * following combinations of properties are supported:
- 14 *
- 15 * <table>
- 16 * <thead><th style="width:12em;">Properties</th><th>Orientation</th></thead>
- 17 * <tbody>
- 18 * <tr><td>left</td><td>vertical</td></tr>
- 19 * <tr><td>right</td><td>vertical</td></tr>
- 20 * <tr><td>left, bottom, top</td><td>vertical</td></tr>
- 21 * <tr><td>right, bottom, top</td><td>vertical</td></tr>
- 22 * <tr><td>top</td><td>horizontal</td></tr>
- 23 * <tr><td>bottom</td><td>horizontal</td></tr>
- 24 * <tr><td>top, left, right</td><td>horizontal</td></tr>
- 25 * <tr><td>bottom, left, right</td><td>horizontal</td></tr>
- 26 * <tr><td>left, top, height</td><td>vertical</td></tr>
- 27 * <tr><td>left, bottom, height</td><td>vertical</td></tr>
- 28 * <tr><td>right, top, height</td><td>vertical</td></tr>
- 29 * <tr><td>right, bottom, height</td><td>vertical</td></tr>
- 30 * <tr><td>left, top, width</td><td>horizontal</td></tr>
- 31 * <tr><td>left, bottom, width</td><td>horizontal</td></tr>
- 32 * <tr><td>right, top, width</td><td>horizontal</td></tr>
- 33 * <tr><td>right, bottom, width</td><td>horizontal</td></tr>
- 34 * </tbody>
- 35 * </table>
- 36 *
- 37 * <p>Small rules can be used as tick marks; alternatively, a {@link Dot} with
- 38 * the "tick" shape can be used.
- 39 *
- 40 * <p>See also the <a href="../../api/Rule.html">Rule guide</a>.
- 41 *
- 42 * @see pv.Line
- 43 * @extends pv.Mark
- 44 */
- 45pv.Rule=function(){
- 46pv.Mark.call(this);
- 47};
- 48
- 49pv.Rule.prototype=pv.extend(pv.Mark)
- 50.property("width",Number)
- 51.property("height",Number)
- 52.property("lineWidth",Number)
- 53.property("strokeStyle",pv.color);
- 54
- 55pv.Rule.prototype.type="rule";
- 56
- 57/**
- 58 * The width of the rule, in pixels. If the left position is specified, the rule
- 59 * extends rightward from the left edge; if the right position is specified, the
- 60 * rule extends leftward from the right edge.
- 61 *
- 62 * @type number
- 63 * @name pv.Rule.prototype.width
- 64 */
- 65
- 66/**
- 67 * The height of the rule, in pixels. If the bottom position is specified, the
- 68 * rule extends upward from the bottom edge; if the top position is specified,
- 69 * the rule extends downward from the top edge.
- 70 *
- 71 * @type number
- 72 * @name pv.Rule.prototype.height
- 73 */
- 74
- 75/**
- 76 * The width of stroked lines, in pixels; used in conjunction with
- 77 * <tt>strokeStyle</tt> to stroke the rule. The default value is 1 pixel.
- 78 *
- 79 * @type number
- 80 * @name pv.Rule.prototype.lineWidth
- 81 */
- 82
- 83/**
- 84 * The style of stroked lines; used in conjunction with <tt>lineWidth</tt> to
- 85 * stroke the rule. The default value of this property is black.
- 86 *
- 87 * @type string
- 88 * @name pv.Rule.prototype.strokeStyle
- 89 * @see pv.color
- 90 */
- 91
- 92/**
- 93 * Default properties for rules. By default, a single-pixel black line is
- 94 * stroked.
- 95 *
- 96 * @type pv.Rule
- 97 */
- 98pv.Rule.prototype.defaults=newpv.Rule()
- 99.extend(pv.Mark.prototype.defaults)
-100.lineWidth(1)
-101.strokeStyle("black")
-102.antialias(false);
-103
-104/**
-105 * Constructs a new rule anchor with default properties. Rules support five
-106 * different anchors:<ul>
-107 *
-108 * <li>top
-109 * <li>left
-110 * <li>center
-111 * <li>bottom
-112 * <li>right
-113 *
-114 * </ul>In addition to positioning properties (left, right, top bottom), the
-115 * anchors support text rendering properties (text-align, text-baseline). Text is
-116 * rendered to appear outside the rule. Note that this behavior is different
-117 * from other mark anchors, which default to rendering text <i>inside</i> the
-118 * mark.
-119 *
-120 * <p>For consistency with the other mark types, the anchor positions are
-121 * defined in terms of their opposite edge. For example, the top anchor defines
-122 * the bottom property, such that a bar added to the top anchor grows upward.
-123 *
-124 * @param {string} name the anchor name; either a string or a property function.
-125 * @returns {pv.Anchor}
-126 */
-127pv.Rule.prototype.anchor=pv.Line.prototype.anchor;
-128
-129/** @private Sets width or height based on orientation. */
-130pv.Rule.prototype.buildImplied=function(s){
-131varl=s.left,r=s.right,t=s.top,b=s.bottom;
-132
-133/* Determine horizontal or vertical orientation. */
-134if((s.width!=null)
-135||((l==null)&&(r==null))
-136||((r!=null)&&(l!=null))){
-137s.height=0;
-138}else{
-139s.width=0;
-140}
-141
-142pv.Mark.prototype.buildImplied.call(this,s);
-143};
-144
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Wedge.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Wedge.js.html
deleted file mode 100644
index de83a55c..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_mark_Wedge.js.html
+++ /dev/null
@@ -1,256 +0,0 @@
-
1/**
- 2 * Constructs a new wedge with default properties. Wedges are not typically
- 3 * constructed directly, but by adding to a panel or an existing mark via
- 4 * {@link pv.Mark#add}.
- 5 *
- 6 * @class Represents a wedge, or pie slice. Specified in terms of start and end
- 7 * angle, inner and outer radius, wedges can be used to construct donut charts
- 8 * and polar bar charts as well. If the {@link #angle} property is used, the end
- 9 * angle is implied by adding this value to start angle. By default, the start
- 10 * angle is the previously-generated wedge's end angle. This design allows
- 11 * explicit control over the wedge placement if desired, while offering
- 12 * convenient defaults for the construction of radial graphs.
- 13 *
- 14 * <p>The center point of the circle is positioned using the standard box model.
- 15 * The wedge can be stroked and filled, similar to {@link pv.Bar}.
- 16 *
- 17 * <p>See also the <a href="../../api/Wedge.html">Wedge guide</a>.
- 18 *
- 19 * @extends pv.Mark
- 20 */
- 21pv.Wedge=function(){
- 22pv.Mark.call(this);
- 23};
- 24
- 25pv.Wedge.prototype=pv.extend(pv.Mark)
- 26.property("startAngle",Number)
- 27.property("endAngle",Number)
- 28.property("angle",Number)
- 29.property("innerRadius",Number)
- 30.property("outerRadius",Number)
- 31.property("lineWidth",Number)
- 32.property("strokeStyle",pv.color)
- 33.property("fillStyle",pv.color);
- 34
- 35pv.Wedge.prototype.type="wedge";
- 36
- 37/**
- 38 * The start angle of the wedge, in radians. The start angle is measured
- 39 * clockwise from the 3 o'clock position. The default value of this property is
- 40 * the end angle of the previous instance (the {@link Mark#sibling}), or -PI / 2
- 41 * for the first wedge; for pie and donut charts, typically only the
- 42 * {@link #angle} property needs to be specified.
- 43 *
- 44 * @type number
- 45 * @name pv.Wedge.prototype.startAngle
- 46 */
- 47
- 48/**
- 49 * The end angle of the wedge, in radians. If not specified, the end angle is
- 50 * implied as the start angle plus the {@link #angle}.
- 51 *
- 52 * @type number
- 53 * @name pv.Wedge.prototype.endAngle
- 54 */
- 55
- 56/**
- 57 * The angular span of the wedge, in radians. This property is used if end angle
- 58 * is not specified.
- 59 *
- 60 * @type number
- 61 * @name pv.Wedge.prototype.angle
- 62 */
- 63
- 64/**
- 65 * The inner radius of the wedge, in pixels. The default value of this property
- 66 * is zero; a positive value will produce a donut slice rather than a pie slice.
- 67 * The inner radius can vary per-wedge.
- 68 *
- 69 * @type number
- 70 * @name pv.Wedge.prototype.innerRadius
- 71 */
- 72
- 73/**
- 74 * The outer radius of the wedge, in pixels. This property is required. For
- 75 * pies, only this radius is required; for donuts, the inner radius must be
- 76 * specified as well. The outer radius can vary per-wedge.
- 77 *
- 78 * @type number
- 79 * @name pv.Wedge.prototype.outerRadius
- 80 */
- 81
- 82/**
- 83 * The width of stroked lines, in pixels; used in conjunction with
- 84 * <tt>strokeStyle</tt> to stroke the wedge's border.
- 85 *
- 86 * @type number
- 87 * @name pv.Wedge.prototype.lineWidth
- 88 */
- 89
- 90/**
- 91 * The style of stroked lines; used in conjunction with <tt>lineWidth</tt> to
- 92 * stroke the wedge's border. The default value of this property is null,
- 93 * meaning wedges are not stroked by default.
- 94 *
- 95 * @type string
- 96 * @name pv.Wedge.prototype.strokeStyle
- 97 * @see pv.color
- 98 */
- 99
-100/**
-101 * The wedge fill style; if non-null, the interior of the wedge is filled with
-102 * the specified color. The default value of this property is a categorical
-103 * color.
-104 *
-105 * @type string
-106 * @name pv.Wedge.prototype.fillStyle
-107 * @see pv.color
-108 */
-109
-110/**
-111 * Default properties for wedges. By default, there is no stroke and the fill
-112 * style is a categorical color.
-113 *
-114 * @type pv.Wedge
-115 */
-116pv.Wedge.prototype.defaults=newpv.Wedge()
-117.extend(pv.Mark.prototype.defaults)
-118.startAngle(function(){
-119vars=this.sibling();
-120returns?s.endAngle:-Math.PI/2;
-121})
-122.innerRadius(0)
-123.lineWidth(1.5)
-124.strokeStyle(null)
-125.fillStyle(pv.Colors.category20().by(pv.index));
-126
-127/**
-128 * Returns the mid-radius of the wedge, which is defined as half-way between the
-129 * inner and outer radii.
-130 *
-131 * @see #innerRadius
-132 * @see #outerRadius
-133 * @returns {number} the mid-radius, in pixels.
-134 */
-135pv.Wedge.prototype.midRadius=function(){
-136return(this.innerRadius()+this.outerRadius())/2;
-137};
-138
-139/**
-140 * Returns the mid-angle of the wedge, which is defined as half-way between the
-141 * start and end angles.
-142 *
-143 * @see #startAngle
-144 * @see #endAngle
-145 * @returns {number} the mid-angle, in radians.
-146 */
-147pv.Wedge.prototype.midAngle=function(){
-148return(this.startAngle()+this.endAngle())/2;
-149};
-150
-151/**
-152 * Constructs a new wedge anchor with default properties. Wedges support five
-153 * different anchors:<ul>
-154 *
-155 * <li>outer
-156 * <li>inner
-157 * <li>center
-158 * <li>start
-159 * <li>end
-160 *
-161 * </ul>In addition to positioning properties (left, right, top bottom), the
-162 * anchors support text rendering properties (text-align, text-baseline,
-163 * textAngle). Text is rendered to appear inside the wedge.
-164 *
-165 * @param {string} name the anchor name; either a string or a property function.
-166 * @returns {pv.Anchor}
-167 */
-168pv.Wedge.prototype.anchor=function(name){
-169functionpartial(s){returns.innerRadius||s.angle<2*Math.PI;}
-170functionmidRadius(s){return(s.innerRadius+s.outerRadius)/2;}
-171functionmidAngle(s){return(s.startAngle+s.endAngle)/2;}
-172varscene;
-173returnpv.Mark.prototype.anchor.call(this,name)
-174.def("$wedge.anchor",function(){
-175scene=this.scene.target;
-176})
-177.left(function(){
-178vars=scene[this.index];
-179if(partial(s))switch(this.name()){
-180case"outer":returns.left+s.outerRadius*Math.cos(midAngle(s));
-181case"inner":returns.left+s.innerRadius*Math.cos(midAngle(s));
-182case"start":returns.left+midRadius(s)*Math.cos(s.startAngle);
-183case"center":returns.left+midRadius(s)*Math.cos(midAngle(s));
-184case"end":returns.left+midRadius(s)*Math.cos(s.endAngle);
-185}
-186returns.left;
-187})
-188.top(function(){
-189vars=scene[this.index];
-190if(partial(s))switch(this.name()){
-191case"outer":returns.top+s.outerRadius*Math.sin(midAngle(s));
-192case"inner":returns.top+s.innerRadius*Math.sin(midAngle(s));
-193case"start":returns.top+midRadius(s)*Math.sin(s.startAngle);
-194case"center":returns.top+midRadius(s)*Math.sin(midAngle(s));
-195case"end":returns.top+midRadius(s)*Math.sin(s.endAngle);
-196}
-197returns.top;
-198})
-199.textAlign(function(){
-200vars=scene[this.index];
-201if(partial(s))switch(this.name()){
-202case"outer":returnpv.Wedge.upright(midAngle(s))?"right":"left";
-203case"inner":returnpv.Wedge.upright(midAngle(s))?"left":"right";
-204}
-205return"center";
-206})
-207.textBaseline(function(){
-208vars=scene[this.index];
-209if(partial(s))switch(this.name()){
-210case"start":returnpv.Wedge.upright(s.startAngle)?"top":"bottom";
-211case"end":returnpv.Wedge.upright(s.endAngle)?"bottom":"top";
-212}
-213return"middle";
-214})
-215.textAngle(function(){
-216vars=scene[this.index],a=0;
-217if(partial(s))switch(this.name()){
-218case"center":
-219case"inner":
-220case"outer":a=midAngle(s);break;
-221case"start":a=s.startAngle;break;
-222case"end":a=s.endAngle;break;
-223}
-224returnpv.Wedge.upright(a)?a:(a+Math.PI);
-225});
-226};
-227
-228/**
-229 * Returns true if the specified angle is considered "upright", as in, text
-230 * rendered at that angle would appear upright. If the angle is not upright,
-231 * text is rotated 180 degrees to be upright, and the text alignment properties
-232 * are correspondingly changed.
-233 *
-234 * @param {number} angle an angle, in radius.
-235 * @returns {boolean} true if the specified angle is upright.
-236 */
-237pv.Wedge.upright=function(angle){
-238angle=angle%(2*Math.PI);
-239angle=(angle<0)?(2*Math.PI+angle):angle;
-240return(angle<Math.PI/2)||(angle>=3*Math.PI/2);
-241};
-242
-243/** @private Sets angle based on endAngle or vice versa. */
-244pv.Wedge.prototype.buildImplied=function(s){
-245if(s.angle==null)s.angle=s.endAngle-s.startAngle;
-246elseif(s.endAngle==null)s.endAngle=s.startAngle+s.angle;
-247pv.Mark.prototype.buildImplied.call(this,s);
-248};
-249
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_BoundConstraint.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_BoundConstraint.js.html
deleted file mode 100644
index 965d107e..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_BoundConstraint.js.html
+++ /dev/null
@@ -1,83 +0,0 @@
-
1/**
- 2 * Constructs a new bound constraint. Before the constraint can be used, the
- 3 * {@link #x} and {@link #y} methods must be call to specify the bounds.
- 4 *
- 5 * @class Constrains particles to within fixed rectangular bounds. For example,
- 6 * this constraint can be used to constrain particles in a physics simulation
- 7 * within the bounds of an enclosing panel.
- 8 *
- 9 * <p>Note that the current implementation treats particles as points, with no
- 10 * area. If the particles are rendered as dots, be sure to include some
- 11 * additional padding to inset the bounds such that the edges of the dots do not
- 12 * get clipped by the panel bounds. If the particles have different radii, this
- 13 * constraint would need to be extended using a radius function, similar to
- 14 * {@link pv.Constraint.collision}.
- 15 *
- 16 * @see pv.Layout.Force
- 17 * @extends pv.Constraint
- 18 */
- 19pv.Constraint.bound=function(){
- 20varconstraint={},
- 21x,
- 22y;
- 23
- 24/**
- 25 * Sets or gets the bounds on the x-coordinate.
- 26 *
- 27 * @function
- 28 * @name pv.Constraint.bound.prototype.x
- 29 * @param {number} min the minimum allowed x-coordinate.
- 30 * @param {number} max the maximum allowed x-coordinate.
- 31 * @returns {pv.Constraint.bound} this.
- 32 */
- 33constraint.x=function(min,max){
- 34if(arguments.length){
- 35x={min:Math.min(min,max),max:Math.max(min,max)};
- 36returnthis;
- 37}
- 38returnx;
- 39};
- 40
- 41/**
- 42 * Sets or gets the bounds on the y-coordinate.
- 43 *
- 44 * @function
- 45 * @name pv.Constraint.bound.prototype.y
- 46 * @param {number} min the minimum allowed y-coordinate.
- 47 * @param {number} max the maximum allowed y-coordinate.
- 48 * @returns {pv.Constraint.bound} this.
- 49 */
- 50constraint.y=function(min,max){
- 51if(arguments.length){
- 52y={min:Math.min(min,max),max:Math.max(min,max)};
- 53returnthis;
- 54}
- 55returny;
- 56};
- 57
- 58/**
- 59 * Applies this constraint to the specified particles.
- 60 *
- 61 * @function
- 62 * @name pv.Constraint.bound.prototype.apply
- 63 * @param {pv.Particle} particles particles to which to apply this constraint.
- 64 */
- 65constraint.apply=function(particles){
- 66if(x)for(varp=particles;p;p=p.next){
- 67p.x=p.x<x.min?x.min:(p.x>x.max?x.max:p.x);
- 68}
- 69if(y)for(varp=particles;p;p=p.next){
- 70p.y=p.y<y.min?y.min:(p.y>y.max?y.max:p.y);
- 71}
- 72};
- 73
- 74returnconstraint;
- 75};
- 76
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_ChargeForce.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_ChargeForce.js.html
deleted file mode 100644
index 0f9543f4..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_ChargeForce.js.html
+++ /dev/null
@@ -1,192 +0,0 @@
-
1/**
- 2 * Constructs a new charge force, with an optional charge constant. The charge
- 3 * constant can be negative for repulsion (e.g., particles with electrical
- 4 * charge of equal sign), or positive for attraction (e.g., massive particles
- 5 * with mutual gravity). The default charge constant is -40.
- 6 *
- 7 * @class An n-body force, as defined by Coulomb's law or Newton's law of
- 8 * gravitation, inversely proportional to the square of the distance between
- 9 * particles. Note that the force is independent of the <i>mass</i> of the
- 10 * associated particles, and that the particles do not have charges of varying
- 11 * magnitude; instead, the attraction or repulsion of all particles is globally
- 12 * specified as the charge {@link #constant}.
- 13 *
- 14 * <p>This particular implementation uses the Barnes-Hut algorithm. For details,
- 15 * see <a
- 16 * href="http://www.nature.com/nature/journal/v324/n6096/abs/324446a0.html">"A
- 17 * hierarchical O(N log N) force-calculation algorithm"</a>, J. Barnes &
- 18 * P. Hut, <i>Nature</i> 1986.
- 19 *
- 20 * @name pv.Force.charge
- 21 * @param {number} [k] the charge constant.
- 22 */
- 23pv.Force.charge=function(k){
- 24varmin=2,// minimum distance at which to observe forces
- 25min1=1/min,
- 26max=500,// maximum distance at which to observe forces
- 27max1=1/max,
- 28theta=.9,// Barnes-Hut theta approximation constant
- 29force={};
- 30
- 31if(!arguments.length)k=-40;// default charge constant (repulsion)
- 32
- 33/**
- 34 * Sets or gets the charge constant. If an argument is specified, it is the
- 35 * new charge constant. The charge constant can be negative for repulsion
- 36 * (e.g., particles with electrical charge of equal sign), or positive for
- 37 * attraction (e.g., massive particles with mutual gravity). The default
- 38 * charge constant is -40.
- 39 *
- 40 * @function
- 41 * @name pv.Force.charge.prototype.constant
- 42 * @param {number} x the charge constant.
- 43 * @returns {pv.Force.charge} this.
- 44 */
- 45force.constant=function(x){
- 46if(arguments.length){
- 47k=Number(x);
- 48returnforce;
- 49}
- 50returnk;
- 51};
- 52
- 53/**
- 54 * Sets or gets the domain; specifies the minimum and maximum domain within
- 55 * which charge forces are applied. A minimum distance threshold avoids
- 56 * applying forces that are two strong (due to granularity of the simulation's
- 57 * numeric integration). A maximum distance threshold improves performance by
- 58 * skipping force calculations for particles that are far apart.
- 59 *
- 60 * <p>The default domain is [2, 500].
- 61 *
- 62 * @function
- 63 * @name pv.Force.charge.prototype.domain
- 64 * @param {number} a
- 65 * @param {number} b
- 66 * @returns {pv.Force.charge} this.
- 67 */
- 68force.domain=function(a,b){
- 69if(arguments.length){
- 70min=Number(a);
- 71min1=1/min;
- 72max=Number(b);
- 73max1=1/max;
- 74returnforce;
- 75}
- 76return[min,max];
- 77};
- 78
- 79/**
- 80 * Sets or gets the Barnes-Hut approximation factor. The Barnes-Hut
- 81 * approximation criterion is the ratio of the size of the quadtree node to
- 82 * the distance from the point to the node's center of mass is beneath some
- 83 * threshold.
- 84 *
- 85 * @function
- 86 * @name pv.Force.charge.prototype.theta
- 87 * @param {number} x the new Barnes-Hut approximation factor.
- 88 * @returns {pv.Force.charge} this.
- 89 */
- 90force.theta=function(x){
- 91if(arguments.length){
- 92theta=Number(x);
- 93returnforce;
- 94}
- 95returntheta;
- 96};
- 97
- 98/**
- 99 * @ignore Recursively computes the center of charge for each node in the
-100 * quadtree. This is equivalent to the center of mass, assuming that all
-101 * particles have unit weight.
-102 */
-103functionaccumulate(n){
-104varcx=0,cy=0;
-105n.cn=0;
-106functionaccumulateChild(c){
-107accumulate(c);
-108n.cn+=c.cn;
-109cx+=c.cn*c.cx;
-110cy+=c.cn*c.cy;
-111}
-112if(!n.leaf){
-113if(n.c1)accumulateChild(n.c1);
-114if(n.c2)accumulateChild(n.c2);
-115if(n.c3)accumulateChild(n.c3);
-116if(n.c4)accumulateChild(n.c4);
-117}
-118if(n.p){
-119n.cn+=k;
-120cx+=k*n.p.x;
-121cy+=k*n.p.y;
-122}
-123n.cx=cx/n.cn;
-124n.cy=cy/n.cn;
-125}
-126
-127/**
-128 * @ignore Recursively computes forces on the given particle using the given
-129 * quadtree node. The Barnes-Hut approximation criterion is the ratio of the
-130 * size of the quadtree node to the distance from the point to the node's
-131 * center of mass is beneath some threshold.
-132 */
-133functionforces(n,p,x1,y1,x2,y2){
-134vardx=n.cx-p.x,
-135dy=n.cy-p.y,
-136dn=1/Math.sqrt(dx*dx+dy*dy);
-137
-138/* Barnes-Hut criterion. */
-139if((n.leaf&&(n.p!=p))||((x2-x1)*dn<theta)){
-140if(dn<max1)return;
-141if(dn>min1)dn=min1;
-142varkc=n.cn*dn*dn*dn,
-143fx=dx*kc,
-144fy=dy*kc;
-145p.fx+=fx;
-146p.fy+=fy;
-147}elseif(!n.leaf){
-148varsx=(x1+x2)*.5,sy=(y1+y2)*.5;
-149if(n.c1)forces(n.c1,p,x1,y1,sx,sy);
-150if(n.c2)forces(n.c2,p,sx,y1,x2,sy);
-151if(n.c3)forces(n.c3,p,x1,sy,sx,y2);
-152if(n.c4)forces(n.c4,p,sx,sy,x2,y2);
-153if(dn<max1)return;
-154if(dn>min1)dn=min1;
-155if(n.p&&(n.p!=p)){
-156varkc=k*dn*dn*dn,
-157fx=dx*kc,
-158fy=dy*kc;
-159p.fx+=fx;
-160p.fy+=fy;
-161}
-162}
-163}
-164
-165/**
-166 * Applies this force to the specified particles. The force is applied between
-167 * all pairs of particles within the domain, using the specified quadtree to
-168 * accelerate n-body force calculation using the Barnes-Hut approximation
-169 * criterion.
-170 *
-171 * @function
-172 * @name pv.Force.charge.prototype.apply
-173 * @param {pv.Particle} particles particles to which to apply this force.
-174 * @param {pv.Quadtree} q a quadtree for spatial acceleration.
-175 */
-176force.apply=function(particles,q){
-177accumulate(q.root);
-178for(varp=particles;p;p=p.next){
-179forces(q.root,p,q.xMin,q.yMin,q.xMax,q.yMax);
-180}
-181};
-182
-183returnforce;
-184};
-185
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_CollisionConstraint.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_CollisionConstraint.js.html
deleted file mode 100644
index e885c4d8..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_CollisionConstraint.js.html
+++ /dev/null
@@ -1,121 +0,0 @@
-
1/**
- 2 * Constructs a new collision constraint. The default search radius is 10, and
- 3 * the default repeat count is 1. A radius function must be specified to compute
- 4 * the radius of particles.
- 5 *
- 6 * @class Constraints circles to avoid overlap. Each particle is treated as a
- 7 * circle, with the radius of the particle computed using a specified function.
- 8 * For example, if the particle has an <tt>r</tt> attribute storing the radius,
- 9 * the radius <tt>function(d) d.r</tt> specifies a collision constraint using
- 10 * this radius. The radius function is passed each {@link pv.Particle} as the
- 11 * first argument.
- 12 *
- 13 * <p>To accelerate collision detection, this implementation uses a quadtree and
- 14 * a search radius. The search radius is computed as the maximum radius of all
- 15 * particles in the simulation.
- 16 *
- 17 * @see pv.Constraint
- 18 * @param {function} radius the radius function.
- 19 */
- 20pv.Constraint.collision=function(radius){
- 21varn=1,// number of times to repeat the constraint
- 22r1,
- 23px1,
- 24py1,
- 25px2,
- 26py2,
- 27constraint={};
- 28
- 29if(!arguments.length)r1=10;// default search radius
- 30
- 31/**
- 32 * Sets or gets the repeat count. If the repeat count is greater than 1, the
- 33 * constraint will be applied repeatedly; this is a form of the Gauss-Seidel
- 34 * method for constraints relaxation. Repeating the collision constraint makes
- 35 * the constraint have more of an effect when there is a potential for many
- 36 * co-occurring collisions.
- 37 *
- 38 * @function
- 39 * @name pv.Constraint.collision.prototype.repeat
- 40 * @param {number} x the number of times to repeat this constraint.
- 41 * @returns {pv.Constraint.collision} this.
- 42 */
- 43constraint.repeat=function(x){
- 44if(arguments.length){
- 45n=Number(x);
- 46returnconstraint;
- 47}
- 48returnn;
- 49};
- 50
- 51/** @private */
- 52functionconstrain(n,p,x1,y1,x2,y2){
- 53if(!n.leaf){
- 54varsx=(x1+x2)*.5,
- 55sy=(y1+y2)*.5,
- 56top=sy>py1,
- 57bottom=sy<py2,
- 58left=sx>px1,
- 59right=sx<px2;
- 60if(top){
- 61if(n.c1&&left)constrain(n.c1,p,x1,y1,sx,sy);
- 62if(n.c2&&right)constrain(n.c2,p,sx,y1,x2,sy);
- 63}
- 64if(bottom){
- 65if(n.c3&&left)constrain(n.c3,p,x1,sy,sx,y2);
- 66if(n.c4&&right)constrain(n.c4,p,sx,sy,x2,y2);
- 67}
- 68}
- 69if(n.p&&(n.p!=p)){
- 70vardx=p.x-n.p.x,
- 71dy=p.y-n.p.y,
- 72l=Math.sqrt(dx*dx+dy*dy),
- 73d=r1+radius(n.p);
- 74if(l<d){
- 75vark=(l-d)/l*.5;
- 76dx*=k;
- 77dy*=k;
- 78p.x-=dx;
- 79p.y-=dy;
- 80n.p.x+=dx;
- 81n.p.y+=dy;
- 82}
- 83}
- 84}
- 85
- 86/**
- 87 * Applies this constraint to the specified particles.
- 88 *
- 89 * @function
- 90 * @name pv.Constraint.collision.prototype.apply
- 91 * @param {pv.Particle} particles particles to which to apply this constraint.
- 92 * @param {pv.Quadtree} q a quadtree for spatial acceleration.
- 93 */
- 94constraint.apply=function(particles,q){
- 95varp,r,max=-Infinity;
- 96for(p=particles;p;p=p.next){
- 97r=radius(p);
- 98if(r>max)max=r;
- 99}
-100for(vari=0;i<n;i++){
-101for(p=particles;p;p=p.next){
-102r=(r1=radius(p))+max;
-103px1=p.x-r;
-104px2=p.x+r;
-105py1=p.y-r;
-106py2=p.y+r;
-107constrain(q.root,p,q.xMin,q.yMin,q.xMax,q.yMax);
-108}
-109}
-110};
-111
-112returnconstraint;
-113};
-114
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_Constraint.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_Constraint.js.html
deleted file mode 100644
index a3f574c6..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_Constraint.js.html
+++ /dev/null
@@ -1,34 +0,0 @@
-
1/**
- 2 * Abstract; see an implementing class.
- 3 *
- 4 * @class Represents a constraint that acts on particles. Note that this
- 5 * interface does not specify how to bind a constraint to specific particles; in
- 6 * general, constraints are applied globally to all particles. However, some
- 7 * constraints may be applied to specific particles or between particles, such
- 8 * as position constraints, through additional specialization.
- 9 *
- 10 * @see pv.Simulation
- 11 * @see pv.Particle
- 12 * @see pv.Constraint.bound
- 13 * @see pv.Constraint.collision
- 14 * @see pv.Constraint.position
- 15 */
- 16pv.Constraint={};
- 17
- 18/**
- 19 * Applies this constraint to the specified particles.
- 20 *
- 21 * @function
- 22 * @name pv.Constraint.prototype.apply
- 23 * @param {pv.Particle} particles particles to which to apply this constraint.
- 24 * @param {pv.Quadtree} q a quadtree for spatial acceleration.
- 25 * @returns {pv.Constraint} this.
- 26 */
- 27
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_DragForce.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_DragForce.js.html
deleted file mode 100644
index 710d7206..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_DragForce.js.html
+++ /dev/null
@@ -1,57 +0,0 @@
-
1/**
- 2 * Constructs a new drag force with the specified constant.
- 3 *
- 4 * @class Implements a drag force, simulating friction. The drag force is
- 5 * applied in the opposite direction of the particle's velocity. Since Position
- 6 * Verlet integration does not track velocities explicitly, the error term with
- 7 * this estimate of velocity is fairly high, so the drag force may be
- 8 * inaccurate.
- 9 *
- 10 * @extends pv.Force
- 11 * @param {number} k the drag constant.
- 12 * @see #constant
- 13 */
- 14pv.Force.drag=function(k){
- 15varforce={};
- 16
- 17if(!arguments.length)k=.1;// default drag constant
- 18
- 19/**
- 20 * Sets or gets the drag constant, in the range [0,1]. The default drag
- 21 * constant is 0.1. The drag forces scales linearly with the particle's
- 22 * velocity based on the given drag constant.
- 23 *
- 24 * @function
- 25 * @name pv.Force.drag.prototype.constant
- 26 * @param {number} x the new drag constant.
- 27 * @returns {pv.Force.drag} this, or the current drag constant.
- 28 */
- 29force.constant=function(x){
- 30if(arguments.length){k=x;returnforce;}
- 31returnk;
- 32};
- 33
- 34/**
- 35 * Applies this force to the specified particles.
- 36 *
- 37 * @function
- 38 * @name pv.Force.drag.prototype.apply
- 39 * @param {pv.Particle} particles particles to which to apply this force.
- 40 */
- 41force.apply=function(particles){
- 42if(k)for(varp=particles;p;p=p.next){
- 43p.fx-=k*p.vx;
- 44p.fy-=k*p.vy;
- 45}
- 46};
- 47
- 48returnforce;
- 49};
- 50
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_Force.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_Force.js.html
deleted file mode 100644
index 0ef965bc..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_Force.js.html
+++ /dev/null
@@ -1,33 +0,0 @@
-
1/**
- 2 * Abstract; see an implementing class.
- 3 *
- 4 * @class Represents a force that acts on particles. Note that this interface
- 5 * does not specify how to bind a force to specific particles; in general,
- 6 * forces are applied globally to all particles. However, some forces may be
- 7 * applied to specific particles or between particles, such as spring forces,
- 8 * through additional specialization.
- 9 *
- 10 * @see pv.Simulation
- 11 * @see pv.Particle
- 12 * @see pv.Force.charge
- 13 * @see pv.Force.drag
- 14 * @see pv.Force.spring
- 15 */
- 16pv.Force={};
- 17
- 18/**
- 19 * Applies this force to the specified particles.
- 20 *
- 21 * @function
- 22 * @name pv.Force.prototype.apply
- 23 * @param {pv.Particle} particles particles to which to apply this force.
- 24 * @param {pv.Quadtree} q a quadtree for spatial acceleration.
- 25 */
- 26
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_Particle.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_Particle.js.html
deleted file mode 100644
index 4b149e99..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_Particle.js.html
+++ /dev/null
@@ -1,89 +0,0 @@
-
1/**
- 2 * Abstract; not implemented. There is no explicit constructor; this class
- 3 * merely serves to document the attributes that are used on particles in
- 4 * physics simulations.
- 5 *
- 6 * @class A weighted particle that can participate in a force simulation.
- 7 *
- 8 * @name pv.Particle
- 9 */
- 10
- 11/**
- 12 * The next particle in the simulation. Particles form a singly-linked list.
- 13 *
- 14 * @field
- 15 * @type pv.Particle
- 16 * @name pv.Particle.prototype.next
- 17 */
- 18
- 19/**
- 20 * The <i>x</i>-position of the particle.
- 21 *
- 22 * @field
- 23 * @type number
- 24 * @name pv.Particle.prototype.x
- 25 */
- 26
- 27/**
- 28 * The <i>y</i>-position of the particle.
- 29 *
- 30 * @field
- 31 * @type number
- 32 * @name pv.Particle.prototype.y
- 33 */
- 34
- 35/**
- 36 * The <i>x</i>-velocity of the particle.
- 37 *
- 38 * @field
- 39 * @type number
- 40 * @name pv.Particle.prototype.vx
- 41 */
- 42
- 43/**
- 44 * The <i>y</i>-velocity of the particle.
- 45 *
- 46 * @field
- 47 * @type number
- 48 * @name pv.Particle.prototype.vy
- 49 */
- 50
- 51/**
- 52 * The <i>x</i>-position of the particle at -dt.
- 53 *
- 54 * @field
- 55 * @type number
- 56 * @name pv.Particle.prototype.px
- 57 */
- 58
- 59/**
- 60 * The <i>y</i>-position of the particle at -dt.
- 61 *
- 62 * @field
- 63 * @type number
- 64 * @name pv.Particle.prototype.py
- 65 */
- 66
- 67/**
- 68 * The <i>x</i>-force on the particle.
- 69 *
- 70 * @field
- 71 * @type number
- 72 * @name pv.Particle.prototype.fx
- 73 */
- 74
- 75/**
- 76 * The <i>y</i>-force on the particle.
- 77 *
- 78 * @field
- 79 * @type number
- 80 * @name pv.Particle.prototype.fy
- 81 */
- 82
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_PositionConstraint.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_PositionConstraint.js.html
deleted file mode 100644
index d3191d43..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_PositionConstraint.js.html
+++ /dev/null
@@ -1,80 +0,0 @@
-
1/**
- 2 * Constructs a default position constraint using the <tt>fix</tt> attribute.
- 3 * An optional position function can be specified to determine how the fixed
- 4 * position per-particle is determined.
- 5 *
- 6 * @class Constraints particles to a fixed position. The fixed position per
- 7 * particle is determined using a given position function, which defaults to
- 8 * <tt>function(d) d.fix</tt>.
- 9 *
- 10 * <p>If the position function returns null, then no position constraint is
- 11 * applied to the given particle. Otherwise, the particle's position is set to
- 12 * the returned position, as expressed by a {@link pv.Vector}. (Note: the
- 13 * position does not need to be an instance of <tt>pv.Vector</tt>, but simply an
- 14 * object with <tt>x</tt> and <tt>y</tt> attributes.)
- 15 *
- 16 * <p>This constraint also supports a configurable alpha parameter, which
- 17 * defaults to 1. If the alpha parameter is in the range [0,1], then rather than
- 18 * setting the particle's new position directly to the position returned by the
- 19 * supplied position function, the particle's position is interpolated towards
- 20 * the fixed position. This results is a smooth (exponential) drift towards the
- 21 * fixed position, which can increase the stability of the physics simulation.
- 22 * In addition, the alpha parameter can be decayed over time, relaxing the
- 23 * position constraint, which helps to stabilize on an optimal solution.
- 24 *
- 25 * @param {function} [f] the position function.
- 26 */
- 27pv.Constraint.position=function(f){
- 28vara=1,// default alpha
- 29constraint={};
- 30
- 31if(!arguments.length)/** @ignore */f=function(p){returnp.fix;};
- 32
- 33/**
- 34 * Sets or gets the alpha parameter for position interpolation. If the alpha
- 35 * parameter is in the range [0,1], then rather than setting the particle's
- 36 * new position directly to the position returned by the supplied position
- 37 * function, the particle's position is interpolated towards the fixed
- 38 * position.
- 39 *
- 40 * @function
- 41 * @name pv.Constraint.position.prototype.alpha
- 42 * @param {number} x the new alpha parameter, in the range [0,1].
- 43 * @returns {pv.Constraint.position} this.
- 44 */
- 45constraint.alpha=function(x){
- 46if(arguments.length){
- 47a=Number(x);
- 48returnconstraint;
- 49}
- 50returna;
- 51};
- 52
- 53/**
- 54 * Applies this constraint to the specified particles.
- 55 *
- 56 * @function
- 57 * @name pv.Constraint.position.prototype.apply
- 58 * @param {pv.Particle} particles particles to which to apply this constraint.
- 59 */
- 60constraint.apply=function(particles){
- 61for(varp=particles;p;p=p.next){
- 62varv=f(p);
- 63if(v){
- 64p.x+=(v.x-p.x)*a;
- 65p.y+=(v.y-p.y)*a;
- 66p.fx=p.fy=p.vx=p.vy=0;
- 67}
- 68}
- 69};
- 70
- 71returnconstraint;
- 72};
- 73
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_Quadtree.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_Quadtree.js.html
deleted file mode 100644
index 865c21c2..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_Quadtree.js.html
+++ /dev/null
@@ -1,203 +0,0 @@
-
1/**
- 2 * Constructs a new quadtree for the specified array of particles.
- 3 *
- 4 * @class Represents a quadtree: a two-dimensional recursive spatial
- 5 * subdivision. This particular implementation uses square partitions, dividing
- 6 * each square into four equally-sized squares. Each particle exists in a unique
- 7 * node; if multiple particles are in the same position, some particles may be
- 8 * stored on internal nodes rather than leaf nodes.
- 9 *
- 10 * <p>This quadtree can be used to accelerate various spatial operations, such
- 11 * as the Barnes-Hut approximation for computing n-body forces, or collision
- 12 * detection.
- 13 *
- 14 * @see pv.Force.charge
- 15 * @see pv.Constraint.collision
- 16 * @param {pv.Particle} particles the linked list of particles.
- 17 */
- 18pv.Quadtree=function(particles){
- 19varp;
- 20
- 21/* Compute bounds. */
- 22varx1=Number.POSITIVE_INFINITY,y1=x1,
- 23x2=Number.NEGATIVE_INFINITY,y2=x2;
- 24for(p=particles;p;p=p.next){
- 25if(p.x<x1)x1=p.x;
- 26if(p.y<y1)y1=p.y;
- 27if(p.x>x2)x2=p.x;
- 28if(p.y>y2)y2=p.y;
- 29}
- 30
- 31/* Squarify the bounds. */
- 32vardx=x2-x1,dy=y2-y1;
- 33if(dx>dy)y2=y1+dx;
- 34elsex2=x1+dy;
- 35this.xMin=x1;
- 36this.yMin=y1;
- 37this.xMax=x2;
- 38this.yMax=y2;
- 39
- 40/**
- 41 * @ignore Recursively inserts the specified particle <i>p</i> at the node
- 42 * <i>n</i> or one of its descendants. The bounds are defined by [<i>x1</i>,
- 43 * <i>x2</i>] and [<i>y1</i>, <i>y2</i>].
- 44 */
- 45functioninsert(n,p,x1,y1,x2,y2){
- 46if(isNaN(p.x)||isNaN(p.y))return;// ignore invalid particles
- 47if(n.leaf){
- 48if(n.p){
- 49/*
- 50 * If the particle at this leaf node is at the same position as the new
- 51 * particle we are adding, we leave the particle associated with the
- 52 * internal node while adding the new particle to a child node. This
- 53 * avoids infinite recursion.
- 54 */
- 55if((Math.abs(n.p.x-p.x)+Math.abs(n.p.y-p.y))<.01){
- 56insertChild(n,p,x1,y1,x2,y2);
- 57}else{
- 58varv=n.p;
- 59n.p=null;
- 60insertChild(n,v,x1,y1,x2,y2);
- 61insertChild(n,p,x1,y1,x2,y2);
- 62}
- 63}else{
- 64n.p=p;
- 65}
- 66}else{
- 67insertChild(n,p,x1,y1,x2,y2);
- 68}
- 69}
- 70
- 71/**
- 72 * @ignore Recursively inserts the specified particle <i>p</i> into a
- 73 * descendant of node <i>n</i>. The bounds are defined by [<i>x1</i>,
- 74 * <i>x2</i>] and [<i>y1</i>, <i>y2</i>].
- 75 */
- 76functioninsertChild(n,p,x1,y1,x2,y2){
- 77/* Compute the split point, and the quadrant in which to insert p. */
- 78varsx=(x1+x2)*.5,
- 79sy=(y1+y2)*.5,
- 80right=p.x>=sx,
- 81bottom=p.y>=sy;
- 82
- 83/* Recursively insert into the child node. */
- 84n.leaf=false;
- 85switch((bottom<<1)+right){
- 86case0:n=n.c1||(n.c1=newpv.Quadtree.Node());break;
- 87case1:n=n.c2||(n.c2=newpv.Quadtree.Node());break;
- 88case2:n=n.c3||(n.c3=newpv.Quadtree.Node());break;
- 89case3:n=n.c4||(n.c4=newpv.Quadtree.Node());break;
- 90}
- 91
- 92/* Update the bounds as we recurse. */
- 93if(right)x1=sx;elsex2=sx;
- 94if(bottom)y1=sy;elsey2=sy;
- 95insert(n,p,x1,y1,x2,y2);
- 96}
- 97
- 98/* Insert all particles. */
- 99this.root=newpv.Quadtree.Node();
-100for(p=particles;p;p=p.next)insert(this.root,p,x1,y1,x2,y2);
-101};
-102
-103/**
-104 * The root node of the quadtree.
-105 *
-106 * @type pv.Quadtree.Node
-107 * @name pv.Quadtree.prototype.root
-108 */
-109
-110/**
-111 * The minimum x-coordinate value of all contained particles.
-112 *
-113 * @type number
-114 * @name pv.Quadtree.prototype.xMin
-115 */
-116
-117/**
-118 * The maximum x-coordinate value of all contained particles.
-119 *
-120 * @type number
-121 * @name pv.Quadtree.prototype.xMax
-122 */
-123
-124/**
-125 * The minimum y-coordinate value of all contained particles.
-126 *
-127 * @type number
-128 * @name pv.Quadtree.prototype.yMin
-129 */
-130
-131/**
-132 * The maximum y-coordinate value of all contained particles.
-133 *
-134 * @type number
-135 * @name pv.Quadtree.prototype.yMax
-136 */
-137
-138/**
-139 * Constructs a new node.
-140 *
-141 * @class A node in a quadtree.
-142 *
-143 * @see pv.Quadtree
-144 */
-145pv.Quadtree.Node=function(){
-146/*
-147 * Prepopulating all attributes significantly increases performance! Also,
-148 * letting the language interpreter manage garbage collection was moderately
-149 * faster than creating a cache pool.
-150 */
-151this.leaf=true;
-152this.c1=null;
-153this.c2=null;
-154this.c3=null;
-155this.c4=null;
-156this.p=null;
-157};
-158
-159/**
-160 * True if this node is a leaf node; i.e., it has no children. Note that both
-161 * leaf nodes and non-leaf (internal) nodes may have associated particles. If
-162 * this is a non-leaf node, then at least one of {@link #c1}, {@link #c2},
-163 * {@link #c3} or {@link #c4} is guaranteed to be non-null.
-164 *
-165 * @type boolean
-166 * @name pv.Quadtree.Node.prototype.leaf
-167 */
-168
-169/**
-170 * The particle associated with this node, if any.
-171 *
-172 * @type pv.Particle
-173 * @name pv.Quadtree.Node.prototype.p
-174 */
-175
-176/**
-177 * The child node for the second quadrant, if any.
-178 *
-179 * @type pv.Quadtree.Node
-180 * @name pv.Quadtree.Node.prototype.c2
-181 */
-182
-183/**
-184 * The child node for the third quadrant, if any.
-185 *
-186 * @type pv.Quadtree.Node
-187 * @name pv.Quadtree.Node.prototype.c3
-188 */
-189
-190/**
-191 * The child node for the fourth quadrant, if any.
-192 *
-193 * @type pv.Quadtree.Node
-194 * @name pv.Quadtree.Node.prototype.c4
-195 */
-196
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_Simulation.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_Simulation.js.html
deleted file mode 100644
index a62f0601..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_Simulation.js.html
+++ /dev/null
@@ -1,167 +0,0 @@
-
1/**
- 2 * Constructs a new empty simulation.
- 3 *
- 4 * @param {array} particles
- 5 * @returns {pv.Simulation} a new simulation for the specified particles.
- 6 * @see pv.Simulation
- 7 */
- 8pv.simulation=function(particles){
- 9returnnewpv.Simulation(particles);
- 10};
- 11
- 12/**
- 13 * Constructs a new simulation for the specified particles.
- 14 *
- 15 * @class Represents a particle simulation. Particles are massive points in
- 16 * two-dimensional space. Forces can be applied to these particles, causing them
- 17 * to move. Constraints can also be applied to restrict particle movement, for
- 18 * example, constraining particles to a fixed position, or simulating collision
- 19 * between circular particles with area.
- 20 *
- 21 * <p>The simulation uses <a
- 22 * href="http://en.wikipedia.org/wiki/Verlet_integration">Position Verlet</a>
- 23 * integration, due to the ease with which <a
- 24 * href="http://www.teknikus.dk/tj/gdc2001.htm">geometric constraints</a> can be
- 25 * implemented. For each time step, Verlet integration is performed, new forces
- 26 * are accumulated, and then constraints are applied.
- 27 *
- 28 * <p>The simulation makes two simplifying assumptions: all particles are
- 29 * equal-mass, and the time step of the simulation is fixed. It would be easy to
- 30 * incorporate variable-mass particles as a future enhancement. Variable time
- 31 * steps are also possible, but are likely to introduce instability in the
- 32 * simulation.
- 33 *
- 34 * <p>This class can be used directly to simulate particle interaction.
- 35 * Alternatively, for network diagrams, see {@link pv.Layout.Force}.
- 36 *
- 37 * @param {array} particles an array of {@link pv.Particle}s to simulate.
- 38 * @see pv.Layout.Force
- 39 * @see pv.Force
- 40 * @see pv.Constraint
- 41 */
- 42pv.Simulation=function(particles){
- 43for(vari=0;i<particles.length;i++)this.particle(particles[i]);
- 44};
- 45
- 46/**
- 47 * The particles in the simulation. Particles are stored as a linked list; this
- 48 * field represents the first particle in the simulation.
- 49 *
- 50 * @field
- 51 * @type pv.Particle
- 52 * @name pv.Simulation.prototype.particles
- 53 */
- 54
- 55/**
- 56 * The forces in the simulation. Forces are stored as a linked list; this field
- 57 * represents the first force in the simulation.
- 58 *
- 59 * @field
- 60 * @type pv.Force
- 61 * @name pv.Simulation.prototype.forces
- 62 */
- 63
- 64/**
- 65 * The constraints in the simulation. Constraints are stored as a linked list;
- 66 * this field represents the first constraint in the simulation.
- 67 *
- 68 * @field
- 69 * @type pv.Constraint
- 70 * @name pv.Simulation.prototype.constraints
- 71 */
- 72
- 73/**
- 74 * Adds the specified particle to the simulation.
- 75 *
- 76 * @param {pv.Particle} p the new particle.
- 77 * @returns {pv.Simulation} this.
- 78 */
- 79pv.Simulation.prototype.particle=function(p){
- 80p.next=this.particles;
- 81/* Default velocities and forces to zero if unset. */
- 82if(isNaN(p.px))p.px=p.x;
- 83if(isNaN(p.py))p.py=p.y;
- 84if(isNaN(p.fx))p.fx=0;
- 85if(isNaN(p.fy))p.fy=0;
- 86this.particles=p;
- 87returnthis;
- 88};
- 89
- 90/**
- 91 * Adds the specified force to the simulation.
- 92 *
- 93 * @param {pv.Force} f the new force.
- 94 * @returns {pv.Simulation} this.
- 95 */
- 96pv.Simulation.prototype.force=function(f){
- 97f.next=this.forces;
- 98this.forces=f;
- 99returnthis;
-100};
-101
-102/**
-103 * Adds the specified constraint to the simulation.
-104 *
-105 * @param {pv.Constraint} c the new constraint.
-106 * @returns {pv.Simulation} this.
-107 */
-108pv.Simulation.prototype.constraint=function(c){
-109c.next=this.constraints;
-110this.constraints=c;
-111returnthis;
-112};
-113
-114/**
-115 * Apply constraints, and then set the velocities to zero.
-116 *
-117 * @returns {pv.Simulation} this.
-118 */
-119pv.Simulation.prototype.stabilize=function(n){
-120varc;
-121if(!arguments.length)n=3;// TODO use cooling schedule
-122for(vari=0;i<n;i++){
-123varq=newpv.Quadtree(this.particles);
-124for(c=this.constraints;c;c=c.next)c.apply(this.particles,q);
-125}
-126for(varp=this.particles;p;p=p.next){
-127p.px=p.x;
-128p.py=p.y;
-129}
-130returnthis;
-131};
-132
-133/**
-134 * Advances the simulation one time-step.
-135 */
-136pv.Simulation.prototype.step=function(){
-137varp,f,c;
-138
-139/*
-140 * Assumptions:
-141 * - The mass (m) of every particles is 1.
-142 * - The time step (dt) is 1.
-143 */
-144
-145/* Position Verlet integration. */
-146for(p=this.particles;p;p=p.next){
-147varpx=p.px,py=p.py;
-148p.px=p.x;
-149p.py=p.y;
-150p.x+=p.vx=((p.x-px)+p.fx);
-151p.y+=p.vy=((p.y-py)+p.fy);
-152}
-153
-154/* Apply constraints, then accumulate new forces. */
-155varq=newpv.Quadtree(this.particles);
-156for(c=this.constraints;c;c=c.next)c.apply(this.particles,q);
-157for(p=this.particles;p;p=p.next)p.fx=p.fy=0;
-158for(f=this.forces;f;f=f.next)f.apply(this.particles,q);
-159};
-160
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_SpringForce.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_SpringForce.js.html
deleted file mode 100644
index 26ecba88..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_physics_SpringForce.js.html
+++ /dev/null
@@ -1,149 +0,0 @@
-
1/**
- 2 * Constructs a new spring force with the specified constant. The links
- 3 * associated with this spring force must be specified before the spring force
- 4 * can be applied.
- 5 *
- 6 * @class Implements a spring force, per Hooke's law. The spring force can be
- 7 * configured with a tension constant, rest length, and damping factor. The
- 8 * tension and damping will automatically be normalized using the inverse square
- 9 * root of the maximum link degree of attached nodes; this makes springs weaker
- 10 * between nodes of high link degree.
- 11 *
- 12 * <p>Unlike other forces (such as charge and drag forces) which may be applied
- 13 * globally, spring forces are only applied between linked particles. Therefore,
- 14 * an array of links must be specified before this force can be applied; the
- 15 * links should be an array of {@link pv.Layout.Network.Link}s. See also
- 16 * {@link pv.Layout.Force} for an example of using spring and charge forces for
- 17 * network layout.
- 18 *
- 19 * @extends pv.Force
- 20 * @param {number} k the spring constant.
- 21 * @see #constant
- 22 * @see #links
- 23 */
- 24pv.Force.spring=function(k){
- 25vard=.1,// default damping factor
- 26l=20,// default rest length
- 27links,// links on which to apply spring forces
- 28kl,// per-spring normalization
- 29force={};
- 30
- 31if(!arguments.length)k=.1;// default spring constant (tension)
- 32
- 33/**
- 34 * Sets or gets the links associated with this spring force. Unlike other
- 35 * forces (such as charge and drag forces) which may be applied globally,
- 36 * spring forces are only applied between linked particles. Therefore, an
- 37 * array of links must be specified before this force can be applied; the
- 38 * links should be an array of {@link pv.Layout.Network.Link}s.
- 39 *
- 40 * @function
- 41 * @name pv.Force.spring.prototype.links
- 42 * @param {array} x the new array of links.
- 43 * @returns {pv.Force.spring} this, or the current array of links.
- 44 */
- 45force.links=function(x){
- 46if(arguments.length){
- 47links=x;
- 48kl=x.map(function(l){
- 49return1/Math.sqrt(Math.max(
- 50l.sourceNode.linkDegree,
- 51l.targetNode.linkDegree));
- 52});
- 53returnforce;
- 54}
- 55returnlinks;
- 56};
- 57
- 58/**
- 59 * Sets or gets the spring constant. The default value is 0.1; greater values
- 60 * will result in stronger tension. The spring tension is automatically
- 61 * normalized using the inverse square root of the maximum link degree of
- 62 * attached nodes.
- 63 *
- 64 * @function
- 65 * @name pv.Force.spring.prototype.constant
- 66 * @param {number} x the new spring constant.
- 67 * @returns {pv.Force.spring} this, or the current spring constant.
- 68 */
- 69force.constant=function(x){
- 70if(arguments.length){
- 71k=Number(x);
- 72returnforce;
- 73}
- 74returnk;
- 75};
- 76
- 77/**
- 78 * The spring damping factor, in the range [0,1]. Damping functions
- 79 * identically to drag forces, damping spring bounciness by applying a force
- 80 * in the opposite direction of attached nodes' velocities. The default value
- 81 * is 0.1. The spring damping is automatically normalized using the inverse
- 82 * square root of the maximum link degree of attached nodes.
- 83 *
- 84 * @function
- 85 * @name pv.Force.spring.prototype.damping
- 86 * @param {number} x the new spring damping factor.
- 87 * @returns {pv.Force.spring} this, or the current spring damping factor.
- 88 */
- 89force.damping=function(x){
- 90if(arguments.length){
- 91d=Number(x);
- 92returnforce;
- 93}
- 94returnd;
- 95};
- 96
- 97/**
- 98 * The spring rest length. The default value is 20 pixels.
- 99 *
-100 * @function
-101 * @name pv.Force.spring.prototype.length
-102 * @param {number} x the new spring rest length.
-103 * @returns {pv.Force.spring} this, or the current spring rest length.
-104 */
-105force.length=function(x){
-106if(arguments.length){
-107l=Number(x);
-108returnforce;
-109}
-110returnl;
-111};
-112
-113/**
-114 * Applies this force to the specified particles.
-115 *
-116 * @function
-117 * @name pv.Force.spring.prototype.apply
-118 * @param {pv.Particle} particles particles to which to apply this force.
-119 */
-120force.apply=function(particles){
-121for(vari=0;i<links.length;i++){
-122vara=links[i].sourceNode,
-123b=links[i].targetNode,
-124dx=a.x-b.x,
-125dy=a.y-b.y,
-126dn=Math.sqrt(dx*dx+dy*dy),
-127dd=dn?(1/dn):1,
-128ks=k*kl[i],// normalized tension
-129kd=d*kl[i],// normalized damping
-130kk=(ks*(dn-l)+kd*(dx*(a.vx-b.vx)+dy*(a.vy-b.vy))*dd)*dd,
-131fx=-kk*(dn?dx:(.01*(.5-Math.random()))),
-132fy=-kk*(dn?dy:(.01*(.5-Math.random())));
-133a.fx+=fx;
-134a.fy+=fy;
-135b.fx-=fx;
-136b.fy-=fy;
-137}
-138};
-139
-140returnforce;
-141};
-142
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_pv-internals.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_pv-internals.js.html
deleted file mode 100644
index 9689d319..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_pv-internals.js.html
+++ /dev/null
@@ -1,162 +0,0 @@
-
1/**
- 2 * @private Returns a prototype object suitable for extending the given class
- 3 * <tt>f</tt>. Rather than constructing a new instance of <tt>f</tt> to serve as
- 4 * the prototype (which unnecessarily runs the constructor on the created
- 5 * prototype object, potentially polluting it), an anonymous function is
- 6 * generated internally that shares the same prototype:
- 7 *
- 8 * <pre>function g() {}
- 9 * g.prototype = f.prototype;
- 10 * return new g();</pre>
- 11 *
- 12 * For more details, see Douglas Crockford's essay on prototypal inheritance.
- 13 *
- 14 * @param {function} f a constructor.
- 15 * @returns a suitable prototype object.
- 16 * @see Douglas Crockford's essay on <a
- 17 * href="http://javascript.crockford.com/prototypal.html">prototypal
- 18 * inheritance</a>.
- 19 */
- 20pv.extend=function(f){
- 21functiong(){}
- 22g.prototype=f.prototype||f;
- 23returnnewg();
- 24};
- 25
- 26try{
- 27eval("pv.parse = function(x) x;");// native support
- 28}catch(e){
- 29
- 30/**
- 31 * @private Parses a Protovis specification, which may use JavaScript 1.8
- 32 * function expresses, replacing those function expressions with proper
- 33 * functions such that the code can be run by a JavaScript 1.6 interpreter. This
- 34 * hack only supports function expressions (using clumsy regular expressions, no
- 35 * less), and not other JavaScript 1.8 features such as let expressions.
- 36 *
- 37 * @param {string} s a Protovis specification (i.e., a string of JavaScript 1.8
- 38 * source code).
- 39 * @returns {string} a conformant JavaScript 1.6 source code.
- 40 */
- 41pv.parse=function(js){// hacky regex support
- 42varre=newRegExp("function\\s*(\\b\\w+)?\\s*\\([^)]*\\)\\s*","mg"),m,d,i=0,s="";
- 43while(m=re.exec(js)){
- 44varj=m.index+m[0].length;
- 45if(js.charAt(j)!='{'){
- 46s+=js.substring(i,j)+"{return ";
- 47i=j;
- 48for(varp=0;p>=0&&j<js.length;j++){
- 49varc=js.charAt(j);
- 50switch(c){
- 51case'"':case'\'':{
- 52while(++j<js.length&&(d=js.charAt(j))!=c){
- 53if(d=='\\')j++;
- 54}
- 55break;
- 56}
- 57case'[':case'(':p++;break;
- 58case']':case')':p--;break;
- 59case';':
- 60case',':if(p==0)p--;break;
- 61}
- 62}
- 63s+=pv.parse(js.substring(i,--j))+";}";
- 64i=j;
- 65}
- 66re.lastIndex=j;
- 67}
- 68s+=js.substring(i);
- 69returns;
- 70};
- 71}
- 72
- 73/**
- 74 * @private Computes the value of the specified CSS property <tt>p</tt> on the
- 75 * specified element <tt>e</tt>.
- 76 *
- 77 * @param {string} p the name of the CSS property.
- 78 * @param e the element on which to compute the CSS property.
- 79 */
- 80pv.css=function(e,p){
- 81returnwindow.getComputedStyle
- 82?window.getComputedStyle(e,null).getPropertyValue(p)
- 83:e.currentStyle[p];
- 84};
- 85
- 86/**
- 87 * @private Reports the specified error to the JavaScript console. Mozilla only
- 88 * allows logging to the console for privileged code; if the console is
- 89 * unavailable, the alert dialog box is used instead.
- 90 *
- 91 * @param e the exception that triggered the error.
- 92 */
- 93pv.error=function(e){
- 94(typeofconsole=="undefined")?alert(e):console.error(e);
- 95};
- 96
- 97/**
- 98 * @private Registers the specified listener for events of the specified type on
- 99 * the specified target. For standards-compliant browsers, this method uses
-100 * <tt>addEventListener</tt>; for Internet Explorer, <tt>attachEvent</tt>.
-101 *
-102 * @param target a DOM element.
-103 * @param {string} type the type of event, such as "click".
-104 * @param {function} the event handler callback.
-105 */
-106pv.listen=function(target,type,listener){
-107listener=pv.listener(listener);
-108returntarget.addEventListener
-109?target.addEventListener(type,listener,false)
-110:target.attachEvent("on"+type,listener);
-111};
-112
-113/**
-114 * @private Returns a wrapper for the specified listener function such that the
-115 * {@link pv.event} is set for the duration of the listener's invocation. The
-116 * wrapper is cached on the returned function, such that duplicate registrations
-117 * of the wrapped event handler are ignored.
-118 *
-119 * @param {function} f an event handler.
-120 * @returns {function} the wrapped event handler.
-121 */
-122pv.listener=function(f){
-123returnf.$listener||(f.$listener=function(e){
-124try{
-125pv.event=e;
-126returnf.call(this,e);
-127}finally{
-128deletepv.event;
-129}
-130});
-131};
-132
-133/**
-134 * @private Returns true iff <i>a</i> is an ancestor of <i>e</i>. This is useful
-135 * for ignoring mouseout and mouseover events that are contained within the
-136 * target element.
-137 */
-138pv.ancestor=function(a,e){
-139while(e){
-140if(e==a)returntrue;
-141e=e.parentNode;
-142}
-143returnfalse;
-144};
-145
-146/** @private Returns a locally-unique positive id. */
-147pv.id=function(){
-148varid=1;returnfunction(){returnid++;};
-149}();
-150
-151/** @private Returns a function wrapping the specified constant. */
-152pv.functor=function(v){
-153returntypeofv=="function"?v:function(){returnv;};
-154};
-155
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_pv.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_pv.js.html
deleted file mode 100644
index cf0f4d87..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_pv.js.html
+++ /dev/null
@@ -1,103 +0,0 @@
-
1/**
- 2 * The top-level Protovis namespace. All public methods and fields should be
- 3 * registered on this object. Note that core Protovis source is surrounded by an
- 4 * anonymous function, so any other declared globals will not be visible outside
- 5 * of core methods. This also allows multiple versions of Protovis to coexist,
- 6 * since each version will see their own <tt>pv</tt> namespace.
- 7 *
- 8 * @namespace The top-level Protovis namespace, <tt>pv</tt>.
- 9 */
- 10varpv={};
- 11
- 12/**
- 13 * Protovis major and minor version numbers.
- 14 *
- 15 * @namespace Protovis major and minor version numbers.
- 16 */
- 17pv.version={
- 18/**
- 19 * The major version number.
- 20 *
- 21 * @type number
- 22 * @constant
- 23 */
- 24major:3,
- 25
- 26/**
- 27 * The minor version number.
- 28 *
- 29 * @type number
- 30 * @constant
- 31 */
- 32minor:2
- 33};
- 34
- 35/**
- 36 * Returns the passed-in argument, <tt>x</tt>; the identity function. This method
- 37 * is provided for convenience since it is used as the default behavior for a
- 38 * number of property functions.
- 39 *
- 40 * @param x a value.
- 41 * @returns the value <tt>x</tt>.
- 42 */
- 43pv.identity=function(x){returnx;};
- 44
- 45/**
- 46 * Returns <tt>this.index</tt>. This method is provided for convenience for use
- 47 * with scales. For example, to color bars by their index, say:
- 48 *
- 49 * <pre>.fillStyle(pv.Colors.category10().by(pv.index))</pre>
- 50 *
- 51 * This method is equivalent to <tt>function() this.index</tt>, but more
- 52 * succinct. Note that the <tt>index</tt> property is also supported for
- 53 * accessor functions with {@link pv.max}, {@link pv.min} and other array
- 54 * utility methods.
- 55 *
- 56 * @see pv.Scale
- 57 * @see pv.Mark#index
- 58 */
- 59pv.index=function(){returnthis.index;};
- 60
- 61/**
- 62 * Returns <tt>this.childIndex</tt>. This method is provided for convenience for
- 63 * use with scales. For example, to color bars by their child index, say:
- 64 *
- 65 * <pre>.fillStyle(pv.Colors.category10().by(pv.child))</pre>
- 66 *
- 67 * This method is equivalent to <tt>function() this.childIndex</tt>, but more
- 68 * succinct.
- 69 *
- 70 * @see pv.Scale
- 71 * @see pv.Mark#childIndex
- 72 */
- 73pv.child=function(){returnthis.childIndex;};
- 74
- 75/**
- 76 * Returns <tt>this.parent.index</tt>. This method is provided for convenience
- 77 * for use with scales. This method is provided for convenience for use with
- 78 * scales. For example, to color bars by their parent index, say:
- 79 *
- 80 * <pre>.fillStyle(pv.Colors.category10().by(pv.parent))</pre>
- 81 *
- 82 * Tthis method is equivalent to <tt>function() this.parent.index</tt>, but more
- 83 * succinct.
- 84 *
- 85 * @see pv.Scale
- 86 * @see pv.Mark#index
- 87 */
- 88pv.parent=function(){returnthis.parent.index;};
- 89
- 90/**
- 91 * Stores the current event. This field is only set within event handlers.
- 92 *
- 93 * @type Event
- 94 * @name pv.event
- 95 */
- 96
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_scene_SvgArea.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_scene_SvgArea.js.html
deleted file mode 100644
index 0f5f689d..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_scene_SvgArea.js.html
+++ /dev/null
@@ -1,180 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_scene_SvgScene.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_scene_SvgScene.js.html
deleted file mode 100644
index 4ff7c73f..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_scene_SvgScene.js.html
+++ /dev/null
@@ -1,193 +0,0 @@
-
1/**
- 2 * @private
- 3 * @namespace
- 4 */
- 5pv.Scene=pv.SvgScene={
- 6/* Various namespaces. */
- 7svg:"http://www.w3.org/2000/svg",
- 8xmlns:"http://www.w3.org/2000/xmlns",
- 9xlink:"http://www.w3.org/1999/xlink",
- 10xhtml:"http://www.w3.org/1999/xhtml",
- 11
- 12/** The pre-multipled scale, based on any enclosing transforms. */
- 13scale:1,
- 14
- 15/** The set of supported events. */
- 16events:[
- 17"DOMMouseScroll",// for Firefox
- 18"mousewheel",
- 19"mousedown",
- 20"mouseup",
- 21"mouseover",
- 22"mouseout",
- 23"mousemove",
- 24"click",
- 25"dblclick"
- 26],
- 27
- 28/** Implicit values for SVG and CSS properties. */
- 29implicit:{
- 30svg:{
- 31"shape-rendering":"auto",
- 32"pointer-events":"painted",
- 33"x":0,
- 34"y":0,
- 35"dy":0,
- 36"text-anchor":"start",
- 37"transform":"translate(0,0)",
- 38"fill":"none",
- 39"fill-opacity":1,
- 40"stroke":"none",
- 41"stroke-opacity":1,
- 42"stroke-width":1.5,
- 43"stroke-linejoin":"miter"
- 44},
- 45css:{
- 46"font":"10px sans-serif"
- 47}
- 48}
- 49};
- 50
- 51/**
- 52 * Updates the display for the specified array of scene nodes.
- 53 *
- 54 * @param scenes {array} an array of scene nodes.
- 55 */
- 56pv.SvgScene.updateAll=function(scenes){
- 57if(scenes.length
- 58&&scenes[0].reverse
- 59&&(scenes.type!="line")
- 60&&(scenes.type!="area")){
- 61varreversed=pv.extend(scenes);
- 62for(vari=0,j=scenes.length-1;j>=0;i++,j--){
- 63reversed[i]=scenes[j];
- 64}
- 65scenes=reversed;
- 66}
- 67this.removeSiblings(this[scenes.type](scenes));
- 68};
- 69
- 70/**
- 71 * Creates a new SVG element of the specified type.
- 72 *
- 73 * @param type {string} an SVG element type, such as "rect".
- 74 * @returns a new SVG element.
- 75 */
- 76pv.SvgScene.create=function(type){
- 77returndocument.createElementNS(this.svg,type);
- 78};
- 79
- 80/**
- 81 * Expects the element <i>e</i> to be the specified type. If the element does
- 82 * not exist, a new one is created. If the element does exist but is the wrong
- 83 * type, it is replaced with the specified element.
- 84 *
- 85 * @param e the current SVG element.
- 86 * @param type {string} an SVG element type, such as "rect".
- 87 * @param attributes an optional attribute map.
- 88 * @param style an optional style map.
- 89 * @returns a new SVG element.
- 90 */
- 91pv.SvgScene.expect=function(e,type,attributes,style){
- 92if(e){
- 93if(e.tagName=="a")e=e.firstChild;
- 94if(e.tagName!=type){
- 95varn=this.create(type);
- 96e.parentNode.replaceChild(n,e);
- 97e=n;
- 98}
- 99}else{
-100e=this.create(type);
-101}
-102for(varnameinattributes){
-103varvalue=attributes[name];
-104if(value==this.implicit.svg[name])value=null;
-105if(value==null)e.removeAttribute(name);
-106elsee.setAttribute(name,value);
-107}
-108for(varnameinstyle){
-109varvalue=style[name];
-110if(value==this.implicit.css[name])value=null;
-111if(value==null)e.style.removeProperty(name);
-112elsee.style[name]=value;
-113}
-114returne;
-115};
-116
-117/** TODO */
-118pv.SvgScene.append=function(e,scenes,index){
-119e.$scene={scenes:scenes,index:index};
-120e=this.title(e,scenes[index]);
-121if(!e.parentNode)scenes.$g.appendChild(e);
-122returne.nextSibling;
-123};
-124
-125/**
-126 * Applies a title tooltip to the specified element <tt>e</tt>, using the
-127 * <tt>title</tt> property of the specified scene node <tt>s</tt>. Note that
-128 * this implementation does not create an SVG <tt>title</tt> element as a child
-129 * of <tt>e</tt>; although this is the recommended standard, it is only
-130 * supported in Opera. Instead, an anchor element is created around the element
-131 * <tt>e</tt>, and the <tt>xlink:title</tt> attribute is set accordingly.
-132 *
-133 * @param e an SVG element.
-134 * @param s a scene node.
-135 */
-136pv.SvgScene.title=function(e,s){
-137vara=e.parentNode;
-138if(a&&(a.tagName!="a"))a=null;
-139if(s.title){
-140if(!a){
-141a=this.create("a");
-142if(e.parentNode)e.parentNode.replaceChild(a,e);
-143a.appendChild(e);
-144}
-145a.setAttributeNS(this.xlink,"title",s.title);
-146returna;
-147}
-148if(a)a.parentNode.replaceChild(e,a);
-149returne;
-150};
-151
-152/** TODO */
-153pv.SvgScene.dispatch=pv.listener(function(e){
-154vart=e.target.$scene;
-155if(t){
-156vartype=e.type;
-157
-158/* Fixes for mousewheel support on Firefox & Opera. */
-159switch(type){
-160case"DOMMouseScroll":{
-161type="mousewheel";
-162e.wheel=-480*e.detail;
-163break;
-164}
-165case"mousewheel":{
-166e.wheel=(window.opera?12:1)*e.wheelDelta;
-167break;
-168}
-169}
-170
-171if(pv.Mark.dispatch(type,t.scenes,t.index))e.preventDefault();
-172}
-173});
-174
-175/** @private Remove siblings following element <i>e</i>. */
-176pv.SvgScene.removeSiblings=function(e){
-177while(e){
-178varn=e.nextSibling;
-179e.parentNode.removeChild(e);
-180e=n;
-181}
-182};
-183
-184/** @private Do nothing when rendering undefined mark types. */
-185pv.SvgScene.undefined=function(){};
-186
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_scene_SvgWedge.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_scene_SvgWedge.js.html
deleted file mode 100644
index 6cbfd124..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_scene_SvgWedge.js.html
+++ /dev/null
@@ -1,74 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_text_DateFormat.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_text_DateFormat.js.html
deleted file mode 100644
index c264921a..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_text_DateFormat.js.html
+++ /dev/null
@@ -1,270 +0,0 @@
-
1/**
- 2 * Constructs a new date format with the specified string pattern.
- 3 *
- 4 * @class The format string is in the same format expected by the
- 5 * <tt>strftime</tt> function in C. The following conversion specifications are
- 6 * supported:<ul>
- 7 *
- 8 * <li>%a - abbreviated weekday name.</li>
- 9 * <li>%A - full weekday name.</li>
- 10 * <li>%b - abbreviated month names.</li>
- 11 * <li>%B - full month names.</li>
- 12 * <li>%c - locale's appropriate date and time.</li>
- 13 * <li>%C - century number.</li>
- 14 * <li>%d - day of month [01,31] (zero padded).</li>
- 15 * <li>%D - same as %m/%d/%y.</li>
- 16 * <li>%e - day of month [ 1,31] (space padded).</li>
- 17 * <li>%h - same as %b.</li>
- 18 * <li>%H - hour (24-hour clock) [00,23] (zero padded).</li>
- 19 * <li>%I - hour (12-hour clock) [01,12] (zero padded).</li>
- 20 * <li>%m - month number [01,12] (zero padded).</li>
- 21 * <li>%M - minute [0,59] (zero padded).</li>
- 22 * <li>%n - newline character.</li>
- 23 * <li>%p - locale's equivalent of a.m. or p.m.</li>
- 24 * <li>%r - same as %I:%M:%S %p.</li>
- 25 * <li>%R - same as %H:%M.</li>
- 26 * <li>%S - second [00,61] (zero padded).</li>
- 27 * <li>%t - tab character.</li>
- 28 * <li>%T - same as %H:%M:%S.</li>
- 29 * <li>%x - same as %m/%d/%y.</li>
- 30 * <li>%X - same as %I:%M:%S %p.</li>
- 31 * <li>%y - year with century [00,99] (zero padded).</li>
- 32 * <li>%Y - year including century.</li>
- 33 * <li>%% - %.</li>
- 34 *
- 35 * </ul>The following conversion specifications are currently <i>unsupported</i>
- 36 * for formatting:<ul>
- 37 *
- 38 * <li>%j - day number [1,366].</li>
- 39 * <li>%u - weekday number [1,7].</li>
- 40 * <li>%U - week number [00,53].</li>
- 41 * <li>%V - week number [01,53].</li>
- 42 * <li>%w - weekday number [0,6].</li>
- 43 * <li>%W - week number [00,53].</li>
- 44 * <li>%Z - timezone name or abbreviation.</li>
- 45 *
- 46 * </ul>In addition, the following conversion specifications are currently
- 47 * <i>unsupported</i> for parsing:<ul>
- 48 *
- 49 * <li>%a - day of week, either abbreviated or full name.</li>
- 50 * <li>%A - same as %a.</li>
- 51 * <li>%c - locale's appropriate date and time.</li>
- 52 * <li>%C - century number.</li>
- 53 * <li>%D - same as %m/%d/%y.</li>
- 54 * <li>%I - hour (12-hour clock) [1,12].</li>
- 55 * <li>%n - any white space.</li>
- 56 * <li>%p - locale's equivalent of a.m. or p.m.</li>
- 57 * <li>%r - same as %I:%M:%S %p.</li>
- 58 * <li>%R - same as %H:%M.</li>
- 59 * <li>%t - same as %n.</li>
- 60 * <li>%T - same as %H:%M:%S.</li>
- 61 * <li>%x - locale's equivalent to %m/%d/%y.</li>
- 62 * <li>%X - locale's equivalent to %I:%M:%S %p.</li>
- 63 *
- 64 * </ul>
- 65 *
- 66 * @see <a
- 67 * href="http://www.opengroup.org/onlinepubs/007908799/xsh/strftime.html">strftime</a>
- 68 * documentation.
- 69 * @see <a
- 70 * href="http://www.opengroup.org/onlinepubs/007908799/xsh/strptime.html">strptime</a>
- 71 * documentation.
- 72 * @extends pv.Format
- 73 * @param {string} pattern the format pattern.
- 74 */
- 75pv.Format.date=function(pattern){
- 76varpad=pv.Format.pad;
- 77
- 78/** @private */
- 79functionformat(d){
- 80returnpattern.replace(/%[a-zA-Z0-9]/g,function(s){
- 81switch(s){
- 82case'%a':return[
- 83"Sun","Mon","Tue","Wed","Thu","Fri","Sat"
- 84][d.getDay()];
- 85case'%A':return[
- 86"Sunday","Monday","Tuesday","Wednesday","Thursday","Friday",
- 87"Saturday"
- 88][d.getDay()];
- 89case'%h':
- 90case'%b':return[
- 91"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep",
- 92"Oct","Nov","Dec"
- 93][d.getMonth()];
- 94case'%B':return[
- 95"January","February","March","April","May","June","July",
- 96"August","September","October","November","December"
- 97][d.getMonth()];
- 98case'%c':returnd.toLocaleString();
- 99case'%C':returnpad("0",2,Math.floor(d.getFullYear()/100)%100);
-100case'%d':returnpad("0",2,d.getDate());
-101case'%x':
-102case'%D':returnpad("0",2,d.getMonth()+1)
-103+"/"+pad("0",2,d.getDate())
-104+"/"+pad("0",2,d.getFullYear()%100);
-105case'%e':returnpad(" ",2,d.getDate());
-106case'%H':returnpad("0",2,d.getHours());
-107case'%I':{
-108varh=d.getHours()%12;
-109returnh?pad("0",2,h):12;
-110}
-111// TODO %j: day of year as a decimal number [001,366]
-112case'%m':returnpad("0",2,d.getMonth()+1);
-113case'%M':returnpad("0",2,d.getMinutes());
-114case'%n':return"\n";
-115case'%p':returnd.getHours()<12?"AM":"PM";
-116case'%T':
-117case'%X':
-118case'%r':{
-119varh=d.getHours()%12;
-120return(h?pad("0",2,h):12)
-121+":"+pad("0",2,d.getMinutes())
-122+":"+pad("0",2,d.getSeconds())
-123+" "+(d.getHours()<12?"AM":"PM");
-124}
-125case'%R':returnpad("0",2,d.getHours())+":"+pad("0",2,d.getMinutes());
-126case'%S':returnpad("0",2,d.getSeconds());
-127case'%Q':returnpad("0",3,d.getMilliseconds());
-128case'%t':return"\t";
-129case'%u':{
-130varw=d.getDay();
-131returnw?w:1;
-132}
-133// TODO %U: week number (sunday first day) [00,53]
-134// TODO %V: week number (monday first day) [01,53] ... with weirdness
-135case'%w':returnd.getDay();
-136// TODO %W: week number (monday first day) [00,53] ... with weirdness
-137case'%y':returnpad("0",2,d.getFullYear()%100);
-138case'%Y':returnd.getFullYear();
-139// TODO %Z: timezone name or abbreviation
-140case'%%':return"%";
-141}
-142returns;
-143});
-144}
-145
-146/**
-147 * Converts a date to a string using the associated formatting pattern.
-148 *
-149 * @function
-150 * @name pv.Format.date.prototype.format
-151 * @param {Date} date a date to format.
-152 * @returns {string} the formatted date as a string.
-153 */
-154format.format=format;
-155
-156/**
-157 * Parses a date from a string using the associated formatting pattern.
-158 *
-159 * @function
-160 * @name pv.Format.date.prototype.parse
-161 * @param {string} s the string to parse as a date.
-162 * @returns {Date} the parsed date.
-163 */
-164format.parse=function(s){
-165varyear=1970,month=0,date=1,hour=0,minute=0,second=0;
-166varfields=[function(){}];
-167
-168/* Register callbacks for each field in the format pattern. */
-169varre=pv.Format.re(pattern).replace(/%[a-zA-Z0-9]/g,function(s){
-170switch(s){
-171// TODO %a: day of week, either abbreviated or full name
-172// TODO %A: same as %a
-173case'%b':{
-174fields.push(function(x){month={
-175Jan:0,Feb:1,Mar:2,Apr:3,May:4,Jun:5,Jul:6,Aug:7,
-176Sep:8,Oct:9,Nov:10,Dec:11
-177}[x];});
-178return"([A-Za-z]+)";
-179}
-180case'%h':
-181case'%B':{
-182fields.push(function(x){month={
-183January:0,February:1,March:2,April:3,May:4,June:5,
-184July:6,August:7,September:8,October:9,November:10,
-185December:11
-186}[x];});
-187return"([A-Za-z]+)";
-188}
-189// TODO %c: locale's appropriate date and time
-190// TODO %C: century number[0,99]
-191case'%e':
-192case'%d':{
-193fields.push(function(x){date=x;});
-194return"([0-9]+)";
-195}
-196// TODO %D: same as %m/%d/%y
-197case'%I':
-198case'%H':{
-199fields.push(function(x){hour=x;});
-200return"([0-9]+)";
-201}
-202// TODO %j: day number [1,366]
-203case'%m':{
-204fields.push(function(x){month=x-1;});
-205return"([0-9]+)";
-206}
-207case'%M':{
-208fields.push(function(x){minute=x;});
-209return"([0-9]+)";
-210}
-211// TODO %n: any white space
-212// TODO %p: locale's equivalent of a.m. or p.m.
-213case'%p':{// TODO this is a hack
-214fields.push(function(x){
-215if(hour==12){
-216if(x=="am")hour=0;
-217}elseif(x=="pm"){
-218hour=Number(hour)+12;
-219}
-220});
-221return"(am|pm)";
-222}
-223// TODO %r: %I:%M:%S %p
-224// TODO %R: %H:%M
-225case'%S':{
-226fields.push(function(x){second=x;});
-227return"([0-9]+)";
-228}
-229// TODO %t: any white space
-230// TODO %T: %H:%M:%S
-231// TODO %U: week number [00,53]
-232// TODO %w: weekday [0,6]
-233// TODO %W: week number [00, 53]
-234// TODO %x: locale date (%m/%d/%y)
-235// TODO %X: locale time (%I:%M:%S %p)
-236case'%y':{
-237fields.push(function(x){
-238x=Number(x);
-239year=x+(((0<=x)&&(x<69))?2000
-240:(((x>=69)&&(x<100)?1900:0)));
-241});
-242return"([0-9]+)";
-243}
-244case'%Y':{
-245fields.push(function(x){year=x;});
-246return"([0-9]+)";
-247}
-248case'%%':{
-249fields.push(function(){});
-250return"%";
-251}
-252}
-253returns;
-254});
-255
-256varmatch=s.match(re);
-257if(match)match.forEach(function(m,i){fields[i](m);});
-258returnnewDate(year,month,date,hour,minute,second);
-259};
-260
-261returnformat;
-262};
-263
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_text_Format.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_text_Format.js.html
deleted file mode 100644
index 11af959e..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_text_Format.js.html
+++ /dev/null
@@ -1,86 +0,0 @@
-
1/**
- 2 * Abstract; see an implementing class.
- 3 *
- 4 * @class Represents an abstract text formatter and parser. A <i>format</i> is a
- 5 * function that converts an object of a given type, such as a <tt>Date</tt>, to
- 6 * a human-readable string representation. The format may also have a
- 7 * {@link #parse} method for converting a string representation back to the
- 8 * given object type.
- 9 *
- 10 * <p>Because formats are themselves functions, they can be used directly as
- 11 * mark properties. For example, if the data associated with a label are dates,
- 12 * a date format can be used as label text:
- 13 *
- 14 * <pre> .text(pv.Format.date("%m/%d/%y"))</pre>
- 15 *
- 16 * And as with scales, if the format is used in multiple places, it can be
- 17 * convenient to declare it as a global variable and then reference it from the
- 18 * appropriate property functions. For example, if the data has a <tt>date</tt>
- 19 * attribute, and <tt>format</tt> references a given date format:
- 20 *
- 21 * <pre> .text(function(d) format(d.date))</pre>
- 22 *
- 23 * Similarly, to parse a string into a date:
- 24 *
- 25 * <pre>var date = format.parse("4/30/2010");</pre>
- 26 *
- 27 * Not all format implementations support parsing. See the implementing class
- 28 * for details.
- 29 *
- 30 * @see pv.Format.date
- 31 * @see pv.Format.number
- 32 * @see pv.Format.time
- 33 */
- 34pv.Format={};
- 35
- 36/**
- 37 * Formats the specified object, returning the string representation.
- 38 *
- 39 * @function
- 40 * @name pv.Format.prototype.format
- 41 * @param {object} x the object to format.
- 42 * @returns {string} the formatted string.
- 43 */
- 44
- 45/**
- 46 * Parses the specified string, returning the object representation.
- 47 *
- 48 * @function
- 49 * @name pv.Format.prototype.parse
- 50 * @param {string} x the string to parse.
- 51 * @returns {object} the parsed object.
- 52 */
- 53
- 54/**
- 55 * @private Given a string that may be used as part of a regular expression,
- 56 * this methods returns an appropriately quoted version of the specified string,
- 57 * with any special characters escaped.
- 58 *
- 59 * @param {string} s a string to quote.
- 60 * @returns {string} the quoted string.
- 61 */
- 62pv.Format.re=function(s){
- 63returns.replace(/[\\\^\$\*\+\?\[\]\(\)\.\{\}]/g,"\\$&");
- 64};
- 65
- 66/**
- 67 * @private Optionally pads the specified string <i>s</i> so that it is at least
- 68 * <i>n</i> characters long, using the padding character <i>c</i>.
- 69 *
- 70 * @param {string} c the padding character.
- 71 * @param {number} n the minimum string length.
- 72 * @param {string} s the string to pad.
- 73 * @returns {string} the padded string.
- 74 */
- 75pv.Format.pad=function(c,n,s){
- 76varm=n-String(s).length;
- 77return(m<1)?s:newArray(m+1).join(c)+s;
- 78};
- 79
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_text_NumberFormat.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_text_NumberFormat.js.html
deleted file mode 100644
index d6bd59eb..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_text_NumberFormat.js.html
+++ /dev/null
@@ -1,216 +0,0 @@
-
1/**
- 2 * Returns a default number format.
- 3 *
- 4 * @class Represents a number format, converting between a <tt>number</tt> and a
- 5 * <tt>string</tt>. This class allows numbers to be formatted with variable
- 6 * precision (both for the integral and fractional part of the number), optional
- 7 * thousands grouping, and optional padding. The thousands (",") and decimal
- 8 * (".") separator can be customized.
- 9 *
- 10 * @returns {pv.Format.number} a number format.
- 11 */
- 12pv.Format.number=function(){
- 13varmini=0,// default minimum integer digits
- 14maxi=Infinity,// default maximum integer digits
- 15mins=0,// mini, including group separators
- 16minf=0,// default minimum fraction digits
- 17maxf=0,// default maximum fraction digits
- 18maxk=1,// 10^maxf
- 19padi="0",// default integer pad
- 20padf="0",// default fraction pad
- 21padg=true,// whether group separator affects integer padding
- 22decimal=".",// default decimal separator
- 23group=",";// default group separator
- 24
- 25/** @private */
- 26functionformat(x){
- 27/* Round the fractional part, and split on decimal separator. */
- 28if(Infinity>maxf)x=Math.round(x*maxk)/maxk;
- 29vars=String(Math.abs(x)).split(".");
- 30
- 31/* Pad, truncate and group the integral part. */
- 32vari=s[0],n=(x<0)?"-":"";
- 33if(i.length>maxi)i=i.substring(i.length-maxi);
- 34if(padg&&(i.length<mini))i=n+newArray(mini-i.length+1).join(padi)+i;
- 35if(i.length>3)i=i.replace(/\B(?=(?:\d{3})+(?!\d))/g,group);
- 36if(!padg&&(i.length<mins))i=newArray(mins-i.length+1).join(padi)+n+i;
- 37s[0]=i;
- 38
- 39/* Pad the fractional part. */
- 40varf=s[1]||"";
- 41if(f.length<minf)s[1]=f+newArray(minf-f.length+1).join(padf);
- 42
- 43returns.join(decimal);
- 44}
- 45
- 46/**
- 47 * @function
- 48 * @name pv.Format.number.prototype.format
- 49 * @param {number} x
- 50 * @returns {string}
- 51 */
- 52format.format=format;
- 53
- 54/**
- 55 * Parses the specified string as a number. Before parsing, leading and
- 56 * trailing padding is removed. Group separators are also removed, and the
- 57 * decimal separator is replaced with the standard point ("."). The integer
- 58 * part is truncated per the maximum integer digits, and the fraction part is
- 59 * rounded per the maximum fraction digits.
- 60 *
- 61 * @function
- 62 * @name pv.Format.number.prototype.parse
- 63 * @param {string} x the string to parse.
- 64 * @returns {number} the parsed number.
- 65 */
- 66format.parse=function(x){
- 67varre=pv.Format.re;
- 68
- 69/* Remove leading and trailing padding. Split on the decimal separator. */
- 70vars=String(x)
- 71.replace(newRegExp("^("+re(padi)+")*"),"")
- 72.replace(newRegExp("("+re(padf)+")*$"),"")
- 73.split(decimal);
- 74
- 75/* Remove grouping and truncate the integral part. */
- 76vari=s[0].replace(newRegExp(re(group),"g"),"");
- 77if(i.length>maxi)i=i.substring(i.length-maxi);
- 78
- 79/* Round the fractional part. */
- 80varf=s[1]?Number("0."+s[1]):0;
- 81if(Infinity>maxf)f=Math.round(f*maxk)/maxk;
- 82
- 83returnMath.round(i)+f;
- 84};
- 85
- 86/**
- 87 * Sets or gets the minimum and maximum number of integer digits. This
- 88 * controls the number of decimal digits to display before the decimal
- 89 * separator for the integral part of the number. If the number of digits is
- 90 * smaller than the minimum, the digits are padded; if the number of digits is
- 91 * larger, the digits are truncated, showing only the lower-order digits. The
- 92 * default range is [0, Infinity].
- 93 *
- 94 * <p>If only one argument is specified to this method, this value is used as
- 95 * both the minimum and maximum number. If no arguments are specified, a
- 96 * two-element array is returned containing the minimum and the maximum.
- 97 *
- 98 * @function
- 99 * @name pv.Format.number.prototype.integerDigits
-100 * @param {number} [min] the minimum integer digits.
-101 * @param {number} [max] the maximum integer digits.
-102 * @returns {pv.Format.number} <tt>this</tt>, or the current integer digits.
-103 */
-104format.integerDigits=function(min,max){
-105if(arguments.length){
-106mini=Number(min);
-107maxi=(arguments.length>1)?Number(max):mini;
-108mins=mini+Math.floor(mini/3)*group.length;
-109returnthis;
-110}
-111return[mini,maxi];
-112};
-113
-114/**
-115 * Sets or gets the minimum and maximum number of fraction digits. The
-116 * controls the number of decimal digits to display after the decimal
-117 * separator for the fractional part of the number. If the number of digits is
-118 * smaller than the minimum, the digits are padded; if the number of digits is
-119 * larger, the fractional part is rounded, showing only the higher-order
-120 * digits. The default range is [0, 0].
-121 *
-122 * <p>If only one argument is specified to this method, this value is used as
-123 * both the minimum and maximum number. If no arguments are specified, a
-124 * two-element array is returned containing the minimum and the maximum.
-125 *
-126 * @function
-127 * @name pv.Format.number.prototype.fractionDigits
-128 * @param {number} [min] the minimum fraction digits.
-129 * @param {number} [max] the maximum fraction digits.
-130 * @returns {pv.Format.number} <tt>this</tt>, or the current fraction digits.
-131 */
-132format.fractionDigits=function(min,max){
-133if(arguments.length){
-134minf=Number(min);
-135maxf=(arguments.length>1)?Number(max):minf;
-136maxk=Math.pow(10,maxf);
-137returnthis;
-138}
-139return[minf,maxf];
-140};
-141
-142/**
-143 * Sets or gets the character used to pad the integer part. The integer pad is
-144 * used when the number of integer digits is smaller than the minimum. The
-145 * default pad character is "0" (zero).
-146 *
-147 * @param {string} [x] the new pad character.
-148 * @returns {pv.Format.number} <tt>this</tt> or the current pad character.
-149 */
-150format.integerPad=function(x){
-151if(arguments.length){
-152padi=String(x);
-153padg=/\d/.test(padi);
-154returnthis;
-155}
-156returnpadi;
-157};
-158
-159/**
-160 * Sets or gets the character used to pad the fration part. The fraction pad
-161 * is used when the number of fraction digits is smaller than the minimum. The
-162 * default pad character is "0" (zero).
-163 *
-164 * @param {string} [x] the new pad character.
-165 * @returns {pv.Format.number} <tt>this</tt> or the current pad character.
-166 */
-167format.fractionPad=function(x){
-168if(arguments.length){
-169padf=String(x);
-170returnthis;
-171}
-172returnpadf;
-173};
-174
-175/**
-176 * Sets or gets the character used as the decimal point, separating the
-177 * integer and fraction parts of the number. The default decimal point is ".".
-178 *
-179 * @param {string} [x] the new decimal separator.
-180 * @returns {pv.Format.number} <tt>this</tt> or the current decimal separator.
-181 */
-182format.decimal=function(x){
-183if(arguments.length){
-184decimal=String(x);
-185returnthis;
-186}
-187returndecimal;
-188};
-189
-190/**
-191 * Sets or gets the character used as the group separator, grouping integer
-192 * digits by thousands. The default decimal point is ",". Grouping can be
-193 * disabled by using "" for the separator.
-194 *
-195 * @param {string} [x] the new group separator.
-196 * @returns {pv.Format.number} <tt>this</tt> or the current group separator.
-197 */
-198format.group=function(x){
-199if(arguments.length){
-200group=x?String(x):"";
-201mins=mini+Math.floor(mini/3)*group.length;
-202returnthis;
-203}
-204returngroup;
-205};
-206
-207returnformat;
-208};
-209
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_text_TimeFormat.js.html b/docs/lib/protovis-3.2/jsdoc/symbols/src/src_text_TimeFormat.js.html
deleted file mode 100644
index 2317835f..00000000
--- a/docs/lib/protovis-3.2/jsdoc/symbols/src/src_text_TimeFormat.js.html
+++ /dev/null
@@ -1,123 +0,0 @@
-
1/**
- 2 * Returns a time format of the given type, either "short" or "long".
- 3 *
- 4 * @class Represents a time format, converting between a <tt>number</tt>
- 5 * representing a duration in milliseconds, and a <tt>string</tt>. Two types of
- 6 * time formats are supported: "short" and "long". The <i>short</i> format type
- 7 * returns a string such as "3.3 days" or "12.1 minutes", while the <i>long</i>
- 8 * format returns "13:04:12" or similar.
- 9 *
- 10 * @extends pv.Format
- 11 * @param {string} type the type; "short" or "long".
- 12 */
- 13pv.Format.time=function(type){
- 14varpad=pv.Format.pad;
- 15
- 16/*
- 17 * MILLISECONDS = 1
- 18 * SECONDS = 1e3
- 19 * MINUTES = 6e4
- 20 * HOURS = 36e5
- 21 * DAYS = 864e5
- 22 * WEEKS = 6048e5
- 23 * MONTHS = 2592e6
- 24 * YEARS = 31536e6
- 25 */
- 26
- 27/** @private */
- 28functionformat(t){
- 29t=Number(t);// force conversion from Date
- 30switch(type){
- 31case"short":{
- 32if(t>=31536e6){
- 33return(t/31536e6).toFixed(1)+" years";
- 34}elseif(t>=6048e5){
- 35return(t/6048e5).toFixed(1)+" weeks";
- 36}elseif(t>=864e5){
- 37return(t/864e5).toFixed(1)+" days";
- 38}elseif(t>=36e5){
- 39return(t/36e5).toFixed(1)+" hours";
- 40}elseif(t>=6e4){
- 41return(t/6e4).toFixed(1)+" minutes";
- 42}
- 43return(t/1e3).toFixed(1)+" seconds";
- 44}
- 45case"long":{
- 46vara=[],
- 47s=((t%6e4)/1e3)>>0,
- 48m=((t%36e5)/6e4)>>0;
- 49a.push(pad("0",2,s));
- 50if(t>=36e5){
- 51varh=((t%864e5)/36e5)>>0;
- 52a.push(pad("0",2,m));
- 53if(t>=864e5){
- 54a.push(pad("0",2,h));
- 55a.push(Math.floor(t/864e5).toFixed());
- 56}else{
- 57a.push(h.toFixed());
- 58}
- 59}else{
- 60a.push(m.toFixed());
- 61}
- 62returna.reverse().join(":");
- 63}
- 64}
- 65}
- 66
- 67/**
- 68 * Formats the specified time, returning the string representation.
- 69 *
- 70 * @function
- 71 * @name pv.Format.time.prototype.format
- 72 * @param {number} t the duration in milliseconds. May also be a <tt>Date</tt>.
- 73 * @returns {string} the formatted string.
- 74 */
- 75format.format=format;
- 76
- 77/**
- 78 * Parses the specified string, returning the time in milliseconds.
- 79 *
- 80 * @function
- 81 * @name pv.Format.time.prototype.parse
- 82 * @param {string} s a formatted string.
- 83 * @returns {number} the parsed duration in milliseconds.
- 84 */
- 85format.parse=function(s){
- 86switch(type){
- 87case"short":{
- 88varre=/([0-9,.]+)\s*([a-z]+)/g,a,t=0;
- 89while(a=re.exec(s)){
- 90varf=parseFloat(a[0].replace(",","")),u=0;
- 91switch(a[2].toLowerCase()){
- 92case"year":case"years":u=31536e6;break;
- 93case"week":case"weeks":u=6048e5;break;
- 94case"day":case"days":u=864e5;break;
- 95case"hour":case"hours":u=36e5;break;
- 96case"minute":case"minutes":u=6e4;break;
- 97case"second":case"seconds":u=1e3;break;
- 98}
- 99t+=f*u;
-100}
-101returnt;
-102}
-103case"long":{
-104vara=s.replace(",","").split(":").reverse(),t=0;
-105if(a.length)t+=parseFloat(a[0])*1e3;
-106if(a.length>1)t+=parseFloat(a[1])*6e4;
-107if(a.length>2)t+=parseFloat(a[2])*36e5;
-108if(a.length>3)t+=parseFloat(a[3])*864e5;
-109returnt;
-110}
-111}
-112}
-113
-114returnformat;
-115};
-116
\ No newline at end of file
diff --git a/docs/lib/protovis-3.2/protovis-d3.2.js b/docs/lib/protovis-3.2/protovis-d3.2.js
deleted file mode 100644
index 255e21d3..00000000
--- a/docs/lib/protovis-3.2/protovis-d3.2.js
+++ /dev/null
@@ -1,15326 +0,0 @@
-// fba9dc272a443cf9fdb984676a7732a6a082f4c0
-/**
- * @class The built-in Array class.
- * @name Array
- */
-
-/**
- * Creates a new array with the results of calling a provided function on every
- * element in this array. Implemented in Javascript 1.6.
- *
- * @function
- * @name Array.prototype.map
- * @see map
- * documentation.
- * @param {function} f function that produces an element of the new Array from
- * an element of the current one.
- * @param [o] object to use as this when executing f.
- */
-if (!Array.prototype.map) Array.prototype.map = function(f, o) {
- var n = this.length;
- var result = new Array(n);
- for (var i = 0; i < n; i++) {
- if (i in this) {
- result[i] = f.call(o, this[i], i, this);
- }
- }
- return result;
-};
-
-/**
- * Creates a new array with all elements that pass the test implemented by the
- * provided function. Implemented in Javascript 1.6.
- *
- * @function
- * @name Array.prototype.filter
- * @see filter
- * documentation.
- * @param {function} f function to test each element of the array.
- * @param [o] object to use as this when executing f.
- */
-if (!Array.prototype.filter) Array.prototype.filter = function(f, o) {
- var n = this.length;
- var result = new Array();
- for (var i = 0; i < n; i++) {
- if (i in this) {
- var v = this[i];
- if (f.call(o, v, i, this)) result.push(v);
- }
- }
- return result;
-};
-
-/**
- * Executes a provided function once per array element. Implemented in
- * Javascript 1.6.
- *
- * @function
- * @name Array.prototype.forEach
- * @see forEach
- * documentation.
- * @param {function} f function to execute for each element.
- * @param [o] object to use as this when executing f.
- */
-if (!Array.prototype.forEach) Array.prototype.forEach = function(f, o) {
- var n = this.length >>> 0;
- for (var i = 0; i < n; i++) {
- if (i in this) f.call(o, this[i], i, this);
- }
-};
-
-/**
- * Apply a function against an accumulator and each value of the array (from
- * left-to-right) as to reduce it to a single value. Implemented in Javascript
- * 1.8.
- *
- * @function
- * @name Array.prototype.reduce
- * @see reduce
- * documentation.
- * @param {function} f function to execute on each value in the array.
- * @param [v] object to use as the first argument to the first call of
- * t.
- */
-if (!Array.prototype.reduce) Array.prototype.reduce = function(f, v) {
- var len = this.length;
- if (!len && (arguments.length == 1)) {
- throw new Error("reduce: empty array, no initial value");
- }
-
- var i = 0;
- if (arguments.length < 2) {
- while (true) {
- if (i in this) {
- v = this[i++];
- break;
- }
- if (++i >= len) {
- throw new Error("reduce: no values, no initial value");
- }
- }
- }
-
- for (; i < len; i++) {
- if (i in this) {
- v = f(v, this[i], i, this);
- }
- }
- return v;
-};
-/**
- * The top-level Protovis namespace. All public methods and fields should be
- * registered on this object. Note that core Protovis source is surrounded by an
- * anonymous function, so any other declared globals will not be visible outside
- * of core methods. This also allows multiple versions of Protovis to coexist,
- * since each version will see their own pv namespace.
- *
- * @namespace The top-level Protovis namespace, pv.
- */
-var pv = {};
-
-/**
- * Protovis major and minor version numbers.
- *
- * @namespace Protovis major and minor version numbers.
- */
-pv.version = {
- /**
- * The major version number.
- *
- * @type number
- * @constant
- */
- major: 3,
-
- /**
- * The minor version number.
- *
- * @type number
- * @constant
- */
- minor: 2
-};
-
-/**
- * Returns the passed-in argument, x; the identity function. This method
- * is provided for convenience since it is used as the default behavior for a
- * number of property functions.
- *
- * @param x a value.
- * @returns the value x.
- */
-pv.identity = function(x) { return x; };
-
-/**
- * Returns this.index. This method is provided for convenience for use
- * with scales. For example, to color bars by their index, say:
- *
- *
.fillStyle(pv.Colors.category10().by(pv.index))
- *
- * This method is equivalent to function() this.index, but more
- * succinct. Note that the index property is also supported for
- * accessor functions with {@link pv.max}, {@link pv.min} and other array
- * utility methods.
- *
- * @see pv.Scale
- * @see pv.Mark#index
- */
-pv.index = function() { return this.index; };
-
-/**
- * Returns this.childIndex. This method is provided for convenience for
- * use with scales. For example, to color bars by their child index, say:
- *
- *
.fillStyle(pv.Colors.category10().by(pv.child))
- *
- * This method is equivalent to function() this.childIndex, but more
- * succinct.
- *
- * @see pv.Scale
- * @see pv.Mark#childIndex
- */
-pv.child = function() { return this.childIndex; };
-
-/**
- * Returns this.parent.index. This method is provided for convenience
- * for use with scales. This method is provided for convenience for use with
- * scales. For example, to color bars by their parent index, say:
- *
- *
.fillStyle(pv.Colors.category10().by(pv.parent))
- *
- * Tthis method is equivalent to function() this.parent.index, but more
- * succinct.
- *
- * @see pv.Scale
- * @see pv.Mark#index
- */
-pv.parent = function() { return this.parent.index; };
-
-/**
- * Stores the current event. This field is only set within event handlers.
- *
- * @type Event
- * @name pv.event
- */
-/**
- * @private Returns a prototype object suitable for extending the given class
- * f. Rather than constructing a new instance of f to serve as
- * the prototype (which unnecessarily runs the constructor on the created
- * prototype object, potentially polluting it), an anonymous function is
- * generated internally that shares the same prototype:
- *
- *
function g() {}
- * g.prototype = f.prototype;
- * return new g();
- *
- * For more details, see Douglas Crockford's essay on prototypal inheritance.
- *
- * @param {function} f a constructor.
- * @returns a suitable prototype object.
- * @see Douglas Crockford's essay on prototypal
- * inheritance.
- */
-pv.extend = function(f) {
- function g() {}
- g.prototype = f.prototype || f;
- return new g();
-};
-
-try {
- eval("pv.parse = function(x) x;"); // native support
-} catch (e) {
-
-/**
- * @private Parses a Protovis specification, which may use JavaScript 1.8
- * function expresses, replacing those function expressions with proper
- * functions such that the code can be run by a JavaScript 1.6 interpreter. This
- * hack only supports function expressions (using clumsy regular expressions, no
- * less), and not other JavaScript 1.8 features such as let expressions.
- *
- * @param {string} s a Protovis specification (i.e., a string of JavaScript 1.8
- * source code).
- * @returns {string} a conformant JavaScript 1.6 source code.
- */
- pv.parse = function(js) { // hacky regex support
- var re = new RegExp("function\\s*(\\b\\w+)?\\s*\\([^)]*\\)\\s*", "mg"), m, d, i = 0, s = "";
- while (m = re.exec(js)) {
- var j = m.index + m[0].length;
- if (js.charAt(j) != '{') {
- s += js.substring(i, j) + "{return ";
- i = j;
- for (var p = 0; p >= 0 && j < js.length; j++) {
- var c = js.charAt(j);
- switch (c) {
- case '"': case '\'': {
- while (++j < js.length && (d = js.charAt(j)) != c) {
- if (d == '\\') j++;
- }
- break;
- }
- case '[': case '(': p++; break;
- case ']': case ')': p--; break;
- case ';':
- case ',': if (p == 0) p--; break;
- }
- }
- s += pv.parse(js.substring(i, --j)) + ";}";
- i = j;
- }
- re.lastIndex = j;
- }
- s += js.substring(i);
- return s;
- };
-}
-
-/**
- * @private Computes the value of the specified CSS property p on the
- * specified element e.
- *
- * @param {string} p the name of the CSS property.
- * @param e the element on which to compute the CSS property.
- */
-pv.css = function(e, p) {
- return window.getComputedStyle
- ? window.getComputedStyle(e, null).getPropertyValue(p)
- : e.currentStyle[p];
-};
-
-/**
- * @private Reports the specified error to the JavaScript console. Mozilla only
- * allows logging to the console for privileged code; if the console is
- * unavailable, the alert dialog box is used instead.
- *
- * @param e the exception that triggered the error.
- */
-pv.error = function(e) {
- (typeof console == "undefined") ? alert(e) : console.error(e);
-};
-
-/**
- * @private Registers the specified listener for events of the specified type on
- * the specified target. For standards-compliant browsers, this method uses
- * addEventListener; for Internet Explorer, attachEvent.
- *
- * @param target a DOM element.
- * @param {string} type the type of event, such as "click".
- * @param {function} the event handler callback.
- */
-pv.listen = function(target, type, listener) {
- listener = pv.listener(listener);
- return target.addEventListener
- ? target.addEventListener(type, listener, false)
- : target.attachEvent("on" + type, listener);
-};
-
-/**
- * @private Returns a wrapper for the specified listener function such that the
- * {@link pv.event} is set for the duration of the listener's invocation. The
- * wrapper is cached on the returned function, such that duplicate registrations
- * of the wrapped event handler are ignored.
- *
- * @param {function} f an event handler.
- * @returns {function} the wrapped event handler.
- */
-pv.listener = function(f) {
- return f.$listener || (f.$listener = function(e) {
- try {
- pv.event = e;
- return f.call(this, e);
- } finally {
- delete pv.event;
- }
- });
-};
-
-/**
- * @private Returns true iff a is an ancestor of e. This is useful
- * for ignoring mouseout and mouseover events that are contained within the
- * target element.
- */
-pv.ancestor = function(a, e) {
- while (e) {
- if (e == a) return true;
- e = e.parentNode;
- }
- return false;
-};
-
-/** @private Returns a locally-unique positive id. */
-pv.id = function() {
- var id = 1; return function() { return id++; };
-}();
-
-/** @private Returns a function wrapping the specified constant. */
-pv.functor = function(v) {
- return typeof v == "function" ? v : function() { return v; };
-};
-/*
- * Parses the Protovis specifications on load, allowing the use of JavaScript
- * 1.8 function expressions on browsers that only support JavaScript 1.6.
- *
- * @see pv.parse
- */
-pv.listen(window, "load", function() {
- /*
- * Note: in Firefox any variables declared here are visible to the eval'd
- * script below. Even worse, any global variables declared by the script
- * could overwrite local variables here (such as the index, `i`)! To protect
- * against this, all variables are explicitly scoped on a pv.$ object.
- */
- pv.$ = {i:0, x:document.getElementsByTagName("script")};
- for (; pv.$.i < pv.$.x.length; pv.$.i++) {
- pv.$.s = pv.$.x[pv.$.i];
- if (pv.$.s.type == "text/javascript+protovis") {
- try {
- window.eval(pv.parse(pv.$.s.text));
- } catch (e) {
- pv.error(e);
- }
- }
- }
- delete pv.$;
- });
-/**
- * Abstract; see an implementing class.
- *
- * @class Represents an abstract text formatter and parser. A format is a
- * function that converts an object of a given type, such as a Date, to
- * a human-readable string representation. The format may also have a
- * {@link #parse} method for converting a string representation back to the
- * given object type.
- *
- *
Because formats are themselves functions, they can be used directly as
- * mark properties. For example, if the data associated with a label are dates,
- * a date format can be used as label text:
- *
- *
.text(pv.Format.date("%m/%d/%y"))
- *
- * And as with scales, if the format is used in multiple places, it can be
- * convenient to declare it as a global variable and then reference it from the
- * appropriate property functions. For example, if the data has a date
- * attribute, and format references a given date format:
- *
- *
.text(function(d) format(d.date))
- *
- * Similarly, to parse a string into a date:
- *
- *
var date = format.parse("4/30/2010");
- *
- * Not all format implementations support parsing. See the implementing class
- * for details.
- *
- * @see pv.Format.date
- * @see pv.Format.number
- * @see pv.Format.time
- */
-pv.Format = {};
-
-/**
- * Formats the specified object, returning the string representation.
- *
- * @function
- * @name pv.Format.prototype.format
- * @param {object} x the object to format.
- * @returns {string} the formatted string.
- */
-
-/**
- * Parses the specified string, returning the object representation.
- *
- * @function
- * @name pv.Format.prototype.parse
- * @param {string} x the string to parse.
- * @returns {object} the parsed object.
- */
-
-/**
- * @private Given a string that may be used as part of a regular expression,
- * this methods returns an appropriately quoted version of the specified string,
- * with any special characters escaped.
- *
- * @param {string} s a string to quote.
- * @returns {string} the quoted string.
- */
-pv.Format.re = function(s) {
- return s.replace(/[\\\^\$\*\+\?\[\]\(\)\.\{\}]/g, "\\$&");
-};
-
-/**
- * @private Optionally pads the specified string s so that it is at least
- * n characters long, using the padding character c.
- *
- * @param {string} c the padding character.
- * @param {number} n the minimum string length.
- * @param {string} s the string to pad.
- * @returns {string} the padded string.
- */
-pv.Format.pad = function(c, n, s) {
- var m = n - String(s).length;
- return (m < 1) ? s : new Array(m + 1).join(c) + s;
-};
-/**
- * Constructs a new date format with the specified string pattern.
- *
- * @class The format string is in the same format expected by the
- * strftime function in C. The following conversion specifications are
- * supported:
- *
- *
%a - abbreviated weekday name.
- *
%A - full weekday name.
- *
%b - abbreviated month names.
- *
%B - full month names.
- *
%c - locale's appropriate date and time.
- *
%C - century number.
- *
%d - day of month [01,31] (zero padded).
- *
%D - same as %m/%d/%y.
- *
%e - day of month [ 1,31] (space padded).
- *
%h - same as %b.
- *
%H - hour (24-hour clock) [00,23] (zero padded).
- *
%I - hour (12-hour clock) [01,12] (zero padded).
- *
%m - month number [01,12] (zero padded).
- *
%M - minute [0,59] (zero padded).
- *
%n - newline character.
- *
%p - locale's equivalent of a.m. or p.m.
- *
%r - same as %I:%M:%S %p.
- *
%R - same as %H:%M.
- *
%S - second [00,61] (zero padded).
- *
%t - tab character.
- *
%T - same as %H:%M:%S.
- *
%x - same as %m/%d/%y.
- *
%X - same as %I:%M:%S %p.
- *
%y - year with century [00,99] (zero padded).
- *
%Y - year including century.
- *
%% - %.
- *
- *
The following conversion specifications are currently unsupported
- * for formatting:
- *
- *
%j - day number [1,366].
- *
%u - weekday number [1,7].
- *
%U - week number [00,53].
- *
%V - week number [01,53].
- *
%w - weekday number [0,6].
- *
%W - week number [00,53].
- *
%Z - timezone name or abbreviation.
- *
- *
In addition, the following conversion specifications are currently
- * unsupported for parsing:
- *
- *
%a - day of week, either abbreviated or full name.
- *
%A - same as %a.
- *
%c - locale's appropriate date and time.
- *
%C - century number.
- *
%D - same as %m/%d/%y.
- *
%I - hour (12-hour clock) [1,12].
- *
%n - any white space.
- *
%p - locale's equivalent of a.m. or p.m.
- *
%r - same as %I:%M:%S %p.
- *
%R - same as %H:%M.
- *
%t - same as %n.
- *
%T - same as %H:%M:%S.
- *
%x - locale's equivalent to %m/%d/%y.
- *
%X - locale's equivalent to %I:%M:%S %p.
- *
- *
- *
- * @see strftime
- * documentation.
- * @see strptime
- * documentation.
- * @extends pv.Format
- * @param {string} pattern the format pattern.
- */
-pv.Format.date = function(pattern) {
- var pad = pv.Format.pad;
-
- /** @private */
- function format(d) {
- return pattern.replace(/%[a-zA-Z0-9]/g, function(s) {
- switch (s) {
- case '%a': return [
- "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
- ][d.getDay()];
- case '%A': return [
- "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
- "Saturday"
- ][d.getDay()];
- case '%h':
- case '%b': return [
- "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep",
- "Oct", "Nov", "Dec"
- ][d.getMonth()];
- case '%B': return [
- "January", "February", "March", "April", "May", "June", "July",
- "August", "September", "October", "November", "December"
- ][d.getMonth()];
- case '%c': return d.toLocaleString();
- case '%C': return pad("0", 2, Math.floor(d.getFullYear() / 100) % 100);
- case '%d': return pad("0", 2, d.getDate());
- case '%x':
- case '%D': return pad("0", 2, d.getMonth() + 1)
- + "/" + pad("0", 2, d.getDate())
- + "/" + pad("0", 2, d.getFullYear() % 100);
- case '%e': return pad(" ", 2, d.getDate());
- case '%H': return pad("0", 2, d.getHours());
- case '%I': {
- var h = d.getHours() % 12;
- return h ? pad("0", 2, h) : 12;
- }
- // TODO %j: day of year as a decimal number [001,366]
- case '%m': return pad("0", 2, d.getMonth() + 1);
- case '%M': return pad("0", 2, d.getMinutes());
- case '%n': return "\n";
- case '%p': return d.getHours() < 12 ? "AM" : "PM";
- case '%T':
- case '%X':
- case '%r': {
- var h = d.getHours() % 12;
- return (h ? pad("0", 2, h) : 12)
- + ":" + pad("0", 2, d.getMinutes())
- + ":" + pad("0", 2, d.getSeconds())
- + " " + (d.getHours() < 12 ? "AM" : "PM");
- }
- case '%R': return pad("0", 2, d.getHours()) + ":" + pad("0", 2, d.getMinutes());
- case '%S': return pad("0", 2, d.getSeconds());
- case '%Q': return pad("0", 3, d.getMilliseconds());
- case '%t': return "\t";
- case '%u': {
- var w = d.getDay();
- return w ? w : 1;
- }
- // TODO %U: week number (sunday first day) [00,53]
- // TODO %V: week number (monday first day) [01,53] ... with weirdness
- case '%w': return d.getDay();
- // TODO %W: week number (monday first day) [00,53] ... with weirdness
- case '%y': return pad("0", 2, d.getFullYear() % 100);
- case '%Y': return d.getFullYear();
- // TODO %Z: timezone name or abbreviation
- case '%%': return "%";
- }
- return s;
- });
- }
-
- /**
- * Converts a date to a string using the associated formatting pattern.
- *
- * @function
- * @name pv.Format.date.prototype.format
- * @param {Date} date a date to format.
- * @returns {string} the formatted date as a string.
- */
- format.format = format;
-
- /**
- * Parses a date from a string using the associated formatting pattern.
- *
- * @function
- * @name pv.Format.date.prototype.parse
- * @param {string} s the string to parse as a date.
- * @returns {Date} the parsed date.
- */
- format.parse = function(s) {
- var year = 1970, month = 0, date = 1, hour = 0, minute = 0, second = 0;
- var fields = [function() {}];
-
- /* Register callbacks for each field in the format pattern. */
- var re = pv.Format.re(pattern).replace(/%[a-zA-Z0-9]/g, function(s) {
- switch (s) {
- // TODO %a: day of week, either abbreviated or full name
- // TODO %A: same as %a
- case '%b': {
- fields.push(function(x) { month = {
- Jan: 0, Feb: 1, Mar: 2, Apr: 3, May: 4, Jun: 5, Jul: 6, Aug: 7,
- Sep: 8, Oct: 9, Nov: 10, Dec: 11
- }[x]; });
- return "([A-Za-z]+)";
- }
- case '%h':
- case '%B': {
- fields.push(function(x) { month = {
- January: 0, February: 1, March: 2, April: 3, May: 4, June: 5,
- July: 6, August: 7, September: 8, October: 9, November: 10,
- December: 11
- }[x]; });
- return "([A-Za-z]+)";
- }
- // TODO %c: locale's appropriate date and time
- // TODO %C: century number[0,99]
- case '%e':
- case '%d': {
- fields.push(function(x) { date = x; });
- return "([0-9]+)";
- }
- // TODO %D: same as %m/%d/%y
- case '%I':
- case '%H': {
- fields.push(function(x) { hour = x; });
- return "([0-9]+)";
- }
- // TODO %j: day number [1,366]
- case '%m': {
- fields.push(function(x) { month = x - 1; });
- return "([0-9]+)";
- }
- case '%M': {
- fields.push(function(x) { minute = x; });
- return "([0-9]+)";
- }
- // TODO %n: any white space
- // TODO %p: locale's equivalent of a.m. or p.m.
- case '%p': { // TODO this is a hack
- fields.push(function(x) {
- if (hour == 12) {
- if (x == "am") hour = 0;
- } else if (x == "pm") {
- hour = Number(hour) + 12;
- }
- });
- return "(am|pm)";
- }
- // TODO %r: %I:%M:%S %p
- // TODO %R: %H:%M
- case '%S': {
- fields.push(function(x) { second = x; });
- return "([0-9]+)";
- }
- // TODO %t: any white space
- // TODO %T: %H:%M:%S
- // TODO %U: week number [00,53]
- // TODO %w: weekday [0,6]
- // TODO %W: week number [00, 53]
- // TODO %x: locale date (%m/%d/%y)
- // TODO %X: locale time (%I:%M:%S %p)
- case '%y': {
- fields.push(function(x) {
- x = Number(x);
- year = x + (((0 <= x) && (x < 69)) ? 2000
- : (((x >= 69) && (x < 100) ? 1900 : 0)));
- });
- return "([0-9]+)";
- }
- case '%Y': {
- fields.push(function(x) { year = x; });
- return "([0-9]+)";
- }
- case '%%': {
- fields.push(function() {});
- return "%";
- }
- }
- return s;
- });
-
- var match = s.match(re);
- if (match) match.forEach(function(m, i) { fields[i](m); });
- return new Date(year, month, date, hour, minute, second);
- };
-
- return format;
-};
-/**
- * Returns a time format of the given type, either "short" or "long".
- *
- * @class Represents a time format, converting between a number
- * representing a duration in milliseconds, and a string. Two types of
- * time formats are supported: "short" and "long". The short format type
- * returns a string such as "3.3 days" or "12.1 minutes", while the long
- * format returns "13:04:12" or similar.
- *
- * @extends pv.Format
- * @param {string} type the type; "short" or "long".
- */
-pv.Format.time = function(type) {
- var pad = pv.Format.pad;
-
- /*
- * MILLISECONDS = 1
- * SECONDS = 1e3
- * MINUTES = 6e4
- * HOURS = 36e5
- * DAYS = 864e5
- * WEEKS = 6048e5
- * MONTHS = 2592e6
- * YEARS = 31536e6
- */
-
- /** @private */
- function format(t) {
- t = Number(t); // force conversion from Date
- switch (type) {
- case "short": {
- if (t >= 31536e6) {
- return (t / 31536e6).toFixed(1) + " years";
- } else if (t >= 6048e5) {
- return (t / 6048e5).toFixed(1) + " weeks";
- } else if (t >= 864e5) {
- return (t / 864e5).toFixed(1) + " days";
- } else if (t >= 36e5) {
- return (t / 36e5).toFixed(1) + " hours";
- } else if (t >= 6e4) {
- return (t / 6e4).toFixed(1) + " minutes";
- }
- return (t / 1e3).toFixed(1) + " seconds";
- }
- case "long": {
- var a = [],
- s = ((t % 6e4) / 1e3) >> 0,
- m = ((t % 36e5) / 6e4) >> 0;
- a.push(pad("0", 2, s));
- if (t >= 36e5) {
- var h = ((t % 864e5) / 36e5) >> 0;
- a.push(pad("0", 2, m));
- if (t >= 864e5) {
- a.push(pad("0", 2, h));
- a.push(Math.floor(t / 864e5).toFixed());
- } else {
- a.push(h.toFixed());
- }
- } else {
- a.push(m.toFixed());
- }
- return a.reverse().join(":");
- }
- }
- }
-
- /**
- * Formats the specified time, returning the string representation.
- *
- * @function
- * @name pv.Format.time.prototype.format
- * @param {number} t the duration in milliseconds. May also be a Date.
- * @returns {string} the formatted string.
- */
- format.format = format;
-
- /**
- * Parses the specified string, returning the time in milliseconds.
- *
- * @function
- * @name pv.Format.time.prototype.parse
- * @param {string} s a formatted string.
- * @returns {number} the parsed duration in milliseconds.
- */
- format.parse = function(s) {
- switch (type) {
- case "short": {
- var re = /([0-9,.]+)\s*([a-z]+)/g, a, t = 0;
- while (a = re.exec(s)) {
- var f = parseFloat(a[0].replace(",", "")), u = 0;
- switch (a[2].toLowerCase()) {
- case "year": case "years": u = 31536e6; break;
- case "week": case "weeks": u = 6048e5; break;
- case "day": case "days": u = 864e5; break;
- case "hour": case "hours": u = 36e5; break;
- case "minute": case "minutes": u = 6e4; break;
- case "second": case "seconds": u = 1e3; break;
- }
- t += f * u;
- }
- return t;
- }
- case "long": {
- var a = s.replace(",", "").split(":").reverse(), t = 0;
- if (a.length) t += parseFloat(a[0]) * 1e3;
- if (a.length > 1) t += parseFloat(a[1]) * 6e4;
- if (a.length > 2) t += parseFloat(a[2]) * 36e5;
- if (a.length > 3) t += parseFloat(a[3]) * 864e5;
- return t;
- }
- }
- }
-
- return format;
-};
-/**
- * Returns a default number format.
- *
- * @class Represents a number format, converting between a number and a
- * string. This class allows numbers to be formatted with variable
- * precision (both for the integral and fractional part of the number), optional
- * thousands grouping, and optional padding. The thousands (",") and decimal
- * (".") separator can be customized.
- *
- * @returns {pv.Format.number} a number format.
- */
-pv.Format.number = function() {
- var mini = 0, // default minimum integer digits
- maxi = Infinity, // default maximum integer digits
- mins = 0, // mini, including group separators
- minf = 0, // default minimum fraction digits
- maxf = 0, // default maximum fraction digits
- maxk = 1, // 10^maxf
- padi = "0", // default integer pad
- padf = "0", // default fraction pad
- padg = true, // whether group separator affects integer padding
- decimal = ".", // default decimal separator
- group = ","; // default group separator
-
- /** @private */
- function format(x) {
- /* Round the fractional part, and split on decimal separator. */
- if (Infinity > maxf) x = Math.round(x * maxk) / maxk;
- var s = String(Math.abs(x)).split(".");
-
- /* Pad, truncate and group the integral part. */
- var i = s[0], n = (x < 0) ? "-" : "";
- if (i.length > maxi) i = i.substring(i.length - maxi);
- if (padg && (i.length < mini)) i = n + new Array(mini - i.length + 1).join(padi) + i;
- if (i.length > 3) i = i.replace(/\B(?=(?:\d{3})+(?!\d))/g, group);
- if (!padg && (i.length < mins)) i = new Array(mins - i.length + 1).join(padi) + n + i;
- s[0] = i;
-
- /* Pad the fractional part. */
- var f = s[1] || "";
- if (f.length < minf) s[1] = f + new Array(minf - f.length + 1).join(padf);
-
- return s.join(decimal);
- }
-
- /**
- * @function
- * @name pv.Format.number.prototype.format
- * @param {number} x
- * @returns {string}
- */
- format.format = format;
-
- /**
- * Parses the specified string as a number. Before parsing, leading and
- * trailing padding is removed. Group separators are also removed, and the
- * decimal separator is replaced with the standard point ("."). The integer
- * part is truncated per the maximum integer digits, and the fraction part is
- * rounded per the maximum fraction digits.
- *
- * @function
- * @name pv.Format.number.prototype.parse
- * @param {string} x the string to parse.
- * @returns {number} the parsed number.
- */
- format.parse = function(x) {
- var re = pv.Format.re;
-
- /* Remove leading and trailing padding. Split on the decimal separator. */
- var s = String(x)
- .replace(new RegExp("^(" + re(padi) + ")*"), "")
- .replace(new RegExp("(" + re(padf) + ")*$"), "")
- .split(decimal);
-
- /* Remove grouping and truncate the integral part. */
- var i = s[0].replace(new RegExp(re(group), "g"), "");
- if (i.length > maxi) i = i.substring(i.length - maxi);
-
- /* Round the fractional part. */
- var f = s[1] ? Number("0." + s[1]) : 0;
- if (Infinity > maxf) f = Math.round(f * maxk) / maxk;
-
- return Math.round(i) + f;
- };
-
- /**
- * Sets or gets the minimum and maximum number of integer digits. This
- * controls the number of decimal digits to display before the decimal
- * separator for the integral part of the number. If the number of digits is
- * smaller than the minimum, the digits are padded; if the number of digits is
- * larger, the digits are truncated, showing only the lower-order digits. The
- * default range is [0, Infinity].
- *
- *
If only one argument is specified to this method, this value is used as
- * both the minimum and maximum number. If no arguments are specified, a
- * two-element array is returned containing the minimum and the maximum.
- *
- * @function
- * @name pv.Format.number.prototype.integerDigits
- * @param {number} [min] the minimum integer digits.
- * @param {number} [max] the maximum integer digits.
- * @returns {pv.Format.number} this, or the current integer digits.
- */
- format.integerDigits = function(min, max) {
- if (arguments.length) {
- mini = Number(min);
- maxi = (arguments.length > 1) ? Number(max) : mini;
- mins = mini + Math.floor(mini / 3) * group.length;
- return this;
- }
- return [mini, maxi];
- };
-
- /**
- * Sets or gets the minimum and maximum number of fraction digits. The
- * controls the number of decimal digits to display after the decimal
- * separator for the fractional part of the number. If the number of digits is
- * smaller than the minimum, the digits are padded; if the number of digits is
- * larger, the fractional part is rounded, showing only the higher-order
- * digits. The default range is [0, 0].
- *
- *
If only one argument is specified to this method, this value is used as
- * both the minimum and maximum number. If no arguments are specified, a
- * two-element array is returned containing the minimum and the maximum.
- *
- * @function
- * @name pv.Format.number.prototype.fractionDigits
- * @param {number} [min] the minimum fraction digits.
- * @param {number} [max] the maximum fraction digits.
- * @returns {pv.Format.number} this, or the current fraction digits.
- */
- format.fractionDigits = function(min, max) {
- if (arguments.length) {
- minf = Number(min);
- maxf = (arguments.length > 1) ? Number(max) : minf;
- maxk = Math.pow(10, maxf);
- return this;
- }
- return [minf, maxf];
- };
-
- /**
- * Sets or gets the character used to pad the integer part. The integer pad is
- * used when the number of integer digits is smaller than the minimum. The
- * default pad character is "0" (zero).
- *
- * @param {string} [x] the new pad character.
- * @returns {pv.Format.number} this or the current pad character.
- */
- format.integerPad = function(x) {
- if (arguments.length) {
- padi = String(x);
- padg = /\d/.test(padi);
- return this;
- }
- return padi;
- };
-
- /**
- * Sets or gets the character used to pad the fration part. The fraction pad
- * is used when the number of fraction digits is smaller than the minimum. The
- * default pad character is "0" (zero).
- *
- * @param {string} [x] the new pad character.
- * @returns {pv.Format.number} this or the current pad character.
- */
- format.fractionPad = function(x) {
- if (arguments.length) {
- padf = String(x);
- return this;
- }
- return padf;
- };
-
- /**
- * Sets or gets the character used as the decimal point, separating the
- * integer and fraction parts of the number. The default decimal point is ".".
- *
- * @param {string} [x] the new decimal separator.
- * @returns {pv.Format.number} this or the current decimal separator.
- */
- format.decimal = function(x) {
- if (arguments.length) {
- decimal = String(x);
- return this;
- }
- return decimal;
- };
-
- /**
- * Sets or gets the character used as the group separator, grouping integer
- * digits by thousands. The default decimal point is ",". Grouping can be
- * disabled by using "" for the separator.
- *
- * @param {string} [x] the new group separator.
- * @returns {pv.Format.number} this or the current group separator.
- */
- format.group = function(x) {
- if (arguments.length) {
- group = x ? String(x) : "";
- mins = mini + Math.floor(mini / 3) * group.length;
- return this;
- }
- return group;
- };
-
- return format;
-};
-/**
- * @private A private variant of Array.prototype.map that supports the index
- * property.
- */
-pv.map = function(array, f) {
- var o = {};
- return f
- ? array.map(function(d, i) { o.index = i; return f.call(o, d); })
- : array.slice();
-};
-
-/**
- * Concatenates the specified array with itself n times. For example,
- * pv.repeat([1, 2]) returns [1, 2, 1, 2].
- *
- * @param {array} a an array.
- * @param {number} [n] the number of times to repeat; defaults to two.
- * @returns {array} an array that repeats the specified array.
- */
-pv.repeat = function(array, n) {
- if (arguments.length == 1) n = 2;
- return pv.blend(pv.range(n).map(function() { return array; }));
-};
-
-/**
- * Given two arrays a and b, returns an array of all possible
- * pairs of elements [ai, bj]. The outer loop is on array
- * a, while the inner loop is on b, such that the order of
- * returned elements is [a0, b0], [a0,
- * b1], ... [a0, bm], [a1,
- * b0], [a1, b1], ... [a1,
- * bm], ... [an, bm]. If either array is empty,
- * an empty array is returned.
- *
- * @param {array} a an array.
- * @param {array} b an array.
- * @returns {array} an array of pairs of elements in a and b.
- */
-pv.cross = function(a, b) {
- var array = [];
- for (var i = 0, n = a.length, m = b.length; i < n; i++) {
- for (var j = 0, x = a[i]; j < m; j++) {
- array.push([x, b[j]]);
- }
- }
- return array;
-};
-
-/**
- * Given the specified array of arrays, concatenates the arrays into a single
- * array. If the individual arrays are explicitly known, an alternative to blend
- * is to use JavaScript's concat method directly. These two equivalent
- * expressions:
- *
- *
pv.blend([[1, 2, 3], ["a", "b", "c"]])
- *
[1, 2, 3].concat(["a", "b", "c"])
- *
- *
return [1, 2, 3, "a", "b", "c"].
- *
- * @param {array[]} arrays an array of arrays.
- * @returns {array} an array containing all the elements of each array in
- * arrays.
- */
-pv.blend = function(arrays) {
- return Array.prototype.concat.apply([], arrays);
-};
-
-/**
- * Given the specified array of arrays, transposes each element
- * arrayij with arrayji. If the array has dimensions
- * n×m, it will have dimensions m×n
- * after this method returns. This method transposes the elements of the array
- * in place, mutating the array, and returning a reference to the array.
- *
- * @param {array[]} arrays an array of arrays.
- * @returns {array[]} the passed-in array, after transposing the elements.
- */
-pv.transpose = function(arrays) {
- var n = arrays.length, m = pv.max(arrays, function(d) { return d.length; });
-
- if (m > n) {
- arrays.length = m;
- for (var i = n; i < m; i++) {
- arrays[i] = new Array(n);
- }
- for (var i = 0; i < n; i++) {
- for (var j = i + 1; j < m; j++) {
- var t = arrays[i][j];
- arrays[i][j] = arrays[j][i];
- arrays[j][i] = t;
- }
- }
- } else {
- for (var i = 0; i < m; i++) {
- arrays[i].length = n;
- }
- for (var i = 0; i < n; i++) {
- for (var j = 0; j < i; j++) {
- var t = arrays[i][j];
- arrays[i][j] = arrays[j][i];
- arrays[j][i] = t;
- }
- }
- }
-
- arrays.length = m;
- for (var i = 0; i < m; i++) {
- arrays[i].length = n;
- }
-
- return arrays;
-};
-
-/**
- * Returns a normalized copy of the specified array, such that the sum of the
- * returned elements sum to one. If the specified array is not an array of
- * numbers, an optional accessor function f can be specified to map the
- * elements to numbers. For example, if array is an array of objects,
- * and each object has a numeric property "foo", the expression
- *
- *
pv.normalize(array, function(d) d.foo)
- *
- * returns a normalized array on the "foo" property. If an accessor function is
- * not specified, the identity function is used. Accessor functions can refer to
- * this.index.
- *
- * @param {array} array an array of objects, or numbers.
- * @param {function} [f] an optional accessor function.
- * @returns {number[]} an array of numbers that sums to one.
- */
-pv.normalize = function(array, f) {
- var norm = pv.map(array, f), sum = pv.sum(norm);
- for (var i = 0; i < norm.length; i++) norm[i] /= sum;
- return norm;
-};
-
-/**
- * Returns a permutation of the specified array, using the specified array of
- * indexes. The returned array contains the corresponding element in
- * array for each index in indexes, in order. For example,
- *
- *
pv.permute(["a", "b", "c"], [1, 2, 0])
- *
- * returns ["b", "c", "a"]. It is acceptable for the array of indexes
- * to be a different length from the array of elements, and for indexes to be
- * duplicated or omitted. The optional accessor function f can be used
- * to perform a simultaneous mapping of the array elements. Accessor functions
- * can refer to this.index.
- *
- * @param {array} array an array.
- * @param {number[]} indexes an array of indexes into array.
- * @param {function} [f] an optional accessor function.
- * @returns {array} an array of elements from array; a permutation.
- */
-pv.permute = function(array, indexes, f) {
- if (!f) f = pv.identity;
- var p = new Array(indexes.length), o = {};
- indexes.forEach(function(j, i) { o.index = j; p[i] = f.call(o, array[j]); });
- return p;
-};
-
-/**
- * Returns a map from key to index for the specified keys array. For
- * example,
- *
- *
pv.numerate(["a", "b", "c"])
- *
- * returns {a: 0, b: 1, c: 2}. Note that since JavaScript maps only
- * support string keys, keys must contain strings, or other values that
- * naturally map to distinct string values. Alternatively, an optional accessor
- * function f can be specified to compute the string key for the given
- * element. Accessor functions can refer to this.index.
- *
- * @param {array} keys an array, usually of string keys.
- * @param {function} [f] an optional key function.
- * @returns a map from key to index.
- */
-pv.numerate = function(keys, f) {
- if (!f) f = pv.identity;
- var map = {}, o = {};
- keys.forEach(function(x, i) { o.index = i; map[f.call(o, x)] = i; });
- return map;
-};
-
-/**
- * Returns the unique elements in the specified array, in the order they appear.
- * Note that since JavaScript maps only support string keys, array must
- * contain strings, or other values that naturally map to distinct string
- * values. Alternatively, an optional accessor function f can be
- * specified to compute the string key for the given element. Accessor functions
- * can refer to this.index.
- *
- * @param {array} array an array, usually of string keys.
- * @param {function} [f] an optional key function.
- * @returns {array} the unique values.
- */
-pv.uniq = function(array, f) {
- if (!f) f = pv.identity;
- var map = {}, keys = [], o = {}, y;
- array.forEach(function(x, i) {
- o.index = i;
- y = f.call(o, x);
- if (!(y in map)) map[y] = keys.push(y);
- });
- return keys;
-};
-
-/**
- * The comparator function for natural order. This can be used in conjunction with
- * the built-in array sort method to sort elements by their natural
- * order, ascending. Note that if no comparator function is specified to the
- * built-in sort method, the default order is lexicographic, not
- * natural!
- *
- * @see Array.sort.
- * @param a an element to compare.
- * @param b an element to compare.
- * @returns {number} negative if a < b; positive if a > b; otherwise 0.
- */
-pv.naturalOrder = function(a, b) {
- return (a < b) ? -1 : ((a > b) ? 1 : 0);
-};
-
-/**
- * The comparator function for reverse natural order. This can be used in
- * conjunction with the built-in array sort method to sort elements by
- * their natural order, descending. Note that if no comparator function is
- * specified to the built-in sort method, the default order is
- * lexicographic, not natural!
- *
- * @see #naturalOrder
- * @param a an element to compare.
- * @param b an element to compare.
- * @returns {number} negative if a < b; positive if a > b; otherwise 0.
- */
-pv.reverseOrder = function(b, a) {
- return (a < b) ? -1 : ((a > b) ? 1 : 0);
-};
-
-/**
- * Searches the specified array of numbers for the specified value using the
- * binary search algorithm. The array must be sorted (as by the sort
- * method) prior to making this call. If it is not sorted, the results are
- * undefined. If the array contains multiple elements with the specified value,
- * there is no guarantee which one will be found.
- *
- *
The insertion point is defined as the point at which the value
- * would be inserted into the array: the index of the first element greater than
- * the value, or array.length, if all elements in the array are less
- * than the specified value. Note that this guarantees that the return value
- * will be nonnegative if and only if the value is found.
- *
- * @param {number[]} array the array to be searched.
- * @param {number} value the value to be searched for.
- * @returns the index of the search value, if it is contained in the array;
- * otherwise, (-(insertion point) - 1).
- * @param {function} [f] an optional key function.
- */
-pv.search = function(array, value, f) {
- if (!f) f = pv.identity;
- var low = 0, high = array.length - 1;
- while (low <= high) {
- var mid = (low + high) >> 1, midValue = f(array[mid]);
- if (midValue < value) low = mid + 1;
- else if (midValue > value) high = mid - 1;
- else return mid;
- }
- return -low - 1;
-};
-
-pv.search.index = function(array, value, f) {
- var i = pv.search(array, value, f);
- return (i < 0) ? (-i - 1) : i;
-};
-/**
- * Returns an array of numbers, starting at start, incrementing by
- * step, until stop is reached. The stop value is
- * exclusive. If only a single argument is specified, this value is interpeted
- * as the stop value, with the start value as zero. If only two
- * arguments are specified, the step value is implied to be one.
- *
- *
The method is modeled after the built-in range method from
- * Python. See the Python documentation for more details.
- *
- * @see Python range
- * @param {number} [start] the start value.
- * @param {number} stop the stop value.
- * @param {number} [step] the step value.
- * @returns {number[]} an array of numbers.
- */
-pv.range = function(start, stop, step) {
- if (arguments.length == 1) {
- stop = start;
- start = 0;
- }
- if (step == undefined) step = 1;
- if ((stop - start) / step == Infinity) throw new Error("range must be finite");
- var array = [], i = 0, j;
- if (step < 0) {
- while ((j = start + step * i++) > stop) {
- array.push(j);
- }
- } else {
- while ((j = start + step * i++) < stop) {
- array.push(j);
- }
- }
- return array;
-};
-
-/**
- * Returns a random number in the range [start, stop) that is
- * a multiple of step. More specifically, the returned number is of the
- * form start + n * step, where n is a
- * nonnegative integer. If step is not specified, it defaults to 1,
- * returning a random integer if start is also an integer.
- *
- * @param {number} [start] the start value value.
- * @param {number} stop the stop value.
- * @param {number} [step] the step value.
- * @returns {number} a random number between start and stop.
- */
-pv.random = function(start, stop, step) {
- if (arguments.length == 1) {
- stop = start;
- start = 0;
- }
- if (step == undefined) step = 1;
- return step
- ? (Math.floor(Math.random() * (stop - start) / step) * step + start)
- : (Math.random() * (stop - start) + start);
-};
-
-/**
- * Returns the sum of the specified array. If the specified array is not an
- * array of numbers, an optional accessor function f can be specified
- * to map the elements to numbers. See {@link #normalize} for an example.
- * Accessor functions can refer to this.index.
- *
- * @param {array} array an array of objects, or numbers.
- * @param {function} [f] an optional accessor function.
- * @returns {number} the sum of the specified array.
- */
-pv.sum = function(array, f) {
- var o = {};
- return array.reduce(f
- ? function(p, d, i) { o.index = i; return p + f.call(o, d); }
- : function(p, d) { return p + d; }, 0);
-};
-
-/**
- * Returns the maximum value of the specified array. If the specified array is
- * not an array of numbers, an optional accessor function f can be
- * specified to map the elements to numbers. See {@link #normalize} for an
- * example. Accessor functions can refer to this.index.
- *
- * @param {array} array an array of objects, or numbers.
- * @param {function} [f] an optional accessor function.
- * @returns {number} the maximum value of the specified array.
- */
-pv.max = function(array, f) {
- if (f == pv.index) return array.length - 1;
- return Math.max.apply(null, f ? pv.map(array, f) : array);
-};
-
-/**
- * Returns the index of the maximum value of the specified array. If the
- * specified array is not an array of numbers, an optional accessor function
- * f can be specified to map the elements to numbers. See
- * {@link #normalize} for an example. Accessor functions can refer to
- * this.index.
- *
- * @param {array} array an array of objects, or numbers.
- * @param {function} [f] an optional accessor function.
- * @returns {number} the index of the maximum value of the specified array.
- */
-pv.max.index = function(array, f) {
- if (!array.length) return -1;
- if (f == pv.index) return array.length - 1;
- if (!f) f = pv.identity;
- var maxi = 0, maxx = -Infinity, o = {};
- for (var i = 0; i < array.length; i++) {
- o.index = i;
- var x = f.call(o, array[i]);
- if (x > maxx) {
- maxx = x;
- maxi = i;
- }
- }
- return maxi;
-}
-
-/**
- * Returns the minimum value of the specified array of numbers. If the specified
- * array is not an array of numbers, an optional accessor function f
- * can be specified to map the elements to numbers. See {@link #normalize} for
- * an example. Accessor functions can refer to this.index.
- *
- * @param {array} array an array of objects, or numbers.
- * @param {function} [f] an optional accessor function.
- * @returns {number} the minimum value of the specified array.
- */
-pv.min = function(array, f) {
- if (f == pv.index) return 0;
- return Math.min.apply(null, f ? pv.map(array, f) : array);
-};
-
-/**
- * Returns the index of the minimum value of the specified array. If the
- * specified array is not an array of numbers, an optional accessor function
- * f can be specified to map the elements to numbers. See
- * {@link #normalize} for an example. Accessor functions can refer to
- * this.index.
- *
- * @param {array} array an array of objects, or numbers.
- * @param {function} [f] an optional accessor function.
- * @returns {number} the index of the minimum value of the specified array.
- */
-pv.min.index = function(array, f) {
- if (!array.length) return -1;
- if (f == pv.index) return 0;
- if (!f) f = pv.identity;
- var mini = 0, minx = Infinity, o = {};
- for (var i = 0; i < array.length; i++) {
- o.index = i;
- var x = f.call(o, array[i]);
- if (x < minx) {
- minx = x;
- mini = i;
- }
- }
- return mini;
-}
-
-/**
- * Returns the arithmetic mean, or average, of the specified array. If the
- * specified array is not an array of numbers, an optional accessor function
- * f can be specified to map the elements to numbers. See
- * {@link #normalize} for an example. Accessor functions can refer to
- * this.index.
- *
- * @param {array} array an array of objects, or numbers.
- * @param {function} [f] an optional accessor function.
- * @returns {number} the mean of the specified array.
- */
-pv.mean = function(array, f) {
- return pv.sum(array, f) / array.length;
-};
-
-/**
- * Returns the median of the specified array. If the specified array is not an
- * array of numbers, an optional accessor function f can be specified
- * to map the elements to numbers. See {@link #normalize} for an example.
- * Accessor functions can refer to this.index.
- *
- * @param {array} array an array of objects, or numbers.
- * @param {function} [f] an optional accessor function.
- * @returns {number} the median of the specified array.
- */
-pv.median = function(array, f) {
- if (f == pv.index) return (array.length - 1) / 2;
- array = pv.map(array, f).sort(pv.naturalOrder);
- if (array.length % 2) return array[Math.floor(array.length / 2)];
- var i = array.length / 2;
- return (array[i - 1] + array[i]) / 2;
-};
-
-/**
- * Returns the unweighted variance of the specified array. If the specified
- * array is not an array of numbers, an optional accessor function f
- * can be specified to map the elements to numbers. See {@link #normalize} for
- * an example. Accessor functions can refer to this.index.
- *
- * @param {array} array an array of objects, or numbers.
- * @param {function} [f] an optional accessor function.
- * @returns {number} the variance of the specified array.
- */
-pv.variance = function(array, f) {
- if (array.length < 1) return NaN;
- if (array.length == 1) return 0;
- var mean = pv.mean(array, f), sum = 0, o = {};
- if (!f) f = pv.identity;
- for (var i = 0; i < array.length; i++) {
- o.index = i;
- var d = f.call(o, array[i]) - mean;
- sum += d * d;
- }
- return sum;
-};
-
-/**
- * Returns an unbiased estimation of the standard deviation of a population,
- * given the specified random sample. If the specified array is not an array of
- * numbers, an optional accessor function f can be specified to map the
- * elements to numbers. See {@link #normalize} for an example. Accessor
- * functions can refer to this.index.
- *
- * @param {array} array an array of objects, or numbers.
- * @param {function} [f] an optional accessor function.
- * @returns {number} the standard deviation of the specified array.
- */
-pv.deviation = function(array, f) {
- return Math.sqrt(pv.variance(array, f) / (array.length - 1));
-};
-
-/**
- * Returns the logarithm with a given base value.
- *
- * @param {number} x the number for which to compute the logarithm.
- * @param {number} b the base of the logarithm.
- * @returns {number} the logarithm value.
- */
-pv.log = function(x, b) {
- return Math.log(x) / Math.log(b);
-};
-
-/**
- * Computes a zero-symmetric logarithm. Computes the logarithm of the absolute
- * value of the input, and determines the sign of the output according to the
- * sign of the input value.
- *
- * @param {number} x the number for which to compute the logarithm.
- * @param {number} b the base of the logarithm.
- * @returns {number} the symmetric log value.
- */
-pv.logSymmetric = function(x, b) {
- return (x == 0) ? 0 : ((x < 0) ? -pv.log(-x, b) : pv.log(x, b));
-};
-
-/**
- * Computes a zero-symmetric logarithm, with adjustment to values between zero
- * and the logarithm base. This adjustment introduces distortion for values less
- * than the base number, but enables simultaneous plotting of log-transformed
- * data involving both positive and negative numbers.
- *
- * @param {number} x the number for which to compute the logarithm.
- * @param {number} b the base of the logarithm.
- * @returns {number} the adjusted, symmetric log value.
- */
-pv.logAdjusted = function(x, b) {
- if (!isFinite(x)) return x;
- var negative = x < 0;
- if (x < b) x += (b - x) / b;
- return negative ? -pv.log(x, b) : pv.log(x, b);
-};
-
-/**
- * Rounds an input value down according to its logarithm. The method takes the
- * floor of the logarithm of the value and then uses the resulting value as an
- * exponent for the base value.
- *
- * @param {number} x the number for which to compute the logarithm floor.
- * @param {number} b the base of the logarithm.
- * @returns {number} the rounded-by-logarithm value.
- */
-pv.logFloor = function(x, b) {
- return (x > 0)
- ? Math.pow(b, Math.floor(pv.log(x, b)))
- : -Math.pow(b, -Math.floor(-pv.log(-x, b)));
-};
-
-/**
- * Rounds an input value up according to its logarithm. The method takes the
- * ceiling of the logarithm of the value and then uses the resulting value as an
- * exponent for the base value.
- *
- * @param {number} x the number for which to compute the logarithm ceiling.
- * @param {number} b the base of the logarithm.
- * @returns {number} the rounded-by-logarithm value.
- */
-pv.logCeil = function(x, b) {
- return (x > 0)
- ? Math.pow(b, Math.ceil(pv.log(x, b)))
- : -Math.pow(b, -Math.ceil(-pv.log(-x, b)));
-};
-
-(function() {
- var radians = Math.PI / 180,
- degrees = 180 / Math.PI;
-
- /** Returns the number of radians corresponding to the specified degrees. */
- pv.radians = function(degrees) { return radians * degrees; };
-
- /** Returns the number of degrees corresponding to the specified radians. */
- pv.degrees = function(radians) { return degrees * radians; };
-})();
-/**
- * Returns all of the property names (keys) of the specified object (a map). The
- * order of the returned array is not defined.
- *
- * @param map an object.
- * @returns {string[]} an array of strings corresponding to the keys.
- * @see #entries
- */
-pv.keys = function(map) {
- var array = [];
- for (var key in map) {
- array.push(key);
- }
- return array;
-};
-
-/**
- * Returns all of the entries (key-value pairs) of the specified object (a
- * map). The order of the returned array is not defined. Each key-value pair is
- * represented as an object with key and value attributes,
- * e.g., {key: "foo", value: 42}.
- *
- * @param map an object.
- * @returns {array} an array of key-value pairs corresponding to the keys.
- */
-pv.entries = function(map) {
- var array = [];
- for (var key in map) {
- array.push({ key: key, value: map[key] });
- }
- return array;
-};
-
-/**
- * Returns all of the values (attribute values) of the specified object (a
- * map). The order of the returned array is not defined.
- *
- * @param map an object.
- * @returns {array} an array of objects corresponding to the values.
- * @see #entries
- */
-pv.values = function(map) {
- var array = [];
- for (var key in map) {
- array.push(map[key]);
- }
- return array;
-};
-
-/**
- * Returns a map constructed from the specified keys, using the
- * function f to compute the value for each key. The single argument to
- * the value function is the key. The callback is invoked only for indexes of
- * the array which have assigned values; it is not invoked for indexes which
- * have been deleted or which have never been assigned values.
- *
- *
For example, this expression creates a map from strings to string length:
- *
- *
- *
- * The returned value is {one: 3, three: 5, seventeen: 9}. Accessor
- * functions can refer to this.index.
- *
- * @param {array} keys an array.
- * @param {function} f a value function.
- * @returns a map from keys to values.
- */
-pv.dict = function(keys, f) {
- var m = {}, o = {};
- for (var i = 0; i < keys.length; i++) {
- if (i in keys) {
- var k = keys[i];
- o.index = i;
- m[k] = f.call(o, k);
- }
- }
- return m;
-};
-/**
- * Returns a {@link pv.Dom} operator for the given map. This is a convenience
- * factory method, equivalent to new pv.Dom(map). To apply the operator
- * and retrieve the root node, call {@link pv.Dom#root}; to retrieve all nodes
- * flattened, use {@link pv.Dom#nodes}.
- *
- * @see pv.Dom
- * @param map a map from which to construct a DOM.
- * @returns {pv.Dom} a DOM operator for the specified map.
- */
-pv.dom = function(map) {
- return new pv.Dom(map);
-};
-
-/**
- * Constructs a DOM operator for the specified map. This constructor should not
- * be invoked directly; use {@link pv.dom} instead.
- *
- * @class Represets a DOM operator for the specified map. This allows easy
- * transformation of a hierarchical JavaScript object (such as a JSON map) to a
- * W3C Document Object Model hierarchy. For more information on which attributes
- * and methods from the specification are supported, see {@link pv.Dom.Node}.
- *
- *
Leaves in the map are determined using an associated leaf function;
- * see {@link #leaf}. By default, leaves are any value whose type is not
- * "object", such as numbers or strings.
- *
- * @param map a map from which to construct a DOM.
- */
-pv.Dom = function(map) {
- this.$map = map;
-};
-
-/** @private The default leaf function. */
-pv.Dom.prototype.$leaf = function(n) {
- return typeof n != "object";
-};
-
-/**
- * Sets or gets the leaf function for this DOM operator. The leaf function
- * identifies which values in the map are leaves, and which are internal nodes.
- * By default, objects are considered internal nodes, and primitives (such as
- * numbers and strings) are considered leaves.
- *
- * @param {function} f the new leaf function.
- * @returns the current leaf function, or this.
- */
-pv.Dom.prototype.leaf = function(f) {
- if (arguments.length) {
- this.$leaf = f;
- return this;
- }
- return this.$leaf;
-};
-
-/**
- * Applies the DOM operator, returning the root node.
- *
- * @returns {pv.Dom.Node} the root node.
- * @param {string} [nodeName] optional node name for the root.
- */
-pv.Dom.prototype.root = function(nodeName) {
- var leaf = this.$leaf, root = recurse(this.$map);
-
- /** @private */
- function recurse(map) {
- var n = new pv.Dom.Node();
- for (var k in map) {
- var v = map[k];
- n.appendChild(leaf(v) ? new pv.Dom.Node(v) : recurse(v)).nodeName = k;
- }
- return n;
- }
-
- root.nodeName = nodeName;
- return root;
-};
-
-/**
- * Applies the DOM operator, returning the array of all nodes in preorder
- * traversal.
- *
- * @returns {array} the array of nodes in preorder traversal.
- */
-pv.Dom.prototype.nodes = function() {
- return this.root().nodes();
-};
-
-/**
- * Constructs a DOM node for the specified value. Instances of this class are
- * not typically created directly; instead they are generated from a JavaScript
- * map using the {@link pv.Dom} operator.
- *
- * @class Represents a Node in the W3C Document Object Model.
- */
-pv.Dom.Node = function(value) {
- this.nodeValue = value;
- this.childNodes = [];
-};
-
-/**
- * The node name. When generated from a map, the node name corresponds to the
- * key at the given level in the map. Note that the root node has no associated
- * key, and thus has an undefined node name (and no parentNode).
- *
- * @type string
- * @field pv.Dom.Node.prototype.nodeName
- */
-
-/**
- * The node value. When generated from a map, node value corresponds to the leaf
- * value for leaf nodes, and is undefined for internal nodes.
- *
- * @field pv.Dom.Node.prototype.nodeValue
- */
-
-/**
- * The array of child nodes. This array is empty for leaf nodes. An easy way to
- * check if child nodes exist is to query firstChild.
- *
- * @type array
- * @field pv.Dom.Node.prototype.childNodes
- */
-
-/**
- * The parent node, which is null for root nodes.
- *
- * @type pv.Dom.Node
- */
-pv.Dom.Node.prototype.parentNode = null;
-
-/**
- * The first child, which is null for leaf nodes.
- *
- * @type pv.Dom.Node
- */
-pv.Dom.Node.prototype.firstChild = null;
-
-/**
- * The last child, which is null for leaf nodes.
- *
- * @type pv.Dom.Node
- */
-pv.Dom.Node.prototype.lastChild = null;
-
-/**
- * The previous sibling node, which is null for the first child.
- *
- * @type pv.Dom.Node
- */
-pv.Dom.Node.prototype.previousSibling = null;
-
-/**
- * The next sibling node, which is null for the last child.
- *
- * @type pv.Dom.Node
- */
-pv.Dom.Node.prototype.nextSibling = null;
-
-/**
- * Removes the specified child node from this node.
- *
- * @throws Error if the specified child is not a child of this node.
- * @returns {pv.Dom.Node} the removed child.
- */
-pv.Dom.Node.prototype.removeChild = function(n) {
- var i = this.childNodes.indexOf(n);
- if (i == -1) throw new Error("child not found");
- this.childNodes.splice(i, 1);
- if (n.previousSibling) n.previousSibling.nextSibling = n.nextSibling;
- else this.firstChild = n.nextSibling;
- if (n.nextSibling) n.nextSibling.previousSibling = n.previousSibling;
- else this.lastChild = n.previousSibling;
- delete n.nextSibling;
- delete n.previousSibling;
- delete n.parentNode;
- return n;
-};
-
-/**
- * Appends the specified child node to this node. If the specified child is
- * already part of the DOM, the child is first removed before being added to
- * this node.
- *
- * @returns {pv.Dom.Node} the appended child.
- */
-pv.Dom.Node.prototype.appendChild = function(n) {
- if (n.parentNode) n.parentNode.removeChild(n);
- n.parentNode = this;
- n.previousSibling = this.lastChild;
- if (this.lastChild) this.lastChild.nextSibling = n;
- else this.firstChild = n;
- this.lastChild = n;
- this.childNodes.push(n);
- return n;
-};
-
-/**
- * Inserts the specified child n before the given reference child
- * r of this node. If r is null, this method is equivalent to
- * {@link #appendChild}. If n is already part of the DOM, it is first
- * removed before being inserted.
- *
- * @throws Error if r is non-null and not a child of this node.
- * @returns {pv.Dom.Node} the inserted child.
- */
-pv.Dom.Node.prototype.insertBefore = function(n, r) {
- if (!r) return this.appendChild(n);
- var i = this.childNodes.indexOf(r);
- if (i == -1) throw new Error("child not found");
- if (n.parentNode) n.parentNode.removeChild(n);
- n.parentNode = this;
- n.nextSibling = r;
- n.previousSibling = r.previousSibling;
- if (r.previousSibling) {
- r.previousSibling.nextSibling = n;
- } else {
- if (r == this.lastChild) this.lastChild = n;
- this.firstChild = n;
- }
- this.childNodes.splice(i, 0, n);
- return n;
-};
-
-/**
- * Replaces the specified child r of this node with the node n. If
- * n is already part of the DOM, it is first removed before being added.
- *
- * @throws Error if r is not a child of this node.
- */
-pv.Dom.Node.prototype.replaceChild = function(n, r) {
- var i = this.childNodes.indexOf(r);
- if (i == -1) throw new Error("child not found");
- if (n.parentNode) n.parentNode.removeChild(n);
- n.parentNode = this;
- n.nextSibling = r.nextSibling;
- n.previousSibling = r.previousSibling;
- if (r.previousSibling) r.previousSibling.nextSibling = n;
- else this.firstChild = n;
- if (r.nextSibling) r.nextSibling.previousSibling = n;
- else this.lastChild = n;
- this.childNodes[i] = n;
- return r;
-};
-
-/**
- * Visits each node in the tree in preorder traversal, applying the specified
- * function f. The arguments to the function are:
- *
- *
The current node.
- *
The current depth, starting at 0 for the root node.
- *
- * @param {function} f a function to apply to each node.
- */
-pv.Dom.Node.prototype.visitBefore = function(f) {
- function visit(n, i) {
- f(n, i);
- for (var c = n.firstChild; c; c = c.nextSibling) {
- visit(c, i + 1);
- }
- }
- visit(this, 0);
-};
-
-/**
- * Visits each node in the tree in postorder traversal, applying the specified
- * function f. The arguments to the function are:
- *
- *
The current node.
- *
The current depth, starting at 0 for the root node.
- *
- * @param {function} f a function to apply to each node.
- */
-pv.Dom.Node.prototype.visitAfter = function(f) {
- function visit(n, i) {
- for (var c = n.firstChild; c; c = c.nextSibling) {
- visit(c, i + 1);
- }
- f(n, i);
- }
- visit(this, 0);
-};
-
-/**
- * Sorts child nodes of this node, and all descendent nodes recursively, using
- * the specified comparator function f. The comparator function is
- * passed two nodes to compare.
- *
- *
Note: during the sort operation, the comparator function should not rely
- * on the tree being well-formed; the values of previousSibling and
- * nextSibling for the nodes being compared are not defined during the
- * sort operation.
- *
- * @param {function} f a comparator function.
- * @returns this.
- */
-pv.Dom.Node.prototype.sort = function(f) {
- if (this.firstChild) {
- this.childNodes.sort(f);
- var p = this.firstChild = this.childNodes[0], c;
- delete p.previousSibling;
- for (var i = 1; i < this.childNodes.length; i++) {
- p.sort(f);
- c = this.childNodes[i];
- c.previousSibling = p;
- p = p.nextSibling = c;
- }
- this.lastChild = p;
- delete p.nextSibling;
- p.sort(f);
- }
- return this;
-};
-
-/**
- * Reverses all sibling nodes.
- *
- * @returns this.
- */
-pv.Dom.Node.prototype.reverse = function() {
- var childNodes = [];
- this.visitAfter(function(n) {
- while (n.lastChild) childNodes.push(n.removeChild(n.lastChild));
- for (var c; c = childNodes.pop();) n.insertBefore(c, n.firstChild);
- });
- return this;
-};
-
-/** Returns all descendants of this node in preorder traversal. */
-pv.Dom.Node.prototype.nodes = function() {
- var array = [];
-
- /** @private */
- function flatten(node) {
- array.push(node);
- node.childNodes.forEach(flatten);
- }
-
- flatten(this, array);
- return array;
-};
-
-/**
- * Toggles the child nodes of this node. If this node is not yet toggled, this
- * method removes all child nodes and appends them to a new toggled
- * array attribute on this node. Otherwise, if this node is toggled, this method
- * re-adds all toggled child nodes and deletes the toggled attribute.
- *
- *
This method has no effect if the node has no child nodes.
- *
- * @param {boolean} [recursive] whether the toggle should apply to descendants.
- */
-pv.Dom.Node.prototype.toggle = function(recursive) {
- if (recursive) return this.toggled
- ? this.visitBefore(function(n) { if (n.toggled) n.toggle(); })
- : this.visitAfter(function(n) { if (!n.toggled) n.toggle(); });
- var n = this;
- if (n.toggled) {
- for (var c; c = n.toggled.pop();) n.appendChild(c);
- delete n.toggled;
- } else if (n.lastChild) {
- n.toggled = [];
- while (n.lastChild) n.toggled.push(n.removeChild(n.lastChild));
- }
-};
-
-/**
- * Given a flat array of values, returns a simple DOM with each value wrapped by
- * a node that is a child of the root node.
- *
- * @param {array} values.
- * @returns {array} nodes.
- */
-pv.nodes = function(values) {
- var root = new pv.Dom.Node();
- for (var i = 0; i < values.length; i++) {
- root.appendChild(new pv.Dom.Node(values[i]));
- }
- return root.nodes();
-};
-/**
- * Returns a {@link pv.Tree} operator for the specified array. This is a
- * convenience factory method, equivalent to new pv.Tree(array).
- *
- * @see pv.Tree
- * @param {array} array an array from which to construct a tree.
- * @returns {pv.Tree} a tree operator for the specified array.
- */
-pv.tree = function(array) {
- return new pv.Tree(array);
-};
-
-/**
- * Constructs a tree operator for the specified array. This constructor should
- * not be invoked directly; use {@link pv.tree} instead.
- *
- * @class Represents a tree operator for the specified array. The tree operator
- * allows a hierarchical map to be constructed from an array; it is similar to
- * the {@link pv.Nest} operator, except the hierarchy is derived dynamically
- * from the array elements.
- *
- *
For example, given an array of size information for ActionScript classes:
- *
- *
- *
- * For visualizations with large data sets, performance improvements may be seen
- * by storing the data in a tree format, and then flattening it into an array at
- * runtime with {@link pv.Flatten}.
- *
- * @param {array} array an array from which to construct a tree.
- */
-pv.Tree = function(array) {
- this.array = array;
-};
-
-/**
- * Assigns a keys function to this operator; required. The keys function
- * returns an array of strings for each element in the associated
- * array; these keys determine how the elements are nested in the tree. The
- * returned keys should be unique for each element in the array; otherwise, the
- * behavior of this operator is undefined.
- *
- * @param {function} k the keys function.
- * @returns {pv.Tree} this.
- */
-pv.Tree.prototype.keys = function(k) {
- this.k = k;
- return this;
-};
-
-/**
- * Assigns a value function to this operator; optional. The value
- * function specifies an optional transformation of the element in the array
- * before it is inserted into the map. If no value function is specified, it is
- * equivalent to using the identity function.
- *
- * @param {function} k the value function.
- * @returns {pv.Tree} this.
- */
-pv.Tree.prototype.value = function(v) {
- this.v = v;
- return this;
-};
-
-/**
- * Returns a hierarchical map of values. The hierarchy is determined by the keys
- * function; the values in the map are determined by the value function.
- *
- * @returns a hierarchical map of values.
- */
-pv.Tree.prototype.map = function() {
- var map = {}, o = {};
- for (var i = 0; i < this.array.length; i++) {
- o.index = i;
- var value = this.array[i], keys = this.k.call(o, value), node = map;
- for (var j = 0; j < keys.length - 1; j++) {
- node = node[keys[j]] || (node[keys[j]] = {});
- }
- node[keys[j]] = this.v ? this.v.call(o, value) : value;
- }
- return map;
-};
-/**
- * Returns a {@link pv.Nest} operator for the specified array. This is a
- * convenience factory method, equivalent to new pv.Nest(array).
- *
- * @see pv.Nest
- * @param {array} array an array of elements to nest.
- * @returns {pv.Nest} a nest operator for the specified array.
- */
-pv.nest = function(array) {
- return new pv.Nest(array);
-};
-
-/**
- * Constructs a nest operator for the specified array. This constructor should
- * not be invoked directly; use {@link pv.nest} instead.
- *
- * @class Represents a {@link Nest} operator for the specified array. Nesting
- * allows elements in an array to be grouped into a hierarchical tree
- * structure. The levels in the tree are specified by key functions. The
- * leaf nodes of the tree can be sorted by value, while the internal nodes can
- * be sorted by key. Finally, the tree can be returned either has a
- * multidimensional array via {@link #entries}, or as a hierarchical map via
- * {@link #map}. The {@link #rollup} routine similarly returns a map, collapsing
- * the elements in each leaf node using a summary function.
- *
- *
For example, consider the following tabular data structure of Barley
- * yields, from various sites in Minnesota during 1931-2:
- *
- *
- *
- * Further details, including sorting and rollup, is provided below on the
- * corresponding methods.
- *
- * @param {array} array an array of elements to nest.
- */
-pv.Nest = function(array) {
- this.array = array;
- this.keys = [];
-};
-
-/**
- * Nests using the specified key function. Multiple keys may be added to the
- * nest; the array elements will be nested in the order keys are specified.
- *
- * @param {function} key a key function; must return a string or suitable map
- * key.
- * @returns {pv.Nest} this.
- */
-pv.Nest.prototype.key = function(key) {
- this.keys.push(key);
- return this;
-};
-
-/**
- * Sorts the previously-added keys. The natural sort order is used by default
- * (see {@link pv.naturalOrder}); if an alternative order is desired,
- * order should be a comparator function. If this method is not called
- * (i.e., keys are unsorted), keys will appear in the order they appear
- * in the underlying elements array. For example,
- *
- *
- *
- * groups yield data by year, then variety, and sorts the variety groups
- * lexicographically (since the variety attribute is a string).
- *
- *
Key sort order is only used in conjunction with {@link #entries}, which
- * returns an array of key-values pairs. If the nest is used to construct a
- * {@link #map} instead, keys are unsorted.
- *
- * @param {function} [order] an optional comparator function.
- * @returns {pv.Nest} this.
- */
-pv.Nest.prototype.sortKeys = function(order) {
- this.keys[this.keys.length - 1].order = order || pv.naturalOrder;
- return this;
-};
-
-/**
- * Sorts the leaf values. The natural sort order is used by default (see
- * {@link pv.naturalOrder}); if an alternative order is desired, order
- * should be a comparator function. If this method is not called (i.e., values
- * are unsorted), values will appear in the order they appear in the
- * underlying elements array. For example,
- *
- *
- *
- * groups yield data by year, then variety, and sorts the values for each
- * variety group by yield.
- *
- *
Value sort order, unlike keys, applies to both {@link #entries} and
- * {@link #map}. It has no effect on {@link #rollup}.
- *
- * @param {function} [order] an optional comparator function.
- * @returns {pv.Nest} this.
- */
-pv.Nest.prototype.sortValues = function(order) {
- this.order = order || pv.naturalOrder;
- return this;
-};
-
-/**
- * Returns a hierarchical map of values. Each key adds one level to the
- * hierarchy. With only a single key, the returned map will have a key for each
- * distinct value of the key function; the correspond value with be an array of
- * elements with that key value. If a second key is added, this will be a nested
- * map. For example:
- *
- *
- *
- * returns a map m such that m[variety][site] is an array, a subset of
- * yields, with each element having the given variety and site.
- *
- * @returns a hierarchical map of values.
- */
-pv.Nest.prototype.map = function() {
- var map = {}, values = [];
-
- /* Build the map. */
- for (var i, j = 0; j < this.array.length; j++) {
- var x = this.array[j];
- var m = map;
- for (i = 0; i < this.keys.length - 1; i++) {
- var k = this.keys[i](x);
- if (!m[k]) m[k] = {};
- m = m[k];
- }
- k = this.keys[i](x);
- if (!m[k]) {
- var a = [];
- values.push(a);
- m[k] = a;
- }
- m[k].push(x);
- }
-
- /* Sort each leaf array. */
- if (this.order) {
- for (var i = 0; i < values.length; i++) {
- values[i].sort(this.order);
- }
- }
-
- return map;
-};
-
-/**
- * Returns a hierarchical nested array. This method is similar to
- * {@link pv.entries}, but works recursively on the entire hierarchy. Rather
- * than returning a map like {@link #map}, this method returns a nested
- * array. Each element of the array has a key and values
- * field. For leaf nodes, the values array will be a subset of the
- * underlying elements array; for non-leaf nodes, the values array will
- * contain more key-values pairs.
- *
- *
For an example usage, see the {@link Nest} constructor.
- *
- * @returns a hierarchical nested array.
- */
-pv.Nest.prototype.entries = function() {
-
- /** Recursively extracts the entries for the given map. */
- function entries(map) {
- var array = [];
- for (var k in map) {
- var v = map[k];
- array.push({ key: k, values: (v instanceof Array) ? v : entries(v) });
- };
- return array;
- }
-
- /** Recursively sorts the values for the given key-values array. */
- function sort(array, i) {
- var o = this.keys[i].order;
- if (o) array.sort(function(a, b) { return o(a.key, b.key); });
- if (++i < this.keys.length) {
- for (var j = 0; j < array.length; j++) {
- sort.call(this, array[j].values, i);
- }
- }
- return array;
- }
-
- return sort.call(this, entries(this.map()), 0);
-};
-
-/**
- * Returns a rollup map. The behavior of this method is the same as
- * {@link #map}, except that the leaf values are replaced with the return value
- * of the specified rollup function f. For example,
- *
- *
- *
- * first groups yield data by site, and then returns a map from site to median
- * yield for the given site.
- *
- * @see #map
- * @param {function} f a rollup function.
- * @returns a hierarchical map, with the leaf values computed by f.
- */
-pv.Nest.prototype.rollup = function(f) {
-
- /** Recursively descends to the leaf nodes (arrays) and does rollup. */
- function rollup(map) {
- for (var key in map) {
- var value = map[key];
- if (value instanceof Array) {
- map[key] = f(value);
- } else {
- rollup(value);
- }
- }
- return map;
- }
-
- return rollup(this.map());
-};
-/**
- * Returns a {@link pv.Flatten} operator for the specified map. This is a
- * convenience factory method, equivalent to new pv.Flatten(map).
- *
- * @see pv.Flatten
- * @param map a map to flatten.
- * @returns {pv.Flatten} a flatten operator for the specified map.
- */
-pv.flatten = function(map) {
- return new pv.Flatten(map);
-};
-
-/**
- * Constructs a flatten operator for the specified map. This constructor should
- * not be invoked directly; use {@link pv.flatten} instead.
- *
- * @class Represents a flatten operator for the specified array. Flattening
- * allows hierarchical maps to be flattened into an array. The levels in the
- * input tree are specified by key functions.
- *
- *
For example, consider the following hierarchical data structure of Barley
- * yields, from various sites in Minnesota during 1931-2:
- *
- *
The flatten operator is roughly the inverse of the {@link pv.Nest} and
- * {@link pv.Tree} operators.
- *
- * @param map a map to flatten.
- */
-pv.Flatten = function(map) {
- this.map = map;
- this.keys = [];
-};
-
-/**
- * Flattens using the specified key function. Multiple keys may be added to the
- * flatten; the tiers of the underlying tree must correspond to the specified
- * keys, in order. The order of the returned array is undefined; however, you
- * can easily sort it.
- *
- * @param {string} key the key name.
- * @param {function} [f] an optional value map function.
- * @returns {pv.Nest} this.
- */
-pv.Flatten.prototype.key = function(key, f) {
- this.keys.push({name: key, value: f});
- delete this.$leaf;
- return this;
-};
-
-/**
- * Flattens using the specified leaf function. This is an alternative to
- * specifying an explicit set of keys; the tiers of the underlying tree will be
- * determined dynamically by recursing on the values, and the resulting keys
- * will be stored in the entries keys attribute. The leaf function must
- * return true for leaves, and false for internal nodes.
- *
- * @param {function} f a leaf function.
- * @returns {pv.Nest} this.
- */
-pv.Flatten.prototype.leaf = function(f) {
- this.keys.length = 0;
- this.$leaf = f;
- return this;
-};
-
-/**
- * Returns the flattened array. Each entry in the array is an object; each
- * object has attributes corresponding to this flatten operator's keys.
- *
- * @returns an array of elements from the flattened map.
- */
-pv.Flatten.prototype.array = function() {
- var entries = [], stack = [], keys = this.keys, leaf = this.$leaf;
-
- /* Recursively visit using the leaf function. */
- if (leaf) {
- function recurse(value, i) {
- if (leaf(value)) {
- entries.push({keys: stack.slice(), value: value});
- } else {
- for (var key in value) {
- stack.push(key);
- recurse(value[key], i + 1);
- stack.pop();
- }
- }
- }
- recurse(this.map, 0);
- return entries;
- }
-
- /* Recursively visits the specified value. */
- function visit(value, i) {
- if (i < keys.length - 1) {
- for (var key in value) {
- stack.push(key);
- visit(value[key], i + 1);
- stack.pop();
- }
- } else {
- entries.push(stack.concat(value));
- }
- }
-
- visit(this.map, 0);
- return entries.map(function(stack) {
- var m = {};
- for (var i = 0; i < keys.length; i++) {
- var k = keys[i], v = stack[i];
- m[k.name] = k.value ? k.value.call(null, v) : v;
- }
- return m;
- });
-};
-/**
- * Returns a {@link pv.Vector} for the specified x and y
- * coordinate. This is a convenience factory method, equivalent to new
- * pv.Vector(x, y).
- *
- * @see pv.Vector
- * @param {number} x the x coordinate.
- * @param {number} y the y coordinate.
- * @returns {pv.Vector} a vector for the specified coordinates.
- */
-pv.vector = function(x, y) {
- return new pv.Vector(x, y);
-};
-
-/**
- * Constructs a {@link pv.Vector} for the specified x and y
- * coordinate. This constructor should not be invoked directly; use
- * {@link pv.vector} instead.
- *
- * @class Represents a two-dimensional vector; a 2-tuple ⟨x,
- * y⟩. The intent of this class is to simplify vector math. Note that
- * in performance-sensitive cases it may be more efficient to represent 2D
- * vectors as simple objects with x and y attributes, rather
- * than using instances of this class.
- *
- * @param {number} x the x coordinate.
- * @param {number} y the y coordinate.
- */
-pv.Vector = function(x, y) {
- this.x = x;
- this.y = y;
-};
-
-/**
- * Returns a vector perpendicular to this vector: ⟨-y, x⟩.
- *
- * @returns {pv.Vector} a perpendicular vector.
- */
-pv.Vector.prototype.perp = function() {
- return new pv.Vector(-this.y, this.x);
-};
-
-/**
- * Returns a normalized copy of this vector: a vector with the same direction,
- * but unit length. If this vector has zero length this method returns a copy of
- * this vector.
- *
- * @returns {pv.Vector} a unit vector.
- */
-pv.Vector.prototype.norm = function() {
- var l = this.length();
- return this.times(l ? (1 / l) : 1);
-};
-
-/**
- * Returns the magnitude of this vector, defined as sqrt(x * x + y * y).
- *
- * @returns {number} a length.
- */
-pv.Vector.prototype.length = function() {
- return Math.sqrt(this.x * this.x + this.y * this.y);
-};
-
-/**
- * Returns a scaled copy of this vector: ⟨x * k, y * k⟩.
- * To perform the equivalent divide operation, use 1 / k.
- *
- * @param {number} k the scale factor.
- * @returns {pv.Vector} a scaled vector.
- */
-pv.Vector.prototype.times = function(k) {
- return new pv.Vector(this.x * k, this.y * k);
-};
-
-/**
- * Returns this vector plus the vector v: ⟨x + v.x, y +
- * v.y⟩. If only one argument is specified, it is interpreted as the
- * vector v.
- *
- * @param {number} x the x coordinate to add.
- * @param {number} y the y coordinate to add.
- * @returns {pv.Vector} a new vector.
- */
-pv.Vector.prototype.plus = function(x, y) {
- return (arguments.length == 1)
- ? new pv.Vector(this.x + x.x, this.y + x.y)
- : new pv.Vector(this.x + x, this.y + y);
-};
-
-/**
- * Returns this vector minus the vector v: ⟨x - v.x, y -
- * v.y⟩. If only one argument is specified, it is interpreted as the
- * vector v.
- *
- * @param {number} x the x coordinate to subtract.
- * @param {number} y the y coordinate to subtract.
- * @returns {pv.Vector} a new vector.
- */
-pv.Vector.prototype.minus = function(x, y) {
- return (arguments.length == 1)
- ? new pv.Vector(this.x - x.x, this.y - x.y)
- : new pv.Vector(this.x - x, this.y - y);
-};
-
-/**
- * Returns the dot product of this vector and the vector v: x * v.x +
- * y * v.y. If only one argument is specified, it is interpreted as the
- * vector v.
- *
- * @param {number} x the x coordinate to dot.
- * @param {number} y the y coordinate to dot.
- * @returns {number} a dot product.
- */
-pv.Vector.prototype.dot = function(x, y) {
- return (arguments.length == 1)
- ? this.x * x.x + this.y * x.y
- : this.x * x + this.y * y;
-};
-/**
- * Returns a new identity transform.
- *
- * @class Represents a transformation matrix. The transformation matrix is
- * limited to expressing translate and uniform scale transforms only; shearing,
- * rotation, general affine, and other transforms are not supported.
- *
- *
The methods on this class treat the transform as immutable, returning a
- * copy of the transformation matrix with the specified transform applied. Note,
- * alternatively, that the matrix fields can be get and set directly.
- */
-pv.Transform = function() {};
-pv.Transform.prototype = {k: 1, x: 0, y: 0};
-
-/**
- * The scale magnitude; defaults to 1.
- *
- * @type number
- * @name pv.Transform.prototype.k
- */
-
-/**
- * The x-offset; defaults to 0.
- *
- * @type number
- * @name pv.Transform.prototype.x
- */
-
-/**
- * The y-offset; defaults to 0.
- *
- * @type number
- * @name pv.Transform.prototype.y
- */
-
-/**
- * @private The identity transform.
- *
- * @type pv.Transform
- */
-pv.Transform.identity = new pv.Transform();
-
-// k 0 x 1 0 a k 0 ka+x
-// 0 k y * 0 1 b = 0 k kb+y
-// 0 0 1 0 0 1 0 0 1
-
-/**
- * Returns a translated copy of this transformation matrix.
- *
- * @param {number} x the x-offset.
- * @param {number} y the y-offset.
- * @returns {pv.Transform} the translated transformation matrix.
- */
-pv.Transform.prototype.translate = function(x, y) {
- var v = new pv.Transform();
- v.k = this.k;
- v.x = this.k * x + this.x;
- v.y = this.k * y + this.y;
- return v;
-};
-
-// k 0 x d 0 0 kd 0 x
-// 0 k y * 0 d 0 = 0 kd y
-// 0 0 1 0 0 1 0 0 1
-
-/**
- * Returns a scaled copy of this transformation matrix.
- *
- * @param {number} k
- * @returns {pv.Transform} the scaled transformation matrix.
- */
-pv.Transform.prototype.scale = function(k) {
- var v = new pv.Transform();
- v.k = this.k * k;
- v.x = this.x;
- v.y = this.y;
- return v;
-};
-
-/**
- * Returns the inverse of this transformation matrix.
- *
- * @returns {pv.Transform} the inverted transformation matrix.
- */
-pv.Transform.prototype.invert = function() {
- var v = new pv.Transform(), k = 1 / this.k;
- v.k = k;
- v.x = -this.x * k;
- v.y = -this.y * k;
- return v;
-};
-
-// k 0 x d 0 a kd 0 ka+x
-// 0 k y * 0 d b = 0 kd kb+y
-// 0 0 1 0 0 1 0 0 1
-
-/**
- * Returns this matrix post-multiplied by the specified matrix m.
- *
- * @param {pv.Transform} m
- * @returns {pv.Transform} the post-multiplied transformation matrix.
- */
-pv.Transform.prototype.times = function(m) {
- var v = new pv.Transform();
- v.k = this.k * m.k;
- v.x = this.k * m.x + this.x;
- v.y = this.k * m.y + this.y;
- return v;
-};
-/**
- * Abstract; see the various scale implementations.
- *
- * @class Represents a scale; a function that performs a transformation from
- * data domain to visual range. For quantitative and quantile scales, the domain
- * is expressed as numbers; for ordinal scales, the domain is expressed as
- * strings (or equivalently objects with unique string representations). The
- * "visual range" may correspond to pixel space, colors, font sizes, and the
- * like.
- *
- *
Note that scales are functions, and thus can be used as properties
- * directly, assuming that the data associated with a mark is a number. While
- * this is convenient for single-use scales, frequently it is desirable to
- * define scales globally:
- *
- *
var y = pv.Scale.linear(0, 100).range(0, 640);
- *
- * The y scale can now be equivalently referenced within a property:
- *
- *
.height(function(d) y(d))
- *
- * Alternatively, if the data are not simple numbers, the appropriate value can
- * be passed to the y scale (e.g., d.foo). The {@link #by}
- * method similarly allows the data to be mapped to a numeric value before
- * performing the linear transformation.
- *
- * @see pv.Scale.quantitative
- * @see pv.Scale.quantile
- * @see pv.Scale.ordinal
- * @extends function
- */
-pv.Scale = function() {};
-
-/**
- * @private Returns a function that interpolators from the start value to the
- * end value, given a parameter t in [0, 1].
- *
- * @param start the start value.
- * @param end the end value.
- */
-pv.Scale.interpolator = function(start, end) {
- if (typeof start == "number") {
- return function(t) {
- return t * (end - start) + start;
- };
- }
-
- /* For now, assume color. */
- start = pv.color(start).rgb();
- end = pv.color(end).rgb();
- return function(t) {
- var a = start.a * (1 - t) + end.a * t;
- if (a < 1e-5) a = 0; // avoid scientific notation
- return (start.a == 0) ? pv.rgb(end.r, end.g, end.b, a)
- : ((end.a == 0) ? pv.rgb(start.r, start.g, start.b, a)
- : pv.rgb(
- Math.round(start.r * (1 - t) + end.r * t),
- Math.round(start.g * (1 - t) + end.g * t),
- Math.round(start.b * (1 - t) + end.b * t), a));
- };
-};
-
-/**
- * Returns a view of this scale by the specified accessor function f.
- * Given a scale y, y.by(function(d) d.foo) is equivalent to
- * function(d) y(d.foo).
- *
- *
This method is provided for convenience, such that scales can be
- * succinctly defined inline. For example, given an array of data elements that
- * have a score attribute with the domain [0, 1], the height property
- * could be specified as:
- *
- *
- *
- * This method should be used judiciously; it is typically more clear to invoke
- * the scale directly, passing in the value to be scaled.
- *
- * @function
- * @name pv.Scale.prototype.by
- * @param {function} f an accessor function.
- * @returns {pv.Scale} a view of this scale by the specified accessor function.
- */
-/**
- * Returns a default quantitative, linear, scale for the specified domain. The
- * arguments to this constructor are optional, and equivalent to calling
- * {@link #domain}. The default domain and range are [0,1].
- *
- *
This constructor is typically not used directly; see one of the
- * quantitative scale implementations instead.
- *
- * @class Represents an abstract quantitative scale; a function that performs a
- * numeric transformation. This class is typically not used directly; see one of
- * the quantitative scale implementations (linear, log, root, etc.)
- * instead. A quantitative
- * scale represents a 1-dimensional transformation from a numeric domain of
- * input data [d0, d1] to a numeric range of
- * pixels [r0, r1]. In addition to
- * readability, scales offer several useful features:
- *
- *
1. The range can be expressed in colors, rather than pixels. For example:
- *
- *
- *
- * will fill the marks "red" on an input value of 0, "green" on an input value
- * of 100, and some color in-between for intermediate values.
- *
- *
2. The domain and range can be subdivided for a non-uniform
- * transformation. For example, you may want a diverging color scale that is
- * increasingly red for negative values, and increasingly green for positive
- * values:
- *
- *
- *
- * The domain can be specified as a series of n monotonically-increasing
- * values; the range must also be specified as n values, resulting in
- * n - 1 contiguous linear scales.
- *
- *
3. Quantitative scales can be inverted for interaction. The
- * {@link #invert} method takes a value in the output range, and returns the
- * corresponding value in the input domain. This is frequently used to convert
- * the mouse location (see {@link pv.Mark#mouse}) to a value in the input
- * domain. Note that inversion is only supported for numeric ranges, and not
- * colors.
- *
- *
4. A scale can be queried for reasonable "tick" values. The {@link #ticks}
- * method provides a convenient way to get a series of evenly-spaced rounded
- * values in the input domain. Frequently these are used in conjunction with
- * {@link pv.Rule} to display tick marks or grid lines.
- *
- *
5. A scale can be "niced" to extend the domain to suitable rounded
- * numbers. If the minimum and maximum of the domain are messy because they are
- * derived from data, you can use {@link #nice} to round these values down and
- * up to even numbers.
- *
- * @param {number...} domain... optional domain values.
- * @see pv.Scale.linear
- * @see pv.Scale.log
- * @see pv.Scale.root
- * @extends pv.Scale
- */
-pv.Scale.quantitative = function() {
- var d = [0, 1], // default domain
- l = [0, 1], // default transformed domain
- r = [0, 1], // default range
- i = [pv.identity], // default interpolators
- type = Number, // default type
- n = false, // whether the domain is negative
- f = pv.identity, // default forward transform
- g = pv.identity, // default inverse transform
- tickFormat = String; // default tick formatting function
-
- /** @private */
- function newDate(x) {
- return new Date(x);
- }
-
- /** @private */
- function scale(x) {
- var j = pv.search(d, x);
- if (j < 0) j = -j - 2;
- j = Math.max(0, Math.min(i.length - 1, j));
- return i[j]((f(x) - l[j]) / (l[j + 1] - l[j]));
- }
-
- /** @private */
- scale.transform = function(forward, inverse) {
- /** @ignore */ f = function(x) { return n ? -forward(-x) : forward(x); };
- /** @ignore */ g = function(y) { return n ? -inverse(-y) : inverse(y); };
- l = d.map(f);
- return this;
- };
-
- /**
- * Sets or gets the input domain. This method can be invoked several ways:
- *
- *
1. domain(min, ..., max)
- *
- *
Specifying the domain as a series of numbers is the most explicit and
- * recommended approach. Most commonly, two numbers are specified: the minimum
- * and maximum value. However, for a diverging scale, or other subdivided
- * non-uniform scales, multiple values can be specified. Values can be derived
- * from data using {@link pv.min} and {@link pv.max}. For example:
- *
- *
.domain(0, pv.max(array))
- *
- * An alternative method for deriving minimum and maximum values from data
- * follows.
- *
- *
2. domain(array, minf, maxf)
- *
- *
When both the minimum and maximum value are derived from data, the
- * arguments to the domain method can be specified as the array of
- * data, followed by zero, one or two accessor functions. For example, if the
- * array of data is just an array of numbers:
- *
- *
.domain(array)
- *
- * On the other hand, if the array elements are objects representing stock
- * values per day, and the domain should consider the stock's daily low and
- * daily high:
- *
- *
- *
- * The first method of setting the domain is preferred because it is more
- * explicit; setting the domain using this second method should be used only
- * if brevity is required.
- *
- *
3. domain()
- *
- *
Invoking the domain method with no arguments returns the
- * current domain as an array of numbers.
- *
- * @function
- * @name pv.Scale.quantitative.prototype.domain
- * @param {number...} domain... domain values.
- * @returns {pv.Scale.quantitative} this, or the current domain.
- */
- scale.domain = function(array, min, max) {
- if (arguments.length) {
- var o; // the object we use to infer the domain type
- if (array instanceof Array) {
- if (arguments.length < 2) min = pv.identity;
- if (arguments.length < 3) max = min;
- o = array.length && min(array[0]);
- d = array.length ? [pv.min(array, min), pv.max(array, max)] : [];
- } else {
- o = array;
- d = Array.prototype.slice.call(arguments).map(Number);
- }
- if (!d.length) d = [-Infinity, Infinity];
- else if (d.length == 1) d = [d[0], d[0]];
- n = (d[0] || d[d.length - 1]) < 0;
- l = d.map(f);
- type = (o instanceof Date) ? newDate : Number;
- return this;
- }
- return d.map(type);
- };
-
- /**
- * Sets or gets the output range. This method can be invoked several ways:
- *
- *
1. range(min, ..., max)
- *
- *
The range may be specified as a series of numbers or colors. Most
- * commonly, two numbers are specified: the minimum and maximum pixel values.
- * For a color scale, values may be specified as {@link pv.Color}s or
- * equivalent strings. For a diverging scale, or other subdivided non-uniform
- * scales, multiple values can be specified. For example:
- *
- *
.range("red", "white", "green")
- *
- *
Currently, only numbers and colors are supported as range values. The
- * number of range values must exactly match the number of domain values, or
- * the behavior of the scale is undefined.
- *
- *
2. range()
- *
- *
Invoking the range method with no arguments returns the current
- * range as an array of numbers or colors.
- *
- * @function
- * @name pv.Scale.quantitative.prototype.range
- * @param {...} range... range values.
- * @returns {pv.Scale.quantitative} this, or the current range.
- */
- scale.range = function() {
- if (arguments.length) {
- r = Array.prototype.slice.call(arguments);
- if (!r.length) r = [-Infinity, Infinity];
- else if (r.length == 1) r = [r[0], r[0]];
- i = [];
- for (var j = 0; j < r.length - 1; j++) {
- i.push(pv.Scale.interpolator(r[j], r[j + 1]));
- }
- return this;
- }
- return r;
- };
-
- /**
- * Inverts the specified value in the output range, returning the
- * corresponding value in the input domain. This is frequently used to convert
- * the mouse location (see {@link pv.Mark#mouse}) to a value in the input
- * domain. Inversion is only supported for numeric ranges, and not colors.
- *
- *
Note that this method does not do any rounding or bounds checking. If
- * the input domain is discrete (e.g., an array index), the returned value
- * should be rounded. If the specified y value is outside the range,
- * the returned value may be equivalently outside the input domain.
- *
- * @function
- * @name pv.Scale.quantitative.prototype.invert
- * @param {number} y a value in the output range (a pixel location).
- * @returns {number} a value in the input domain.
- */
- scale.invert = function(y) {
- var j = pv.search(r, y);
- if (j < 0) j = -j - 2;
- j = Math.max(0, Math.min(i.length - 1, j));
- return type(g(l[j] + (y - r[j]) / (r[j + 1] - r[j]) * (l[j + 1] - l[j])));
- };
-
- /**
- * Returns an array of evenly-spaced, suitably-rounded values in the input
- * domain. This method attempts to return between 5 and 10 tick values. These
- * values are frequently used in conjunction with {@link pv.Rule} to display
- * tick marks or grid lines.
- *
- * @function
- * @name pv.Scale.quantitative.prototype.ticks
- * @param {number} [m] optional number of desired ticks.
- * @returns {number[]} an array input domain values to use as ticks.
- */
- scale.ticks = function(m) {
- var start = d[0],
- end = d[d.length - 1],
- reverse = end < start,
- min = reverse ? end : start,
- max = reverse ? start : end,
- span = max - min;
-
- /* Special case: empty, invalid or infinite span. */
- if (!span || !isFinite(span)) {
- if (type == newDate) tickFormat = pv.Format.date("%x");
- return [type(min)];
- }
-
- /* Special case: dates. */
- if (type == newDate) {
- /* Floor the date d given the precision p. */
- function floor(d, p) {
- switch (p) {
- case 31536e6: d.setMonth(0);
- case 2592e6: d.setDate(1);
- case 6048e5: if (p == 6048e5) d.setDate(d.getDate() - d.getDay());
- case 864e5: d.setHours(0);
- case 36e5: d.setMinutes(0);
- case 6e4: d.setSeconds(0);
- case 1e3: d.setMilliseconds(0);
- }
- }
-
- var precision, format, increment, step = 1;
- if (span >= 3 * 31536e6) {
- precision = 31536e6;
- format = "%Y";
- /** @ignore */ increment = function(d) { d.setFullYear(d.getFullYear() + step); };
- } else if (span >= 3 * 2592e6) {
- precision = 2592e6;
- format = "%m/%Y";
- /** @ignore */ increment = function(d) { d.setMonth(d.getMonth() + step); };
- } else if (span >= 3 * 6048e5) {
- precision = 6048e5;
- format = "%m/%d";
- /** @ignore */ increment = function(d) { d.setDate(d.getDate() + 7 * step); };
- } else if (span >= 3 * 864e5) {
- precision = 864e5;
- format = "%m/%d";
- /** @ignore */ increment = function(d) { d.setDate(d.getDate() + step); };
- } else if (span >= 3 * 36e5) {
- precision = 36e5;
- format = "%I:%M %p";
- /** @ignore */ increment = function(d) { d.setHours(d.getHours() + step); };
- } else if (span >= 3 * 6e4) {
- precision = 6e4;
- format = "%I:%M %p";
- /** @ignore */ increment = function(d) { d.setMinutes(d.getMinutes() + step); };
- } else if (span >= 3 * 1e3) {
- precision = 1e3;
- format = "%I:%M:%S";
- /** @ignore */ increment = function(d) { d.setSeconds(d.getSeconds() + step); };
- } else {
- precision = 1;
- format = "%S.%Qs";
- /** @ignore */ increment = function(d) { d.setTime(d.getTime() + step); };
- }
- tickFormat = pv.Format.date(format);
-
- var date = new Date(min), dates = [];
- floor(date, precision);
-
- /* If we'd generate too many ticks, skip some!. */
- var n = span / precision;
- if (n > 10) {
- switch (precision) {
- case 36e5: {
- step = (n > 20) ? 6 : 3;
- date.setHours(Math.floor(date.getHours() / step) * step);
- break;
- }
- case 2592e6: {
- step = 3; // seasons
- date.setMonth(Math.floor(date.getMonth() / step) * step);
- break;
- }
- case 6e4: {
- step = (n > 30) ? 15 : ((n > 15) ? 10 : 5);
- date.setMinutes(Math.floor(date.getMinutes() / step) * step);
- break;
- }
- case 1e3: {
- step = (n > 90) ? 15 : ((n > 60) ? 10 : 5);
- date.setSeconds(Math.floor(date.getSeconds() / step) * step);
- break;
- }
- case 1: {
- step = (n > 1000) ? 250 : ((n > 200) ? 100 : ((n > 100) ? 50 : ((n > 50) ? 25 : 5)));
- date.setMilliseconds(Math.floor(date.getMilliseconds() / step) * step);
- break;
- }
- default: {
- step = pv.logCeil(n / 15, 10);
- if (n / step < 2) step /= 5;
- else if (n / step < 5) step /= 2;
- date.setFullYear(Math.floor(date.getFullYear() / step) * step);
- break;
- }
- }
- }
-
- while (true) {
- increment(date);
- if (date > max) break;
- dates.push(new Date(date));
- }
- return reverse ? dates.reverse() : dates;
- }
-
- /* Normal case: numbers. */
- if (!arguments.length) m = 10;
- var step = pv.logFloor(span / m, 10),
- err = m / (span / step);
- if (err <= .15) step *= 10;
- else if (err <= .35) step *= 5;
- else if (err <= .75) step *= 2;
- var start = Math.ceil(min / step) * step,
- end = Math.floor(max / step) * step;
- tickFormat = pv.Format.number()
- .fractionDigits(Math.max(0, -Math.floor(pv.log(step, 10) + .01)));
- var ticks = pv.range(start, end + step, step);
- return reverse ? ticks.reverse() : ticks;
- };
-
- /**
- * Formats the specified tick value using the appropriate precision, based on
- * the step interval between tick marks. If {@link #ticks} has not been called,
- * the argument is converted to a string, but no formatting is applied.
- *
- * @function
- * @name pv.Scale.quantitative.prototype.tickFormat
- * @param {number} t a tick value.
- * @returns {string} a formatted tick value.
- */
- scale.tickFormat = function (t) { return tickFormat(t); };
-
- /**
- * "Nices" this scale, extending the bounds of the input domain to
- * evenly-rounded values. Nicing is useful if the domain is computed
- * dynamically from data, and may be irregular. For example, given a domain of
- * [0.20147987687960267, 0.996679553296417], a call to nice() might
- * extend the domain to [0.2, 1].
- *
- *
This method must be invoked each time after setting the domain.
- *
- * @function
- * @name pv.Scale.quantitative.prototype.nice
- * @returns {pv.Scale.quantitative} this.
- */
- scale.nice = function() {
- if (d.length != 2) return this; // TODO support non-uniform domains
- var start = d[0],
- end = d[d.length - 1],
- reverse = end < start,
- min = reverse ? end : start,
- max = reverse ? start : end,
- span = max - min;
-
- /* Special case: empty, invalid or infinite span. */
- if (!span || !isFinite(span)) return this;
-
- var step = Math.pow(10, Math.round(Math.log(span) / Math.log(10)) - 1);
- d = [Math.floor(min / step) * step, Math.ceil(max / step) * step];
- if (reverse) d.reverse();
- l = d.map(f);
- return this;
- };
-
- /**
- * Returns a view of this scale by the specified accessor function f.
- * Given a scale y, y.by(function(d) d.foo) is equivalent to
- * function(d) y(d.foo).
- *
- *
This method is provided for convenience, such that scales can be
- * succinctly defined inline. For example, given an array of data elements
- * that have a score attribute with the domain [0, 1], the height
- * property could be specified as:
- *
- *
- *
- * This method should be used judiciously; it is typically more clear to
- * invoke the scale directly, passing in the value to be scaled.
- *
- * @function
- * @name pv.Scale.quantitative.prototype.by
- * @param {function} f an accessor function.
- * @returns {pv.Scale.quantitative} a view of this scale by the specified
- * accessor function.
- */
- scale.by = function(f) {
- function by() { return scale(f.apply(this, arguments)); }
- for (var method in scale) by[method] = scale[method];
- return by;
- };
-
- scale.domain.apply(scale, arguments);
- return scale;
-};
-/**
- * Returns a linear scale for the specified domain. The arguments to this
- * constructor are optional, and equivalent to calling {@link #domain}.
- * The default domain and range are [0,1].
- *
- * @class Represents a linear scale; a function that performs a linear
- * transformation. Most
- * commonly, a linear scale represents a 1-dimensional linear transformation
- * from a numeric domain of input data [d0,
- * d1] to a numeric range of pixels [r0,
- * r1]. The equation for such a scale is:
- *
- *
f(x) = (x - d0) / (d1 - d0) *
- * (r1 - r0) + r0
- *
- * For example, a linear scale from the domain [0, 100] to range [0, 640]:
- *
- *
- *
- * Note that the scale is itself a function, and thus can be used as a property
- * directly, assuming that the data associated with a mark is a number. While
- * this is convenient for single-use scales, frequently it is desirable to
- * define scales globally:
- *
- *
var y = pv.Scale.linear(0, 100).range(0, 640);
- *
- * The y scale can now be equivalently referenced within a property:
- *
- *
.height(function(d) y(d))
- *
- * Alternatively, if the data are not simple numbers, the appropriate value can
- * be passed to the y scale (e.g., d.foo). The {@link #by}
- * method similarly allows the data to be mapped to a numeric value before
- * performing the linear transformation.
- *
- * @param {number...} domain... optional domain values.
- * @extends pv.Scale.quantitative
- */
-pv.Scale.linear = function() {
- var scale = pv.Scale.quantitative();
- scale.domain.apply(scale, arguments);
- return scale;
-};
-/**
- * Returns a log scale for the specified domain. The arguments to this
- * constructor are optional, and equivalent to calling {@link #domain}.
- * The default domain is [1,10] and the default range is [0,1].
- *
- * @class Represents a log scale. Most commonly, a log scale
- * represents a 1-dimensional log transformation from a numeric domain of input
- * data [d0, d1] to a numeric range of
- * pixels [r0, r1]. The equation for such a
- * scale is:
- *
- *
- *
- * where log(x) represents the zero-symmetric logarthim of x using
- * the scale's associated base (default: 10, see {@link pv.logSymmetric}). For
- * example, a log scale from the domain [1, 100] to range [0, 640]:
- *
- *
- *
- * Note that the scale is itself a function, and thus can be used as a property
- * directly, assuming that the data associated with a mark is a number. While
- * this is convenient for single-use scales, frequently it is desirable to
- * define scales globally:
- *
- *
var y = pv.Scale.log(1, 100).range(0, 640);
- *
- * The y scale can now be equivalently referenced within a property:
- *
- *
.height(function(d) y(d))
- *
- * Alternatively, if the data are not simple numbers, the appropriate value can
- * be passed to the y scale (e.g., d.foo). The {@link #by}
- * method similarly allows the data to be mapped to a numeric value before
- * performing the log transformation.
- *
- * @param {number...} domain... optional domain values.
- * @extends pv.Scale.quantitative
- */
-pv.Scale.log = function() {
- var scale = pv.Scale.quantitative(1, 10),
- b, // logarithm base
- p, // cached Math.log(b)
- /** @ignore */ log = function(x) { return Math.log(x) / p; },
- /** @ignore */ pow = function(y) { return Math.pow(b, y); };
-
- /**
- * Returns an array of evenly-spaced, suitably-rounded values in the input
- * domain. These values are frequently used in conjunction with
- * {@link pv.Rule} to display tick marks or grid lines.
- *
- * @function
- * @name pv.Scale.log.prototype.ticks
- * @returns {number[]} an array input domain values to use as ticks.
- */
- scale.ticks = function() {
- // TODO support non-uniform domains
- var d = scale.domain(),
- n = d[0] < 0,
- i = Math.floor(n ? -log(-d[0]) : log(d[0])),
- j = Math.ceil(n ? -log(-d[1]) : log(d[1])),
- ticks = [];
- if (n) {
- ticks.push(-pow(-i));
- for (; i++ < j;) for (var k = b - 1; k > 0; k--) ticks.push(-pow(-i) * k);
- } else {
- for (; i < j; i++) for (var k = 1; k < b; k++) ticks.push(pow(i) * k);
- ticks.push(pow(i));
- }
- for (i = 0; ticks[i] < d[0]; i++); // strip small values
- for (j = ticks.length; ticks[j - 1] > d[1]; j--); // strip big values
- return ticks.slice(i, j);
- };
-
- /**
- * Formats the specified tick value using the appropriate precision, assuming
- * base 10.
- *
- * @function
- * @name pv.Scale.log.prototype.tickFormat
- * @param {number} t a tick value.
- * @returns {string} a formatted tick value.
- */
- scale.tickFormat = function(t) {
- return t.toPrecision(1);
- };
-
- /**
- * "Nices" this scale, extending the bounds of the input domain to
- * evenly-rounded values. This method uses {@link pv.logFloor} and
- * {@link pv.logCeil}. Nicing is useful if the domain is computed dynamically
- * from data, and may be irregular. For example, given a domain of
- * [0.20147987687960267, 0.996679553296417], a call to nice() might
- * extend the domain to [0.1, 1].
- *
- *
This method must be invoked each time after setting the domain (and
- * base).
- *
- * @function
- * @name pv.Scale.log.prototype.nice
- * @returns {pv.Scale.log} this.
- */
- scale.nice = function() {
- // TODO support non-uniform domains
- var d = scale.domain();
- return scale.domain(pv.logFloor(d[0], b), pv.logCeil(d[1], b));
- };
-
- /**
- * Sets or gets the logarithm base. Defaults to 10.
- *
- * @function
- * @name pv.Scale.log.prototype.base
- * @param {number} [v] the new base.
- * @returns {pv.Scale.log} this, or the current base.
- */
- scale.base = function(v) {
- if (arguments.length) {
- b = Number(v);
- p = Math.log(b);
- scale.transform(log, pow); // update transformed domain
- return this;
- }
- return b;
- };
-
- scale.domain.apply(scale, arguments);
- return scale.base(10);
-};
-/**
- * Returns a root scale for the specified domain. The arguments to this
- * constructor are optional, and equivalent to calling {@link #domain}.
- * The default domain and range are [0,1].
- *
- * @class Represents a root scale; a function that performs a power
- * transformation. Most
- * commonly, a root scale represents a 1-dimensional root transformation from a
- * numeric domain of input data [d0, d1] to
- * a numeric range of pixels [r0, r1].
- *
- *
Note that the scale is itself a function, and thus can be used as a
- * property directly, assuming that the data associated with a mark is a
- * number. While this is convenient for single-use scales, frequently it is
- * desirable to define scales globally:
- *
- *
var y = pv.Scale.root(0, 100).range(0, 640);
- *
- * The y scale can now be equivalently referenced within a property:
- *
- *
.height(function(d) y(d))
- *
- * Alternatively, if the data are not simple numbers, the appropriate value can
- * be passed to the y scale (e.g., d.foo). The {@link #by}
- * method similarly allows the data to be mapped to a numeric value before
- * performing the root transformation.
- *
- * @param {number...} domain... optional domain values.
- * @extends pv.Scale.quantitative
- */
-pv.Scale.root = function() {
- var scale = pv.Scale.quantitative();
-
- /**
- * Sets or gets the exponent; defaults to 2.
- *
- * @function
- * @name pv.Scale.root.prototype.power
- * @param {number} [v] the new exponent.
- * @returns {pv.Scale.root} this, or the current base.
- */
- scale.power = function(v) {
- if (arguments.length) {
- var b = Number(v), p = 1 / b;
- scale.transform(
- function(x) { return Math.pow(x, p); },
- function(y) { return Math.pow(y, b); });
- return this;
- }
- return b;
- };
-
- scale.domain.apply(scale, arguments);
- return scale.power(2);
-};
-/**
- * Returns an ordinal scale for the specified domain. The arguments to this
- * constructor are optional, and equivalent to calling {@link #domain}.
- *
- * @class Represents an ordinal scale. An ordinal scale represents a
- * pairwise mapping from n discrete values in the input domain to
- * n discrete values in the output range. For example, an ordinal scale
- * might map a domain of species ["setosa", "versicolor", "virginica"] to colors
- * ["red", "green", "blue"]. Thus, saying
- *
- *
- *
- * If the mapping from species to color does not need to be specified
- * explicitly, the domain can be omitted. In this case it will be inferred
- * lazily from the data:
- *
- *
- *
- * When the domain is inferred, the first time the scale is invoked, the first
- * element from the range will be returned. Subsequent calls with unique values
- * will return subsequent elements from the range. If the inferred domain grows
- * larger than the range, range values will be reused. However, it is strongly
- * recommended that the domain and the range contain the same number of
- * elements.
- *
- *
A range can be discretized from a continuous interval (e.g., for pixel
- * positioning) by using {@link #split}, {@link #splitFlush} or
- * {@link #splitBanded} after the domain has been set. For example, if
- * states is an array of the fifty U.S. state names, the state name can
- * be encoded in the left position:
- *
- *
N.B.: ordinal scales are not invertible (at least not yet), since the
- * domain and range and discontinuous. A workaround is to use a linear scale.
- *
- * @param {...} domain... optional domain values.
- * @extends pv.Scale
- * @see pv.colors
- */
-pv.Scale.ordinal = function() {
- var d = [], i = {}, r = [], band = 0;
-
- /** @private */
- function scale(x) {
- if (!(x in i)) i[x] = d.push(x) - 1;
- return r[i[x] % r.length];
- }
-
- /**
- * Sets or gets the input domain. This method can be invoked several ways:
- *
- *
1. domain(values...)
- *
- *
Specifying the domain as a series of values is the most explicit and
- * recommended approach. However, if the domain values are derived from data,
- * you may find the second method more appropriate.
- *
- *
2. domain(array, f)
- *
- *
Rather than enumerating the domain values as explicit arguments to this
- * method, you can specify a single argument of an array. In addition, you can
- * specify an optional accessor function to extract the domain values from the
- * array.
- *
- *
3. domain()
- *
- *
Invoking the domain method with no arguments returns the
- * current domain as an array.
- *
- * @function
- * @name pv.Scale.ordinal.prototype.domain
- * @param {...} domain... domain values.
- * @returns {pv.Scale.ordinal} this, or the current domain.
- */
- scale.domain = function(array, f) {
- if (arguments.length) {
- array = (array instanceof Array)
- ? ((arguments.length > 1) ? pv.map(array, f) : array)
- : Array.prototype.slice.call(arguments);
-
- /* Filter the specified ordinals to their unique values. */
- d = [];
- var seen = {};
- for (var j = 0; j < array.length; j++) {
- var o = array[j];
- if (!(o in seen)) {
- seen[o] = true;
- d.push(o);
- }
- }
-
- i = pv.numerate(d);
- return this;
- }
- return d;
- };
-
- /**
- * Sets or gets the output range. This method can be invoked several ways:
- *
- *
1. range(values...)
- *
- *
Specifying the range as a series of values is the most explicit and
- * recommended approach. However, if the range values are derived from data,
- * you may find the second method more appropriate.
- *
- *
2. range(array, f)
- *
- *
Rather than enumerating the range values as explicit arguments to this
- * method, you can specify a single argument of an array. In addition, you can
- * specify an optional accessor function to extract the range values from the
- * array.
- *
- *
3. range()
- *
- *
Invoking the range method with no arguments returns the
- * current range as an array.
- *
- * @function
- * @name pv.Scale.ordinal.prototype.range
- * @param {...} range... range values.
- * @returns {pv.Scale.ordinal} this, or the current range.
- */
- scale.range = function(array, f) {
- if (arguments.length) {
- r = (array instanceof Array)
- ? ((arguments.length > 1) ? pv.map(array, f) : array)
- : Array.prototype.slice.call(arguments);
- if (typeof r[0] == "string") r = r.map(pv.color);
- return this;
- }
- return r;
- };
-
- /**
- * Sets the range from the given continuous interval. The interval
- * [min, max] is subdivided into n equispaced points,
- * where n is the number of (unique) values in the domain. The first
- * and last point are offset from the edge of the range by half the distance
- * between points.
- *
- *
This method must be called after the domain is set.
- *
- * @function
- * @name pv.Scale.ordinal.prototype.split
- * @param {number} min minimum value of the output range.
- * @param {number} max maximum value of the output range.
- * @returns {pv.Scale.ordinal} this.
- * @see #splitFlush
- * @see #splitBanded
- */
- scale.split = function(min, max) {
- var step = (max - min) / this.domain().length;
- r = pv.range(min + step / 2, max, step);
- return this;
- };
-
- /**
- * Sets the range from the given continuous interval. The interval
- * [min, max] is subdivided into n equispaced points,
- * where n is the number of (unique) values in the domain. The first
- * and last point are exactly on the edge of the range.
- *
- *
This method must be called after the domain is set.
- *
- * @function
- * @name pv.Scale.ordinal.prototype.splitFlush
- * @param {number} min minimum value of the output range.
- * @param {number} max maximum value of the output range.
- * @returns {pv.Scale.ordinal} this.
- * @see #split
- */
- scale.splitFlush = function(min, max) {
- var n = this.domain().length, step = (max - min) / (n - 1);
- r = (n == 1) ? [(min + max) / 2]
- : pv.range(min, max + step / 2, step);
- return this;
- };
-
- /**
- * Sets the range from the given continuous interval. The interval
- * [min, max] is subdivided into n equispaced bands,
- * where n is the number of (unique) values in the domain. The first
- * and last band are offset from the edge of the range by the distance between
- * bands.
- *
- *
The band width argument, band, is typically in the range [0, 1]
- * and defaults to 1. This fraction corresponds to the amount of space in the
- * range to allocate to the bands, as opposed to padding. A value of 0.5 means
- * that the band width will be equal to the padding width. The computed
- * absolute band width can be retrieved from the range as
- * scale.range().band.
- *
- *
If the band width argument is negative, this method will allocate bands
- * of a fixed width -band, rather than a relative fraction of
- * the available space.
- *
- *
Tip: to inset the bands by a fixed amount p, specify a minimum
- * value of min + p (or simply p, if min is
- * 0). Then set the mark width to scale.range().band - p.
- *
- *
This method must be called after the domain is set.
- *
- * @function
- * @name pv.Scale.ordinal.prototype.splitBanded
- * @param {number} min minimum value of the output range.
- * @param {number} max maximum value of the output range.
- * @param {number} [band] the fractional band width in [0, 1]; defaults to 1.
- * @returns {pv.Scale.ordinal} this.
- * @see #split
- */
- scale.splitBanded = function(min, max, band) {
- if (arguments.length < 3) band = 1;
- if (band < 0) {
- var n = this.domain().length,
- total = -band * n,
- remaining = max - min - total,
- padding = remaining / (n + 1);
- r = pv.range(min + padding, max, padding - band);
- r.band = -band;
- } else {
- var step = (max - min) / (this.domain().length + (1 - band));
- r = pv.range(min + step * (1 - band), max, step);
- r.band = step * band;
- }
- return this;
- };
-
- /**
- * Returns a view of this scale by the specified accessor function f.
- * Given a scale y, y.by(function(d) d.foo) is equivalent to
- * function(d) y(d.foo). This method should be used judiciously; it
- * is typically more clear to invoke the scale directly, passing in the value
- * to be scaled.
- *
- * @function
- * @name pv.Scale.ordinal.prototype.by
- * @param {function} f an accessor function.
- * @returns {pv.Scale.ordinal} a view of this scale by the specified accessor
- * function.
- */
- scale.by = function(f) {
- function by() { return scale(f.apply(this, arguments)); }
- for (var method in scale) by[method] = scale[method];
- return by;
- };
-
- scale.domain.apply(scale, arguments);
- return scale;
-};
-/**
- * Constructs a default quantile scale. The arguments to this constructor are
- * optional, and equivalent to calling {@link #domain}. The default domain is
- * the empty set, and the default range is [0,1].
- *
- * @class Represents a quantile scale; a function that maps from a value within
- * a sortable domain to a quantized numeric range. Typically, the domain is a
- * set of numbers, but any sortable value (such as strings) can be used as the
- * domain of a quantile scale. The range defaults to [0,1], with 0 corresponding
- * to the smallest value in the domain, 1 the largest, .5 the median, etc.
- *
- *
By default, the number of quantiles in the range corresponds to the number
- * of values in the domain. The {@link #quantiles} method can be used to specify
- * an explicit number of quantiles; for example, quantiles(4) produces
- * a standard quartile scale. A quartile scale's range is a set of four discrete
- * values, such as [0, 1/3, 2/3, 1]. Calling the {@link #range} method will
- * scale these discrete values accordingly, similar to {@link
- * pv.Scale.ordinal#splitFlush}.
- *
- *
For example, given the strings ["c", "a", "b"], a default quantile scale:
- *
- *
pv.Scale.quantile("c", "a", "b")
- *
- * will return 0 for "a", .5 for "b", and 1 for "c".
- *
- * @extends pv.Scale
- */
-pv.Scale.quantile = function() {
- var n = -1, // number of quantiles
- j = -1, // max quantile index
- q = [], // quantile boundaries
- d = [], // domain
- y = pv.Scale.linear(); // range
-
- /** @private */
- function scale(x) {
- return y(Math.max(0, Math.min(j, pv.search.index(q, x) - 1)) / j);
- }
-
- /**
- * Sets or gets the quantile boundaries. By default, each element in the
- * domain is in its own quantile. If the argument to this method is a number,
- * it specifies the number of equal-sized quantiles by which to divide the
- * domain.
- *
- *
If no arguments are specified, this method returns the quantile
- * boundaries; the first element is always the minimum value of the domain,
- * and the last element is the maximum value of the domain. Thus, the length
- * of the returned array is always one greater than the number of quantiles.
- *
- * @function
- * @name pv.Scale.quantile.prototype.quantiles
- * @param {number} x the number of quantiles.
- */
- scale.quantiles = function(x) {
- if (arguments.length) {
- n = Number(x);
- if (n < 0) {
- q = [d[0]].concat(d);
- j = d.length - 1;
- } else {
- q = [];
- q[0] = d[0];
- for (var i = 1; i <= n; i++) {
- q[i] = d[~~(i * (d.length - 1) / n)];
- }
- j = n - 1;
- }
- return this;
- }
- return q;
- };
-
- /**
- * Sets or gets the input domain. This method can be invoked several ways:
- *
- *
1. domain(values...)
- *
- *
Specifying the domain as a series of values is the most explicit and
- * recommended approach. However, if the domain values are derived from data,
- * you may find the second method more appropriate.
- *
- *
2. domain(array, f)
- *
- *
Rather than enumerating the domain values as explicit arguments to this
- * method, you can specify a single argument of an array. In addition, you can
- * specify an optional accessor function to extract the domain values from the
- * array.
- *
- *
3. domain()
- *
- *
Invoking the domain method with no arguments returns the
- * current domain as an array.
- *
- * @function
- * @name pv.Scale.quantile.prototype.domain
- * @param {...} domain... domain values.
- * @returns {pv.Scale.quantile} this, or the current domain.
- */
- scale.domain = function(array, f) {
- if (arguments.length) {
- d = (array instanceof Array)
- ? pv.map(array, f)
- : Array.prototype.slice.call(arguments);
- d.sort(pv.naturalOrder);
- scale.quantiles(n); // recompute quantiles
- return this;
- }
- return d;
- };
-
- /**
- * Sets or gets the output range. This method can be invoked several ways:
- *
- *
1. range(min, ..., max)
- *
- *
The range may be specified as a series of numbers or colors. Most
- * commonly, two numbers are specified: the minimum and maximum pixel values.
- * For a color scale, values may be specified as {@link pv.Color}s or
- * equivalent strings. For a diverging scale, or other subdivided non-uniform
- * scales, multiple values can be specified. For example:
- *
- *
.range("red", "white", "green")
- *
- *
Currently, only numbers and colors are supported as range values. The
- * number of range values must exactly match the number of domain values, or
- * the behavior of the scale is undefined.
- *
- *
2. range()
- *
- *
Invoking the range method with no arguments returns the current
- * range as an array of numbers or colors.
- *
- * @function
- * @name pv.Scale.quantile.prototype.range
- * @param {...} range... range values.
- * @returns {pv.Scale.quantile} this, or the current range.
- */
- scale.range = function() {
- if (arguments.length) {
- y.range.apply(y, arguments);
- return this;
- }
- return y.range();
- };
-
- /**
- * Returns a view of this scale by the specified accessor function f.
- * Given a scale y, y.by(function(d) d.foo) is equivalent to
- * function(d) y(d.foo).
- *
- *
This method is provided for convenience, such that scales can be
- * succinctly defined inline. For example, given an array of data elements
- * that have a score attribute with the domain [0, 1], the height
- * property could be specified as:
- *
- *
- *
- * This method should be used judiciously; it is typically more clear to
- * invoke the scale directly, passing in the value to be scaled.
- *
- * @function
- * @name pv.Scale.quantile.prototype.by
- * @param {function} f an accessor function.
- * @returns {pv.Scale.quantile} a view of this scale by the specified
- * accessor function.
- */
- scale.by = function(f) {
- function by() { return scale(f.apply(this, arguments)); }
- for (var method in scale) by[method] = scale[method];
- return by;
- };
-
- scale.domain.apply(scale, arguments);
- return scale;
-};
-/**
- * Returns a histogram operator for the specified data, with an optional
- * accessor function. If the data specified is not an array of numbers, an
- * accessor function must be specified to map the data to numeric values.
- *
- * @class Represents a histogram operator.
- *
- * @param {array} data an array of numbers or objects.
- * @param {function} [f] an optional accessor function.
- */
-pv.histogram = function(data, f) {
- var frequency = true;
- return {
-
- /**
- * Returns the computed histogram bins. An optional array of numbers,
- * ticks, may be specified as the break points. If the ticks are
- * not specified, default ticks will be computed using a linear scale on the
- * data domain.
- *
- *
The returned array contains {@link pv.histogram.Bin}s. The x
- * attribute corresponds to the bin's start value (inclusive), while the
- * dx attribute stores the bin size (end - start). The y
- * attribute stores either the frequency count or probability, depending on
- * how the histogram operator has been configured.
- *
- *
The {@link pv.histogram.Bin} objects are themselves arrays, containing
- * the data elements present in each bin, i.e., the elements in the
- * data array (prior to invoking the accessor function, if any).
- * For example, if the data represented countries, and the accessor function
- * returned the GDP of each country, the returned bins would be arrays of
- * countries (not GDPs).
- *
- * @function
- * @name pv.histogram.prototype.bins
- * @param {array} [ticks]
- * @returns {array}
- */ /** @private */
- bins: function(ticks) {
- var x = pv.map(data, f), bins = [];
-
- /* Initialize default ticks. */
- if (!arguments.length) ticks = pv.Scale.linear(x).ticks();
-
- /* Initialize the bins. */
- for (var i = 0; i < ticks.length - 1; i++) {
- var bin = bins[i] = [];
- bin.x = ticks[i];
- bin.dx = ticks[i + 1] - ticks[i];
- bin.y = 0;
- }
-
- /* Count the number of samples per bin. */
- for (var i = 0; i < x.length; i++) {
- var j = pv.search.index(ticks, x[i]) - 1,
- bin = bins[Math.max(0, Math.min(bins.length - 1, j))];
- bin.y++;
- bin.push(data[i]);
- }
-
- /* Convert frequencies to probabilities. */
- if (!frequency) for (var i = 0; i < bins.length; i++) {
- bins[i].y /= x.length;
- }
-
- return bins;
- },
-
- /**
- * Sets or gets whether this histogram operator returns frequencies or
- * probabilities.
- *
- * @function
- * @name pv.histogram.prototype.frequency
- * @param {boolean} [x]
- * @returns {pv.histogram} this.
- */ /** @private */
- frequency: function(x) {
- if (arguments.length) {
- frequency = Boolean(x);
- return this;
- }
- return frequency;
- }
- };
-};
-
-/**
- * @class Represents a bin returned by the {@link pv.histogram} operator. Bins
- * are themselves arrays containing the data elements present in the given bin
- * (prior to the accessor function being invoked to convert the data object to a
- * numeric value). These bin arrays have additional attributes with meta
- * information about the bin.
- *
- * @name pv.histogram.Bin
- * @extends array
- * @see pv.histogram
- */
-
-/**
- * The start value of the bin's range.
- *
- * @type number
- * @name pv.histogram.Bin.prototype.x
- */
-
-/**
- * The magnitude value of the bin's range; end - start.
- *
- * @type number
- * @name pv.histogram.Bin.prototype.dx
- */
-
-/**
- * The frequency or probability of the bin, depending on how the histogram
- * operator was configured.
- *
- * @type number
- * @name pv.histogram.Bin.prototype.y
- */
-/**
- * Returns the {@link pv.Color} for the specified color format string. Colors
- * may have an associated opacity, or alpha channel. Color formats are specified
- * by CSS Color Modular Level 3, using either in RGB or HSL color space. For
- * example:
- *
- *
#f00 // #rgb
- *
#ff0000 // #rrggbb
- *
rgb(255, 0, 0)
- *
rgb(100%, 0%, 0%)
- *
hsl(0, 100%, 50%)
- *
rgba(0, 0, 255, 0.5)
- *
hsla(120, 100%, 50%, 1)
- *
- *
The SVG 1.0 color keywords names are also supported, such as "aliceblue"
- * and "yellowgreen". The "transparent" keyword is supported for fully-
- * transparent black.
- *
- *
If the format argument is already an instance of Color,
- * the argument is returned with no further processing.
- *
- * @param {string} format the color specification string, such as "#f00".
- * @returns {pv.Color} the corresponding Color.
- * @see SVG color
- * keywords
- * @see CSS3 color module
- */
-pv.color = function(format) {
- if (format.rgb) return format.rgb();
-
- /* Handle hsl, rgb. */
- var m1 = /([a-z]+)\((.*)\)/i.exec(format);
- if (m1) {
- var m2 = m1[2].split(","), a = 1;
- switch (m1[1]) {
- case "hsla":
- case "rgba": {
- a = parseFloat(m2[3]);
- if (!a) return pv.Color.transparent;
- break;
- }
- }
- switch (m1[1]) {
- case "hsla":
- case "hsl": {
- var h = parseFloat(m2[0]), // degrees
- s = parseFloat(m2[1]) / 100, // percentage
- l = parseFloat(m2[2]) / 100; // percentage
- return (new pv.Color.Hsl(h, s, l, a)).rgb();
- }
- case "rgba":
- case "rgb": {
- function parse(c) { // either integer or percentage
- var f = parseFloat(c);
- return (c[c.length - 1] == '%') ? Math.round(f * 2.55) : f;
- }
- var r = parse(m2[0]), g = parse(m2[1]), b = parse(m2[2]);
- return pv.rgb(r, g, b, a);
- }
- }
- }
-
- /* Named colors. */
- var named = pv.Color.names[format];
- if (named) return named;
-
- /* Hexadecimal colors: #rgb and #rrggbb. */
- if (format.charAt(0) == "#") {
- var r, g, b;
- if (format.length == 4) {
- r = format.charAt(1); r += r;
- g = format.charAt(2); g += g;
- b = format.charAt(3); b += b;
- } else if (format.length == 7) {
- r = format.substring(1, 3);
- g = format.substring(3, 5);
- b = format.substring(5, 7);
- }
- return pv.rgb(parseInt(r, 16), parseInt(g, 16), parseInt(b, 16), 1);
- }
-
- /* Otherwise, pass-through unsupported colors. */
- return new pv.Color(format, 1);
-};
-
-/**
- * Constructs a color with the specified color format string and opacity. This
- * constructor should not be invoked directly; use {@link pv.color} instead.
- *
- * @class Represents an abstract (possibly translucent) color. The color is
- * divided into two parts: the color attribute, an opaque color format
- * string, and the opacity attribute, a float in [0, 1]. The color
- * space is dependent on the implementing class; all colors support the
- * {@link #rgb} method to convert to RGB color space for interpolation.
- *
- *
See also the Color guide.
- *
- * @param {string} color an opaque color format string, such as "#f00".
- * @param {number} opacity the opacity, in [0,1].
- * @see pv.color
- */
-pv.Color = function(color, opacity) {
- /**
- * An opaque color format string, such as "#f00".
- *
- * @type string
- * @see SVG color
- * keywords
- * @see CSS3 color module
- */
- this.color = color;
-
- /**
- * The opacity, a float in [0, 1].
- *
- * @type number
- */
- this.opacity = opacity;
-};
-
-/**
- * Returns a new color that is a brighter version of this color. The behavior of
- * this method may vary slightly depending on the underlying color space.
- * Although brighter and darker are inverse operations, the results of a series
- * of invocations of these two methods might be inconsistent because of rounding
- * errors.
- *
- * @param [k] {number} an optional scale factor; defaults to 1.
- * @see #darker
- * @returns {pv.Color} a brighter color.
- */
-pv.Color.prototype.brighter = function(k) {
- return this.rgb().brighter(k);
-};
-
-/**
- * Returns a new color that is a brighter version of this color. The behavior of
- * this method may vary slightly depending on the underlying color space.
- * Although brighter and darker are inverse operations, the results of a series
- * of invocations of these two methods might be inconsistent because of rounding
- * errors.
- *
- * @param [k] {number} an optional scale factor; defaults to 1.
- * @see #brighter
- * @returns {pv.Color} a darker color.
- */
-pv.Color.prototype.darker = function(k) {
- return this.rgb().darker(k);
-};
-
-/**
- * Constructs a new RGB color with the specified channel values.
- *
- * @param {number} r the red channel, an integer in [0,255].
- * @param {number} g the green channel, an integer in [0,255].
- * @param {number} b the blue channel, an integer in [0,255].
- * @param {number} [a] the alpha channel, a float in [0,1].
- * @returns pv.Color.Rgb
- */
-pv.rgb = function(r, g, b, a) {
- return new pv.Color.Rgb(r, g, b, (arguments.length == 4) ? a : 1);
-};
-
-/**
- * Constructs a new RGB color with the specified channel values.
- *
- * @class Represents a color in RGB space.
- *
- * @param {number} r the red channel, an integer in [0,255].
- * @param {number} g the green channel, an integer in [0,255].
- * @param {number} b the blue channel, an integer in [0,255].
- * @param {number} a the alpha channel, a float in [0,1].
- * @extends pv.Color
- */
-pv.Color.Rgb = function(r, g, b, a) {
- pv.Color.call(this, a ? ("rgb(" + r + "," + g + "," + b + ")") : "none", a);
-
- /**
- * The red channel, an integer in [0, 255].
- *
- * @type number
- */
- this.r = r;
-
- /**
- * The green channel, an integer in [0, 255].
- *
- * @type number
- */
- this.g = g;
-
- /**
- * The blue channel, an integer in [0, 255].
- *
- * @type number
- */
- this.b = b;
-
- /**
- * The alpha channel, a float in [0, 1].
- *
- * @type number
- */
- this.a = a;
-};
-pv.Color.Rgb.prototype = pv.extend(pv.Color);
-
-/**
- * Constructs a new RGB color with the same green, blue and alpha channels as
- * this color, with the specified red channel.
- *
- * @param {number} r the red channel, an integer in [0,255].
- */
-pv.Color.Rgb.prototype.red = function(r) {
- return pv.rgb(r, this.g, this.b, this.a);
-};
-
-/**
- * Constructs a new RGB color with the same red, blue and alpha channels as this
- * color, with the specified green channel.
- *
- * @param {number} g the green channel, an integer in [0,255].
- */
-pv.Color.Rgb.prototype.green = function(g) {
- return pv.rgb(this.r, g, this.b, this.a);
-};
-
-/**
- * Constructs a new RGB color with the same red, green and alpha channels as
- * this color, with the specified blue channel.
- *
- * @param {number} b the blue channel, an integer in [0,255].
- */
-pv.Color.Rgb.prototype.blue = function(b) {
- return pv.rgb(this.r, this.g, b, this.a);
-};
-
-/**
- * Constructs a new RGB color with the same red, green and blue channels as this
- * color, with the specified alpha channel.
- *
- * @param {number} a the alpha channel, a float in [0,1].
- */
-pv.Color.Rgb.prototype.alpha = function(a) {
- return pv.rgb(this.r, this.g, this.b, a);
-};
-
-/**
- * Returns the RGB color equivalent to this color. This method is abstract and
- * must be implemented by subclasses.
- *
- * @returns {pv.Color.Rgb} an RGB color.
- * @function
- * @name pv.Color.prototype.rgb
- */
-
-/**
- * Returns this.
- *
- * @returns {pv.Color.Rgb} this.
- */
-pv.Color.Rgb.prototype.rgb = function() { return this; };
-
-/**
- * Returns a new color that is a brighter version of this color. This method
- * applies an arbitrary scale factor to each of the three RGB components of this
- * color to create a brighter version of this color. Although brighter and
- * darker are inverse operations, the results of a series of invocations of
- * these two methods might be inconsistent because of rounding errors.
- *
- * @param [k] {number} an optional scale factor; defaults to 1.
- * @see #darker
- * @returns {pv.Color.Rgb} a brighter color.
- */
-pv.Color.Rgb.prototype.brighter = function(k) {
- k = Math.pow(0.7, arguments.length ? k : 1);
- var r = this.r, g = this.g, b = this.b, i = 30;
- if (!r && !g && !b) return pv.rgb(i, i, i, this.a);
- if (r && (r < i)) r = i;
- if (g && (g < i)) g = i;
- if (b && (b < i)) b = i;
- return pv.rgb(
- Math.min(255, Math.floor(r / k)),
- Math.min(255, Math.floor(g / k)),
- Math.min(255, Math.floor(b / k)),
- this.a);
-};
-
-/**
- * Returns a new color that is a darker version of this color. This method
- * applies an arbitrary scale factor to each of the three RGB components of this
- * color to create a darker version of this color. Although brighter and darker
- * are inverse operations, the results of a series of invocations of these two
- * methods might be inconsistent because of rounding errors.
- *
- * @param [k] {number} an optional scale factor; defaults to 1.
- * @see #brighter
- * @returns {pv.Color.Rgb} a darker color.
- */
-pv.Color.Rgb.prototype.darker = function(k) {
- k = Math.pow(0.7, arguments.length ? k : 1);
- return pv.rgb(
- Math.max(0, Math.floor(k * this.r)),
- Math.max(0, Math.floor(k * this.g)),
- Math.max(0, Math.floor(k * this.b)),
- this.a);
-};
-
-/**
- * Constructs a new HSL color with the specified values.
- *
- * @param {number} h the hue, an integer in [0, 360].
- * @param {number} s the saturation, a float in [0, 1].
- * @param {number} l the lightness, a float in [0, 1].
- * @param {number} [a] the opacity, a float in [0, 1].
- * @returns pv.Color.Hsl
- */
-pv.hsl = function(h, s, l, a) {
- return new pv.Color.Hsl(h, s, l, (arguments.length == 4) ? a : 1);
-};
-
-/**
- * Constructs a new HSL color with the specified values.
- *
- * @class Represents a color in HSL space.
- *
- * @param {number} h the hue, an integer in [0, 360].
- * @param {number} s the saturation, a float in [0, 1].
- * @param {number} l the lightness, a float in [0, 1].
- * @param {number} a the opacity, a float in [0, 1].
- * @extends pv.Color
- */
-pv.Color.Hsl = function(h, s, l, a) {
- pv.Color.call(this, "hsl(" + h + "," + (s * 100) + "%," + (l * 100) + "%)", a);
-
- /**
- * The hue, an integer in [0, 360].
- *
- * @type number
- */
- this.h = h;
-
- /**
- * The saturation, a float in [0, 1].
- *
- * @type number
- */
- this.s = s;
-
- /**
- * The lightness, a float in [0, 1].
- *
- * @type number
- */
- this.l = l;
-
- /**
- * The opacity, a float in [0, 1].
- *
- * @type number
- */
- this.a = a;
-};
-pv.Color.Hsl.prototype = pv.extend(pv.Color);
-
-/**
- * Constructs a new HSL color with the same saturation, lightness and alpha as
- * this color, and the specified hue.
- *
- * @param {number} h the hue, an integer in [0, 360].
- */
-pv.Color.Hsl.prototype.hue = function(h) {
- return pv.hsl(h, this.s, this.l, this.a);
-};
-
-/**
- * Constructs a new HSL color with the same hue, lightness and alpha as this
- * color, and the specified saturation.
- *
- * @param {number} s the saturation, a float in [0, 1].
- */
-pv.Color.Hsl.prototype.saturation = function(s) {
- return pv.hsl(this.h, s, this.l, this.a);
-};
-
-/**
- * Constructs a new HSL color with the same hue, saturation and alpha as this
- * color, and the specified lightness.
- *
- * @param {number} l the lightness, a float in [0, 1].
- */
-pv.Color.Hsl.prototype.lightness = function(l) {
- return pv.hsl(this.h, this.s, l, this.a);
-};
-
-/**
- * Constructs a new HSL color with the same hue, saturation and lightness as
- * this color, and the specified alpha.
- *
- * @param {number} a the opacity, a float in [0, 1].
- */
-pv.Color.Hsl.prototype.alpha = function(a) {
- return pv.hsl(this.h, this.s, this.l, a);
-};
-
-/**
- * Returns the RGB color equivalent to this HSL color.
- *
- * @returns {pv.Color.Rgb} an RGB color.
- */
-pv.Color.Hsl.prototype.rgb = function() {
- var h = this.h, s = this.s, l = this.l;
-
- /* Some simple corrections for h, s and l. */
- h = h % 360; if (h < 0) h += 360;
- s = Math.max(0, Math.min(s, 1));
- l = Math.max(0, Math.min(l, 1));
-
- /* From FvD 13.37, CSS Color Module Level 3 */
- var m2 = (l <= .5) ? (l * (1 + s)) : (l + s - l * s);
- var m1 = 2 * l - m2;
- function v(h) {
- if (h > 360) h -= 360;
- else if (h < 0) h += 360;
- if (h < 60) return m1 + (m2 - m1) * h / 60;
- if (h < 180) return m2;
- if (h < 240) return m1 + (m2 - m1) * (240 - h) / 60;
- return m1;
- }
- function vv(h) {
- return Math.round(v(h) * 255);
- }
-
- return pv.rgb(vv(h + 120), vv(h), vv(h - 120), this.a);
-};
-
-/**
- * @private SVG color keywords, per CSS Color Module Level 3.
- *
- * @see SVG color
- * keywords
- */
-pv.Color.names = {
- aliceblue: "#f0f8ff",
- antiquewhite: "#faebd7",
- aqua: "#00ffff",
- aquamarine: "#7fffd4",
- azure: "#f0ffff",
- beige: "#f5f5dc",
- bisque: "#ffe4c4",
- black: "#000000",
- blanchedalmond: "#ffebcd",
- blue: "#0000ff",
- blueviolet: "#8a2be2",
- brown: "#a52a2a",
- burlywood: "#deb887",
- cadetblue: "#5f9ea0",
- chartreuse: "#7fff00",
- chocolate: "#d2691e",
- coral: "#ff7f50",
- cornflowerblue: "#6495ed",
- cornsilk: "#fff8dc",
- crimson: "#dc143c",
- cyan: "#00ffff",
- darkblue: "#00008b",
- darkcyan: "#008b8b",
- darkgoldenrod: "#b8860b",
- darkgray: "#a9a9a9",
- darkgreen: "#006400",
- darkgrey: "#a9a9a9",
- darkkhaki: "#bdb76b",
- darkmagenta: "#8b008b",
- darkolivegreen: "#556b2f",
- darkorange: "#ff8c00",
- darkorchid: "#9932cc",
- darkred: "#8b0000",
- darksalmon: "#e9967a",
- darkseagreen: "#8fbc8f",
- darkslateblue: "#483d8b",
- darkslategray: "#2f4f4f",
- darkslategrey: "#2f4f4f",
- darkturquoise: "#00ced1",
- darkviolet: "#9400d3",
- deeppink: "#ff1493",
- deepskyblue: "#00bfff",
- dimgray: "#696969",
- dimgrey: "#696969",
- dodgerblue: "#1e90ff",
- firebrick: "#b22222",
- floralwhite: "#fffaf0",
- forestgreen: "#228b22",
- fuchsia: "#ff00ff",
- gainsboro: "#dcdcdc",
- ghostwhite: "#f8f8ff",
- gold: "#ffd700",
- goldenrod: "#daa520",
- gray: "#808080",
- green: "#008000",
- greenyellow: "#adff2f",
- grey: "#808080",
- honeydew: "#f0fff0",
- hotpink: "#ff69b4",
- indianred: "#cd5c5c",
- indigo: "#4b0082",
- ivory: "#fffff0",
- khaki: "#f0e68c",
- lavender: "#e6e6fa",
- lavenderblush: "#fff0f5",
- lawngreen: "#7cfc00",
- lemonchiffon: "#fffacd",
- lightblue: "#add8e6",
- lightcoral: "#f08080",
- lightcyan: "#e0ffff",
- lightgoldenrodyellow: "#fafad2",
- lightgray: "#d3d3d3",
- lightgreen: "#90ee90",
- lightgrey: "#d3d3d3",
- lightpink: "#ffb6c1",
- lightsalmon: "#ffa07a",
- lightseagreen: "#20b2aa",
- lightskyblue: "#87cefa",
- lightslategray: "#778899",
- lightslategrey: "#778899",
- lightsteelblue: "#b0c4de",
- lightyellow: "#ffffe0",
- lime: "#00ff00",
- limegreen: "#32cd32",
- linen: "#faf0e6",
- magenta: "#ff00ff",
- maroon: "#800000",
- mediumaquamarine: "#66cdaa",
- mediumblue: "#0000cd",
- mediumorchid: "#ba55d3",
- mediumpurple: "#9370db",
- mediumseagreen: "#3cb371",
- mediumslateblue: "#7b68ee",
- mediumspringgreen: "#00fa9a",
- mediumturquoise: "#48d1cc",
- mediumvioletred: "#c71585",
- midnightblue: "#191970",
- mintcream: "#f5fffa",
- mistyrose: "#ffe4e1",
- moccasin: "#ffe4b5",
- navajowhite: "#ffdead",
- navy: "#000080",
- oldlace: "#fdf5e6",
- olive: "#808000",
- olivedrab: "#6b8e23",
- orange: "#ffa500",
- orangered: "#ff4500",
- orchid: "#da70d6",
- palegoldenrod: "#eee8aa",
- palegreen: "#98fb98",
- paleturquoise: "#afeeee",
- palevioletred: "#db7093",
- papayawhip: "#ffefd5",
- peachpuff: "#ffdab9",
- peru: "#cd853f",
- pink: "#ffc0cb",
- plum: "#dda0dd",
- powderblue: "#b0e0e6",
- purple: "#800080",
- red: "#ff0000",
- rosybrown: "#bc8f8f",
- royalblue: "#4169e1",
- saddlebrown: "#8b4513",
- salmon: "#fa8072",
- sandybrown: "#f4a460",
- seagreen: "#2e8b57",
- seashell: "#fff5ee",
- sienna: "#a0522d",
- silver: "#c0c0c0",
- skyblue: "#87ceeb",
- slateblue: "#6a5acd",
- slategray: "#708090",
- slategrey: "#708090",
- snow: "#fffafa",
- springgreen: "#00ff7f",
- steelblue: "#4682b4",
- tan: "#d2b48c",
- teal: "#008080",
- thistle: "#d8bfd8",
- tomato: "#ff6347",
- turquoise: "#40e0d0",
- violet: "#ee82ee",
- wheat: "#f5deb3",
- white: "#ffffff",
- whitesmoke: "#f5f5f5",
- yellow: "#ffff00",
- yellowgreen: "#9acd32",
- transparent: pv.Color.transparent = pv.rgb(0, 0, 0, 0)
-};
-
-/* Initialized named colors. */
-(function() {
- var names = pv.Color.names;
- for (var name in names) names[name] = pv.color(names[name]);
-})();
-/**
- * Returns a new categorical color encoding using the specified colors. The
- * arguments to this method are an array of colors; see {@link pv.color}. For
- * example, to create a categorical color encoding using the species
- * attribute:
- *
- *
- *
- * The result of this expression can be used as a fill- or stroke-style
- * property. This assumes that the data's species attribute is a
- * string.
- *
- * @param {string} colors... categorical colors.
- * @see pv.Scale.ordinal
- * @returns {pv.Scale.ordinal} an ordinal color scale.
- */
-pv.colors = function() {
- var scale = pv.Scale.ordinal();
- scale.range.apply(scale, arguments);
- return scale;
-};
-
-/**
- * A collection of standard color palettes for categorical encoding.
- *
- * @namespace A collection of standard color palettes for categorical encoding.
- */
-pv.Colors = {};
-
-/**
- * Returns a new 10-color scheme. The arguments to this constructor are
- * optional, and equivalent to calling {@link pv.Scale.OrdinalScale#domain}. The
- * following colors are used:
- *
- *
#1f77b4
- *
#ff7f0e
- *
#2ca02c
- *
#d62728
- *
#9467bd
- *
#8c564b
- *
#e377c2
- *
#7f7f7f
- *
#bcbd22
- *
#17becf
- *
- * @param {number...} domain... domain values.
- * @returns {pv.Scale.ordinal} a new ordinal color scale.
- * @see pv.color
- */
-pv.Colors.category10 = function() {
- var scale = pv.colors(
- "#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd",
- "#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf");
- scale.domain.apply(scale, arguments);
- return scale;
-};
-
-/**
- * Returns a new 20-color scheme. The arguments to this constructor are
- * optional, and equivalent to calling {@link pv.Scale.OrdinalScale#domain}. The
- * following colors are used:
- *
- *
#1f77b4
- *
#aec7e8
- *
#ff7f0e
- *
#ffbb78
- *
#2ca02c
- *
#98df8a
- *
#d62728
- *
#ff9896
- *
#9467bd
- *
#c5b0d5
- *
#8c564b
- *
#c49c94
- *
#e377c2
- *
#f7b6d2
- *
#7f7f7f
- *
#c7c7c7
- *
#bcbd22
- *
#dbdb8d
- *
#17becf
- *
#9edae5
- *
- * @param {number...} domain... domain values.
- * @returns {pv.Scale.ordinal} a new ordinal color scale.
- * @see pv.color
-*/
-pv.Colors.category20 = function() {
- var scale = pv.colors(
- "#1f77b4", "#aec7e8", "#ff7f0e", "#ffbb78", "#2ca02c",
- "#98df8a", "#d62728", "#ff9896", "#9467bd", "#c5b0d5",
- "#8c564b", "#c49c94", "#e377c2", "#f7b6d2", "#7f7f7f",
- "#c7c7c7", "#bcbd22", "#dbdb8d", "#17becf", "#9edae5");
- scale.domain.apply(scale, arguments);
- return scale;
-};
-
-/**
- * Returns a new alternative 19-color scheme. The arguments to this constructor
- * are optional, and equivalent to calling
- * {@link pv.Scale.OrdinalScale#domain}. The following colors are used:
- *
- *
#9c9ede
- *
#7375b5
- *
#4a5584
- *
#cedb9c
- *
#b5cf6b
- *
#8ca252
- *
#637939
- *
#e7cb94
- *
#e7ba52
- *
#bd9e39
- *
#8c6d31
- *
#e7969c
- *
#d6616b
- *
#ad494a
- *
#843c39
- *
#de9ed6
- *
#ce6dbd
- *
#a55194
- *
#7b4173
- *
- * @param {number...} domain... domain values.
- * @returns {pv.Scale.ordinal} a new ordinal color scale.
- * @see pv.color
- */
-pv.Colors.category19 = function() {
- var scale = pv.colors(
- "#9c9ede", "#7375b5", "#4a5584", "#cedb9c", "#b5cf6b",
- "#8ca252", "#637939", "#e7cb94", "#e7ba52", "#bd9e39",
- "#8c6d31", "#e7969c", "#d6616b", "#ad494a", "#843c39",
- "#de9ed6", "#ce6dbd", "#a55194", "#7b4173");
- scale.domain.apply(scale, arguments);
- return scale;
-};
-/**
- * Returns a linear color ramp from the specified start color to the
- * specified end color. The color arguments may be specified either as
- * strings or as {@link pv.Color}s. This is equivalent to:
- *
- *
pv.Scale.linear().domain(0, 1).range(...)
- *
- * @param {string} start the start color; may be a pv.Color.
- * @param {string} end the end color; may be a pv.Color.
- * @returns {Function} a color ramp from start to end.
- * @see pv.Scale.linear
- */
-pv.ramp = function(start, end) {
- var scale = pv.Scale.linear();
- scale.range.apply(scale, arguments);
- return scale;
-};
-/**
- * @private
- * @namespace
- */
-pv.Scene = pv.SvgScene = {
- /* Various namespaces. */
- svg: "http://www.w3.org/2000/svg",
- xmlns: "http://www.w3.org/2000/xmlns",
- xlink: "http://www.w3.org/1999/xlink",
- xhtml: "http://www.w3.org/1999/xhtml",
-
- /** The pre-multipled scale, based on any enclosing transforms. */
- scale: 1,
-
- /** The set of supported events. */
- events: [
- "DOMMouseScroll", // for Firefox
- "mousewheel",
- "mousedown",
- "mouseup",
- "mouseover",
- "mouseout",
- "mousemove",
- "click",
- "dblclick"
- ],
-
- /** Implicit values for SVG and CSS properties. */
- implicit: {
- svg: {
- "shape-rendering": "auto",
- "pointer-events": "painted",
- "x": 0,
- "y": 0,
- "dy": 0,
- "text-anchor": "start",
- "transform": "translate(0,0)",
- "fill": "none",
- "fill-opacity": 1,
- "stroke": "none",
- "stroke-opacity": 1,
- "stroke-width": 1.5,
- "stroke-linejoin": "miter"
- },
- css: {
- "font": "10px sans-serif"
- }
- }
-};
-
-/**
- * Updates the display for the specified array of scene nodes.
- *
- * @param scenes {array} an array of scene nodes.
- */
-pv.SvgScene.updateAll = function(scenes) {
- if (scenes.length
- && scenes[0].reverse
- && (scenes.type != "line")
- && (scenes.type != "area")) {
- var reversed = pv.extend(scenes);
- for (var i = 0, j = scenes.length - 1; j >= 0; i++, j--) {
- reversed[i] = scenes[j];
- }
- scenes = reversed;
- }
- this.removeSiblings(this[scenes.type](scenes));
-};
-
-/**
- * Creates a new SVG element of the specified type.
- *
- * @param type {string} an SVG element type, such as "rect".
- * @returns a new SVG element.
- */
-pv.SvgScene.create = function(type) {
- return document.createElementNS(this.svg, type);
-};
-
-/**
- * Expects the element e to be the specified type. If the element does
- * not exist, a new one is created. If the element does exist but is the wrong
- * type, it is replaced with the specified element.
- *
- * @param e the current SVG element.
- * @param type {string} an SVG element type, such as "rect".
- * @param attributes an optional attribute map.
- * @param style an optional style map.
- * @returns a new SVG element.
- */
-pv.SvgScene.expect = function(e, type, attributes, style) {
- if (e) {
- if (e.tagName == "a") e = e.firstChild;
- if (e.tagName != type) {
- var n = this.create(type);
- e.parentNode.replaceChild(n, e);
- e = n;
- }
- } else {
- e = this.create(type);
- }
- for (var name in attributes) {
- var value = attributes[name];
- if (value == this.implicit.svg[name]) value = null;
- if (value == null) e.removeAttribute(name);
- else e.setAttribute(name, value);
- }
- for (var name in style) {
- var value = style[name];
- if (value == this.implicit.css[name]) value = null;
- if (value == null) e.style.removeProperty(name);
- else e.style[name] = value;
- }
- return e;
-};
-
-/** TODO */
-pv.SvgScene.append = function(e, scenes, index) {
- e.$scene = {scenes:scenes, index:index};
- e = this.title(e, scenes[index]);
- if (!e.parentNode) scenes.$g.appendChild(e);
- return e.nextSibling;
-};
-
-/**
- * Applies a title tooltip to the specified element e, using the
- * title property of the specified scene node s. Note that
- * this implementation does not create an SVG title element as a child
- * of e; although this is the recommended standard, it is only
- * supported in Opera. Instead, an anchor element is created around the element
- * e, and the xlink:title attribute is set accordingly.
- *
- * @param e an SVG element.
- * @param s a scene node.
- */
-pv.SvgScene.title = function(e, s) {
- var a = e.parentNode;
- if (a && (a.tagName != "a")) a = null;
- if (s.title) {
- if (!a) {
- a = this.create("a");
- if (e.parentNode) e.parentNode.replaceChild(a, e);
- a.appendChild(e);
- }
- a.setAttributeNS(this.xlink, "title", s.title);
- return a;
- }
- if (a) a.parentNode.replaceChild(e, a);
- return e;
-};
-
-/** TODO */
-pv.SvgScene.dispatch = pv.listener(function(e) {
- var t = e.target.$scene;
- if (t) {
- var type = e.type;
-
- /* Fixes for mousewheel support on Firefox & Opera. */
- switch (type) {
- case "DOMMouseScroll": {
- type = "mousewheel";
- e.wheel = -480 * e.detail;
- break;
- }
- case "mousewheel": {
- e.wheel = (window.opera ? 12 : 1) * e.wheelDelta;
- break;
- }
- }
-
- if (pv.Mark.dispatch(type, t.scenes, t.index)) e.preventDefault();
- }
-});
-
-/** @private Remove siblings following element e. */
-pv.SvgScene.removeSiblings = function(e) {
- while (e) {
- var n = e.nextSibling;
- e.parentNode.removeChild(e);
- e = n;
- }
-};
-
-/** @private Do nothing when rendering undefined mark types. */
-pv.SvgScene.undefined = function() {};
-/**
- * @private Converts the specified b-spline curve segment to a bezier curve
- * compatible with SVG "C".
- *
- * @param p0 the first control point.
- * @param p1 the second control point.
- * @param p2 the third control point.
- * @param p3 the fourth control point.
- */
-pv.SvgScene.pathBasis = (function() {
-
- /**
- * Matrix to transform basis (b-spline) control points to bezier control
- * points. Derived from FvD 11.2.8.
- */
- var basis = [
- [ 1/6, 2/3, 1/6, 0 ],
- [ 0, 2/3, 1/3, 0 ],
- [ 0, 1/3, 2/3, 0 ],
- [ 0, 1/6, 2/3, 1/6 ]
- ];
-
- /**
- * Returns the point that is the weighted sum of the specified control points,
- * using the specified weights. This method requires that there are four
- * weights and four control points.
- */
- function weight(w, p0, p1, p2, p3) {
- return {
- x: w[0] * p0.left + w[1] * p1.left + w[2] * p2.left + w[3] * p3.left,
- y: w[0] * p0.top + w[1] * p1.top + w[2] * p2.top + w[3] * p3.top
- };
- }
-
- var convert = function(p0, p1, p2, p3) {
- var b1 = weight(basis[1], p0, p1, p2, p3),
- b2 = weight(basis[2], p0, p1, p2, p3),
- b3 = weight(basis[3], p0, p1, p2, p3);
- return "C" + b1.x + "," + b1.y
- + "," + b2.x + "," + b2.y
- + "," + b3.x + "," + b3.y;
- };
-
- convert.segment = function(p0, p1, p2, p3) {
- var b0 = weight(basis[0], p0, p1, p2, p3),
- b1 = weight(basis[1], p0, p1, p2, p3),
- b2 = weight(basis[2], p0, p1, p2, p3),
- b3 = weight(basis[3], p0, p1, p2, p3);
- return "M" + b0.x + "," + b0.y
- + "C" + b1.x + "," + b1.y
- + "," + b2.x + "," + b2.y
- + "," + b3.x + "," + b3.y;
- };
-
- return convert;
-})();
-
-/**
- * @private Interpolates the given points using the basis spline interpolation.
- * Returns an SVG path without the leading M instruction to allow path
- * appending.
- *
- * @param points the array of points.
- */
-pv.SvgScene.curveBasis = function(points) {
- if (points.length <= 2) return "";
- var path = "",
- p0 = points[0],
- p1 = p0,
- p2 = p0,
- p3 = points[1];
- path += this.pathBasis(p0, p1, p2, p3);
- for (var i = 2; i < points.length; i++) {
- p0 = p1;
- p1 = p2;
- p2 = p3;
- p3 = points[i];
- path += this.pathBasis(p0, p1, p2, p3);
- }
- /* Cycle through to get the last point. */
- path += this.pathBasis(p1, p2, p3, p3);
- path += this.pathBasis(p2, p3, p3, p3);
- return path;
-};
-
-/**
- * @private Interpolates the given points using the basis spline interpolation.
- * If points.length == tangents.length then a regular Hermite interpolation is
- * performed, if points.length == tangents.length + 2 then the first and last
- * segments are filled in with cubic bazier segments. Returns an array of path
- * strings.
- *
- * @param points the array of points.
- */
-pv.SvgScene.curveBasisSegments = function(points) {
- if (points.length <= 2) return "";
- var paths = [],
- p0 = points[0],
- p1 = p0,
- p2 = p0,
- p3 = points[1],
- firstPath = this.pathBasis.segment(p0, p1, p2, p3);
-
- p0 = p1;
- p1 = p2;
- p2 = p3;
- p3 = points[2];
- paths.push(firstPath + this.pathBasis(p0, p1, p2, p3)); // merge first & second path
- for (var i = 3; i < points.length; i++) {
- p0 = p1;
- p1 = p2;
- p2 = p3;
- p3 = points[i];
- paths.push(this.pathBasis.segment(p0, p1, p2, p3));
- }
-
- // merge last & second-to-last path
- paths.push(this.pathBasis.segment(p1, p2, p3, p3) + this.pathBasis(p2, p3, p3, p3));
- return paths;
-};
-
-/**
- * @private Interpolates the given points with respective tangents using the cubic
- * Hermite spline interpolation. If points.length == tangents.length then a regular
- * Hermite interpolation is performed, if points.length == tangents.length + 2 then
- * the first and last segments are filled in with cubic bazier segments.
- * Returns an SVG path without the leading M instruction to allow path appending.
- *
- * @param points the array of points.
- * @param tangents the array of tangent vectors.
- */
-pv.SvgScene.curveHermite = function(points, tangents) {
- if (tangents.length < 1
- || (points.length != tangents.length
- && points.length != tangents.length + 2)) return "";
- var quad = points.length != tangents.length,
- path = "",
- p0 = points[0],
- p = points[1],
- t0 = tangents[0],
- t = t0,
- pi = 1;
-
- if (quad) {
- path += "Q" + (p.left - t0.x * 2 / 3) + "," + (p.top - t0.y * 2 / 3)
- + "," + p.left + "," + p.top;
- p0 = points[1];
- pi = 2;
- }
-
- if (tangents.length > 1) {
- t = tangents[1];
- p = points[pi];
- pi++;
- path += "C" + (p0.left + t0.x) + "," + (p0.top + t0.y)
- + "," + (p.left - t.x) + "," + (p.top - t.y)
- + "," + p.left + "," + p.top;
- for (var i = 2; i < tangents.length; i++, pi++) {
- p = points[pi];
- t = tangents[i];
- path += "S" + (p.left - t.x) + "," + (p.top - t.y)
- + "," + p.left + "," + p.top;
- }
- }
-
- if (quad) {
- var lp = points[pi];
- path += "Q" + (p.left + t.x * 2 / 3) + "," + (p.top + t.y * 2 / 3) + ","
- + lp.left + "," + lp.top;
- }
-
- return path;
-};
-
-/**
- * @private Interpolates the given points with respective tangents using the
- * cubic Hermite spline interpolation. Returns an array of path strings.
- *
- * @param points the array of points.
- * @param tangents the array of tangent vectors.
- */
-pv.SvgScene.curveHermiteSegments = function(points, tangents) {
- if (tangents.length < 1
- || (points.length != tangents.length
- && points.length != tangents.length + 2)) return [];
- var quad = points.length != tangents.length,
- paths = [],
- p0 = points[0],
- p = p0,
- t0 = tangents[0],
- t = t0,
- pi = 1;
-
- if (quad) {
- p = points[1];
- paths.push("M" + p0.left + "," + p0.top
- + "Q" + (p.left - t.x * 2 / 3) + "," + (p.top - t.y * 2 / 3)
- + "," + p.left + "," + p.top);
- pi = 2;
- }
-
- for (var i = 1; i < tangents.length; i++, pi++) {
- p0 = p;
- t0 = t;
- p = points[pi];
- t = tangents[i];
- paths.push("M" + p0.left + "," + p0.top
- + "C" + (p0.left + t0.x) + "," + (p0.top + t0.y)
- + "," + (p.left - t.x) + "," + (p.top - t.y)
- + "," + p.left + "," + p.top);
- }
-
- if (quad) {
- var lp = points[pi];
- paths.push("M" + p.left + "," + p.top
- + "Q" + (p.left + t.x * 2 / 3) + "," + (p.top + t.y * 2 / 3) + ","
- + lp.left + "," + lp.top);
- }
-
- return paths;
-};
-
-/**
- * @private Computes the tangents for the given points needed for cardinal
- * spline interpolation. Returns an array of tangent vectors. Note: that for n
- * points only the n-2 well defined tangents are returned.
- *
- * @param points the array of points.
- * @param tension the tension of hte cardinal spline.
- */
-pv.SvgScene.cardinalTangents = function(points, tension) {
- var tangents = [],
- a = (1 - tension) / 2,
- p0 = points[0],
- p1 = points[1],
- p2 = points[2];
-
- for (var i = 3; i < points.length; i++) {
- tangents.push({x: a * (p2.left - p0.left), y: a * (p2.top - p0.top)});
- p0 = p1;
- p1 = p2;
- p2 = points[i];
- }
-
- tangents.push({x: a * (p2.left - p0.left), y: a * (p2.top - p0.top)});
- return tangents;
-};
-
-/**
- * @private Interpolates the given points using cardinal spline interpolation.
- * Returns an SVG path without the leading M instruction to allow path
- * appending.
- *
- * @param points the array of points.
- * @param tension the tension of hte cardinal spline.
- */
-pv.SvgScene.curveCardinal = function(points, tension) {
- if (points.length <= 2) return "";
- return this.curveHermite(points, this.cardinalTangents(points, tension));
-};
-
-/**
- * @private Interpolates the given points using cardinal spline interpolation.
- * Returns an array of path strings.
- *
- * @param points the array of points.
- * @param tension the tension of hte cardinal spline.
- */
-pv.SvgScene.curveCardinalSegments = function(points, tension) {
- if (points.length <= 2) return "";
- return this.curveHermiteSegments(points, this.cardinalTangents(points, tension));
-};
-
-/**
- * @private Interpolates the given points using Fritsch-Carlson Monotone cubic
- * Hermite interpolation. Returns an array of tangent vectors.
- *
- * @param points the array of points.
- */
-pv.SvgScene.monotoneTangents = function(points) {
- var tangents = [],
- d = [],
- m = [],
- dx = [],
- k = 0;
-
- /* Compute the slopes of the secant lines between successive points. */
- for (k = 0; k < points.length-1; k++) {
- d[k] = (points[k+1].top - points[k].top)/(points[k+1].left - points[k].left);
- }
-
- /* Initialize the tangents at every point as the average of the secants. */
- m[0] = d[0];
- dx[0] = points[1].left - points[0].left;
- for (k = 1; k < points.length - 1; k++) {
- m[k] = (d[k-1]+d[k])/2;
- dx[k] = (points[k+1].left - points[k-1].left)/2;
- }
- m[k] = d[k-1];
- dx[k] = (points[k].left - points[k-1].left);
-
- /* Step 3. Very important, step 3. Yep. Wouldn't miss it. */
- for (k = 0; k < points.length - 1; k++) {
- if (d[k] == 0) {
- m[ k ] = 0;
- m[k+1] = 0;
- }
- }
-
- /* Step 4 + 5. Out of 5 or more steps. */
- for (k = 0; k < points.length - 1; k++) {
- if ((Math.abs(m[k]) < 1e-5) || (Math.abs(m[k+1]) < 1e-5)) continue;
- var ak = m[k] / d[k],
- bk = m[k + 1] / d[k],
- s = ak * ak + bk * bk; // monotone constant (?)
- if (s > 9) {
- var tk = 3 / Math.sqrt(s);
- m[k] = tk * ak * d[k];
- m[k + 1] = tk * bk * d[k];
- }
- }
-
- var len;
- for (var i = 0; i < points.length; i++) {
- len = 1 + m[i] * m[i]; // pv.vector(1, m[i]).norm().times(dx[i]/3)
- tangents.push({x: dx[i] / 3 / len, y: m[i] * dx[i] / 3 / len});
- }
-
- return tangents;
-};
-
-/**
- * @private Interpolates the given points using Fritsch-Carlson Monotone cubic
- * Hermite interpolation. Returns an SVG path without the leading M instruction
- * to allow path appending.
- *
- * @param points the array of points.
- */
-pv.SvgScene.curveMonotone = function(points) {
- if (points.length <= 2) return "";
- return this.curveHermite(points, this.monotoneTangents(points));
-}
-
-/**
- * @private Interpolates the given points using Fritsch-Carlson Monotone cubic
- * Hermite interpolation.
- * Returns an array of path strings.
- *
- * @param points the array of points.
- */
-pv.SvgScene.curveMonotoneSegments = function(points) {
- if (points.length <= 2) return "";
- return this.curveHermiteSegments(points, this.monotoneTangents(points));
-};
-pv.SvgScene.area = function(scenes) {
- var e = scenes.$g.firstChild;
- if (!scenes.length) return e;
- var s = scenes[0];
-
- /* segmented */
- if (s.segmented) return this.areaSegment(scenes);
-
- /* visible */
- if (!s.visible) return e;
- var fill = s.fillStyle, stroke = s.strokeStyle;
- if (!fill.opacity && !stroke.opacity) return e;
-
- /** @private Computes the straight path for the range [i, j]. */
- function path(i, j) {
- var p1 = [], p2 = [];
- for (var k = j; i <= k; i++, j--) {
- var si = scenes[i],
- sj = scenes[j],
- pi = si.left + "," + si.top,
- pj = (sj.left + sj.width) + "," + (sj.top + sj.height);
-
- /* interpolate */
- if (i < k) {
- var sk = scenes[i + 1], sl = scenes[j - 1];
- switch (s.interpolate) {
- case "step-before": {
- pi += "V" + sk.top;
- pj += "H" + (sl.left + sl.width);
- break;
- }
- case "step-after": {
- pi += "H" + sk.left;
- pj += "V" + (sl.top + sl.height);
- break;
- }
- }
- }
-
- p1.push(pi);
- p2.push(pj);
- }
- return p1.concat(p2).join("L");
- }
-
- /** @private Computes the curved path for the range [i, j]. */
- function pathCurve(i, j) {
- var pointsT = [], pointsB = [], pathT, pathB;
-
- for (var k = j; i <= k; i++, j--) {
- var sj = scenes[j];
- pointsT.push(scenes[i]);
- pointsB.push({left: sj.left + sj.width, top: sj.top + sj.height});
- }
-
- if (s.interpolate == "basis") {
- pathT = pv.SvgScene.curveBasis(pointsT);
- pathB = pv.SvgScene.curveBasis(pointsB);
- } else if (s.interpolate == "cardinal") {
- pathT = pv.SvgScene.curveCardinal(pointsT, s.tension);
- pathB = pv.SvgScene.curveCardinal(pointsB, s.tension);
- } else { // monotone
- pathT = pv.SvgScene.curveMonotone(pointsT);
- pathB = pv.SvgScene.curveMonotone(pointsB);
- }
-
- return pointsT[0].left + "," + pointsT[0].top + pathT
- + "L" + pointsB[0].left + "," + pointsB[0].top + pathB;
- }
-
- /* points */
- var d = [], si, sj;
- for (var i = 0; i < scenes.length; i++) {
- si = scenes[i]; if (!si.width && !si.height) continue;
- for (var j = i + 1; j < scenes.length; j++) {
- sj = scenes[j]; if (!sj.width && !sj.height) break;
- }
- if (i && (s.interpolate != "step-after")) i--;
- if ((j < scenes.length) && (s.interpolate != "step-before")) j++;
- d.push(((j - i > 2
- && (s.interpolate == "basis"
- || s.interpolate == "cardinal"
- || s.interpolate == "monotone"))
- ? pathCurve : path)(i, j - 1));
- i = j - 1;
- }
- if (!d.length) return e;
-
- e = this.expect(e, "path", {
- "shape-rendering": s.antialias ? null : "crispEdges",
- "pointer-events": s.events,
- "cursor": s.cursor,
- "d": "M" + d.join("ZM") + "Z",
- "fill": fill.color,
- "fill-opacity": fill.opacity || null,
- "stroke": stroke.color,
- "stroke-opacity": stroke.opacity || null,
- "stroke-width": stroke.opacity ? s.lineWidth / this.scale : null
- });
- return this.append(e, scenes, 0);
-};
-
-pv.SvgScene.areaSegment = function(scenes) {
- var e = scenes.$g.firstChild, s = scenes[0], pathsT, pathsB;
- if (s.interpolate == "basis"
- || s.interpolate == "cardinal"
- || s.interpolate == "monotone") {
- var pointsT = [], pointsB = [];
-
- for (var i = 0, n = scenes.length; i < n; i++) {
- var sj = scenes[n - i - 1];
- pointsT.push(scenes[i]);
- pointsB.push({left: sj.left + sj.width, top: sj.top + sj.height});
- }
-
- if (s.interpolate == "basis") {
- pathsT = this.curveBasisSegments(pointsT);
- pathsB = this.curveBasisSegments(pointsB);
- } else if (s.interpolate == "cardinal") {
- pathsT = this.curveCardinalSegments(pointsT, s.tension);
- pathsB = this.curveCardinalSegments(pointsB, s.tension);
- } else { // monotone
- pathsT = this.curveMonotoneSegments(pointsT);
- pathsB = this.curveMonotoneSegments(pointsB);
- }
- }
-
- for (var i = 0, n = scenes.length - 1; i < n; i++) {
- var s1 = scenes[i], s2 = scenes[i + 1];
-
- /* visible */
- if (!s1.visible || !s2.visible) continue;
- var fill = s1.fillStyle, stroke = s1.strokeStyle;
- if (!fill.opacity && !stroke.opacity) continue;
-
- var d;
- if (pathsT) {
- var pathT = pathsT[i],
- pathB = "L" + pathsB[n - i - 1].substr(1);
-
- d = pathT + pathB + "Z";
- } else {
- /* interpolate */
- var si = s1, sj = s2;
- switch (s1.interpolate) {
- case "step-before": si = s2; break;
- case "step-after": sj = s1; break;
- }
-
- /* path */
- d = "M" + s1.left + "," + si.top
- + "L" + s2.left + "," + sj.top
- + "L" + (s2.left + s2.width) + "," + (sj.top + sj.height)
- + "L" + (s1.left + s1.width) + "," + (si.top + si.height)
- + "Z";
- }
-
- e = this.expect(e, "path", {
- "shape-rendering": s1.antialias ? null : "crispEdges",
- "pointer-events": s1.events,
- "cursor": s1.cursor,
- "d": d,
- "fill": fill.color,
- "fill-opacity": fill.opacity || null,
- "stroke": stroke.color,
- "stroke-opacity": stroke.opacity || null,
- "stroke-width": stroke.opacity ? s1.lineWidth / this.scale : null
- });
- e = this.append(e, scenes, i);
- }
- return e;
-};
-pv.SvgScene.bar = function(scenes) {
- var e = scenes.$g.firstChild;
- for (var i = 0; i < scenes.length; i++) {
- var s = scenes[i];
-
- /* visible */
- if (!s.visible) continue;
- var fill = s.fillStyle, stroke = s.strokeStyle;
- if (!fill.opacity && !stroke.opacity) continue;
-
- e = this.expect(e, "rect", {
- "shape-rendering": s.antialias ? null : "crispEdges",
- "pointer-events": s.events,
- "cursor": s.cursor,
- "x": s.left,
- "y": s.top,
- "width": Math.max(1E-10, s.width),
- "height": Math.max(1E-10, s.height),
- "fill": fill.color,
- "fill-opacity": fill.opacity || null,
- "stroke": stroke.color,
- "stroke-opacity": stroke.opacity || null,
- "stroke-width": stroke.opacity ? s.lineWidth / this.scale : null
- });
- e = this.append(e, scenes, i);
- }
- return e;
-};
-pv.SvgScene.dot = function(scenes) {
- var e = scenes.$g.firstChild;
- for (var i = 0; i < scenes.length; i++) {
- var s = scenes[i];
-
- /* visible */
- if (!s.visible) continue;
- var fill = s.fillStyle, stroke = s.strokeStyle;
- if (!fill.opacity && !stroke.opacity) continue;
-
- /* points */
- var radius = s.radius, path = null;
- switch (s.shape) {
- case "cross": {
- path = "M" + -radius + "," + -radius
- + "L" + radius + "," + radius
- + "M" + radius + "," + -radius
- + "L" + -radius + "," + radius;
- break;
- }
- case "triangle": {
- var h1 = radius * 1.3333,
- h2 = radius * 0.6666,
- w = radius * 1.1547; // 2 / Math.sqrt(3)
- path = "M0," + h1
- + "L" + w +"," + -h2
- + " " + -w + "," + -h2
- + "Z";
- break;
- }
- case "diamond": {
- radius *= Math.SQRT2;
- path = "M0," + -radius
- + "L" + radius + ",0"
- + " 0," + radius
- + " " + -radius + ",0"
- + "Z";
- break;
- }
- case "square": {
- path = "M" + -radius + "," + -radius
- + "L" + radius + "," + -radius
- + " " + radius + "," + radius
- + " " + -radius + "," + radius
- + "Z";
- break;
- }
- case "tick": {
- path = "M0,0L0," + -s.size;
- break;
- }
- case "bar": {
- path = "M0," + (s.size / 2) + "L0," + -(s.size / 2);
- break;
- }
- }
-
- /* Use for circles, for everything else. */
- var svg = {
- "shape-rendering": s.antialias ? null : "crispEdges",
- "pointer-events": s.events,
- "cursor": s.cursor,
- "fill": fill.color,
- "fill-opacity": fill.opacity || null,
- "stroke": stroke.color,
- "stroke-opacity": stroke.opacity || null,
- "stroke-width": stroke.opacity ? s.lineWidth / this.scale : null
- };
- if (path) {
- svg.transform = "translate(" + s.left + "," + s.top + ")";
- if (s.angle) svg.transform += " rotate(" + 180 * s.angle / Math.PI + ")";
- svg.d = path;
- e = this.expect(e, "path", svg);
- } else {
- svg.cx = s.left;
- svg.cy = s.top;
- svg.r = radius;
- e = this.expect(e, "circle", svg);
- }
- e = this.append(e, scenes, i);
- }
- return e;
-};
-pv.SvgScene.image = function(scenes) {
- var e = scenes.$g.firstChild;
- for (var i = 0; i < scenes.length; i++) {
- var s = scenes[i];
-
- /* visible */
- if (!s.visible) continue;
-
- /* fill */
- e = this.fill(e, scenes, i);
-
- /* image */
- if (s.image) {
- e = this.expect(e, "foreignObject", {
- "cursor": s.cursor,
- "x": s.left,
- "y": s.top,
- "width": s.width,
- "height": s.height
- });
- var c = e.firstChild || e.appendChild(document.createElementNS(this.xhtml, "canvas"));
- c.$scene = {scenes:scenes, index:i};
- c.style.width = s.width;
- c.style.height = s.height;
- c.width = s.imageWidth;
- c.height = s.imageHeight;
- c.getContext("2d").putImageData(s.image, 0, 0);
- } else {
- e = this.expect(e, "image", {
- "preserveAspectRatio": "none",
- "cursor": s.cursor,
- "x": s.left,
- "y": s.top,
- "width": s.width,
- "height": s.height
- });
- e.setAttributeNS(this.xlink, "href", s.url);
- }
- e = this.append(e, scenes, i);
-
- /* stroke */
- e = this.stroke(e, scenes, i);
- }
- return e;
-};
-pv.SvgScene.label = function(scenes) {
- var e = scenes.$g.firstChild;
- for (var i = 0; i < scenes.length; i++) {
- var s = scenes[i];
-
- /* visible */
- if (!s.visible) continue;
- var fill = s.textStyle;
- if (!fill.opacity || !s.text) continue;
-
- /* text-baseline, text-align */
- var x = 0, y = 0, dy = 0, anchor = "start";
- switch (s.textBaseline) {
- case "middle": dy = ".35em"; break;
- case "top": dy = ".71em"; y = s.textMargin; break;
- case "bottom": y = "-" + s.textMargin; break;
- }
- switch (s.textAlign) {
- case "right": anchor = "end"; x = "-" + s.textMargin; break;
- case "center": anchor = "middle"; break;
- case "left": x = s.textMargin; break;
- }
-
- e = this.expect(e, "text", {
- "pointer-events": s.events,
- "cursor": s.cursor,
- "x": x,
- "y": y,
- "dy": dy,
- "transform": "translate(" + s.left + "," + s.top + ")"
- + (s.textAngle ? " rotate(" + 180 * s.textAngle / Math.PI + ")" : "")
- + (this.scale != 1 ? " scale(" + 1 / this.scale + ")" : ""),
- "fill": fill.color,
- "fill-opacity": fill.opacity || null,
- "text-anchor": anchor
- }, {
- "font": s.font,
- "text-shadow": s.textShadow,
- "text-decoration": s.textDecoration
- });
- if (e.firstChild) e.firstChild.nodeValue = s.text;
- else e.appendChild(document.createTextNode(s.text));
- e = this.append(e, scenes, i);
- }
- return e;
-};
-pv.SvgScene.line = function(scenes) {
- var e = scenes.$g.firstChild;
- if (scenes.length < 2) return e;
- var s = scenes[0];
-
- /* segmented */
- if (s.segmented) return this.lineSegment(scenes);
-
- /* visible */
- if (!s.visible) return e;
- var fill = s.fillStyle, stroke = s.strokeStyle;
- if (!fill.opacity && !stroke.opacity) return e;
-
- /* points */
- var d = "M" + s.left + "," + s.top;
-
- if (scenes.length > 2 && (s.interpolate == "basis" || s.interpolate == "cardinal" || s.interpolate == "monotone")) {
- switch (s.interpolate) {
- case "basis": d += this.curveBasis(scenes); break;
- case "cardinal": d += this.curveCardinal(scenes, s.tension); break;
- case "monotone": d += this.curveMonotone(scenes); break;
- }
- } else {
- for (var i = 1; i < scenes.length; i++) {
- d += this.pathSegment(scenes[i - 1], scenes[i]);
- }
- }
-
- e = this.expect(e, "path", {
- "shape-rendering": s.antialias ? null : "crispEdges",
- "pointer-events": s.events,
- "cursor": s.cursor,
- "d": d,
- "fill": fill.color,
- "fill-opacity": fill.opacity || null,
- "stroke": stroke.color,
- "stroke-opacity": stroke.opacity || null,
- "stroke-width": stroke.opacity ? s.lineWidth / this.scale : null,
- "stroke-linejoin": s.lineJoin
- });
- return this.append(e, scenes, 0);
-};
-
-pv.SvgScene.lineSegment = function(scenes) {
- var e = scenes.$g.firstChild;
-
- var s = scenes[0];
- var paths;
- switch (s.interpolate) {
- case "basis": paths = this.curveBasisSegments(scenes); break;
- case "cardinal": paths = this.curveCardinalSegments(scenes, s.tension); break;
- case "monotone": paths = this.curveMonotoneSegments(scenes); break;
- }
-
- for (var i = 0, n = scenes.length - 1; i < n; i++) {
- var s1 = scenes[i], s2 = scenes[i + 1];
-
- /* visible */
- if (!s1.visible || !s2.visible) continue;
- var stroke = s1.strokeStyle, fill = pv.Color.transparent;
- if (!stroke.opacity) continue;
-
- /* interpolate */
- var d;
- if ((s1.interpolate == "linear") && (s1.lineJoin == "miter")) {
- fill = stroke;
- stroke = pv.Color.transparent;
- d = this.pathJoin(scenes[i - 1], s1, s2, scenes[i + 2]);
- } else if(paths) {
- d = paths[i];
- } else {
- d = "M" + s1.left + "," + s1.top + this.pathSegment(s1, s2);
- }
-
- e = this.expect(e, "path", {
- "shape-rendering": s1.antialias ? null : "crispEdges",
- "pointer-events": s1.events,
- "cursor": s1.cursor,
- "d": d,
- "fill": fill.color,
- "fill-opacity": fill.opacity || null,
- "stroke": stroke.color,
- "stroke-opacity": stroke.opacity || null,
- "stroke-width": stroke.opacity ? s1.lineWidth / this.scale : null,
- "stroke-linejoin": s1.lineJoin
- });
- e = this.append(e, scenes, i);
- }
- return e;
-};
-
-/** @private Returns the path segment for the specified points. */
-pv.SvgScene.pathSegment = function(s1, s2) {
- var l = 1; // sweep-flag
- switch (s1.interpolate) {
- case "polar-reverse":
- l = 0;
- case "polar": {
- var dx = s2.left - s1.left,
- dy = s2.top - s1.top,
- e = 1 - s1.eccentricity,
- r = Math.sqrt(dx * dx + dy * dy) / (2 * e);
- if ((e <= 0) || (e > 1)) break; // draw a straight line
- return "A" + r + "," + r + " 0 0," + l + " " + s2.left + "," + s2.top;
- }
- case "step-before": return "V" + s2.top + "H" + s2.left;
- case "step-after": return "H" + s2.left + "V" + s2.top;
- }
- return "L" + s2.left + "," + s2.top;
-};
-
-/** @private Line-line intersection, per Akenine-Moller 16.16.1. */
-pv.SvgScene.lineIntersect = function(o1, d1, o2, d2) {
- return o1.plus(d1.times(o2.minus(o1).dot(d2.perp()) / d1.dot(d2.perp())));
-}
-
-/** @private Returns the miter join path for the specified points. */
-pv.SvgScene.pathJoin = function(s0, s1, s2, s3) {
- /*
- * P1-P2 is the current line segment. V is a vector that is perpendicular to
- * the line segment, and has length lineWidth / 2. ABCD forms the initial
- * bounding box of the line segment (i.e., the line segment if we were to do
- * no joins).
- */
- var p1 = pv.vector(s1.left, s1.top),
- p2 = pv.vector(s2.left, s2.top),
- p = p2.minus(p1),
- v = p.perp().norm(),
- w = v.times(s1.lineWidth / (2 * this.scale)),
- a = p1.plus(w),
- b = p2.plus(w),
- c = p2.minus(w),
- d = p1.minus(w);
-
- /*
- * Start join. P0 is the previous line segment's start point. We define the
- * cutting plane as the average of the vector perpendicular to P0-P1, and
- * the vector perpendicular to P1-P2. This insures that the cross-section of
- * the line on the cutting plane is equal if the line-width is unchanged.
- * Note that we don't implement miter limits, so these can get wild.
- */
- if (s0 && s0.visible) {
- var v1 = p1.minus(s0.left, s0.top).perp().norm().plus(v);
- d = this.lineIntersect(p1, v1, d, p);
- a = this.lineIntersect(p1, v1, a, p);
- }
-
- /* Similarly, for end join. */
- if (s3 && s3.visible) {
- var v2 = pv.vector(s3.left, s3.top).minus(p2).perp().norm().plus(v);
- c = this.lineIntersect(p2, v2, c, p);
- b = this.lineIntersect(p2, v2, b, p);
- }
-
- return "M" + a.x + "," + a.y
- + "L" + b.x + "," + b.y
- + " " + c.x + "," + c.y
- + " " + d.x + "," + d.y;
-};
-pv.SvgScene.panel = function(scenes) {
- var g = scenes.$g, e = g && g.firstChild;
- for (var i = 0; i < scenes.length; i++) {
- var s = scenes[i];
-
- /* visible */
- if (!s.visible) continue;
-
- /* svg */
- if (!scenes.parent) {
- s.canvas.style.display = "inline-block";
- if (g && (g.parentNode != s.canvas)) {
- g = s.canvas.firstChild;
- e = g && g.firstChild;
- }
- if (!g) {
- g = s.canvas.appendChild(this.create("svg"));
- g.setAttribute("font-size", "10px");
- g.setAttribute("font-family", "sans-serif");
- g.setAttribute("fill", "none");
- g.setAttribute("stroke", "none");
- g.setAttribute("stroke-width", 1.5);
- for (var j = 0; j < this.events.length; j++) {
- g.addEventListener(this.events[j], this.dispatch, false);
- }
- e = g.firstChild;
- }
- scenes.$g = g;
- g.setAttribute("width", s.width + s.left + s.right);
- g.setAttribute("height", s.height + s.top + s.bottom);
- }
-
- /* clip (nest children) */
- if (s.overflow == "hidden") {
- var id = pv.id().toString(36),
- c = this.expect(e, "g", {"clip-path": "url(#" + id + ")"});
- if (!c.parentNode) g.appendChild(c);
- scenes.$g = g = c;
- e = c.firstChild;
-
- e = this.expect(e, "clipPath", {"id": id});
- var r = e.firstChild || e.appendChild(this.create("rect"));
- r.setAttribute("x", s.left);
- r.setAttribute("y", s.top);
- r.setAttribute("width", s.width);
- r.setAttribute("height", s.height);
- if (!e.parentNode) g.appendChild(e);
- e = e.nextSibling;
- }
-
- /* fill */
- e = this.fill(e, scenes, i);
-
- /* transform (push) */
- var k = this.scale,
- t = s.transform,
- x = s.left + t.x,
- y = s.top + t.y;
- this.scale *= t.k;
-
- /* children */
- for (var j = 0; j < s.children.length; j++) {
- s.children[j].$g = e = this.expect(e, "g", {
- "transform": "translate(" + x + "," + y + ")"
- + (t.k != 1 ? " scale(" + t.k + ")" : "")
- });
- this.updateAll(s.children[j]);
- if (!e.parentNode) g.appendChild(e);
- e = e.nextSibling;
- }
-
- /* transform (pop) */
- this.scale = k;
-
- /* stroke */
- e = this.stroke(e, scenes, i);
-
- /* clip (restore group) */
- if (s.overflow == "hidden") {
- scenes.$g = g = c.parentNode;
- e = c.nextSibling;
- }
- }
- return e;
-};
-
-pv.SvgScene.fill = function(e, scenes, i) {
- var s = scenes[i], fill = s.fillStyle;
- if (fill.opacity || s.events == "all") {
- e = this.expect(e, "rect", {
- "shape-rendering": s.antialias ? null : "crispEdges",
- "pointer-events": s.events,
- "cursor": s.cursor,
- "x": s.left,
- "y": s.top,
- "width": s.width,
- "height": s.height,
- "fill": fill.color,
- "fill-opacity": fill.opacity,
- "stroke": null
- });
- e = this.append(e, scenes, i);
- }
- return e;
-};
-
-pv.SvgScene.stroke = function(e, scenes, i) {
- var s = scenes[i], stroke = s.strokeStyle;
- if (stroke.opacity || s.events == "all") {
- e = this.expect(e, "rect", {
- "shape-rendering": s.antialias ? null : "crispEdges",
- "pointer-events": s.events == "all" ? "stroke" : s.events,
- "cursor": s.cursor,
- "x": s.left,
- "y": s.top,
- "width": Math.max(1E-10, s.width),
- "height": Math.max(1E-10, s.height),
- "fill": null,
- "stroke": stroke.color,
- "stroke-opacity": stroke.opacity,
- "stroke-width": s.lineWidth / this.scale
- });
- e = this.append(e, scenes, i);
- }
- return e;
-};
-pv.SvgScene.rule = function(scenes) {
- var e = scenes.$g.firstChild;
- for (var i = 0; i < scenes.length; i++) {
- var s = scenes[i];
-
- /* visible */
- if (!s.visible) continue;
- var stroke = s.strokeStyle;
- if (!stroke.opacity) continue;
-
- e = this.expect(e, "line", {
- "shape-rendering": s.antialias ? null : "crispEdges",
- "pointer-events": s.events,
- "cursor": s.cursor,
- "x1": s.left,
- "y1": s.top,
- "x2": s.left + s.width,
- "y2": s.top + s.height,
- "stroke": stroke.color,
- "stroke-opacity": stroke.opacity,
- "stroke-width": s.lineWidth / this.scale
- });
- e = this.append(e, scenes, i);
- }
- return e;
-};
-pv.SvgScene.wedge = function(scenes) {
- var e = scenes.$g.firstChild;
- for (var i = 0; i < scenes.length; i++) {
- var s = scenes[i];
-
- /* visible */
- if (!s.visible) continue;
- var fill = s.fillStyle, stroke = s.strokeStyle;
- if (!fill.opacity && !stroke.opacity) continue;
-
- /* points */
- var r1 = s.innerRadius, r2 = s.outerRadius, a = Math.abs(s.angle), p;
- if (a >= 2 * Math.PI) {
- if (r1) {
- p = "M0," + r2
- + "A" + r2 + "," + r2 + " 0 1,1 0," + (-r2)
- + "A" + r2 + "," + r2 + " 0 1,1 0," + r2
- + "M0," + r1
- + "A" + r1 + "," + r1 + " 0 1,1 0," + (-r1)
- + "A" + r1 + "," + r1 + " 0 1,1 0," + r1
- + "Z";
- } else {
- p = "M0," + r2
- + "A" + r2 + "," + r2 + " 0 1,1 0," + (-r2)
- + "A" + r2 + "," + r2 + " 0 1,1 0," + r2
- + "Z";
- }
- } else {
- var sa = Math.min(s.startAngle, s.endAngle),
- ea = Math.max(s.startAngle, s.endAngle),
- c1 = Math.cos(sa), c2 = Math.cos(ea),
- s1 = Math.sin(sa), s2 = Math.sin(ea);
- if (r1) {
- p = "M" + r2 * c1 + "," + r2 * s1
- + "A" + r2 + "," + r2 + " 0 "
- + ((a < Math.PI) ? "0" : "1") + ",1 "
- + r2 * c2 + "," + r2 * s2
- + "L" + r1 * c2 + "," + r1 * s2
- + "A" + r1 + "," + r1 + " 0 "
- + ((a < Math.PI) ? "0" : "1") + ",0 "
- + r1 * c1 + "," + r1 * s1 + "Z";
- } else {
- p = "M" + r2 * c1 + "," + r2 * s1
- + "A" + r2 + "," + r2 + " 0 "
- + ((a < Math.PI) ? "0" : "1") + ",1 "
- + r2 * c2 + "," + r2 * s2 + "L0,0Z";
- }
- }
-
- e = this.expect(e, "path", {
- "shape-rendering": s.antialias ? null : "crispEdges",
- "pointer-events": s.events,
- "cursor": s.cursor,
- "transform": "translate(" + s.left + "," + s.top + ")",
- "d": p,
- "fill": fill.color,
- "fill-rule": "evenodd",
- "fill-opacity": fill.opacity || null,
- "stroke": stroke.color,
- "stroke-opacity": stroke.opacity || null,
- "stroke-width": stroke.opacity ? s.lineWidth / this.scale : null
- });
- e = this.append(e, scenes, i);
- }
- return e;
-};
-/**
- * Constructs a new mark with default properties. Marks, with the exception of
- * the root panel, are not typically constructed directly; instead, they are
- * added to a panel or an existing mark via {@link pv.Mark#add}.
- *
- * @class Represents a data-driven graphical mark. The Mark class is
- * the base class for all graphical marks in Protovis; it does not provide any
- * specific rendering functionality, but together with {@link Panel} establishes
- * the core framework.
- *
- *
Concrete mark types include familiar visual elements such as bars, lines
- * and labels. Although a bar mark may be used to construct a bar chart, marks
- * know nothing about charts; it is only through their specification and
- * composition that charts are produced. These building blocks permit many
- * combinatorial possibilities.
- *
- *
Marks are associated with data: a mark is generated once per
- * associated datum, mapping the datum to visual properties such as
- * position and color. Thus, a single mark specification represents a set of
- * visual elements that share the same data and visual encoding. The type of
- * mark defines the names of properties and their meaning. A property may be
- * static, ignoring the associated datum and returning a constant; or, it may be
- * dynamic, derived from the associated datum or index. Such dynamic encodings
- * can be specified succinctly using anonymous functions. Special properties
- * called event handlers can be registered to add interactivity.
- *
- *
Protovis uses inheritance to simplify the specification of related
- * marks: a new mark can be derived from an existing mark, inheriting its
- * properties. The new mark can then override properties to specify new
- * behavior, potentially in terms of the old behavior. In this way, the old mark
- * serves as the prototype for the new mark. Most mark types share the
- * same basic properties for consistency and to facilitate inheritance.
- *
- *
The prioritization of redundant properties is as follows:
- *
- *
If the width property is not specified (i.e., null), its value
- * is the width of the parent panel, minus this mark's left and right margins;
- * the left and right margins are zero if not specified.
- *
- *
Otherwise, if the right margin is not specified, its value is
- * the width of the parent panel, minus this mark's width and left margin; the
- * left margin is zero if not specified.
- *
- *
Otherwise, if the left property is not specified, its value is
- * the width of the parent panel, minus this mark's width and the right margin.
- *
- *
This prioritization is then duplicated for the height,
- * bottom and top properties, respectively.
- *
- *
While most properties are variable, some mark types, such as lines
- * and areas, generate a single visual element rather than a distinct visual
- * element per datum. With these marks, some properties may be fixed.
- * Fixed properties can vary per mark, but not per datum! These
- * properties are evaluated solely for the first (0-index) datum, and typically
- * are specified as a constant. However, it is valid to use a function if the
- * property varies between panels or is dynamically generated.
- *
- *
See also the Protovis guide.
- */
-pv.Mark = function() {
- /*
- * TYPE 0 constant defs
- * TYPE 1 function defs
- * TYPE 2 constant properties
- * TYPE 3 function properties
- * in order of evaluation!
- */
- this.$properties = [];
- this.$handlers = {};
-};
-
-/** @private Records which properties are defined on this mark type. */
-pv.Mark.prototype.properties = {};
-
-/** @private Records the cast function for each property. */
-pv.Mark.cast = {};
-
-/**
- * @private Defines and registers a property method for the property with the
- * given name. This method should be called on a mark class prototype to define
- * each exposed property. (Note this refers to the JavaScript
- * prototype, not the Protovis mark prototype, which is the {@link
- * #proto} field.)
- *
- *
The created property method supports several modes of invocation:
- *
- *
If invoked with a Function argument, this function is evaluated
- * for each associated datum. The return value of the function is used as the
- * computed property value. The context of the function (this) is this
- * mark. The arguments to the function are the associated data of this mark and
- * any enclosing panels. For example, a linear encoding of numerical data to
- * height is specified as
- *
- *
m.height(function(d) d * 100);
- *
- * The expression d * 100 will be evaluated for the height property of
- * each mark instance. The return value of the property method (e.g.,
- * m.height) is this mark (m)).
- *
- *
If invoked with a non-function argument, the property is treated as a
- * constant. The return value of the property method (e.g., m.height)
- * is this mark.
- *
- *
If invoked with no arguments, the computed property value for the current
- * mark instance in the scene graph is returned. This facilitates property
- * chaining, where one mark's properties are defined in terms of another's.
- * For example, to offset a mark's location from its prototype, you might say
- *
- *
m.top(function() this.proto.top() + 10);
- *
- * Note that the index of the mark being evaluated (in the above example,
- * this.proto) is inherited from the Mark class and set by
- * this mark. So, if the fifth element's top property is being evaluated, the
- * fifth instance of this.proto will similarly be queried for the value
- * of its top property. If the mark being evaluated has a different number of
- * instances, or its data is unrelated, the behavior of this method is
- * undefined. In these cases it may be better to index the scene
- * explicitly to specify the exact instance.
- *
- *
Property names should follow standard JavaScript method naming
- * conventions, using lowerCamel-style capitalization.
- *
- *
In addition to creating the property method, every property is registered
- * in the {@link #properties} map on the prototype. Although this is an
- * instance field, it is considered immutable and shared by all instances of a
- * given mark type. The properties map can be queried to see if a mark
- * type defines a particular property, such as width or height.
- *
- * @param {string} name the property name.
- * @param {function} [cast] the cast function for this property.
- */
-pv.Mark.prototype.property = function(name, cast) {
- if (!this.hasOwnProperty("properties")) {
- this.properties = pv.extend(this.properties);
- }
- this.properties[name] = true;
-
- /*
- * Define the setter-getter globally, since the default behavior should be the
- * same for all properties, and since the Protovis inheritance chain is
- * independent of the JavaScript inheritance chain. For example, anchors
- * define a "name" property that is evaluated on derived marks, even though
- * those marks don't normally have a name.
- */
- pv.Mark.prototype.propertyMethod(name, false, pv.Mark.cast[name] = cast);
- return this;
-};
-
-/**
- * @private Defines a setter-getter for the specified property.
- *
- *
If a cast function has been assigned to the specified property name, the
- * property function is wrapped by the cast function, or, if a constant is
- * specified, the constant is immediately cast. Note, however, that if the
- * property value is null, the cast function is not invoked.
- *
- * @param {string} name the property name.
- * @param {boolean} [def] whether is a property or a def.
- * @param {function} [cast] the cast function for this property.
- */
-pv.Mark.prototype.propertyMethod = function(name, def, cast) {
- if (!cast) cast = pv.Mark.cast[name];
- this[name] = function(v) {
-
- /* If this is a def, use it rather than property. */
- if (def && this.scene) {
- var defs = this.scene.defs;
- if (arguments.length) {
- defs[name] = {
- id: (v == null) ? 0 : pv.id(),
- value: ((v != null) && cast) ? cast(v) : v
- };
- return this;
- }
- return defs[name] ? defs[name].value : null;
- }
-
- /* If arguments are specified, set the property value. */
- if (arguments.length) {
- var type = !def << 1 | (typeof v == "function");
- this.propertyValue(name, (type & 1 && cast) ? function() {
- var x = v.apply(this, arguments);
- return (x != null) ? cast(x) : null;
- } : (((v != null) && cast) ? cast(v) : v)).type = type;
- return this;
- }
-
- return this.instance()[name];
- };
-};
-
-/** @private Sets the value of the property name to v. */
-pv.Mark.prototype.propertyValue = function(name, v) {
- var properties = this.$properties, p = {name: name, id: pv.id(), value: v};
- for (var i = 0; i < properties.length; i++) {
- if (properties[i].name == name) {
- properties.splice(i, 1);
- break;
- }
- }
- properties.push(p);
- return p;
-};
-
-/* Define all global properties. */
-pv.Mark.prototype
- .property("data")
- .property("visible", Boolean)
- .property("left", Number)
- .property("right", Number)
- .property("top", Number)
- .property("bottom", Number)
- .property("cursor", String)
- .property("title", String)
- .property("reverse", Boolean)
- .property("antialias", Boolean)
- .property("events", String);
-
-/**
- * The mark type; a lower camelCase name. The type name controls rendering
- * behavior, and unless the rendering engine is extended, must be one of the
- * built-in concrete mark types: area, bar, dot, image, label, line, panel,
- * rule, or wedge.
- *
- * @type string
- * @name pv.Mark.prototype.type
- */
-
-/**
- * The mark prototype, possibly undefined, from which to inherit property
- * functions. The mark prototype is not necessarily of the same type as this
- * mark. Any properties defined on this mark will override properties inherited
- * either from the prototype or from the type-specific defaults.
- *
- * @type pv.Mark
- * @name pv.Mark.prototype.proto
- */
-
-/**
- * The enclosing parent panel. The parent panel is generally undefined only for
- * the root panel; however, it is possible to create "offscreen" marks that are
- * used only for inheritance purposes.
- *
- * @type pv.Panel
- * @name pv.Mark.prototype.parent
- */
-
-/**
- * The child index. -1 if the enclosing parent panel is null; otherwise, the
- * zero-based index of this mark into the parent panel's children array.
- *
- * @type number
- */
-pv.Mark.prototype.childIndex = -1;
-
-/**
- * The mark index. The value of this field depends on which instance (i.e.,
- * which element of the data array) is currently being evaluated. During the
- * build phase, the index is incremented over each datum; when handling events,
- * the index is set to the instance that triggered the event.
- *
- * @type number
- */
-pv.Mark.prototype.index = -1;
-
-/**
- * The current scale factor, based on any enclosing transforms. The current
- * scale can be used to create scale-independent graphics. For example, to
- * define a dot that has a radius of 10 irrespective of any zooming, say:
- *
- *
dot.radius(function() 10 / this.scale)
- *
- * Note that the stroke width and font size are defined irrespective of scale
- * (i.e., in screen space) already. Also note that when a transform is applied
- * to a panel, the scale affects only the child marks, not the panel itself.
- *
- * @type number
- * @see pv.Panel#transform
- */
-pv.Mark.prototype.scale = 1;
-
-/**
- * @private The scene graph. The scene graph is an array of objects; each object
- * (or "node") corresponds to an instance of this mark and an element in the
- * data array. The scene graph can be traversed to lookup previously-evaluated
- * properties.
- *
- * @name pv.Mark.prototype.scene
- */
-
-/**
- * The root parent panel. This may be undefined for "offscreen" marks that are
- * created for inheritance purposes only.
- *
- * @type pv.Panel
- * @name pv.Mark.prototype.root
- */
-
-/**
- * The data property; an array of objects. The size of the array determines the
- * number of marks that will be instantiated; each element in the array will be
- * passed to property functions to compute the property values. Typically, the
- * data property is specified as a constant array, such as
- *
- *
m.data([1, 2, 3, 4, 5]);
- *
- * However, it is perfectly acceptable to define the data property as a
- * function. This function might compute the data dynamically, allowing
- * different data to be used per enclosing panel. For instance, in the stacked
- * area graph example (see {@link #scene}), the data function on the area mark
- * dereferences each series.
- *
- * @type array
- * @name pv.Mark.prototype.data
- */
-
-/**
- * The visible property; a boolean determining whether or not the mark instance
- * is visible. If a mark instance is not visible, its other properties will not
- * be evaluated. Similarly, for panels no child marks will be rendered.
- *
- * @type boolean
- * @name pv.Mark.prototype.visible
- */
-
-/**
- * The left margin; the distance, in pixels, between the left edge of the
- * enclosing panel and the left edge of this mark. Note that in some cases this
- * property may be redundant with the right property, or with the conjunction of
- * right and width.
- *
- * @type number
- * @name pv.Mark.prototype.left
- */
-
-/**
- * The right margin; the distance, in pixels, between the right edge of the
- * enclosing panel and the right edge of this mark. Note that in some cases this
- * property may be redundant with the left property, or with the conjunction of
- * left and width.
- *
- * @type number
- * @name pv.Mark.prototype.right
- */
-
-/**
- * The top margin; the distance, in pixels, between the top edge of the
- * enclosing panel and the top edge of this mark. Note that in some cases this
- * property may be redundant with the bottom property, or with the conjunction
- * of bottom and height.
- *
- * @type number
- * @name pv.Mark.prototype.top
- */
-
-/**
- * The bottom margin; the distance, in pixels, between the bottom edge of the
- * enclosing panel and the bottom edge of this mark. Note that in some cases
- * this property may be redundant with the top property, or with the conjunction
- * of top and height.
- *
- * @type number
- * @name pv.Mark.prototype.bottom
- */
-
-/**
- * The cursor property; corresponds to the CSS cursor property. This is
- * typically used in conjunction with event handlers to indicate interactivity.
- *
- * @type string
- * @name pv.Mark.prototype.cursor
- * @see CSS2 cursor
- */
-
-/**
- * The title property; corresponds to the HTML/SVG title property, allowing the
- * general of simple plain text tooltips.
- *
- * @type string
- * @name pv.Mark.prototype.title
- */
-
-/**
- * The events property; corresponds to the SVG pointer-events property,
- * specifying how the mark should participate in mouse events. The default value
- * is "painted". Supported values are:
- *
- *
"painted": The given mark may receive events when the mouse is over a
- * "painted" area. The painted areas are the interior (i.e., fill) of the mark
- * if a 'fillStyle' is specified, and the perimeter (i.e., stroke) of the mark
- * if a 'strokeStyle' is specified.
- *
- *
"all": The given mark may receive events when the mouse is over either the
- * interior (i.e., fill) or the perimeter (i.e., stroke) of the mark, regardless
- * of the specified fillStyle and strokeStyle.
- *
- *
"none": The given mark may not receive events.
- *
- * @type string
- * @name pv.Mark.prototype.events
- */
-
-/**
- * The reverse property; a boolean determining whether marks are ordered from
- * front-to-back or back-to-front. SVG does not support explicit z-ordering;
- * shapes are rendered in the order they appear. Thus, by default, marks are
- * rendered in data order. Setting the reverse property to false reverses the
- * order in which they are rendered; however, the properties are still evaluated
- * (i.e., built) in forward order.
- *
- * @type boolean
- * @name pv.Mark.prototype.reverse
- */
-
-/**
- * Default properties for all mark types. By default, the data array is the
- * parent data as a single-element array; if the data property is not specified,
- * this causes each mark to be instantiated as a singleton with the parents
- * datum. The visible property is true by default, and the reverse property is
- * false.
- *
- * @type pv.Mark
- */
-pv.Mark.prototype.defaults = new pv.Mark()
- .data(function(d) { return [d]; })
- .visible(true)
- .antialias(true)
- .events("painted");
-
-/**
- * Sets the prototype of this mark to the specified mark. Any properties not
- * defined on this mark may be inherited from the specified prototype mark, or
- * its prototype, and so on. The prototype mark need not be the same type of
- * mark as this mark. (Note that for inheritance to be useful, properties with
- * the same name on different mark types should have equivalent meaning.)
- *
- * @param {pv.Mark} proto the new prototype.
- * @returns {pv.Mark} this mark.
- * @see #add
- */
-pv.Mark.prototype.extend = function(proto) {
- this.proto = proto;
- return this;
-};
-
-/**
- * Adds a new mark of the specified type to the enclosing parent panel, whilst
- * simultaneously setting the prototype of the new mark to be this mark.
- *
- * @param {function} type the type of mark to add; a constructor, such as
- * pv.Bar.
- * @returns {pv.Mark} the new mark.
- * @see #extend
- */
-pv.Mark.prototype.add = function(type) {
- return this.parent.add(type).extend(this);
-};
-
-/**
- * Defines a custom property on this mark. Custom properties are currently
- * fixed, in that they are initialized once per mark set (i.e., per parent panel
- * instance). Custom properties can be used to store local state for the mark,
- * such as data needed by other properties (e.g., a custom scale) or interaction
- * state.
- *
- *
WARNING We plan on changing this feature in a future release to define
- * standard properties, as opposed to fixed properties that behave
- * idiosyncratically within event handlers. Furthermore, we recommend storing
- * state in an external data structure, rather than tying it to the
- * visualization specification as with defs.
- *
- * @param {string} name the name of the local variable.
- * @param {function} [v] an optional initializer; may be a constant or a
- * function.
- */
-pv.Mark.prototype.def = function(name, v) {
- this.propertyMethod(name, true);
- return this[name](arguments.length > 1 ? v : null);
-};
-
-/**
- * Returns an anchor with the specified name. All marks support the five
- * standard anchor names:
- *
- *
top
- *
left
- *
center
- *
bottom
- *
right
- *
- *
In addition to positioning properties (left, right, top bottom), the
- * anchors support text rendering properties (text-align, text-baseline). Text is
- * rendered to appear inside the mark by default.
- *
- *
To facilitate stacking, anchors are defined in terms of their opposite
- * edge. For example, the top anchor defines the bottom property, such that the
- * mark extends upwards; the bottom anchor instead defines the top property,
- * such that the mark extends downwards. See also {@link pv.Layout.Stack}.
- *
- *
While anchor names are typically constants, the anchor name is a true
- * property, which means you can specify a function to compute the anchor name
- * dynamically. See the {@link pv.Anchor#name} property for details.
- *
- * @param {string} name the anchor name; either a string or a property function.
- * @returns {pv.Anchor} the new anchor.
- */
-pv.Mark.prototype.anchor = function(name) {
- var target = this, scene;
-
- /* Default anchor name. */
- if (!name) name = "center";
-
- /** @private Find the instances of target that match source. */
- function instances(source) {
- var mark = target, index = [];
-
- /* Mirrored descent. */
- while (!(scene = mark.scene)) {
- source = source.parent;
- index.push({index: source.index, childIndex: mark.childIndex});
- mark = mark.parent;
- }
- while (index.length) {
- var i = index.pop();
- scene = scene[i.index].children[i.childIndex];
- }
-
- /*
- * When the anchor target is also an ancestor, as in the case of adding
- * to a panel anchor, only generate one instance per panel. Also, set
- * the margins to zero, since they are offset by the enclosing panel.
- */
- if (target.hasOwnProperty("index")) {
- var s = pv.extend(scene[target.index]);
- s.right = s.top = s.left = s.bottom = 0;
- return [s];
- }
- return scene;
- }
-
- return new pv.Anchor(this)
- .name(name)
- .def("$mark.anchor", function() {
- scene = this.scene.target = instances(this);
- })
- .data(function() {
- return scene.map(function(s) { return s.data; });
- })
- .visible(function() {
- return scene[this.index].visible;
- })
- .left(function() {
- var s = scene[this.index], w = s.width || 0;
- switch (this.name()) {
- case "bottom":
- case "top":
- case "center": return s.left + w / 2;
- case "left": return null;
- }
- return s.left + w;
- })
- .top(function() {
- var s = scene[this.index], h = s.height || 0;
- switch (this.name()) {
- case "left":
- case "right":
- case "center": return s.top + h / 2;
- case "top": return null;
- }
- return s.top + h;
- })
- .right(function() {
- var s = scene[this.index];
- return this.name() == "left" ? s.right + (s.width || 0) : null;
- })
- .bottom(function() {
- var s = scene[this.index];
- return this.name() == "top" ? s.bottom + (s.height || 0) : null;
- })
- .textAlign(function() {
- switch (this.name()) {
- case "bottom":
- case "top":
- case "center": return "center";
- case "right": return "right";
- }
- return "left";
- })
- .textBaseline(function() {
- switch (this.name()) {
- case "right":
- case "left":
- case "center": return "middle";
- case "top": return "top";
- }
- return "bottom";
- });
-};
-
-/**
- * Returns the anchor target of this mark, if it is derived from an anchor;
- * otherwise returns null. For example, if a label is derived from a bar anchor,
- *
- *
bar.anchor("top").add(pv.Label);
- *
- * then property functions on the label can refer to the bar via the
- * anchorTarget method. This method is also useful for mark types
- * defining properties on custom anchors.
- *
- * @returns {pv.Mark} the anchor target of this mark; possibly null.
- */
-pv.Mark.prototype.anchorTarget = function() {
- return this.proto.anchorTarget();
-};
-
-/**
- * Alias for setting the left, right, top and bottom properties simultaneously.
- *
- * @see #left
- * @see #right
- * @see #top
- * @see #bottom
- * @returns {pv.Mark} this.
- */
-pv.Mark.prototype.margin = function(n) {
- return this.left(n).right(n).top(n).bottom(n);
-};
-
-/**
- * @private Returns the current instance of this mark in the scene graph. This
- * is typically equivalent to this.scene[this.index], however if the
- * scene or index is unset, the default instance of the mark is returned. If no
- * default is set, the default is the last instance. Similarly, if the scene or
- * index of the parent panel is unset, the default instance of this mark in the
- * last instance of the enclosing panel is returned, and so on.
- *
- * @returns a node in the scene graph.
- */
-pv.Mark.prototype.instance = function(defaultIndex) {
- var scene = this.scene || this.parent.instance(-1).children[this.childIndex],
- index = !arguments.length || this.hasOwnProperty("index") ? this.index : defaultIndex;
- return scene[index < 0 ? scene.length - 1 : index];
-};
-
-/**
- * @private Returns the first instance of this mark in the scene graph. This
- * method can only be called when the mark is bound to the scene graph (for
- * example, from an event handler, or within a property function).
- *
- * @returns a node in the scene graph.
- */
-pv.Mark.prototype.first = function() {
- return this.scene[0];
-};
-
-/**
- * @private Returns the last instance of this mark in the scene graph. This
- * method can only be called when the mark is bound to the scene graph (for
- * example, from an event handler, or within a property function). In addition,
- * note that mark instances are built sequentially, so the last instance of this
- * mark may not yet be constructed.
- *
- * @returns a node in the scene graph.
- */
-pv.Mark.prototype.last = function() {
- return this.scene[this.scene.length - 1];
-};
-
-/**
- * @private Returns the previous instance of this mark in the scene graph, or
- * null if this is the first instance.
- *
- * @returns a node in the scene graph, or null.
- */
-pv.Mark.prototype.sibling = function() {
- return (this.index == 0) ? null : this.scene[this.index - 1];
-};
-
-/**
- * @private Returns the current instance in the scene graph of this mark, in the
- * previous instance of the enclosing parent panel. May return null if this
- * instance could not be found.
- *
- * @returns a node in the scene graph, or null.
- */
-pv.Mark.prototype.cousin = function() {
- var p = this.parent, s = p && p.sibling();
- return (s && s.children) ? s.children[this.childIndex][this.index] : null;
-};
-
-/**
- * Renders this mark, including recursively rendering all child marks if this is
- * a panel. This method finds all instances of this mark and renders them. This
- * method descends recursively to the level of the mark to be rendered, finding
- * all visible instances of the mark. After the marks are rendered, the scene
- * and index attributes are removed from the mark to restore them to a clean
- * state.
- *
- *
If an enclosing panel has an index property set (as is the case inside in
- * an event handler), then only instances of this mark inside the given instance
- * of the panel will be rendered; otherwise, all visible instances of the mark
- * will be rendered.
- */
-pv.Mark.prototype.render = function() {
- var parent = this.parent,
- stack = pv.Mark.stack;
-
- /* For the first render, take it from the top. */
- if (parent && !this.root.scene) {
- this.root.render();
- return;
- }
-
- /* Record the path to this mark. */
- var indexes = [];
- for (var mark = this; mark.parent; mark = mark.parent) {
- indexes.unshift(mark.childIndex);
- }
-
- /** @private */
- function render(mark, depth, scale) {
- mark.scale = scale;
- if (depth < indexes.length) {
- stack.unshift(null);
- if (mark.hasOwnProperty("index")) {
- renderInstance(mark, depth, scale);
- } else {
- for (var i = 0, n = mark.scene.length; i < n; i++) {
- mark.index = i;
- renderInstance(mark, depth, scale);
- }
- delete mark.index;
- }
- stack.shift();
- } else {
- mark.build();
-
- /*
- * In the update phase, the scene is rendered by creating and updating
- * elements and attributes in the SVG image. No properties are evaluated
- * during the update phase; instead the values computed previously in the
- * build phase are simply translated into SVG. The update phase is
- * decoupled (see pv.Scene) to allow different rendering engines.
- */
- pv.Scene.scale = scale;
- pv.Scene.updateAll(mark.scene);
- }
- delete mark.scale;
- }
-
- /**
- * @private Recursively renders the current instance of the specified mark.
- * This is slightly tricky because `index` and `scene` properties may or may
- * not already be set; if they are set, it means we are rendering only a
- * specific instance; if they are unset, we are rendering all instances.
- * Furthermore, we must preserve the original context of these properties when
- * rendering completes.
- *
- *
Another tricky aspect is that the `scene` attribute should be set for
- * any preceding children, so as to allow property chaining. This is
- * consistent with first-pass rendering.
- */
- function renderInstance(mark, depth, scale) {
- var s = mark.scene[mark.index], i;
- if (s.visible) {
- var childIndex = indexes[depth],
- child = mark.children[childIndex];
-
- /* Set preceding child scenes. */
- for (i = 0; i < childIndex; i++) {
- mark.children[i].scene = s.children[i];
- }
-
- /* Set current child scene, if necessary. */
- stack[0] = s.data;
- if (child.scene) {
- render(child, depth + 1, scale * s.transform.k);
- } else {
- child.scene = s.children[childIndex];
- render(child, depth + 1, scale * s.transform.k);
- delete child.scene;
- }
-
- /* Clear preceding child scenes. */
- for (i = 0; i < childIndex; i++) {
- delete mark.children[i].scene;
- }
- }
- }
-
- /* Bind this mark's property definitions. */
- this.bind();
-
- /* The render context is the first ancestor with an explicit index. */
- while (parent && !parent.hasOwnProperty("index")) parent = parent.parent;
-
- /* Recursively render all instances of this mark. */
- this.context(
- parent ? parent.scene : undefined,
- parent ? parent.index : -1,
- function() { render(this.root, 0, 1); });
-};
-
-/** @private Stores the current data stack. */
-pv.Mark.stack = [];
-
-/**
- * @private In the bind phase, inherited property definitions are cached so they
- * do not need to be queried during build.
- */
-pv.Mark.prototype.bind = function() {
- var seen = {}, types = [[], [], [], []], data, visible;
-
- /** Scans the proto chain for the specified mark. */
- function bind(mark) {
- do {
- var properties = mark.$properties;
- for (var i = properties.length - 1; i >= 0 ; i--) {
- var p = properties[i];
- if (!(p.name in seen)) {
- seen[p.name] = p;
- switch (p.name) {
- case "data": data = p; break;
- case "visible": visible = p; break;
- default: types[p.type].push(p); break;
- }
- }
- }
- } while (mark = mark.proto);
- }
-
- /* Scan the proto chain for all defined properties. */
- bind(this);
- bind(this.defaults);
- types[1].reverse();
- types[3].reverse();
-
- /* Any undefined properties are null. */
- var mark = this;
- do for (var name in mark.properties) {
- if (!(name in seen)) {
- types[2].push(seen[name] = {name: name, type: 2, value: null});
- }
- } while (mark = mark.proto);
-
- /* Define setter-getter for inherited defs. */
- var defs = types[0].concat(types[1]);
- for (var i = 0; i < defs.length; i++) {
- this.propertyMethod(defs[i].name, true);
- }
-
- /* Setup binds to evaluate constants before functions. */
- this.binds = {
- properties: seen,
- data: data,
- defs: defs,
- required: [visible],
- optional: pv.blend(types)
- };
-};
-
-/**
- * @private Evaluates properties and computes implied properties. Properties are
- * stored in the {@link #scene} array for each instance of this mark.
- *
- *
As marks are built recursively, the {@link #index} property is updated to
- * match the current index into the data array for each mark. Note that the
- * index property is only set for the mark currently being built and its
- * enclosing parent panels. The index property for other marks is unset, but is
- * inherited from the global Mark class prototype. This allows mark
- * properties to refer to properties on other marks in the same panel
- * conveniently; however, in general it is better to reference mark instances
- * specifically through the scene graph rather than depending on the magical
- * behavior of {@link #index}.
- *
- *
The root scene array has a special property, data, which stores
- * the current data stack. The first element in this stack is the current datum,
- * followed by the datum of the enclosing parent panel, and so on. The data
- * stack should not be accessed directly; instead, property functions are passed
- * the current data stack as arguments.
- *
- *
The evaluation of the data and visible properties is
- * special. The data property is evaluated first; unlike the other
- * properties, the data stack is from the parent panel, rather than the current
- * mark, since the data is not defined until the data property is evaluated.
- * The visisble property is subsequently evaluated for each instance;
- * only if true will the {@link #buildInstance} method be called, evaluating
- * other properties and recursively building the scene graph.
- *
- *
If this mark is being re-built, any old instances of this mark that no
- * longer exist (because the new data array contains fewer elements) will be
- * cleared using {@link #clearInstance}.
- *
- * @param parent the instance of the parent panel from the scene graph.
- */
-pv.Mark.prototype.build = function() {
- var scene = this.scene, stack = pv.Mark.stack;
- if (!scene) {
- scene = this.scene = [];
- scene.mark = this;
- scene.type = this.type;
- scene.childIndex = this.childIndex;
- if (this.parent) {
- scene.parent = this.parent.scene;
- scene.parentIndex = this.parent.index;
- }
- }
-
- /* Evaluate defs. */
- if (this.binds.defs.length) {
- var defs = scene.defs;
- if (!defs) scene.defs = defs = {};
- for (var i = 0; i < this.binds.defs.length; i++) {
- var p = this.binds.defs[i], d = defs[p.name];
- if (!d || (p.id > d.id)) {
- defs[p.name] = {
- id: 0, // this def will be re-evaluated on next build
- value: (p.type & 1) ? p.value.apply(this, stack) : p.value
- };
- }
- }
- }
-
- /* Evaluate special data property. */
- var data = this.binds.data;
- data = data.type & 1 ? data.value.apply(this, stack) : data.value;
-
- /* Create, update and delete scene nodes. */
- stack.unshift(null);
- scene.length = data.length;
- for (var i = 0; i < data.length; i++) {
- pv.Mark.prototype.index = this.index = i;
- var s = scene[i];
- if (!s) scene[i] = s = {};
- s.data = stack[0] = data[i];
- this.buildInstance(s);
- }
- pv.Mark.prototype.index = -1;
- delete this.index;
- stack.shift();
-
- return this;
-};
-
-/**
- * @private Evaluates the specified array of properties for the specified
- * instance s in the scene graph.
- *
- * @param s a node in the scene graph; the instance of the mark to build.
- * @param properties an array of properties.
- */
-pv.Mark.prototype.buildProperties = function(s, properties) {
- for (var i = 0, n = properties.length; i < n; i++) {
- var p = properties[i], v = p.value; // assume case 2 (constant)
- switch (p.type) {
- case 0:
- case 1: v = this.scene.defs[p.name].value; break;
- case 3: v = v.apply(this, pv.Mark.stack); break;
- }
- s[p.name] = v;
- }
-};
-
-/**
- * @private Evaluates all of the properties for this mark for the specified
- * instance s in the scene graph. The set of properties to evaluate is
- * retrieved from the {@link #properties} array for this mark type (see {@link
- * #type}). After these properties are evaluated, any implied properties
- * may be computed by the mark and set on the scene graph; see
- * {@link #buildImplied}.
- *
- *
For panels, this method recursively builds the scene graph for all child
- * marks as well. In general, this method should not need to be overridden by
- * concrete mark types.
- *
- * @param s a node in the scene graph; the instance of the mark to build.
- */
-pv.Mark.prototype.buildInstance = function(s) {
- this.buildProperties(s, this.binds.required);
- if (s.visible) {
- this.buildProperties(s, this.binds.optional);
- this.buildImplied(s);
- }
-};
-
-/**
- * @private Computes the implied properties for this mark for the specified
- * instance s in the scene graph. Implied properties are those with
- * dependencies on multiple other properties; for example, the width property
- * may be implied if the left and right properties are set. This method can be
- * overridden by concrete mark types to define new implied properties, if
- * necessary.
- *
- * @param s a node in the scene graph; the instance of the mark to build.
- */
-pv.Mark.prototype.buildImplied = function(s) {
- var l = s.left;
- var r = s.right;
- var t = s.top;
- var b = s.bottom;
-
- /* Assume width and height are zero if not supported by this mark type. */
- var p = this.properties;
- var w = p.width ? s.width : 0;
- var h = p.height ? s.height : 0;
-
- /* Compute implied width, right and left. */
- var width = this.parent ? this.parent.width() : (w + l + r);
- if (w == null) {
- w = width - (r = r || 0) - (l = l || 0);
- } else if (r == null) {
- r = width - w - (l = l || 0);
- } else if (l == null) {
- l = width - w - (r = r || 0);
- }
-
- /* Compute implied height, bottom and top. */
- var height = this.parent ? this.parent.height() : (h + t + b);
- if (h == null) {
- h = height - (t = t || 0) - (b = b || 0);
- } else if (b == null) {
- b = height - h - (t = t || 0);
- } else if (t == null) {
- t = height - h - (b = b || 0);
- }
-
- s.left = l;
- s.right = r;
- s.top = t;
- s.bottom = b;
-
- /* Only set width and height if they are supported by this mark type. */
- if (p.width) s.width = w;
- if (p.height) s.height = h;
-
- /* Set any null colors to pv.Color.transparent. */
- if (p.textStyle && !s.textStyle) s.textStyle = pv.Color.transparent;
- if (p.fillStyle && !s.fillStyle) s.fillStyle = pv.Color.transparent;
- if (p.strokeStyle && !s.strokeStyle) s.strokeStyle = pv.Color.transparent;
-};
-
-/**
- * Returns the current location of the mouse (cursor) relative to this mark's
- * parent. The x coordinate corresponds to the left margin, while the
- * y coordinate corresponds to the top margin.
- *
- * @returns {pv.Vector} the mouse location.
- */
-pv.Mark.prototype.mouse = function() {
-
- /* Compute xy-coordinates relative to the panel. */
- var x = pv.event.pageX || 0,
- y = pv.event.pageY || 0,
- n = this.root.canvas();
- do {
- x -= n.offsetLeft;
- y -= n.offsetTop;
- } while (n = n.offsetParent);
-
- /* Compute the inverse transform of all enclosing panels. */
- var t = pv.Transform.identity,
- p = this.properties.transform ? this : this.parent,
- pz = [];
- do { pz.push(p); } while (p = p.parent);
- while (p = pz.pop()) t = t.translate(p.left(), p.top()).times(p.transform());
- t = t.invert();
-
- return pv.vector(x * t.k + t.x, y * t.k + t.y);
-};
-
-/**
- * Registers an event handler for the specified event type with this mark. When
- * an event of the specified type is triggered, the specified handler will be
- * invoked. The handler is invoked in a similar method to property functions:
- * the context is this mark instance, and the arguments are the full
- * data stack. Event handlers can use property methods to manipulate the display
- * properties of the mark:
- *
- *
- *
- * The return value of the event handler determines which mark gets re-rendered.
- * Use defs ({@link #def}) to set temporary state from event handlers.
- *
- *
The complete set of event types is defined by SVG; see the reference
- * below. The set of supported event types is:
- *
- *
click
- *
mousedown
- *
mouseup
- *
mouseover
- *
mousemove
- *
mouseout
- *
- *
Since Protovis does not specify any concept of focus, it does not
- * support key events; these should be handled outside the visualization using
- * standard JavaScript. In the future, support for interaction may be extended
- * to support additional event types, particularly those most relevant to
- * interactive visualization, such as selection.
- *
- *
TODO In the current implementation, event handlers are not inherited from
- * prototype marks. They must be defined explicitly on each interactive mark. In
- * addition, only one event handler for a given event type can be defined; when
- * specifying multiple event handlers for the same type, only the last one will
- * be used.
- *
- * @see SVG events
- * @param {string} type the event type.
- * @param {function} handler the event handler.
- * @returns {pv.Mark} this.
- */
-pv.Mark.prototype.event = function(type, handler) {
- this.$handlers[type] = pv.functor(handler);
- return this;
-};
-
-/** @private Evaluates the function f with the specified context. */
-pv.Mark.prototype.context = function(scene, index, f) {
- var proto = pv.Mark.prototype,
- stack = pv.Mark.stack,
- oscene = pv.Mark.scene,
- oindex = proto.index;
-
- /** @private Sets the context. */
- function apply(scene, index) {
- pv.Mark.scene = scene;
- proto.index = index;
- if (!scene) return;
-
- var that = scene.mark,
- mark = that,
- ancestors = [];
-
- /* Set ancestors' scene and index; populate data stack. */
- do {
- ancestors.push(mark);
- stack.push(scene[index].data);
- mark.index = index;
- mark.scene = scene;
- index = scene.parentIndex;
- scene = scene.parent;
- } while (mark = mark.parent);
-
- /* Set ancestors' scale; requires top-down. */
- for (var i = ancestors.length - 1, k = 1; i > 0; i--) {
- mark = ancestors[i];
- mark.scale = k;
- k *= mark.scene[mark.index].transform.k;
- }
-
- /* Set children's scene and scale. */
- if (that.children) for (var i = 0, n = that.children.length; i < n; i++) {
- mark = that.children[i];
- mark.scene = that.scene[that.index].children[i];
- mark.scale = k;
- }
- }
-
- /** @private Clears the context. */
- function clear(scene, index) {
- if (!scene) return;
- var that = scene.mark,
- mark;
-
- /* Reset children. */
- if (that.children) for (var i = 0, n = that.children.length; i < n; i++) {
- mark = that.children[i];
- delete mark.scene;
- delete mark.scale;
- }
-
- /* Reset ancestors. */
- mark = that;
- do {
- stack.pop();
- if (mark.parent) {
- delete mark.scene;
- delete mark.scale;
- }
- delete mark.index;
- } while (mark = mark.parent);
- }
-
- /* Context switch, invoke the function, then switch back. */
- clear(oscene, oindex);
- apply(scene, index);
- try {
- f.apply(this, stack);
- } finally {
- clear(scene, index);
- apply(oscene, oindex);
- }
-};
-
-/** @private Execute the event listener, then re-render. */
-pv.Mark.dispatch = function(type, scene, index) {
- var m = scene.mark, p = scene.parent, l = m.$handlers[type];
- if (!l) return p && pv.Mark.dispatch(type, p, scene.parentIndex);
- m.context(scene, index, function() {
- m = l.apply(m, pv.Mark.stack);
- if (m && m.render) m.render();
- });
- return true;
-};
-/**
- * Constructs a new mark anchor with default properties.
- *
- * @class Represents an anchor on a given mark. An anchor is itself a mark, but
- * without a visual representation. It serves only to provide useful default
- * properties that can be inherited by other marks. Each type of mark can define
- * any number of named anchors for convenience. If the concrete mark type does
- * not define an anchor implementation specifically, one will be inherited from
- * the mark's parent class.
- *
- *
For example, the bar mark provides anchors for its four sides: left,
- * right, top and bottom. Adding a label to the top anchor of a bar,
- *
- *
bar.anchor("top").add(pv.Label);
- *
- * will render a text label on the top edge of the bar; the top anchor defines
- * the appropriate position properties (top and left), as well as text-rendering
- * properties for convenience (textAlign and textBaseline).
- *
- *
Note that anchors do not inherit from their targets; the positional
- * properties are copied from the scene graph, which guarantees that the anchors
- * are positioned correctly, even if the positional properties are not defined
- * deterministically. (In addition, it also improves performance by avoiding
- * re-evaluating expensive properties.) If you want the anchor to inherit from
- * the target, use {@link pv.Mark#extend} before adding. For example:
- *
- *
bar.anchor("top").extend(bar).add(pv.Label);
- *
- * The anchor defines it's own positional properties, but other properties (such
- * as the title property, say) can be inherited using the above idiom. Also note
- * that you can override positional properties in the anchor for custom
- * behavior.
- *
- * @extends pv.Mark
- * @param {pv.Mark} target the anchor target.
- */
-pv.Anchor = function(target) {
- pv.Mark.call(this);
- this.target = target;
- this.parent = target.parent;
-};
-
-pv.Anchor.prototype = pv.extend(pv.Mark)
- .property("name", String);
-
-/**
- * The anchor name. The set of supported anchor names is dependent on the
- * concrete mark type; see the mark type for details. For example, bars support
- * left, right, top and bottom anchors.
- *
- *
While anchor names are typically constants, the anchor name is a true
- * property, which means you can specify a function to compute the anchor name
- * dynamically. For instance, if you wanted to alternate top and bottom anchors,
- * saying
- *
- *
- *
- * would have the desired effect.
- *
- * @type string
- * @name pv.Anchor.prototype.name
- */
-
-/**
- * Returns the anchor target of this mark, if it is derived from an anchor;
- * otherwise returns null. For example, if a label is derived from a bar anchor,
- *
- *
bar.anchor("top").add(pv.Label);
- *
- * then property functions on the label can refer to the bar via the
- * anchorTarget method. This method is also useful for mark types
- * defining properties on custom anchors.
- *
- * @returns {pv.Mark} the anchor target of this mark; possibly null.
- */
-pv.Anchor.prototype.anchorTarget = function() {
- return this.target;
-};
-/**
- * Constructs a new area mark with default properties. Areas are not typically
- * constructed directly, but by adding to a panel or an existing mark via
- * {@link pv.Mark#add}.
- *
- * @class Represents an area mark: the solid area between two series of
- * connected line segments. Unsurprisingly, areas are used most frequently for
- * area charts.
- *
- *
Just as a line represents a polyline, the Area mark type
- * represents a polygon. However, an area is not an arbitrary polygon;
- * vertices are paired either horizontally or vertically into parallel
- * spans, and each span corresponds to an associated datum. Either the
- * width or the height must be specified, but not both; this determines whether
- * the area is horizontally-oriented or vertically-oriented. Like lines, areas
- * can be stroked and filled with arbitrary colors.
- *
- *
See also the Area guide.
- *
- * @extends pv.Mark
- */
-pv.Area = function() {
- pv.Mark.call(this);
-};
-
-pv.Area.prototype = pv.extend(pv.Mark)
- .property("width", Number)
- .property("height", Number)
- .property("lineWidth", Number)
- .property("strokeStyle", pv.color)
- .property("fillStyle", pv.color)
- .property("segmented", Boolean)
- .property("interpolate", String)
- .property("tension", Number);
-
-pv.Area.prototype.type = "area";
-
-/**
- * The width of a given span, in pixels; used for horizontal spans. If the width
- * is specified, the height property should be 0 (the default). Either the top
- * or bottom property should be used to space the spans vertically, typically as
- * a multiple of the index.
- *
- * @type number
- * @name pv.Area.prototype.width
- */
-
-/**
- * The height of a given span, in pixels; used for vertical spans. If the height
- * is specified, the width property should be 0 (the default). Either the left
- * or right property should be used to space the spans horizontally, typically
- * as a multiple of the index.
- *
- * @type number
- * @name pv.Area.prototype.height
- */
-
-/**
- * The width of stroked lines, in pixels; used in conjunction with
- * strokeStyle to stroke the perimeter of the area. Unlike the
- * {@link Line} mark type, the entire perimeter is stroked, rather than just one
- * edge. The default value of this property is 1.5, but since the default stroke
- * style is null, area marks are not stroked by default.
- *
- *
This property is fixed for non-segmented areas. See
- * {@link pv.Mark}.
- *
- * @type number
- * @name pv.Area.prototype.lineWidth
- */
-
-/**
- * The style of stroked lines; used in conjunction with lineWidth to
- * stroke the perimeter of the area. Unlike the {@link Line} mark type, the
- * entire perimeter is stroked, rather than just one edge. The default value of
- * this property is null, meaning areas are not stroked by default.
- *
- *
This property is fixed for non-segmented areas. See
- * {@link pv.Mark}.
- *
- * @type string
- * @name pv.Area.prototype.strokeStyle
- * @see pv.color
- */
-
-/**
- * The area fill style; if non-null, the interior of the polygon forming the
- * area is filled with the specified color. The default value of this property
- * is a categorical color.
- *
- *
This property is fixed for non-segmented areas. See
- * {@link pv.Mark}.
- *
- * @type string
- * @name pv.Area.prototype.fillStyle
- * @see pv.color
- */
-
-/**
- * Whether the area is segmented; whether variations in fill style, stroke
- * style, and the other properties are treated as fixed. Rendering segmented
- * areas is noticeably slower than non-segmented areas.
- *
- *
This property is fixed. See {@link pv.Mark}.
- *
- * @type boolean
- * @name pv.Area.prototype.segmented
- */
-
-/**
- * How to interpolate between values. Linear interpolation ("linear") is the
- * default, producing a straight line between points. For piecewise constant
- * functions (i.e., step functions), either "step-before" or "step-after" can be
- * specified. To draw open uniform b-splines, specify "basis". To draw cardinal
- * splines, specify "cardinal"; see also {@link #tension}.
- *
- *
This property is fixed. See {@link pv.Mark}.
- *
- * @type string
- * @name pv.Area.prototype.interpolate
- */
-
-/**
- * The tension of cardinal splines; used in conjunction with
- * interpolate("cardinal"). A value between 0 and 1 draws cardinal splines with
- * the given tension. In some sense, the tension can be interpreted as the
- * "length" of the tangent; a tension of 1 will yield all zero tangents (i.e.,
- * linear interpolation), and a tension of 0 yields a Catmull-Rom spline. The
- * default value is 0.7.
- *
- *
This property is fixed. See {@link pv.Mark}.
- *
- * @type number
- * @name pv.Area.prototype.tension
- */
-
-/**
- * Default properties for areas. By default, there is no stroke and the fill
- * style is a categorical color.
- *
- * @type pv.Area
- */
-pv.Area.prototype.defaults = new pv.Area()
- .extend(pv.Mark.prototype.defaults)
- .lineWidth(1.5)
- .fillStyle(pv.Colors.category20().by(pv.parent))
- .interpolate("linear")
- .tension(.7);
-
-/** @private Sets width and height to zero if null. */
-pv.Area.prototype.buildImplied = function(s) {
- if (s.height == null) s.height = 0;
- if (s.width == null) s.width = 0;
- pv.Mark.prototype.buildImplied.call(this, s);
-};
-
-/** @private Records which properties may be fixed. */
-pv.Area.fixed = {
- lineWidth: 1,
- lineJoin: 1,
- strokeStyle: 1,
- fillStyle: 1,
- segmented: 1,
- interpolate: 1,
- tension: 1
-};
-
-/**
- * @private Make segmented required, such that this fixed property is always
- * evaluated, even if the first segment is not visible. Also cache which
- * properties are normally fixed.
- */
-pv.Area.prototype.bind = function() {
- pv.Mark.prototype.bind.call(this);
- var binds = this.binds,
- required = binds.required,
- optional = binds.optional;
- for (var i = 0, n = optional.length; i < n; i++) {
- var p = optional[i];
- p.fixed = p.name in pv.Area.fixed;
- if (p.name == "segmented") {
- required.push(p);
- optional.splice(i, 1);
- i--;
- n--;
- }
- }
-
- /* Cache the original arrays so they can be restored on build. */
- this.binds.$required = required;
- this.binds.$optional = optional;
-};
-
-/**
- * @private Override the default build behavior such that fixed properties are
- * determined dynamically, based on the value of the (always) fixed segmented
- * property. Any fixed properties are only evaluated on the first instance,
- * although their values are propagated to subsequent instances, so that they
- * are available for property chaining and the like.
- */
-pv.Area.prototype.buildInstance = function(s) {
- var binds = this.binds;
-
- /* Handle fixed properties on secondary instances. */
- if (this.index) {
- var fixed = binds.fixed;
-
- /* Determine which properties are fixed. */
- if (!fixed) {
- fixed = binds.fixed = [];
- function f(p) { return !p.fixed || (fixed.push(p), false); }
- binds.required = binds.required.filter(f);
- if (!this.scene[0].segmented) binds.optional = binds.optional.filter(f);
- }
-
- /* Copy fixed property values from the first instance. */
- for (var i = 0, n = fixed.length; i < n; i++) {
- var p = fixed[i].name;
- s[p] = this.scene[0][p];
- }
- }
-
- /* Evaluate all properties on the first instance. */
- else {
- binds.required = binds.$required;
- binds.optional = binds.$optional;
- binds.fixed = null;
- }
-
- pv.Mark.prototype.buildInstance.call(this, s);
-};
-
-/**
- * Constructs a new area anchor with default properties. Areas support five
- * different anchors:
- *
- *
top
- *
left
- *
center
- *
bottom
- *
right
- *
- *
In addition to positioning properties (left, right, top bottom), the
- * anchors support text rendering properties (text-align, text-baseline). Text
- * is rendered to appear inside the area. The area anchor also propagates the
- * interpolate, eccentricity, and tension properties such that an anchored area
- * or line will match positions between control points.
- *
- *
For consistency with the other mark types, the anchor positions are
- * defined in terms of their opposite edge. For example, the top anchor defines
- * the bottom property, such that an area added to the top anchor grows upward.
- *
- * @param {string} name the anchor name; either a string or a property function.
- * @returns {pv.Anchor}
- */
-pv.Area.prototype.anchor = function(name) {
- var scene;
- return pv.Mark.prototype.anchor.call(this, name)
- .def("$area.anchor", function() {
- scene = this.scene.target;
- })
- .interpolate(function() {
- return scene[this.index].interpolate;
- })
- .eccentricity(function() {
- return scene[this.index].eccentricity;
- })
- .tension(function() {
- return scene[this.index].tension;
- });
-};
-/**
- * Constructs a new bar mark with default properties. Bars are not typically
- * constructed directly, but by adding to a panel or an existing mark via
- * {@link pv.Mark#add}.
- *
- * @class Represents a bar: an axis-aligned rectangle that can be stroked and
- * filled. Bars are used for many chart types, including bar charts, histograms
- * and Gantt charts. Bars can also be used as decorations, for example to draw a
- * frame border around a panel; in fact, a panel is a special type (a subclass)
- * of bar.
- *
- *
Bars can be positioned in several ways. Most commonly, one of the four
- * corners is fixed using two margins, and then the width and height properties
- * determine the extent of the bar relative to this fixed location. For example,
- * using the bottom and left properties fixes the bottom-left corner; the width
- * then extends to the right, while the height extends to the top. As an
- * alternative to the four corners, a bar can be positioned exclusively using
- * margins; this is convenient as an inset from the containing panel, for
- * example. See {@link pv.Mark} for details on the prioritization of redundant
- * positioning properties.
- *
- *
See also the Bar guide.
- *
- * @extends pv.Mark
- */
-pv.Bar = function() {
- pv.Mark.call(this);
-};
-
-pv.Bar.prototype = pv.extend(pv.Mark)
- .property("width", Number)
- .property("height", Number)
- .property("lineWidth", Number)
- .property("strokeStyle", pv.color)
- .property("fillStyle", pv.color);
-
-pv.Bar.prototype.type = "bar";
-
-/**
- * The width of the bar, in pixels. If the left position is specified, the bar
- * extends rightward from the left edge; if the right position is specified, the
- * bar extends leftward from the right edge.
- *
- * @type number
- * @name pv.Bar.prototype.width
- */
-
-/**
- * The height of the bar, in pixels. If the bottom position is specified, the
- * bar extends upward from the bottom edge; if the top position is specified,
- * the bar extends downward from the top edge.
- *
- * @type number
- * @name pv.Bar.prototype.height
- */
-
-/**
- * The width of stroked lines, in pixels; used in conjunction with
- * strokeStyle to stroke the bar's border.
- *
- * @type number
- * @name pv.Bar.prototype.lineWidth
- */
-
-/**
- * The style of stroked lines; used in conjunction with lineWidth to
- * stroke the bar's border. The default value of this property is null, meaning
- * bars are not stroked by default.
- *
- * @type string
- * @name pv.Bar.prototype.strokeStyle
- * @see pv.color
- */
-
-/**
- * The bar fill style; if non-null, the interior of the bar is filled with the
- * specified color. The default value of this property is a categorical color.
- *
- * @type string
- * @name pv.Bar.prototype.fillStyle
- * @see pv.color
- */
-
-/**
- * Default properties for bars. By default, there is no stroke and the fill
- * style is a categorical color.
- *
- * @type pv.Bar
- */
-pv.Bar.prototype.defaults = new pv.Bar()
- .extend(pv.Mark.prototype.defaults)
- .lineWidth(1.5)
- .fillStyle(pv.Colors.category20().by(pv.parent));
-/**
- * Constructs a new dot mark with default properties. Dots are not typically
- * constructed directly, but by adding to a panel or an existing mark via
- * {@link pv.Mark#add}.
- *
- * @class Represents a dot; a dot is simply a sized glyph centered at a given
- * point that can also be stroked and filled. The size property is
- * proportional to the area of the rendered glyph to encourage meaningful visual
- * encodings. Dots can visually encode up to eight dimensions of data, though
- * this may be unwise due to integrality. See {@link pv.Mark} for details on the
- * prioritization of redundant positioning properties.
- *
- *
See also the Dot guide.
- *
- * @extends pv.Mark
- */
-pv.Dot = function() {
- pv.Mark.call(this);
-};
-
-pv.Dot.prototype = pv.extend(pv.Mark)
- .property("size", Number)
- .property("radius", Number)
- .property("shape", String)
- .property("angle", Number)
- .property("lineWidth", Number)
- .property("strokeStyle", pv.color)
- .property("fillStyle", pv.color);
-
-pv.Dot.prototype.type = "dot";
-
-/**
- * The size of the dot, in square pixels. Square pixels are used such that the
- * area of the dot is linearly proportional to the value of the size property,
- * facilitating representative encodings.
- *
- * @see #radius
- * @type number
- * @name pv.Dot.prototype.size
- */
-
-/**
- * The radius of the dot, in pixels. This is an alternative to using
- * {@link #size}.
- *
- * @see #size
- * @type number
- * @name pv.Dot.prototype.radius
- */
-
-/**
- * The shape name. Several shapes are supported:
- *
- *
cross
- *
triangle
- *
diamond
- *
square
- *
circle
- *
tick
- *
bar
- *
- *
These shapes can be further changed using the {@link #angle} property;
- * for instance, a cross can be turned into a plus by rotating. Similarly, the
- * tick, which is vertical by default, can be rotated horizontally. Note that
- * some shapes (cross and tick) do not have interior areas, and thus do not
- * support fill style meaningfully.
- *
- *
Note: it may be more natural to use the {@link pv.Rule} mark for
- * horizontal and vertical ticks. The tick shape is only necessary if angled
- * ticks are needed.
- *
- * @type string
- * @name pv.Dot.prototype.shape
- */
-
-/**
- * The rotation angle, in radians. Used to rotate shapes, such as to turn a
- * cross into a plus.
- *
- * @type number
- * @name pv.Dot.prototype.angle
- */
-
-/**
- * The width of stroked lines, in pixels; used in conjunction with
- * strokeStyle to stroke the dot's shape.
- *
- * @type number
- * @name pv.Dot.prototype.lineWidth
- */
-
-/**
- * The style of stroked lines; used in conjunction with lineWidth to
- * stroke the dot's shape. The default value of this property is a categorical
- * color.
- *
- * @type string
- * @name pv.Dot.prototype.strokeStyle
- * @see pv.color
- */
-
-/**
- * The fill style; if non-null, the interior of the dot is filled with the
- * specified color. The default value of this property is null, meaning dots are
- * not filled by default.
- *
- * @type string
- * @name pv.Dot.prototype.fillStyle
- * @see pv.color
- */
-
-/**
- * Default properties for dots. By default, there is no fill and the stroke
- * style is a categorical color. The default shape is "circle" with size 20.
- *
- * @type pv.Dot
- */
-pv.Dot.prototype.defaults = new pv.Dot()
- .extend(pv.Mark.prototype.defaults)
- .size(20)
- .shape("circle")
- .lineWidth(1.5)
- .strokeStyle(pv.Colors.category10().by(pv.parent));
-
-/**
- * Constructs a new dot anchor with default properties. Dots support five
- * different anchors:
- *
- *
top
- *
left
- *
center
- *
bottom
- *
right
- *
- *
In addition to positioning properties (left, right, top bottom), the
- * anchors support text rendering properties (text-align, text-baseline). Text is
- * rendered to appear outside the dot. Note that this behavior is different from
- * other mark anchors, which default to rendering text inside the mark.
- *
- *
For consistency with the other mark types, the anchor positions are
- * defined in terms of their opposite edge. For example, the top anchor defines
- * the bottom property, such that a bar added to the top anchor grows upward.
- *
- * @param {string} name the anchor name; either a string or a property function.
- * @returns {pv.Anchor}
- */
-pv.Dot.prototype.anchor = function(name) {
- var scene;
- return pv.Mark.prototype.anchor.call(this, name)
- .def("$wedge.anchor", function() {
- scene = this.scene.target;
- })
- .left(function() {
- var s = scene[this.index];
- switch (this.name()) {
- case "bottom":
- case "top":
- case "center": return s.left;
- case "left": return null;
- }
- return s.left + s.radius;
- })
- .right(function() {
- var s = scene[this.index];
- return this.name() == "left" ? s.right + s.radius : null;
- })
- .top(function() {
- var s = scene[this.index];
- switch (this.name()) {
- case "left":
- case "right":
- case "center": return s.top;
- case "top": return null;
- }
- return s.top + s.radius;
- })
- .bottom(function() {
- var s = scene[this.index];
- return this.name() == "top" ? s.bottom + s.radius : null;
- })
- .textAlign(function() {
- switch (this.name()) {
- case "left": return "right";
- case "bottom":
- case "top":
- case "center": return "center";
- }
- return "left";
- })
- .textBaseline(function() {
- switch (this.name()) {
- case "right":
- case "left":
- case "center": return "middle";
- case "bottom": return "top";
- }
- return "bottom";
- });
-};
-
-/** @private Sets radius based on size or vice versa. */
-pv.Dot.prototype.buildImplied = function(s) {
- if (s.radius == null) s.radius = Math.sqrt(s.size);
- else if (s.size == null) s.size = s.radius * s.radius;
- pv.Mark.prototype.buildImplied.call(this, s);
-};
-/**
- * Constructs a new label mark with default properties. Labels are not typically
- * constructed directly, but by adding to a panel or an existing mark via
- * {@link pv.Mark#add}.
- *
- * @class Represents a text label, allowing textual annotation of other marks or
- * arbitrary text within the visualization. The character data must be plain
- * text (unicode), though the text can be styled using the {@link #font}
- * property. If rich text is needed, external HTML elements can be overlaid on
- * the canvas by hand.
- *
- *
Labels are positioned using the box model, similarly to {@link Dot}. Thus,
- * a label has no width or height, but merely a text anchor location. The text
- * is positioned relative to this anchor location based on the
- * {@link #textAlign}, {@link #textBaseline} and {@link #textMargin} properties.
- * Furthermore, the text may be rotated using {@link #textAngle}.
- *
- *
Labels ignore events, so as to not interfere with event handlers on
- * underlying marks, such as bars. In the future, we may support event handlers
- * on labels.
- *
- *
See also the Label guide.
- *
- * @extends pv.Mark
- */
-pv.Label = function() {
- pv.Mark.call(this);
-};
-
-pv.Label.prototype = pv.extend(pv.Mark)
- .property("text", String)
- .property("font", String)
- .property("textAngle", Number)
- .property("textStyle", pv.color)
- .property("textAlign", String)
- .property("textBaseline", String)
- .property("textMargin", Number)
- .property("textDecoration", String)
- .property("textShadow", String);
-
-pv.Label.prototype.type = "label";
-
-/**
- * The character data to render; a string. The default value of the text
- * property is the identity function, meaning the label's associated datum will
- * be rendered using its toString.
- *
- * @type string
- * @name pv.Label.prototype.text
- */
-
-/**
- * The font format, per the CSS Level 2 specification. The default font is "10px
- * sans-serif", for consistency with the HTML 5 canvas element specification.
- * Note that since text is not wrapped, any line-height property will be
- * ignored. The other font-style, font-variant, font-weight, font-size and
- * font-family properties are supported.
- *
- * @see CSS2 fonts
- * @type string
- * @name pv.Label.prototype.font
- */
-
-/**
- * The rotation angle, in radians. Text is rotated clockwise relative to the
- * anchor location. For example, with the default left alignment, an angle of
- * Math.PI / 2 causes text to proceed downwards. The default angle is zero.
- *
- * @type number
- * @name pv.Label.prototype.textAngle
- */
-
-/**
- * The text color. The name "textStyle" is used for consistency with "fillStyle"
- * and "strokeStyle", although it might be better to rename this property (and
- * perhaps use the same name as "strokeStyle"). The default color is black.
- *
- * @type string
- * @name pv.Label.prototype.textStyle
- * @see pv.color
- */
-
-/**
- * The horizontal text alignment. One of:
- *
- *
left
- *
center
- *
right
- *
- *
The default horizontal alignment is left.
- *
- * @type string
- * @name pv.Label.prototype.textAlign
- */
-
-/**
- * The vertical text alignment. One of:
- *
- *
top
- *
middle
- *
bottom
- *
- *
The default vertical alignment is bottom.
- *
- * @type string
- * @name pv.Label.prototype.textBaseline
- */
-
-/**
- * The text margin; may be specified in pixels, or in font-dependent units (such
- * as ".1ex"). The margin can be used to pad text away from its anchor location,
- * in a direction dependent on the horizontal and vertical alignment
- * properties. For example, if the text is left- and middle-aligned, the margin
- * shifts the text to the right. The default margin is 3 pixels.
- *
- * @type number
- * @name pv.Label.prototype.textMargin
- */
-
-/**
- * A list of shadow effects to be applied to text, per the CSS Text Level 3
- * text-shadow property. An example specification is "0.1em 0.1em 0.1em
- * rgba(0,0,0,.5)"; the first length is the horizontal offset, the second the
- * vertical offset, and the third the blur radius.
- *
- * @see CSS3 text
- * @type string
- * @name pv.Label.prototype.textShadow
- */
-
-/**
- * A list of decoration to be applied to text, per the CSS Text Level 3
- * text-decoration property. An example specification is "underline".
- *
- * @see CSS3 text
- * @type string
- * @name pv.Label.prototype.textDecoration
- */
-
-/**
- * Default properties for labels. See the individual properties for the default
- * values.
- *
- * @type pv.Label
- */
-pv.Label.prototype.defaults = new pv.Label()
- .extend(pv.Mark.prototype.defaults)
- .events("none")
- .text(pv.identity)
- .font("10px sans-serif")
- .textAngle(0)
- .textStyle("black")
- .textAlign("left")
- .textBaseline("bottom")
- .textMargin(3);
-/**
- * Constructs a new line mark with default properties. Lines are not typically
- * constructed directly, but by adding to a panel or an existing mark via
- * {@link pv.Mark#add}.
- *
- * @class Represents a series of connected line segments, or polyline,
- * that can be stroked with a configurable color and thickness. Each
- * articulation point in the line corresponds to a datum; for n points,
- * n-1 connected line segments are drawn. The point is positioned using
- * the box model. Arbitrary paths are also possible, allowing radar plots and
- * other custom visualizations.
- *
- *
Like areas, lines can be stroked and filled with arbitrary colors. In most
- * cases, lines are only stroked, but the fill style can be used to construct
- * arbitrary polygons.
- *
- *
See also the Line guide.
- *
- * @extends pv.Mark
- */
-pv.Line = function() {
- pv.Mark.call(this);
-};
-
-pv.Line.prototype = pv.extend(pv.Mark)
- .property("lineWidth", Number)
- .property("lineJoin", String)
- .property("strokeStyle", pv.color)
- .property("fillStyle", pv.color)
- .property("segmented", Boolean)
- .property("interpolate", String)
- .property("eccentricity", Number)
- .property("tension", Number);
-
-pv.Line.prototype.type = "line";
-
-/**
- * The width of stroked lines, in pixels; used in conjunction with
- * strokeStyle to stroke the line.
- *
- * @type number
- * @name pv.Line.prototype.lineWidth
- */
-
-/**
- * The style of stroked lines; used in conjunction with lineWidth to
- * stroke the line. The default value of this property is a categorical color.
- *
- * @type string
- * @name pv.Line.prototype.strokeStyle
- * @see pv.color
- */
-
-/**
- * The type of corners where two lines meet. Accepted values are "bevel",
- * "round" and "miter". The default value is "miter".
- *
- *
For segmented lines, only "miter" joins and "linear" interpolation are
- * currently supported. Any other value, including null, will disable joins,
- * producing disjoint line segments. Note that the miter joins must be computed
- * manually (at least in the current SVG renderer); since this calculation may
- * be expensive and unnecessary for small lines, specifying null can improve
- * performance significantly.
- *
- *
This property is fixed. See {@link pv.Mark}.
- *
- * @type string
- * @name pv.Line.prototype.lineJoin
- */
-
-/**
- * The line fill style; if non-null, the interior of the line is closed and
- * filled with the specified color. The default value of this property is a
- * null, meaning that lines are not filled by default.
- *
- *
This property is fixed. See {@link pv.Mark}.
- *
- * @type string
- * @name pv.Line.prototype.fillStyle
- * @see pv.color
- */
-
-/**
- * Whether the line is segmented; whether variations in stroke style, line width
- * and the other properties are treated as fixed. Rendering segmented lines is
- * noticeably slower than non-segmented lines.
- *
- *
This property is fixed. See {@link pv.Mark}.
- *
- * @type boolean
- * @name pv.Line.prototype.segmented
- */
-
-/**
- * How to interpolate between values. Linear interpolation ("linear") is the
- * default, producing a straight line between points. For piecewise constant
- * functions (i.e., step functions), either "step-before" or "step-after" can be
- * specified. To draw a clockwise circular arc between points, specify "polar";
- * to draw a counterclockwise circular arc between points, specify
- * "polar-reverse". To draw open uniform b-splines, specify "basis". To draw
- * cardinal splines, specify "cardinal"; see also {@link #tension}.
- *
- *
This property is fixed. See {@link pv.Mark}.
- *
- * @type string
- * @name pv.Line.prototype.interpolate
- */
-
-/**
- * The eccentricity of polar line segments; used in conjunction with
- * interpolate("polar"). The default value of 0 means that line segments are
- * drawn as circular arcs. A value of 1 draws a straight line. A value between 0
- * and 1 draws an elliptical arc with the given eccentricity.
- *
- * @type number
- * @name pv.Line.prototype.eccentricity
- */
-
-/**
- * The tension of cardinal splines; used in conjunction with
- * interpolate("cardinal"). A value between 0 and 1 draws cardinal splines with
- * the given tension. In some sense, the tension can be interpreted as the
- * "length" of the tangent; a tension of 1 will yield all zero tangents (i.e.,
- * linear interpolation), and a tension of 0 yields a Catmull-Rom spline. The
- * default value is 0.7.
- *
- *
This property is fixed. See {@link pv.Mark}.
- *
- * @type number
- * @name pv.Line.prototype.tension
- */
-
-/**
- * Default properties for lines. By default, there is no fill and the stroke
- * style is a categorical color. The default interpolation is linear.
- *
- * @type pv.Line
- */
-pv.Line.prototype.defaults = new pv.Line()
- .extend(pv.Mark.prototype.defaults)
- .lineJoin("miter")
- .lineWidth(1.5)
- .strokeStyle(pv.Colors.category10().by(pv.parent))
- .interpolate("linear")
- .eccentricity(0)
- .tension(.7);
-
-/** @private Reuse Area's implementation for segmented bind & build. */
-pv.Line.prototype.bind = pv.Area.prototype.bind;
-pv.Line.prototype.buildInstance = pv.Area.prototype.buildInstance;
-
-/**
- * Constructs a new line anchor with default properties. Lines support five
- * different anchors:
- *
- *
top
- *
left
- *
center
- *
bottom
- *
right
- *
- *
In addition to positioning properties (left, right, top bottom), the
- * anchors support text rendering properties (text-align, text-baseline). Text is
- * rendered to appear outside the line. Note that this behavior is different
- * from other mark anchors, which default to rendering text inside the
- * mark.
- *
- *
For consistency with the other mark types, the anchor positions are
- * defined in terms of their opposite edge. For example, the top anchor defines
- * the bottom property, such that a bar added to the top anchor grows upward.
- *
- * @param {string} name the anchor name; either a string or a property function.
- * @returns {pv.Anchor}
- */
-pv.Line.prototype.anchor = function(name) {
- return pv.Area.prototype.anchor.call(this, name)
- .textAlign(function(d) {
- switch (this.name()) {
- case "left": return "right";
- case "bottom":
- case "top":
- case "center": return "center";
- case "right": return "left";
- }
- })
- .textBaseline(function(d) {
- switch (this.name()) {
- case "right":
- case "left":
- case "center": return "middle";
- case "top": return "bottom";
- case "bottom": return "top";
- }
- });
-};
-/**
- * Constructs a new rule with default properties. Rules are not typically
- * constructed directly, but by adding to a panel or an existing mark via
- * {@link pv.Mark#add}.
- *
- * @class Represents a horizontal or vertical rule. Rules are frequently used
- * for axes and grid lines. For example, specifying only the bottom property
- * draws horizontal rules, while specifying only the left draws vertical
- * rules. Rules can also be used as thin bars. The visual style is controlled in
- * the same manner as lines.
- *
- *
Rules are positioned exclusively the standard box model properties. The
- * following combinations of properties are supported:
- *
- *
- *
Properties
Orientation
- *
- *
left
vertical
- *
right
vertical
- *
left, bottom, top
vertical
- *
right, bottom, top
vertical
- *
top
horizontal
- *
bottom
horizontal
- *
top, left, right
horizontal
- *
bottom, left, right
horizontal
- *
left, top, height
vertical
- *
left, bottom, height
vertical
- *
right, top, height
vertical
- *
right, bottom, height
vertical
- *
left, top, width
horizontal
- *
left, bottom, width
horizontal
- *
right, top, width
horizontal
- *
right, bottom, width
horizontal
- *
- *
- *
- *
Small rules can be used as tick marks; alternatively, a {@link Dot} with
- * the "tick" shape can be used.
- *
- *
See also the Rule guide.
- *
- * @see pv.Line
- * @extends pv.Mark
- */
-pv.Rule = function() {
- pv.Mark.call(this);
-};
-
-pv.Rule.prototype = pv.extend(pv.Mark)
- .property("width", Number)
- .property("height", Number)
- .property("lineWidth", Number)
- .property("strokeStyle", pv.color);
-
-pv.Rule.prototype.type = "rule";
-
-/**
- * The width of the rule, in pixels. If the left position is specified, the rule
- * extends rightward from the left edge; if the right position is specified, the
- * rule extends leftward from the right edge.
- *
- * @type number
- * @name pv.Rule.prototype.width
- */
-
-/**
- * The height of the rule, in pixels. If the bottom position is specified, the
- * rule extends upward from the bottom edge; if the top position is specified,
- * the rule extends downward from the top edge.
- *
- * @type number
- * @name pv.Rule.prototype.height
- */
-
-/**
- * The width of stroked lines, in pixels; used in conjunction with
- * strokeStyle to stroke the rule. The default value is 1 pixel.
- *
- * @type number
- * @name pv.Rule.prototype.lineWidth
- */
-
-/**
- * The style of stroked lines; used in conjunction with lineWidth to
- * stroke the rule. The default value of this property is black.
- *
- * @type string
- * @name pv.Rule.prototype.strokeStyle
- * @see pv.color
- */
-
-/**
- * Default properties for rules. By default, a single-pixel black line is
- * stroked.
- *
- * @type pv.Rule
- */
-pv.Rule.prototype.defaults = new pv.Rule()
- .extend(pv.Mark.prototype.defaults)
- .lineWidth(1)
- .strokeStyle("black")
- .antialias(false);
-
-/**
- * Constructs a new rule anchor with default properties. Rules support five
- * different anchors:
- *
- *
top
- *
left
- *
center
- *
bottom
- *
right
- *
- *
In addition to positioning properties (left, right, top bottom), the
- * anchors support text rendering properties (text-align, text-baseline). Text is
- * rendered to appear outside the rule. Note that this behavior is different
- * from other mark anchors, which default to rendering text inside the
- * mark.
- *
- *
For consistency with the other mark types, the anchor positions are
- * defined in terms of their opposite edge. For example, the top anchor defines
- * the bottom property, such that a bar added to the top anchor grows upward.
- *
- * @param {string} name the anchor name; either a string or a property function.
- * @returns {pv.Anchor}
- */
-pv.Rule.prototype.anchor = pv.Line.prototype.anchor;
-
-/** @private Sets width or height based on orientation. */
-pv.Rule.prototype.buildImplied = function(s) {
- var l = s.left, r = s.right, t = s.top, b = s.bottom;
-
- /* Determine horizontal or vertical orientation. */
- if ((s.width != null)
- || ((l == null) && (r == null))
- || ((r != null) && (l != null))) {
- s.height = 0;
- } else {
- s.width = 0;
- }
-
- pv.Mark.prototype.buildImplied.call(this, s);
-};
-/**
- * Constructs a new, empty panel with default properties. Panels, with the
- * exception of the root panel, are not typically constructed directly; instead,
- * they are added to an existing panel or mark via {@link pv.Mark#add}.
- *
- * @class Represents a container mark. Panels allow repeated or nested
- * structures, commonly used in small multiple displays where a small
- * visualization is tiled to facilitate comparison across one or more
- * dimensions. Other types of visualizations may benefit from repeated and
- * possibly overlapping structure as well, such as stacked area charts. Panels
- * can also offset the position of marks to provide padding from surrounding
- * content.
- *
- *
All Protovis displays have at least one panel; this is the root panel to
- * which marks are rendered. The box model properties (four margins, width and
- * height) are used to offset the positions of contained marks. The data
- * property determines the panel count: a panel is generated once per associated
- * datum. When nested panels are used, property functions can declare additional
- * arguments to access the data associated with enclosing panels.
- *
- *
Panels can be rendered inline, facilitating the creation of sparklines.
- * This allows designers to reuse browser layout features, such as text flow and
- * tables; designers can also overlay HTML elements such as rich text and
- * images.
- *
- *
All panels have a children array (possibly empty) containing the
- * child marks in the order they were added. Panels also have a root
- * field which points to the root (outermost) panel; the root panel's root field
- * points to itself.
- *
- *
See also the Protovis guide.
- *
- * @extends pv.Bar
- */
-pv.Panel = function() {
- pv.Bar.call(this);
-
- /**
- * The child marks; zero or more {@link pv.Mark}s in the order they were
- * added.
- *
- * @see #add
- * @type pv.Mark[]
- */
- this.children = [];
- this.root = this;
-
- /**
- * The internal $dom field is set by the Protovis loader; see lang/init.js. It
- * refers to the script element that contains the Protovis specification, so
- * that the panel knows where in the DOM to insert the generated SVG element.
- *
- * @private
- */
- this.$dom = pv.$ && pv.$.s;
-};
-
-pv.Panel.prototype = pv.extend(pv.Bar)
- .property("transform")
- .property("overflow", String)
- .property("canvas", function(c) {
- return (typeof c == "string")
- ? document.getElementById(c)
- : c; // assume that c is the passed-in element
- });
-
-pv.Panel.prototype.type = "panel";
-
-/**
- * The canvas element; either the string ID of the canvas element in the current
- * document, or a reference to the canvas element itself. If null, a canvas
- * element will be created and inserted into the document at the location of the
- * script element containing the current Protovis specification. This property
- * only applies to root panels and is ignored on nested panels.
- *
- *
Note: the "canvas" element here refers to a div (or other suitable
- * HTML container element), not a canvas element. The name of
- * this property is a historical anachronism from the first implementation that
- * used HTML 5 canvas, rather than SVG.
- *
- * @type string
- * @name pv.Panel.prototype.canvas
- */
-
-/**
- * Specifies whether child marks are clipped when they overflow this panel.
- * This affects the clipping of all this panel's descendant marks.
- *
- * @type string
- * @name pv.Panel.prototype.overflow
- * @see CSS2
- */
-
-/**
- * The transform to be applied to child marks. The default transform is
- * identity, which has no effect. Note that the panel's own fill and stroke are
- * not affected by the transform, and panel's transform only affects the
- * scale of child marks, not the panel itself.
- *
- * @type pv.Transform
- * @name pv.Panel.prototype.transform
- * @see pv.Mark#scale
- */
-
-/**
- * Default properties for panels. By default, the margins are zero, the fill
- * style is transparent.
- *
- * @type pv.Panel
- */
-pv.Panel.prototype.defaults = new pv.Panel()
- .extend(pv.Bar.prototype.defaults)
- .fillStyle(null) // override Bar default
- .overflow("visible");
-
-/**
- * Returns an anchor with the specified name. This method is overridden such
- * that adding to a panel's anchor adds to the panel, rather than to the panel's
- * parent.
- *
- * @param {string} name the anchor name; either a string or a property function.
- * @returns {pv.Anchor} the new anchor.
- */
-pv.Panel.prototype.anchor = function(name) {
- var anchor = pv.Bar.prototype.anchor.call(this, name);
- anchor.parent = this;
- return anchor;
-};
-
-/**
- * Adds a new mark of the specified type to this panel. Unlike the normal
- * {@link Mark#add} behavior, adding a mark to a panel does not cause the mark
- * to inherit from the panel. Since the contained marks are offset by the panel
- * margins already, inheriting properties is generally undesirable; of course,
- * it is always possible to change this behavior by calling {@link Mark#extend}
- * explicitly.
- *
- * @param {function} type the type of the new mark to add.
- * @returns {pv.Mark} the new mark.
- */
-pv.Panel.prototype.add = function(type) {
- var child = new type();
- child.parent = this;
- child.root = this.root;
- child.childIndex = this.children.length;
- this.children.push(child);
- return child;
-};
-
-/** @private Bind this panel, then any child marks recursively. */
-pv.Panel.prototype.bind = function() {
- pv.Mark.prototype.bind.call(this);
- for (var i = 0; i < this.children.length; i++) {
- this.children[i].bind();
- }
-};
-
-/**
- * @private Evaluates all of the properties for this panel for the specified
- * instance s in the scene graph, including recursively building the
- * scene graph for child marks.
- *
- * @param s a node in the scene graph; the instance of the panel to build.
- * @see Mark#scene
- */
-pv.Panel.prototype.buildInstance = function(s) {
- pv.Bar.prototype.buildInstance.call(this, s);
- if (!s.visible) return;
- if (!s.children) s.children = [];
-
- /*
- * Multiply the current scale factor by this panel's transform. Also clear the
- * default index as we recurse into child marks; it will be reset to the
- * current index when the next panel instance is built.
- */
- var scale = this.scale * s.transform.k, child, n = this.children.length;
- pv.Mark.prototype.index = -1;
-
- /*
- * Build each child, passing in the parent (this panel) scene graph node. The
- * child mark's scene is initialized from the corresponding entry in the
- * existing scene graph, such that properties from the previous build can be
- * reused; this is largely to facilitate the recycling of SVG elements.
- */
- for (var i = 0; i < n; i++) {
- child = this.children[i];
- child.scene = s.children[i]; // possibly undefined
- child.scale = scale;
- child.build();
- }
-
- /*
- * Once the child marks have been built, the new scene graph nodes are removed
- * from the child marks and placed into the scene graph. The nodes cannot
- * remain on the child nodes because this panel (or a parent panel) may be
- * instantiated multiple times!
- */
- for (var i = 0; i < n; i++) {
- child = this.children[i];
- s.children[i] = child.scene;
- delete child.scene;
- delete child.scale;
- }
-
- /* Delete any expired child scenes. */
- s.children.length = n;
-};
-
-/**
- * @private Computes the implied properties for this panel for the specified
- * instance s in the scene graph. Panels have two implied
- * properties:
- *
- *
The canvas property references the DOM element, typically a DIV,
- * that contains the SVG element that is used to display the visualization. This
- * property may be specified as a string, referring to the unique ID of the
- * element in the DOM. The string is converted to a reference to the DOM
- * element. The width and height of the SVG element is inferred from this DOM
- * element. If no canvas property is specified, a new SVG element is created and
- * inserted into the document, using the panel dimensions; see
- * {@link #createCanvas}.
- *
- *
The children array, while not a property per se, contains the
- * scene graph for each child mark. This array is initialized to be empty, and
- * is populated above in {@link #buildInstance}.
- *
- *
The current implementation creates the SVG element, if necessary, during
- * the build phase; in the future, it may be preferrable to move this to the
- * update phase, although then the canvas property would be undefined. In
- * addition, DOM inspection is necessary to define the implied width and height
- * properties that may be inferred from the DOM.
- *
- * @param s a node in the scene graph; the instance of the panel to build.
- */
-pv.Panel.prototype.buildImplied = function(s) {
- if (!this.parent) {
- var c = s.canvas;
- if (c) {
- /* Clear the container if it's not associated with this panel. */
- if (c.$panel != this) {
- c.$panel = this;
- while (c.lastChild) c.removeChild(c.lastChild);
- }
-
- /* If width and height weren't specified, inspect the container. */
- var w, h;
- if (s.width == null) {
- w = parseFloat(pv.css(c, "width"));
- s.width = w - s.left - s.right;
- }
- if (s.height == null) {
- h = parseFloat(pv.css(c, "height"));
- s.height = h - s.top - s.bottom;
- }
- } else {
- var cache = this.$canvas || (this.$canvas = []);
- if (!(c = cache[this.index])) {
- c = cache[this.index] = document.createElement("span");
- if (this.$dom) { // script element for text/javascript+protovis
- this.$dom.parentNode.insertBefore(c, this.$dom);
- } else { // find the last element in the body
- var n = document.body;
- while (n.lastChild && n.lastChild.tagName) n = n.lastChild;
- if (n != document.body) n = n.parentNode;
- n.appendChild(c);
- }
- }
- }
- s.canvas = c;
- }
- if (!s.transform) s.transform = pv.Transform.identity;
- pv.Mark.prototype.buildImplied.call(this, s);
-};
-/**
- * Constructs a new image with default properties. Images are not typically
- * constructed directly, but by adding to a panel or an existing mark via
- * {@link pv.Mark#add}.
- *
- * @class Represents an image, either a static resource or a dynamically-
- * generated pixel buffer. Images share the same layout and style properties as
- * bars. The external image resource is specified via the {@link #url}
- * property. The optional fill, if specified, appears beneath the image, while
- * the optional stroke appears above the image.
- *
- *
Dynamic images such as heatmaps are supported using the {@link #image}
- * psuedo-property. This function is passed the x and y index, in
- * addition to the current data stack. The return value is a {@link pv.Color},
- * or null for transparent. A string can also be returned, which will be parsed
- * into a color; however, it is typically much faster to return an object with
- * r, g, b and a attributes, to avoid the
- * cost of parsing and object instantiation.
- *
- *
See {@link pv.Bar} for details on positioning properties.
- *
- * @extends pv.Bar
- */
-pv.Image = function() {
- pv.Bar.call(this);
-};
-
-pv.Image.prototype = pv.extend(pv.Bar)
- .property("url", String)
- .property("imageWidth", Number)
- .property("imageHeight", Number);
-
-pv.Image.prototype.type = "image";
-
-/**
- * The URL of the image to display. The set of supported image types is
- * browser-dependent; PNG and JPEG are recommended.
- *
- * @type string
- * @name pv.Image.prototype.url
- */
-
-/**
- * The width of the image in pixels. For static images, this property is
- * computed implicitly from the loaded image resources. For dynamic images, this
- * property can be used to specify the width of the pixel buffer; otherwise, the
- * value is derived from the width property.
- *
- * @type number
- * @name pv.Image.prototype.imageWidth
- */
-
-/**
- * The height of the image in pixels. For static images, this property is
- * computed implicitly from the loaded image resources. For dynamic images, this
- * property can be used to specify the height of the pixel buffer; otherwise, the
- * value is derived from the height property.
- *
- * @type number
- * @name pv.Image.prototype.imageHeight
- */
-
-/**
- * Default properties for images. By default, there is no stroke or fill style.
- *
- * @type pv.Image
- */
-pv.Image.prototype.defaults = new pv.Image()
- .extend(pv.Bar.prototype.defaults)
- .fillStyle(null);
-
-/**
- * Specifies the dynamic image function. By default, no image function is
- * specified and the url property is used to load a static image
- * resource. If an image function is specified, it will be invoked for each
- * pixel in the image, based on the related imageWidth and
- * imageHeight properties.
- *
- *
For example, given a two-dimensional array heatmap, containing
- * numbers in the range [0, 1] in row-major order, a simple monochrome heatmap
- * image can be specified as:
- *
- *
- *
- * For fastest performance, use an ordinal scale which caches the fixed color
- * palette, or return an object literal with r, g, b
- * and a attributes. A {@link pv.Color} or string can also be returned,
- * though this typically results in slower performance.
- *
- * @param {function} f the new sizing function.
- * @returns {pv.Layout.Pack} this.
- */
-pv.Image.prototype.image = function(f) {
- /** @private */
- this.$image = function() {
- var c = f.apply(this, arguments);
- return c == null ? pv.Color.transparent
- : typeof c == "string" ? pv.color(c)
- : c;
- };
- return this;
-};
-
-/** @private Scan the proto chain for an image function. */
-pv.Image.prototype.bind = function() {
- pv.Bar.prototype.bind.call(this);
- var binds = this.binds, mark = this;
- do {
- binds.image = mark.$image;
- } while (!binds.image && (mark = mark.proto));
-};
-
-/** @private */
-pv.Image.prototype.buildImplied = function(s) {
- pv.Bar.prototype.buildImplied.call(this, s);
- if (!s.visible) return;
-
- /* Compute the implied image dimensions. */
- if (s.imageWidth == null) s.imageWidth = s.width;
- if (s.imageHeight == null) s.imageHeight = s.height;
-
- /* Compute the pixel values. */
- if ((s.url == null) && this.binds.image) {
-
- /* Cache the canvas element to reuse across renders. */
- var canvas = this.$canvas || (this.$canvas = document.createElement("canvas")),
- context = canvas.getContext("2d"),
- w = s.imageWidth,
- h = s.imageHeight,
- stack = pv.Mark.stack,
- data;
-
- /* Evaluate the image function, storing into a CanvasPixelArray. */
- canvas.width = w;
- canvas.height = h;
- data = (s.image = context.createImageData(w, h)).data;
- stack.unshift(null, null);
- for (var y = 0, p = 0; y < h; y++) {
- stack[1] = y;
- for (var x = 0; x < w; x++) {
- stack[0] = x;
- var color = this.binds.image.apply(this, stack);
- data[p++] = color.r;
- data[p++] = color.g;
- data[p++] = color.b;
- data[p++] = 255 * color.a;
- }
- }
- stack.splice(0, 2);
- }
-};
-/**
- * Constructs a new wedge with default properties. Wedges are not typically
- * constructed directly, but by adding to a panel or an existing mark via
- * {@link pv.Mark#add}.
- *
- * @class Represents a wedge, or pie slice. Specified in terms of start and end
- * angle, inner and outer radius, wedges can be used to construct donut charts
- * and polar bar charts as well. If the {@link #angle} property is used, the end
- * angle is implied by adding this value to start angle. By default, the start
- * angle is the previously-generated wedge's end angle. This design allows
- * explicit control over the wedge placement if desired, while offering
- * convenient defaults for the construction of radial graphs.
- *
- *
The center point of the circle is positioned using the standard box model.
- * The wedge can be stroked and filled, similar to {@link pv.Bar}.
- *
- *
See also the Wedge guide.
- *
- * @extends pv.Mark
- */
-pv.Wedge = function() {
- pv.Mark.call(this);
-};
-
-pv.Wedge.prototype = pv.extend(pv.Mark)
- .property("startAngle", Number)
- .property("endAngle", Number)
- .property("angle", Number)
- .property("innerRadius", Number)
- .property("outerRadius", Number)
- .property("lineWidth", Number)
- .property("strokeStyle", pv.color)
- .property("fillStyle", pv.color);
-
-pv.Wedge.prototype.type = "wedge";
-
-/**
- * The start angle of the wedge, in radians. The start angle is measured
- * clockwise from the 3 o'clock position. The default value of this property is
- * the end angle of the previous instance (the {@link Mark#sibling}), or -PI / 2
- * for the first wedge; for pie and donut charts, typically only the
- * {@link #angle} property needs to be specified.
- *
- * @type number
- * @name pv.Wedge.prototype.startAngle
- */
-
-/**
- * The end angle of the wedge, in radians. If not specified, the end angle is
- * implied as the start angle plus the {@link #angle}.
- *
- * @type number
- * @name pv.Wedge.prototype.endAngle
- */
-
-/**
- * The angular span of the wedge, in radians. This property is used if end angle
- * is not specified.
- *
- * @type number
- * @name pv.Wedge.prototype.angle
- */
-
-/**
- * The inner radius of the wedge, in pixels. The default value of this property
- * is zero; a positive value will produce a donut slice rather than a pie slice.
- * The inner radius can vary per-wedge.
- *
- * @type number
- * @name pv.Wedge.prototype.innerRadius
- */
-
-/**
- * The outer radius of the wedge, in pixels. This property is required. For
- * pies, only this radius is required; for donuts, the inner radius must be
- * specified as well. The outer radius can vary per-wedge.
- *
- * @type number
- * @name pv.Wedge.prototype.outerRadius
- */
-
-/**
- * The width of stroked lines, in pixels; used in conjunction with
- * strokeStyle to stroke the wedge's border.
- *
- * @type number
- * @name pv.Wedge.prototype.lineWidth
- */
-
-/**
- * The style of stroked lines; used in conjunction with lineWidth to
- * stroke the wedge's border. The default value of this property is null,
- * meaning wedges are not stroked by default.
- *
- * @type string
- * @name pv.Wedge.prototype.strokeStyle
- * @see pv.color
- */
-
-/**
- * The wedge fill style; if non-null, the interior of the wedge is filled with
- * the specified color. The default value of this property is a categorical
- * color.
- *
- * @type string
- * @name pv.Wedge.prototype.fillStyle
- * @see pv.color
- */
-
-/**
- * Default properties for wedges. By default, there is no stroke and the fill
- * style is a categorical color.
- *
- * @type pv.Wedge
- */
-pv.Wedge.prototype.defaults = new pv.Wedge()
- .extend(pv.Mark.prototype.defaults)
- .startAngle(function() {
- var s = this.sibling();
- return s ? s.endAngle : -Math.PI / 2;
- })
- .innerRadius(0)
- .lineWidth(1.5)
- .strokeStyle(null)
- .fillStyle(pv.Colors.category20().by(pv.index));
-
-/**
- * Returns the mid-radius of the wedge, which is defined as half-way between the
- * inner and outer radii.
- *
- * @see #innerRadius
- * @see #outerRadius
- * @returns {number} the mid-radius, in pixels.
- */
-pv.Wedge.prototype.midRadius = function() {
- return (this.innerRadius() + this.outerRadius()) / 2;
-};
-
-/**
- * Returns the mid-angle of the wedge, which is defined as half-way between the
- * start and end angles.
- *
- * @see #startAngle
- * @see #endAngle
- * @returns {number} the mid-angle, in radians.
- */
-pv.Wedge.prototype.midAngle = function() {
- return (this.startAngle() + this.endAngle()) / 2;
-};
-
-/**
- * Constructs a new wedge anchor with default properties. Wedges support five
- * different anchors:
- *
- *
outer
- *
inner
- *
center
- *
start
- *
end
- *
- *
In addition to positioning properties (left, right, top bottom), the
- * anchors support text rendering properties (text-align, text-baseline,
- * textAngle). Text is rendered to appear inside the wedge.
- *
- * @param {string} name the anchor name; either a string or a property function.
- * @returns {pv.Anchor}
- */
-pv.Wedge.prototype.anchor = function(name) {
- function partial(s) { return s.innerRadius || s.angle < 2 * Math.PI; }
- function midRadius(s) { return (s.innerRadius + s.outerRadius) / 2; }
- function midAngle(s) { return (s.startAngle + s.endAngle) / 2; }
- var scene;
- return pv.Mark.prototype.anchor.call(this, name)
- .def("$wedge.anchor", function() {
- scene = this.scene.target;
- })
- .left(function() {
- var s = scene[this.index];
- if (partial(s)) switch (this.name()) {
- case "outer": return s.left + s.outerRadius * Math.cos(midAngle(s));
- case "inner": return s.left + s.innerRadius * Math.cos(midAngle(s));
- case "start": return s.left + midRadius(s) * Math.cos(s.startAngle);
- case "center": return s.left + midRadius(s) * Math.cos(midAngle(s));
- case "end": return s.left + midRadius(s) * Math.cos(s.endAngle);
- }
- return s.left;
- })
- .top(function() {
- var s = scene[this.index];
- if (partial(s)) switch (this.name()) {
- case "outer": return s.top + s.outerRadius * Math.sin(midAngle(s));
- case "inner": return s.top + s.innerRadius * Math.sin(midAngle(s));
- case "start": return s.top + midRadius(s) * Math.sin(s.startAngle);
- case "center": return s.top + midRadius(s) * Math.sin(midAngle(s));
- case "end": return s.top + midRadius(s) * Math.sin(s.endAngle);
- }
- return s.top;
- })
- .textAlign(function() {
- var s = scene[this.index];
- if (partial(s)) switch (this.name()) {
- case "outer": return pv.Wedge.upright(midAngle(s)) ? "right" : "left";
- case "inner": return pv.Wedge.upright(midAngle(s)) ? "left" : "right";
- }
- return "center";
- })
- .textBaseline(function() {
- var s = scene[this.index];
- if (partial(s)) switch (this.name()) {
- case "start": return pv.Wedge.upright(s.startAngle) ? "top" : "bottom";
- case "end": return pv.Wedge.upright(s.endAngle) ? "bottom" : "top";
- }
- return "middle";
- })
- .textAngle(function() {
- var s = scene[this.index], a = 0;
- if (partial(s)) switch (this.name()) {
- case "center":
- case "inner":
- case "outer": a = midAngle(s); break;
- case "start": a = s.startAngle; break;
- case "end": a = s.endAngle; break;
- }
- return pv.Wedge.upright(a) ? a : (a + Math.PI);
- });
-};
-
-/**
- * Returns true if the specified angle is considered "upright", as in, text
- * rendered at that angle would appear upright. If the angle is not upright,
- * text is rotated 180 degrees to be upright, and the text alignment properties
- * are correspondingly changed.
- *
- * @param {number} angle an angle, in radius.
- * @returns {boolean} true if the specified angle is upright.
- */
-pv.Wedge.upright = function(angle) {
- angle = angle % (2 * Math.PI);
- angle = (angle < 0) ? (2 * Math.PI + angle) : angle;
- return (angle < Math.PI / 2) || (angle >= 3 * Math.PI / 2);
-};
-
-/** @private Sets angle based on endAngle or vice versa. */
-pv.Wedge.prototype.buildImplied = function(s) {
- if (s.angle == null) s.angle = s.endAngle - s.startAngle;
- else if (s.endAngle == null) s.endAngle = s.startAngle + s.angle;
- pv.Mark.prototype.buildImplied.call(this, s);
-};
-/**
- * Abstract; not implemented. There is no explicit constructor; this class
- * merely serves to document the attributes that are used on particles in
- * physics simulations.
- *
- * @class A weighted particle that can participate in a force simulation.
- *
- * @name pv.Particle
- */
-
-/**
- * The next particle in the simulation. Particles form a singly-linked list.
- *
- * @field
- * @type pv.Particle
- * @name pv.Particle.prototype.next
- */
-
-/**
- * The x-position of the particle.
- *
- * @field
- * @type number
- * @name pv.Particle.prototype.x
- */
-
-/**
- * The y-position of the particle.
- *
- * @field
- * @type number
- * @name pv.Particle.prototype.y
- */
-
-/**
- * The x-velocity of the particle.
- *
- * @field
- * @type number
- * @name pv.Particle.prototype.vx
- */
-
-/**
- * The y-velocity of the particle.
- *
- * @field
- * @type number
- * @name pv.Particle.prototype.vy
- */
-
-/**
- * The x-position of the particle at -dt.
- *
- * @field
- * @type number
- * @name pv.Particle.prototype.px
- */
-
-/**
- * The y-position of the particle at -dt.
- *
- * @field
- * @type number
- * @name pv.Particle.prototype.py
- */
-
-/**
- * The x-force on the particle.
- *
- * @field
- * @type number
- * @name pv.Particle.prototype.fx
- */
-
-/**
- * The y-force on the particle.
- *
- * @field
- * @type number
- * @name pv.Particle.prototype.fy
- */
-/**
- * Constructs a new empty simulation.
- *
- * @param {array} particles
- * @returns {pv.Simulation} a new simulation for the specified particles.
- * @see pv.Simulation
- */
-pv.simulation = function(particles) {
- return new pv.Simulation(particles);
-};
-
-/**
- * Constructs a new simulation for the specified particles.
- *
- * @class Represents a particle simulation. Particles are massive points in
- * two-dimensional space. Forces can be applied to these particles, causing them
- * to move. Constraints can also be applied to restrict particle movement, for
- * example, constraining particles to a fixed position, or simulating collision
- * between circular particles with area.
- *
- *
The simulation uses Position Verlet
- * integration, due to the ease with which geometric constraints can be
- * implemented. For each time step, Verlet integration is performed, new forces
- * are accumulated, and then constraints are applied.
- *
- *
The simulation makes two simplifying assumptions: all particles are
- * equal-mass, and the time step of the simulation is fixed. It would be easy to
- * incorporate variable-mass particles as a future enhancement. Variable time
- * steps are also possible, but are likely to introduce instability in the
- * simulation.
- *
- *
This class can be used directly to simulate particle interaction.
- * Alternatively, for network diagrams, see {@link pv.Layout.Force}.
- *
- * @param {array} particles an array of {@link pv.Particle}s to simulate.
- * @see pv.Layout.Force
- * @see pv.Force
- * @see pv.Constraint
- */
-pv.Simulation = function(particles) {
- for (var i = 0; i < particles.length; i++) this.particle(particles[i]);
-};
-
-/**
- * The particles in the simulation. Particles are stored as a linked list; this
- * field represents the first particle in the simulation.
- *
- * @field
- * @type pv.Particle
- * @name pv.Simulation.prototype.particles
- */
-
-/**
- * The forces in the simulation. Forces are stored as a linked list; this field
- * represents the first force in the simulation.
- *
- * @field
- * @type pv.Force
- * @name pv.Simulation.prototype.forces
- */
-
-/**
- * The constraints in the simulation. Constraints are stored as a linked list;
- * this field represents the first constraint in the simulation.
- *
- * @field
- * @type pv.Constraint
- * @name pv.Simulation.prototype.constraints
- */
-
-/**
- * Adds the specified particle to the simulation.
- *
- * @param {pv.Particle} p the new particle.
- * @returns {pv.Simulation} this.
- */
-pv.Simulation.prototype.particle = function(p) {
- p.next = this.particles;
- /* Default velocities and forces to zero if unset. */
- if (isNaN(p.px)) p.px = p.x;
- if (isNaN(p.py)) p.py = p.y;
- if (isNaN(p.fx)) p.fx = 0;
- if (isNaN(p.fy)) p.fy = 0;
- this.particles = p;
- return this;
-};
-
-/**
- * Adds the specified force to the simulation.
- *
- * @param {pv.Force} f the new force.
- * @returns {pv.Simulation} this.
- */
-pv.Simulation.prototype.force = function(f) {
- f.next = this.forces;
- this.forces = f;
- return this;
-};
-
-/**
- * Adds the specified constraint to the simulation.
- *
- * @param {pv.Constraint} c the new constraint.
- * @returns {pv.Simulation} this.
- */
-pv.Simulation.prototype.constraint = function(c) {
- c.next = this.constraints;
- this.constraints = c;
- return this;
-};
-
-/**
- * Apply constraints, and then set the velocities to zero.
- *
- * @returns {pv.Simulation} this.
- */
-pv.Simulation.prototype.stabilize = function(n) {
- var c;
- if (!arguments.length) n = 3; // TODO use cooling schedule
- for (var i = 0; i < n; i++) {
- var q = new pv.Quadtree(this.particles);
- for (c = this.constraints; c; c = c.next) c.apply(this.particles, q);
- }
- for (var p = this.particles; p; p = p.next) {
- p.px = p.x;
- p.py = p.y;
- }
- return this;
-};
-
-/**
- * Advances the simulation one time-step.
- */
-pv.Simulation.prototype.step = function() {
- var p, f, c;
-
- /*
- * Assumptions:
- * - The mass (m) of every particles is 1.
- * - The time step (dt) is 1.
- */
-
- /* Position Verlet integration. */
- for (p = this.particles; p; p = p.next) {
- var px = p.px, py = p.py;
- p.px = p.x;
- p.py = p.y;
- p.x += p.vx = ((p.x - px) + p.fx);
- p.y += p.vy = ((p.y - py) + p.fy);
- }
-
- /* Apply constraints, then accumulate new forces. */
- var q = new pv.Quadtree(this.particles);
- for (c = this.constraints; c; c = c.next) c.apply(this.particles, q);
- for (p = this.particles; p; p = p.next) p.fx = p.fy = 0;
- for (f = this.forces; f; f = f.next) f.apply(this.particles, q);
-};
-/**
- * Constructs a new quadtree for the specified array of particles.
- *
- * @class Represents a quadtree: a two-dimensional recursive spatial
- * subdivision. This particular implementation uses square partitions, dividing
- * each square into four equally-sized squares. Each particle exists in a unique
- * node; if multiple particles are in the same position, some particles may be
- * stored on internal nodes rather than leaf nodes.
- *
- *
This quadtree can be used to accelerate various spatial operations, such
- * as the Barnes-Hut approximation for computing n-body forces, or collision
- * detection.
- *
- * @see pv.Force.charge
- * @see pv.Constraint.collision
- * @param {pv.Particle} particles the linked list of particles.
- */
-pv.Quadtree = function(particles) {
- var p;
-
- /* Compute bounds. */
- var x1 = Number.POSITIVE_INFINITY, y1 = x1,
- x2 = Number.NEGATIVE_INFINITY, y2 = x2;
- for (p = particles; p; p = p.next) {
- if (p.x < x1) x1 = p.x;
- if (p.y < y1) y1 = p.y;
- if (p.x > x2) x2 = p.x;
- if (p.y > y2) y2 = p.y;
- }
-
- /* Squarify the bounds. */
- var dx = x2 - x1, dy = y2 - y1;
- if (dx > dy) y2 = y1 + dx;
- else x2 = x1 + dy;
- this.xMin = x1;
- this.yMin = y1;
- this.xMax = x2;
- this.yMax = y2;
-
- /**
- * @ignore Recursively inserts the specified particle p at the node
- * n or one of its descendants. The bounds are defined by [x1,
- * x2] and [y1, y2].
- */
- function insert(n, p, x1, y1, x2, y2) {
- if (isNaN(p.x) || isNaN(p.y)) return; // ignore invalid particles
- if (n.leaf) {
- if (n.p) {
- /*
- * If the particle at this leaf node is at the same position as the new
- * particle we are adding, we leave the particle associated with the
- * internal node while adding the new particle to a child node. This
- * avoids infinite recursion.
- */
- if ((Math.abs(n.p.x - p.x) + Math.abs(n.p.y - p.y)) < .01) {
- insertChild(n, p, x1, y1, x2, y2);
- } else {
- var v = n.p;
- n.p = null;
- insertChild(n, v, x1, y1, x2, y2);
- insertChild(n, p, x1, y1, x2, y2);
- }
- } else {
- n.p = p;
- }
- } else {
- insertChild(n, p, x1, y1, x2, y2);
- }
- }
-
- /**
- * @ignore Recursively inserts the specified particle p into a
- * descendant of node n. The bounds are defined by [x1,
- * x2] and [y1, y2].
- */
- function insertChild(n, p, x1, y1, x2, y2) {
- /* Compute the split point, and the quadrant in which to insert p. */
- var sx = (x1 + x2) * .5,
- sy = (y1 + y2) * .5,
- right = p.x >= sx,
- bottom = p.y >= sy;
-
- /* Recursively insert into the child node. */
- n.leaf = false;
- switch ((bottom << 1) + right) {
- case 0: n = n.c1 || (n.c1 = new pv.Quadtree.Node()); break;
- case 1: n = n.c2 || (n.c2 = new pv.Quadtree.Node()); break;
- case 2: n = n.c3 || (n.c3 = new pv.Quadtree.Node()); break;
- case 3: n = n.c4 || (n.c4 = new pv.Quadtree.Node()); break;
- }
-
- /* Update the bounds as we recurse. */
- if (right) x1 = sx; else x2 = sx;
- if (bottom) y1 = sy; else y2 = sy;
- insert(n, p, x1, y1, x2, y2);
- }
-
- /* Insert all particles. */
- this.root = new pv.Quadtree.Node();
- for (p = particles; p; p = p.next) insert(this.root, p, x1, y1, x2, y2);
-};
-
-/**
- * The root node of the quadtree.
- *
- * @type pv.Quadtree.Node
- * @name pv.Quadtree.prototype.root
- */
-
-/**
- * The minimum x-coordinate value of all contained particles.
- *
- * @type number
- * @name pv.Quadtree.prototype.xMin
- */
-
-/**
- * The maximum x-coordinate value of all contained particles.
- *
- * @type number
- * @name pv.Quadtree.prototype.xMax
- */
-
-/**
- * The minimum y-coordinate value of all contained particles.
- *
- * @type number
- * @name pv.Quadtree.prototype.yMin
- */
-
-/**
- * The maximum y-coordinate value of all contained particles.
- *
- * @type number
- * @name pv.Quadtree.prototype.yMax
- */
-
-/**
- * Constructs a new node.
- *
- * @class A node in a quadtree.
- *
- * @see pv.Quadtree
- */
-pv.Quadtree.Node = function() {
- /*
- * Prepopulating all attributes significantly increases performance! Also,
- * letting the language interpreter manage garbage collection was moderately
- * faster than creating a cache pool.
- */
- this.leaf = true;
- this.c1 = null;
- this.c2 = null;
- this.c3 = null;
- this.c4 = null;
- this.p = null;
-};
-
-/**
- * True if this node is a leaf node; i.e., it has no children. Note that both
- * leaf nodes and non-leaf (internal) nodes may have associated particles. If
- * this is a non-leaf node, then at least one of {@link #c1}, {@link #c2},
- * {@link #c3} or {@link #c4} is guaranteed to be non-null.
- *
- * @type boolean
- * @name pv.Quadtree.Node.prototype.leaf
- */
-
-/**
- * The particle associated with this node, if any.
- *
- * @type pv.Particle
- * @name pv.Quadtree.Node.prototype.p
- */
-
-/**
- * The child node for the second quadrant, if any.
- *
- * @type pv.Quadtree.Node
- * @name pv.Quadtree.Node.prototype.c2
- */
-
-/**
- * The child node for the third quadrant, if any.
- *
- * @type pv.Quadtree.Node
- * @name pv.Quadtree.Node.prototype.c3
- */
-
-/**
- * The child node for the fourth quadrant, if any.
- *
- * @type pv.Quadtree.Node
- * @name pv.Quadtree.Node.prototype.c4
- */
-/**
- * Abstract; see an implementing class.
- *
- * @class Represents a force that acts on particles. Note that this interface
- * does not specify how to bind a force to specific particles; in general,
- * forces are applied globally to all particles. However, some forces may be
- * applied to specific particles or between particles, such as spring forces,
- * through additional specialization.
- *
- * @see pv.Simulation
- * @see pv.Particle
- * @see pv.Force.charge
- * @see pv.Force.drag
- * @see pv.Force.spring
- */
-pv.Force = {};
-
-/**
- * Applies this force to the specified particles.
- *
- * @function
- * @name pv.Force.prototype.apply
- * @param {pv.Particle} particles particles to which to apply this force.
- * @param {pv.Quadtree} q a quadtree for spatial acceleration.
- */
-/**
- * Constructs a new charge force, with an optional charge constant. The charge
- * constant can be negative for repulsion (e.g., particles with electrical
- * charge of equal sign), or positive for attraction (e.g., massive particles
- * with mutual gravity). The default charge constant is -40.
- *
- * @class An n-body force, as defined by Coulomb's law or Newton's law of
- * gravitation, inversely proportional to the square of the distance between
- * particles. Note that the force is independent of the mass of the
- * associated particles, and that the particles do not have charges of varying
- * magnitude; instead, the attraction or repulsion of all particles is globally
- * specified as the charge {@link #constant}.
- *
- *
This particular implementation uses the Barnes-Hut algorithm. For details,
- * see "A
- * hierarchical O(N log N) force-calculation algorithm", J. Barnes &
- * P. Hut, Nature 1986.
- *
- * @name pv.Force.charge
- * @param {number} [k] the charge constant.
- */
-pv.Force.charge = function(k) {
- var min = 2, // minimum distance at which to observe forces
- min1 = 1 / min,
- max = 500, // maximum distance at which to observe forces
- max1 = 1 / max,
- theta = .9, // Barnes-Hut theta approximation constant
- force = {};
-
- if (!arguments.length) k = -40; // default charge constant (repulsion)
-
- /**
- * Sets or gets the charge constant. If an argument is specified, it is the
- * new charge constant. The charge constant can be negative for repulsion
- * (e.g., particles with electrical charge of equal sign), or positive for
- * attraction (e.g., massive particles with mutual gravity). The default
- * charge constant is -40.
- *
- * @function
- * @name pv.Force.charge.prototype.constant
- * @param {number} x the charge constant.
- * @returns {pv.Force.charge} this.
- */
- force.constant = function(x) {
- if (arguments.length) {
- k = Number(x);
- return force;
- }
- return k;
- };
-
- /**
- * Sets or gets the domain; specifies the minimum and maximum domain within
- * which charge forces are applied. A minimum distance threshold avoids
- * applying forces that are two strong (due to granularity of the simulation's
- * numeric integration). A maximum distance threshold improves performance by
- * skipping force calculations for particles that are far apart.
- *
- *
The default domain is [2, 500].
- *
- * @function
- * @name pv.Force.charge.prototype.domain
- * @param {number} a
- * @param {number} b
- * @returns {pv.Force.charge} this.
- */
- force.domain = function(a, b) {
- if (arguments.length) {
- min = Number(a);
- min1 = 1 / min;
- max = Number(b);
- max1 = 1 / max;
- return force;
- }
- return [min, max];
- };
-
- /**
- * Sets or gets the Barnes-Hut approximation factor. The Barnes-Hut
- * approximation criterion is the ratio of the size of the quadtree node to
- * the distance from the point to the node's center of mass is beneath some
- * threshold.
- *
- * @function
- * @name pv.Force.charge.prototype.theta
- * @param {number} x the new Barnes-Hut approximation factor.
- * @returns {pv.Force.charge} this.
- */
- force.theta = function(x) {
- if (arguments.length) {
- theta = Number(x);
- return force;
- }
- return theta;
- };
-
- /**
- * @ignore Recursively computes the center of charge for each node in the
- * quadtree. This is equivalent to the center of mass, assuming that all
- * particles have unit weight.
- */
- function accumulate(n) {
- var cx = 0, cy = 0;
- n.cn = 0;
- function accumulateChild(c) {
- accumulate(c);
- n.cn += c.cn;
- cx += c.cn * c.cx;
- cy += c.cn * c.cy;
- }
- if (!n.leaf) {
- if (n.c1) accumulateChild(n.c1);
- if (n.c2) accumulateChild(n.c2);
- if (n.c3) accumulateChild(n.c3);
- if (n.c4) accumulateChild(n.c4);
- }
- if (n.p) {
- n.cn += k;
- cx += k * n.p.x;
- cy += k * n.p.y;
- }
- n.cx = cx / n.cn;
- n.cy = cy / n.cn;
- }
-
- /**
- * @ignore Recursively computes forces on the given particle using the given
- * quadtree node. The Barnes-Hut approximation criterion is the ratio of the
- * size of the quadtree node to the distance from the point to the node's
- * center of mass is beneath some threshold.
- */
- function forces(n, p, x1, y1, x2, y2) {
- var dx = n.cx - p.x,
- dy = n.cy - p.y,
- dn = 1 / Math.sqrt(dx * dx + dy * dy);
-
- /* Barnes-Hut criterion. */
- if ((n.leaf && (n.p != p)) || ((x2 - x1) * dn < theta)) {
- if (dn < max1) return;
- if (dn > min1) dn = min1;
- var kc = n.cn * dn * dn * dn,
- fx = dx * kc,
- fy = dy * kc;
- p.fx += fx;
- p.fy += fy;
- } else if (!n.leaf) {
- var sx = (x1 + x2) * .5, sy = (y1 + y2) * .5;
- if (n.c1) forces(n.c1, p, x1, y1, sx, sy);
- if (n.c2) forces(n.c2, p, sx, y1, x2, sy);
- if (n.c3) forces(n.c3, p, x1, sy, sx, y2);
- if (n.c4) forces(n.c4, p, sx, sy, x2, y2);
- if (dn < max1) return;
- if (dn > min1) dn = min1;
- if (n.p && (n.p != p)) {
- var kc = k * dn * dn * dn,
- fx = dx * kc,
- fy = dy * kc;
- p.fx += fx;
- p.fy += fy;
- }
- }
- }
-
- /**
- * Applies this force to the specified particles. The force is applied between
- * all pairs of particles within the domain, using the specified quadtree to
- * accelerate n-body force calculation using the Barnes-Hut approximation
- * criterion.
- *
- * @function
- * @name pv.Force.charge.prototype.apply
- * @param {pv.Particle} particles particles to which to apply this force.
- * @param {pv.Quadtree} q a quadtree for spatial acceleration.
- */
- force.apply = function(particles, q) {
- accumulate(q.root);
- for (var p = particles; p; p = p.next) {
- forces(q.root, p, q.xMin, q.yMin, q.xMax, q.yMax);
- }
- };
-
- return force;
-};
-/**
- * Constructs a new drag force with the specified constant.
- *
- * @class Implements a drag force, simulating friction. The drag force is
- * applied in the opposite direction of the particle's velocity. Since Position
- * Verlet integration does not track velocities explicitly, the error term with
- * this estimate of velocity is fairly high, so the drag force may be
- * inaccurate.
- *
- * @extends pv.Force
- * @param {number} k the drag constant.
- * @see #constant
- */
-pv.Force.drag = function(k) {
- var force = {};
-
- if (!arguments.length) k = .1; // default drag constant
-
- /**
- * Sets or gets the drag constant, in the range [0,1]. The default drag
- * constant is 0.1. The drag forces scales linearly with the particle's
- * velocity based on the given drag constant.
- *
- * @function
- * @name pv.Force.drag.prototype.constant
- * @param {number} x the new drag constant.
- * @returns {pv.Force.drag} this, or the current drag constant.
- */
- force.constant = function(x) {
- if (arguments.length) { k = x; return force; }
- return k;
- };
-
- /**
- * Applies this force to the specified particles.
- *
- * @function
- * @name pv.Force.drag.prototype.apply
- * @param {pv.Particle} particles particles to which to apply this force.
- */
- force.apply = function(particles) {
- if (k) for (var p = particles; p; p = p.next) {
- p.fx -= k * p.vx;
- p.fy -= k * p.vy;
- }
- };
-
- return force;
-};
-/**
- * Constructs a new spring force with the specified constant. The links
- * associated with this spring force must be specified before the spring force
- * can be applied.
- *
- * @class Implements a spring force, per Hooke's law. The spring force can be
- * configured with a tension constant, rest length, and damping factor. The
- * tension and damping will automatically be normalized using the inverse square
- * root of the maximum link degree of attached nodes; this makes springs weaker
- * between nodes of high link degree.
- *
- *
Unlike other forces (such as charge and drag forces) which may be applied
- * globally, spring forces are only applied between linked particles. Therefore,
- * an array of links must be specified before this force can be applied; the
- * links should be an array of {@link pv.Layout.Network.Link}s. See also
- * {@link pv.Layout.Force} for an example of using spring and charge forces for
- * network layout.
- *
- * @extends pv.Force
- * @param {number} k the spring constant.
- * @see #constant
- * @see #links
- */
-pv.Force.spring = function(k) {
- var d = .1, // default damping factor
- l = 20, // default rest length
- links, // links on which to apply spring forces
- kl, // per-spring normalization
- force = {};
-
- if (!arguments.length) k = .1; // default spring constant (tension)
-
- /**
- * Sets or gets the links associated with this spring force. Unlike other
- * forces (such as charge and drag forces) which may be applied globally,
- * spring forces are only applied between linked particles. Therefore, an
- * array of links must be specified before this force can be applied; the
- * links should be an array of {@link pv.Layout.Network.Link}s.
- *
- * @function
- * @name pv.Force.spring.prototype.links
- * @param {array} x the new array of links.
- * @returns {pv.Force.spring} this, or the current array of links.
- */
- force.links = function(x) {
- if (arguments.length) {
- links = x;
- kl = x.map(function(l) {
- return 1 / Math.sqrt(Math.max(
- l.sourceNode.linkDegree,
- l.targetNode.linkDegree));
- });
- return force;
- }
- return links;
- };
-
- /**
- * Sets or gets the spring constant. The default value is 0.1; greater values
- * will result in stronger tension. The spring tension is automatically
- * normalized using the inverse square root of the maximum link degree of
- * attached nodes.
- *
- * @function
- * @name pv.Force.spring.prototype.constant
- * @param {number} x the new spring constant.
- * @returns {pv.Force.spring} this, or the current spring constant.
- */
- force.constant = function(x) {
- if (arguments.length) {
- k = Number(x);
- return force;
- }
- return k;
- };
-
- /**
- * The spring damping factor, in the range [0,1]. Damping functions
- * identically to drag forces, damping spring bounciness by applying a force
- * in the opposite direction of attached nodes' velocities. The default value
- * is 0.1. The spring damping is automatically normalized using the inverse
- * square root of the maximum link degree of attached nodes.
- *
- * @function
- * @name pv.Force.spring.prototype.damping
- * @param {number} x the new spring damping factor.
- * @returns {pv.Force.spring} this, or the current spring damping factor.
- */
- force.damping = function(x) {
- if (arguments.length) {
- d = Number(x);
- return force;
- }
- return d;
- };
-
- /**
- * The spring rest length. The default value is 20 pixels.
- *
- * @function
- * @name pv.Force.spring.prototype.length
- * @param {number} x the new spring rest length.
- * @returns {pv.Force.spring} this, or the current spring rest length.
- */
- force.length = function(x) {
- if (arguments.length) {
- l = Number(x);
- return force;
- }
- return l;
- };
-
- /**
- * Applies this force to the specified particles.
- *
- * @function
- * @name pv.Force.spring.prototype.apply
- * @param {pv.Particle} particles particles to which to apply this force.
- */
- force.apply = function(particles) {
- for (var i = 0; i < links.length; i++) {
- var a = links[i].sourceNode,
- b = links[i].targetNode,
- dx = a.x - b.x,
- dy = a.y - b.y,
- dn = Math.sqrt(dx * dx + dy * dy),
- dd = dn ? (1 / dn) : 1,
- ks = k * kl[i], // normalized tension
- kd = d * kl[i], // normalized damping
- kk = (ks * (dn - l) + kd * (dx * (a.vx - b.vx) + dy * (a.vy - b.vy)) * dd) * dd,
- fx = -kk * (dn ? dx : (.01 * (.5 - Math.random()))),
- fy = -kk * (dn ? dy : (.01 * (.5 - Math.random())));
- a.fx += fx;
- a.fy += fy;
- b.fx -= fx;
- b.fy -= fy;
- }
- };
-
- return force;
-};
-/**
- * Abstract; see an implementing class.
- *
- * @class Represents a constraint that acts on particles. Note that this
- * interface does not specify how to bind a constraint to specific particles; in
- * general, constraints are applied globally to all particles. However, some
- * constraints may be applied to specific particles or between particles, such
- * as position constraints, through additional specialization.
- *
- * @see pv.Simulation
- * @see pv.Particle
- * @see pv.Constraint.bound
- * @see pv.Constraint.collision
- * @see pv.Constraint.position
- */
-pv.Constraint = {};
-
-/**
- * Applies this constraint to the specified particles.
- *
- * @function
- * @name pv.Constraint.prototype.apply
- * @param {pv.Particle} particles particles to which to apply this constraint.
- * @param {pv.Quadtree} q a quadtree for spatial acceleration.
- * @returns {pv.Constraint} this.
- */
-/**
- * Constructs a new collision constraint. The default search radius is 10, and
- * the default repeat count is 1. A radius function must be specified to compute
- * the radius of particles.
- *
- * @class Constraints circles to avoid overlap. Each particle is treated as a
- * circle, with the radius of the particle computed using a specified function.
- * For example, if the particle has an r attribute storing the radius,
- * the radius function(d) d.r specifies a collision constraint using
- * this radius. The radius function is passed each {@link pv.Particle} as the
- * first argument.
- *
- *
To accelerate collision detection, this implementation uses a quadtree and
- * a search radius. The search radius is computed as the maximum radius of all
- * particles in the simulation.
- *
- * @see pv.Constraint
- * @param {function} radius the radius function.
- */
-pv.Constraint.collision = function(radius) {
- var n = 1, // number of times to repeat the constraint
- r1,
- px1,
- py1,
- px2,
- py2,
- constraint = {};
-
- if (!arguments.length) r1 = 10; // default search radius
-
- /**
- * Sets or gets the repeat count. If the repeat count is greater than 1, the
- * constraint will be applied repeatedly; this is a form of the Gauss-Seidel
- * method for constraints relaxation. Repeating the collision constraint makes
- * the constraint have more of an effect when there is a potential for many
- * co-occurring collisions.
- *
- * @function
- * @name pv.Constraint.collision.prototype.repeat
- * @param {number} x the number of times to repeat this constraint.
- * @returns {pv.Constraint.collision} this.
- */
- constraint.repeat = function(x) {
- if (arguments.length) {
- n = Number(x);
- return constraint;
- }
- return n;
- };
-
- /** @private */
- function constrain(n, p, x1, y1, x2, y2) {
- if (!n.leaf) {
- var sx = (x1 + x2) * .5,
- sy = (y1 + y2) * .5,
- top = sy > py1,
- bottom = sy < py2,
- left = sx > px1,
- right = sx < px2;
- if (top) {
- if (n.c1 && left) constrain(n.c1, p, x1, y1, sx, sy);
- if (n.c2 && right) constrain(n.c2, p, sx, y1, x2, sy);
- }
- if (bottom) {
- if (n.c3 && left) constrain(n.c3, p, x1, sy, sx, y2);
- if (n.c4 && right) constrain(n.c4, p, sx, sy, x2, y2);
- }
- }
- if (n.p && (n.p != p)) {
- var dx = p.x - n.p.x,
- dy = p.y - n.p.y,
- l = Math.sqrt(dx * dx + dy * dy),
- d = r1 + radius(n.p);
- if (l < d) {
- var k = (l - d) / l * .5;
- dx *= k;
- dy *= k;
- p.x -= dx;
- p.y -= dy;
- n.p.x += dx;
- n.p.y += dy;
- }
- }
- }
-
- /**
- * Applies this constraint to the specified particles.
- *
- * @function
- * @name pv.Constraint.collision.prototype.apply
- * @param {pv.Particle} particles particles to which to apply this constraint.
- * @param {pv.Quadtree} q a quadtree for spatial acceleration.
- */
- constraint.apply = function(particles, q) {
- var p, r, max = -Infinity;
- for (p = particles; p; p = p.next) {
- r = radius(p);
- if (r > max) max = r;
- }
- for (var i = 0; i < n; i++) {
- for (p = particles; p; p = p.next) {
- r = (r1 = radius(p)) + max;
- px1 = p.x - r;
- px2 = p.x + r;
- py1 = p.y - r;
- py2 = p.y + r;
- constrain(q.root, p, q.xMin, q.yMin, q.xMax, q.yMax);
- }
- }
- };
-
- return constraint;
-};
-/**
- * Constructs a default position constraint using the fix attribute.
- * An optional position function can be specified to determine how the fixed
- * position per-particle is determined.
- *
- * @class Constraints particles to a fixed position. The fixed position per
- * particle is determined using a given position function, which defaults to
- * function(d) d.fix.
- *
- *
If the position function returns null, then no position constraint is
- * applied to the given particle. Otherwise, the particle's position is set to
- * the returned position, as expressed by a {@link pv.Vector}. (Note: the
- * position does not need to be an instance of pv.Vector, but simply an
- * object with x and y attributes.)
- *
- *
This constraint also supports a configurable alpha parameter, which
- * defaults to 1. If the alpha parameter is in the range [0,1], then rather than
- * setting the particle's new position directly to the position returned by the
- * supplied position function, the particle's position is interpolated towards
- * the fixed position. This results is a smooth (exponential) drift towards the
- * fixed position, which can increase the stability of the physics simulation.
- * In addition, the alpha parameter can be decayed over time, relaxing the
- * position constraint, which helps to stabilize on an optimal solution.
- *
- * @param {function} [f] the position function.
- */
-pv.Constraint.position = function(f) {
- var a = 1, // default alpha
- constraint = {};
-
- if (!arguments.length) /** @ignore */ f = function(p) { return p.fix; };
-
- /**
- * Sets or gets the alpha parameter for position interpolation. If the alpha
- * parameter is in the range [0,1], then rather than setting the particle's
- * new position directly to the position returned by the supplied position
- * function, the particle's position is interpolated towards the fixed
- * position.
- *
- * @function
- * @name pv.Constraint.position.prototype.alpha
- * @param {number} x the new alpha parameter, in the range [0,1].
- * @returns {pv.Constraint.position} this.
- */
- constraint.alpha = function(x) {
- if (arguments.length) {
- a = Number(x);
- return constraint;
- }
- return a;
- };
-
- /**
- * Applies this constraint to the specified particles.
- *
- * @function
- * @name pv.Constraint.position.prototype.apply
- * @param {pv.Particle} particles particles to which to apply this constraint.
- */
- constraint.apply = function(particles) {
- for (var p = particles; p; p = p.next) {
- var v = f(p);
- if (v) {
- p.x += (v.x - p.x) * a;
- p.y += (v.y - p.y) * a;
- p.fx = p.fy = p.vx = p.vy = 0;
- }
- }
- };
-
- return constraint;
-};
-/**
- * Constructs a new bound constraint. Before the constraint can be used, the
- * {@link #x} and {@link #y} methods must be call to specify the bounds.
- *
- * @class Constrains particles to within fixed rectangular bounds. For example,
- * this constraint can be used to constrain particles in a physics simulation
- * within the bounds of an enclosing panel.
- *
- *
Note that the current implementation treats particles as points, with no
- * area. If the particles are rendered as dots, be sure to include some
- * additional padding to inset the bounds such that the edges of the dots do not
- * get clipped by the panel bounds. If the particles have different radii, this
- * constraint would need to be extended using a radius function, similar to
- * {@link pv.Constraint.collision}.
- *
- * @see pv.Layout.Force
- * @extends pv.Constraint
- */
-pv.Constraint.bound = function() {
- var constraint = {},
- x,
- y;
-
- /**
- * Sets or gets the bounds on the x-coordinate.
- *
- * @function
- * @name pv.Constraint.bound.prototype.x
- * @param {number} min the minimum allowed x-coordinate.
- * @param {number} max the maximum allowed x-coordinate.
- * @returns {pv.Constraint.bound} this.
- */
- constraint.x = function(min, max) {
- if (arguments.length) {
- x = {min: Math.min(min, max), max: Math.max(min, max)};
- return this;
- }
- return x;
- };
-
- /**
- * Sets or gets the bounds on the y-coordinate.
- *
- * @function
- * @name pv.Constraint.bound.prototype.y
- * @param {number} min the minimum allowed y-coordinate.
- * @param {number} max the maximum allowed y-coordinate.
- * @returns {pv.Constraint.bound} this.
- */
- constraint.y = function(min, max) {
- if (arguments.length) {
- y = {min: Math.min(min, max), max: Math.max(min, max)};
- return this;
- }
- return y;
- };
-
- /**
- * Applies this constraint to the specified particles.
- *
- * @function
- * @name pv.Constraint.bound.prototype.apply
- * @param {pv.Particle} particles particles to which to apply this constraint.
- */
- constraint.apply = function(particles) {
- if (x) for (var p = particles; p; p = p.next) {
- p.x = p.x < x.min ? x.min : (p.x > x.max ? x.max : p.x);
- }
- if (y) for (var p = particles; p; p = p.next) {
- p.y = p.y < y.min ? y.min : (p.y > y.max ? y.max : p.y);
- }
- };
-
- return constraint;
-};
-/**
- * Constructs a new, empty layout with default properties. Layouts are not
- * typically constructed directly; instead, a concrete subclass is added to an
- * existing panel via {@link pv.Mark#add}.
- *
- * @class Represents an abstract layout, encapsulating a visualization technique
- * such as a streamgraph or treemap. Layouts are themselves containers,
- * extending from {@link pv.Panel}, and defining a set of mark prototypes as
- * children. These mark prototypes provide default properties that together
- * implement the given visualization technique.
- *
- *
Layouts do not initially contain any marks; any exported marks (such as a
- * network layout's link and node) are intended to be used as
- * prototypes. By adding a concrete mark, such as a {@link pv.Bar}, to the
- * appropriate mark prototype, the mark is added to the layout and inherits the
- * given properties. This approach allows further customization of the layout,
- * either by choosing a different mark type to add, or more simply by overriding
- * some of the layout's defined properties.
- *
- *
Each concrete layout, such as treemap or circle-packing, has different
- * behavior and may export different mark prototypes, depending on what marks
- * are typically needed to render the desired visualization. Therefore it is
- * important to understand how each layout is structured, such that the provided
- * mark prototypes are used appropriately.
- *
- *
In addition to the mark prototypes, layouts may define custom properties
- * that affect the overall behavior of the layout. For example, a treemap layout
- * might use a property to specify which layout algorithm to use. These
- * properties are just like other mark properties, and can be defined as
- * constants or as functions. As with panels, the data property can be used to
- * replicate layouts, and properties can be defined to in terms of layout data.
- *
- * @extends pv.Panel
- */
-pv.Layout = function() {
- pv.Panel.call(this);
-};
-
-pv.Layout.prototype = pv.extend(pv.Panel);
-
-/**
- * @private Defines a local property with the specified name and cast. Note that
- * although the property method is only defined locally, the cast function is
- * global, which is necessary since properties are inherited!
- *
- * @param {string} name the property name.
- * @param {function} [cast] the cast function for this property.
- */
-pv.Layout.prototype.property = function(name, cast) {
- if (!this.hasOwnProperty("properties")) {
- this.properties = pv.extend(this.properties);
- }
- this.properties[name] = true;
- this.propertyMethod(name, false, pv.Mark.cast[name] = cast);
- return this;
-};
-/**
- * Constructs a new, empty network layout. Layouts are not typically constructed
- * directly; instead, they are added to an existing panel via
- * {@link pv.Mark#add}.
- *
- * @class Represents an abstract layout for network diagrams. This class
- * provides the basic structure for both node-link diagrams (such as
- * force-directed graph layout) and space-filling network diagrams (such as
- * sunbursts and treemaps). Note that "network" here is a general term that
- * includes hierarchical structures; a tree is represented using links from
- * child to parent.
- *
- *
Network layouts require the graph data structure to be defined using two
- * properties:
- *
- *
nodes - an array of objects representing nodes. Objects in this
- * array must conform to the {@link pv.Layout.Network.Node} interface; which is
- * to say, be careful to avoid naming collisions with automatic attributes such
- * as index and linkDegree. If the nodes property is defined
- * as an array of primitives, such as numbers or strings, these primitives are
- * automatically wrapped in an object; the resulting object's nodeValue
- * attribute points to the original primitive value.
- *
- *
links - an array of objects representing links. Objects in
- * this array must conform to the {@link pv.Layout.Network.Link} interface; at a
- * minimum, either source and target indexes or
- * sourceNode and targetNode references must be set. Note that
- * if the links property is defined after the nodes property, the links can be
- * defined in terms of this.nodes().
- *
- *
- *
- *
Three standard mark prototypes are provided:
- *
- *
node - for rendering nodes; typically a {@link pv.Dot}. The node
- * mark is added directly to the layout, with the data property defined via the
- * layout's nodes property. Properties such as strokeStyle and
- * fillStyle can be overridden to compute properties from node data
- * dynamically.
- *
- *
link - for rendering links; typically a {@link pv.Line}. The
- * link mark is added to a child panel, whose data property is defined as
- * layout's links property. The link's data property is then a
- * two-element array of the source node and target node. Thus, poperties such as
- * strokeStyle and fillStyle can be overridden to compute
- * properties from either the node data (the first argument) or the link data
- * (the second argument; the parent panel data) dynamically.
- *
- *
label - for rendering node labels; typically a
- * {@link pv.Label}. The label mark is added directly to the layout, with the
- * data property defined via the layout's nodes property. Properties
- * such as strokeStyle and fillStyle can be overridden to
- * compute properties from node data dynamically.
- *
- *
Note that some network implementations may not support all three
- * standard mark prototypes; for example, space-filling hierarchical layouts
- * typically do not use a link prototype, as the parent-child links are
- * implied by the structure of the space-filling node marks. Check the
- * specific network layout for implementation details.
- *
- *
Network layout properties, including nodes and links,
- * are typically cached rather than re-evaluated with every call to render. This
- * is a performance optimization, as network layout algorithms can be
- * expensive. If the network structure changes, call {@link #reset} to clear the
- * cache before rendering. Note that although the network layout properties are
- * cached, child mark properties, such as the marks used to render the nodes and
- * links, are not. Therefore, non-structural changes to the network
- * layout, such as changing the color of a mark on mouseover, do not need to
- * reset the layout.
- *
- * @see pv.Layout.Hierarchy
- * @see pv.Layout.Force
- * @see pv.Layout.Matrix
- * @see pv.Layout.Arc
- * @see pv.Layout.Rollup
- * @extends pv.Layout
- */
-pv.Layout.Network = function() {
- pv.Layout.call(this);
- var that = this;
-
- /* @private Version tracking to cache layout state, improving performance. */
- this.$id = pv.id();
-
- /**
- * The node prototype. This prototype is intended to be used with a Dot mark
- * in conjunction with the link prototype.
- *
- * @type pv.Mark
- * @name pv.Layout.Network.prototype.node
- */
- (this.node = new pv.Mark()
- .data(function() { return that.nodes(); })
- .strokeStyle("#1f77b4")
- .fillStyle("#fff")
- .left(function(n) { return n.x; })
- .top(function(n) { return n.y; })).parent = this;
-
- /**
- * The link prototype, which renders edges between source nodes and target
- * nodes. This prototype is intended to be used with a Line mark in
- * conjunction with the node prototype.
- *
- * @type pv.Mark
- * @name pv.Layout.Network.prototype.link
- */
- this.link = new pv.Mark()
- .extend(this.node)
- .data(function(p) { return [p.sourceNode, p.targetNode]; })
- .fillStyle(null)
- .lineWidth(function(d, p) { return p.linkValue * 1.5; })
- .strokeStyle("rgba(0,0,0,.2)");
-
- this.link.add = function(type) {
- return that.add(pv.Panel)
- .data(function() { return that.links(); })
- .add(type)
- .extend(this);
- };
-
- /**
- * The node label prototype, which renders the node name adjacent to the node.
- * This prototype is provided as an alternative to using the anchor on the
- * node mark; it is primarily intended to be used with radial node-link
- * layouts, since it provides a convenient mechanism to set the text angle.
- *
- * @type pv.Mark
- * @name pv.Layout.Network.prototype.label
- */
- (this.label = new pv.Mark()
- .extend(this.node)
- .textMargin(7)
- .textBaseline("middle")
- .text(function(n) { return n.nodeName || n.nodeValue; })
- .textAngle(function(n) {
- var a = n.midAngle;
- return pv.Wedge.upright(a) ? a : (a + Math.PI);
- })
- .textAlign(function(n) {
- return pv.Wedge.upright(n.midAngle) ? "left" : "right";
- })).parent = this;
-};
-
-/**
- * @class Represents a node in a network layout. There is no explicit
- * constructor; this class merely serves to document the attributes that are
- * used on nodes in network layouts. (Note that hierarchical nodes place
- * additional requirements on node representation, vis {@link pv.Dom.Node}.)
- *
- * @see pv.Layout.Network
- * @name pv.Layout.Network.Node
- */
-
-/**
- * The node index, zero-based. This attribute is populated automatically based
- * on the index in the array returned by the nodes property.
- *
- * @type number
- * @name pv.Layout.Network.Node.prototype.index
- */
-
-/**
- * The link degree; the sum of link values for all incoming and outgoing links.
- * This attribute is populated automatically.
- *
- * @type number
- * @name pv.Layout.Network.Node.prototype.linkDegree
- */
-
-/**
- * The node name; optional. If present, this attribute will be used to provide
- * the text for node labels. If not present, the label text will fallback to the
- * nodeValue attribute.
- *
- * @type string
- * @name pv.Layout.Network.Node.prototype.nodeName
- */
-
-/**
- * The node value; optional. If present, and no nodeName attribute is
- * present, the node value will be used as the label text. This attribute is
- * also automatically populated if the nodes are specified as an array of
- * primitives, such as strings or numbers.
- *
- * @type object
- * @name pv.Layout.Network.Node.prototype.nodeValue
- */
-
-/**
- * @class Represents a link in a network layout. There is no explicit
- * constructor; this class merely serves to document the attributes that are
- * used on links in network layouts. For hierarchical layouts, this class is
- * used to represent the parent-child links.
- *
- * @see pv.Layout.Network
- * @name pv.Layout.Network.Link
- */
-
-/**
- * The link value, or weight; optional. If not specified (or not a number), the
- * default value of 1 is used.
- *
- * @type number
- * @name pv.Layout.Network.Link.prototype.linkValue
- */
-
-/**
- * The link's source node. If not set, this value will be derived from the
- * source attribute index.
- *
- * @type pv.Layout.Network.Node
- * @name pv.Layout.Network.Link.prototype.sourceNode
- */
-
-/**
- * The link's target node. If not set, this value will be derived from the
- * target attribute index.
- *
- * @type pv.Layout.Network.Node
- * @name pv.Layout.Network.Link.prototype.targetNode
- */
-
-/**
- * Alias for sourceNode, as expressed by the index of the source node.
- * This attribute is not populated automatically, but may be used as a more
- * convenient identification of the link's source, for example in a static JSON
- * representation.
- *
- * @type number
- * @name pv.Layout.Network.Link.prototype.source
- */
-
-/**
- * Alias for targetNode, as expressed by the index of the target node.
- * This attribute is not populated automatically, but may be used as a more
- * convenient identification of the link's target, for example in a static JSON
- * representation.
- *
- * @type number
- * @name pv.Layout.Network.Link.prototype.target
- */
-
-/**
- * Alias for linkValue. This attribute is not populated automatically,
- * but may be used instead of the linkValue attribute when specifying
- * links.
- *
- * @type number
- * @name pv.Layout.Network.Link.prototype.value
- */
-
-/** @private Transform nodes and links on cast. */
-pv.Layout.Network.prototype = pv.extend(pv.Layout)
- .property("nodes", function(v) {
- return v.map(function(d, i) {
- if (typeof d != "object") d = {nodeValue: d};
- d.index = i;
- d.linkDegree = 0;
- return d;
- });
- })
- .property("links", function(v) {
- return v.map(function(d) {
- if (isNaN(d.linkValue)) d.linkValue = isNaN(d.value) ? 1 : d.value;
- return d;
- });
- });
-
-/**
- * Resets the cache, such that changes to layout property definitions will be
- * visible on subsequent render. Unlike normal marks (and normal layouts),
- * properties associated with network layouts are not automatically re-evaluated
- * on render; the properties are cached, and any expensive layout algorithms are
- * only run after the layout is explicitly reset.
- *
- * @returns {pv.Layout.Network} this.
- */
-pv.Layout.Network.prototype.reset = function() {
- this.$id = pv.id();
- return this;
-};
-
-/** @private Skip evaluating properties if cached. */
-pv.Layout.Network.prototype.buildProperties = function(s, properties) {
- if ((s.$id || 0) < this.$id) {
- pv.Layout.prototype.buildProperties.call(this, s, properties);
- }
-};
-
-/** @private Compute link degrees; map source and target indexes to nodes. */
-pv.Layout.Network.prototype.buildImplied = function(s) {
- pv.Layout.prototype.buildImplied.call(this, s);
- if (s.$id >= this.$id) return true;
- s.$id = this.$id;
- s.links.forEach(function(d) {
- var v = d.linkValue;
- (d.sourceNode || (d.sourceNode = s.nodes[d.source])).linkDegree += v;
- (d.targetNode || (d.targetNode = s.nodes[d.target])).linkDegree += v;
- });
-};
-/**
- * Constructs a new, empty hierarchy layout. Layouts are not typically
- * constructed directly; instead, they are added to an existing panel via
- * {@link pv.Mark#add}.
- *
- * @class Represents an abstract layout for hierarchy diagrams. This class is a
- * specialization of {@link pv.Layout.Network}, providing the basic structure
- * for both hierarchical node-link diagrams (such as Reingold-Tilford trees) and
- * space-filling hierarchy diagrams (such as sunbursts and treemaps).
- *
- *
Unlike general network layouts, the links property need not be
- * defined explicitly. Instead, the links are computed implicitly from the
- * parentNode attribute of the node objects, as defined by the
- * nodes property. This implementation is also available as
- * {@link #links}, for reuse with non-hierarchical layouts; for example, to
- * render a tree using force-directed layout.
- *
- *
Correspondingly, the nodes property is represented as a union of
- * {@link pv.Layout.Network.Node} and {@link pv.Dom.Node}. To construct a node
- * hierarchy from a simple JSON map, use the {@link pv.Dom} operator; this
- * operator also provides an easy way to sort nodes before passing them to the
- * layout.
- *
- *
For more details on how to use this layout, see
- * {@link pv.Layout.Network}.
- *
- * @see pv.Layout.Cluster
- * @see pv.Layout.Partition
- * @see pv.Layout.Tree
- * @see pv.Layout.Treemap
- * @see pv.Layout.Indent
- * @see pv.Layout.Pack
- * @extends pv.Layout.Network
- */
-pv.Layout.Hierarchy = function() {
- pv.Layout.Network.call(this);
- this.link.strokeStyle("#ccc");
-};
-
-pv.Layout.Hierarchy.prototype = pv.extend(pv.Layout.Network);
-
-/** @private Compute the implied links. (Links are null by default.) */
-pv.Layout.Hierarchy.prototype.buildImplied = function(s) {
- if (!s.links) s.links = pv.Layout.Hierarchy.links.call(this);
- pv.Layout.Network.prototype.buildImplied.call(this, s);
-};
-
-/** The implied links; computes links using the parentNode attribute. */
-pv.Layout.Hierarchy.links = function() {
- return this.nodes()
- .filter(function(n) { return n.parentNode; })
- .map(function(n) {
- return {
- sourceNode: n,
- targetNode: n.parentNode,
- linkValue: 1
- };
- });
-};
-
-/** @private Provides standard node-link layout based on breadth & depth. */
-pv.Layout.Hierarchy.NodeLink = {
-
- /** @private */
- buildImplied: function(s) {
- var nodes = s.nodes,
- orient = s.orient,
- horizontal = /^(top|bottom)$/.test(orient),
- w = s.width,
- h = s.height;
-
- /* Compute default inner and outer radius. */
- if (orient == "radial") {
- var ir = s.innerRadius, or = s.outerRadius;
- if (ir == null) ir = 0;
- if (or == null) or = Math.min(w, h) / 2;
- }
-
- /** @private Returns the radius of the given node. */
- function radius(n) {
- return n.parentNode ? (n.depth * (or - ir) + ir) : 0;
- }
-
- /** @private Returns the angle of the given node. */
- function midAngle(n) {
- return (n.parentNode ? (n.breadth - .25) * 2 * Math.PI : 0);
- }
-
- /** @private */
- function x(n) {
- switch (orient) {
- case "left": return n.depth * w;
- case "right": return w - n.depth * w;
- case "top": return n.breadth * w;
- case "bottom": return w - n.breadth * w;
- case "radial": return w / 2 + radius(n) * Math.cos(n.midAngle);
- }
- }
-
- /** @private */
- function y(n) {
- switch (orient) {
- case "left": return n.breadth * h;
- case "right": return h - n.breadth * h;
- case "top": return n.depth * h;
- case "bottom": return h - n.depth * h;
- case "radial": return h / 2 + radius(n) * Math.sin(n.midAngle);
- }
- }
-
- for (var i = 0; i < nodes.length; i++) {
- var n = nodes[i];
- n.midAngle = orient == "radial" ? midAngle(n)
- : horizontal ? Math.PI / 2 : 0;
- n.x = x(n);
- n.y = y(n);
- if (n.firstChild) n.midAngle += Math.PI;
- }
- }
-};
-
-/** @private Provides standard space-filling layout based on breadth & depth. */
-pv.Layout.Hierarchy.Fill = {
-
- /** @private */
- constructor: function() {
- this.node
- .strokeStyle("#fff")
- .fillStyle("#ccc")
- .width(function(n) { return n.dx; })
- .height(function(n) { return n.dy; })
- .innerRadius(function(n) { return n.innerRadius; })
- .outerRadius(function(n) { return n.outerRadius; })
- .startAngle(function(n) { return n.startAngle; })
- .angle(function(n) { return n.angle; });
-
- this.label
- .textAlign("center")
- .left(function(n) { return n.x + (n.dx / 2); })
- .top(function(n) { return n.y + (n.dy / 2); });
-
- /* Hide unsupported link. */
- delete this.link;
- },
-
- /** @private */
- buildImplied: function(s) {
- var nodes = s.nodes,
- orient = s.orient,
- horizontal = /^(top|bottom)$/.test(orient),
- w = s.width,
- h = s.height,
- depth = -nodes[0].minDepth;
-
- /* Compute default inner and outer radius. */
- if (orient == "radial") {
- var ir = s.innerRadius, or = s.outerRadius;
- if (ir == null) ir = 0;
- if (ir) depth *= 2; // use full depth step for root
- if (or == null) or = Math.min(w, h) / 2;
- }
-
- /** @private Scales the specified depth for a space-filling layout. */
- function scale(d, depth) {
- return (d + depth) / (1 + depth);
- }
-
- /** @private */
- function x(n) {
- switch (orient) {
- case "left": return scale(n.minDepth, depth) * w;
- case "right": return (1 - scale(n.maxDepth, depth)) * w;
- case "top": return n.minBreadth * w;
- case "bottom": return (1 - n.maxBreadth) * w;
- case "radial": return w / 2;
- }
- }
-
- /** @private */
- function y(n) {
- switch (orient) {
- case "left": return n.minBreadth * h;
- case "right": return (1 - n.maxBreadth) * h;
- case "top": return scale(n.minDepth, depth) * h;
- case "bottom": return (1 - scale(n.maxDepth, depth)) * h;
- case "radial": return h / 2;
- }
- }
-
- /** @private */
- function dx(n) {
- switch (orient) {
- case "left":
- case "right": return (n.maxDepth - n.minDepth) / (1 + depth) * w;
- case "top":
- case "bottom": return (n.maxBreadth - n.minBreadth) * w;
- case "radial": return n.parentNode ? (n.innerRadius + n.outerRadius) * Math.cos(n.midAngle) : 0;
- }
- }
-
- /** @private */
- function dy(n) {
- switch (orient) {
- case "left":
- case "right": return (n.maxBreadth - n.minBreadth) * h;
- case "top":
- case "bottom": return (n.maxDepth - n.minDepth) / (1 + depth) * h;
- case "radial": return n.parentNode ? (n.innerRadius + n.outerRadius) * Math.sin(n.midAngle) : 0;
- }
- }
-
- /** @private */
- function innerRadius(n) {
- return Math.max(0, scale(n.minDepth, depth / 2)) * (or - ir) + ir;
- }
-
- /** @private */
- function outerRadius(n) {
- return scale(n.maxDepth, depth / 2) * (or - ir) + ir;
- }
-
- /** @private */
- function startAngle(n) {
- return (n.parentNode ? n.minBreadth - .25 : 0) * 2 * Math.PI;
- }
-
- /** @private */
- function angle(n) {
- return (n.parentNode ? n.maxBreadth - n.minBreadth : 1) * 2 * Math.PI;
- }
-
- for (var i = 0; i < nodes.length; i++) {
- var n = nodes[i];
- n.x = x(n);
- n.y = y(n);
- if (orient == "radial") {
- n.innerRadius = innerRadius(n);
- n.outerRadius = outerRadius(n);
- n.startAngle = startAngle(n);
- n.angle = angle(n);
- n.midAngle = n.startAngle + n.angle / 2;
- } else {
- n.midAngle = horizontal ? -Math.PI / 2 : 0;
- }
- n.dx = dx(n);
- n.dy = dy(n);
- }
- }
-};
-/**
- * Constructs a new, empty grid layout. Layouts are not typically constructed
- * directly; instead, they are added to an existing panel via
- * {@link pv.Mark#add}.
- *
- * @class Implements a grid layout with regularly-sized rows and columns. The
- * number of rows and columns are determined from their respective
- * properties. For example, the 2×3 array:
- *
- *
1 2 3
- * 4 5 6
- *
- * can be represented using the rows property as:
- *
- *
[[1, 2, 3], [4, 5, 6]]
- *
- * If your data is in column-major order, you can equivalently use the
- * columns property. If the rows property is an array, it
- * takes priority over the columns property. The data is implicitly
- * transposed, as if the {@link pv.transpose} operator were applied.
- *
- *
This layout exports a single cell mark prototype, which is
- * intended to be used with a bar, panel, layout, or subclass thereof. The data
- * property of the cell prototype is defined as the elements in the array. For
- * example, if the array is a two-dimensional array of values in the range
- * [0,1], a simple heatmap can be generated as:
- *
- *
- *
- * The grid subdivides the full width and height of the parent panel into equal
- * rectangles. Note, however, that for large, interactive, or animated heatmaps,
- * you may see significantly better performance through dynamic {@link pv.Image}
- * generation.
- *
- *
For irregular grids using value-based spatial partitioning, see {@link
- * pv.Layout.Treemap}.
- *
- * @extends pv.Layout
- */
-pv.Layout.Grid = function() {
- pv.Layout.call(this);
- var that = this;
-
- /**
- * The cell prototype. This prototype is intended to be used with a bar,
- * panel, or layout (or subclass thereof) to render the grid cells.
- *
- * @type pv.Mark
- * @name pv.Layout.Grid.prototype.cell
- */
- (this.cell = new pv.Mark()
- .data(function() {
- return that.scene[that.index].$grid;
- })
- .width(function() {
- return that.width() / that.cols();
- })
- .height(function() {
- return that.height() / that.rows();
- })
- .left(function() {
- return this.width() * (this.index % that.cols());
- })
- .top(function() {
- return this.height() * Math.floor(this.index / that.cols());
- })).parent = this;
-};
-
-pv.Layout.Grid.prototype = pv.extend(pv.Layout)
- .property("rows")
- .property("cols");
-
-/**
- * Default properties for grid layouts. By default, there is one row and one
- * column, and the data is the propagated to the child cell.
- *
- * @type pv.Layout.Grid
- */
-pv.Layout.Grid.prototype.defaults = new pv.Layout.Grid()
- .extend(pv.Layout.prototype.defaults)
- .rows(1)
- .cols(1);
-
-/** @private */
-pv.Layout.Grid.prototype.buildImplied = function(s) {
- pv.Layout.prototype.buildImplied.call(this, s);
- var r = s.rows, c = s.cols;
- if (typeof c == "object") r = pv.transpose(c);
- if (typeof r == "object") {
- s.$grid = pv.blend(r);
- s.rows = r.length;
- s.cols = r[0] ? r[0].length : 0;
- } else {
- s.$grid = pv.repeat([s.data], r * c);
- }
-};
-
-/**
- * The number of rows. This property can also be specified as the data in
- * row-major order; in this case, the rows property is implicitly set to the
- * length of the array, and the cols property is set to the length of the first
- * element in the array.
- *
- * @type number
- * @name pv.Layout.Grid.prototype.rows
- */
-
-/**
- * The number of columns. This property can also be specified as the data in
- * column-major order; in this case, the cols property is implicitly set to the
- * length of the array, and the rows property is set to the length of the first
- * element in the array.
- *
- * @type number
- * @name pv.Layout.Grid.prototype.cols
- */
-/**
- * Constructs a new, empty stack layout. Layouts are not typically constructed
- * directly; instead, they are added to an existing panel via
- * {@link pv.Mark#add}.
- *
- * @class Implements a layout for stacked visualizations, ranging from simple
- * stacked bar charts to more elaborate "streamgraphs" composed of stacked
- * areas. Stack layouts uses length as a visual encoding, as opposed to
- * position, as the layers do not share an aligned axis.
- *
- *
Marks can be stacked vertically or horizontally. For example,
- *
- *
- *
- * specifies a vertically-stacked area chart, using the default "bottom-left"
- * orientation with "zero" offset. This visualization can be easily changed into
- * a streamgraph using the "wiggle" offset, which attempts to minimize change in
- * slope weighted by layer thickness. See the {@link #offset} property for more
- * supported streamgraph algorithms.
- *
- *
In the simplest case, the layer data can be specified as a two-dimensional
- * array of numbers. The x and y psuedo-properties are used to
- * define the thickness of each layer at the given position, respectively; in
- * the above example of the "bottom-left" orientation, the x and
- * y psuedo-properties are equivalent to the left and
- * height properties that you might use if you implemented a stacked
- * area by hand.
- *
- *
The advantage of using the stack layout is that the baseline, i.e., the
- * bottom property is computed automatically using the specified offset
- * algorithm. In addition, the order of layers can be computed using a built-in
- * algorithm via the order property.
- *
- *
With the exception of the "expand" offset, the stack layout does
- * not perform any automatic scaling of data; the values returned from
- * x and y specify pixel sizes. To simplify scaling math, use
- * this layout in conjunction with {@link pv.Scale.linear} or similar.
- *
- *
In other cases, the values psuedo-property can be used to define
- * the data more flexibly. As with a typical panel & area, the
- * layers property corresponds to the data in the enclosing panel,
- * while the values psuedo-property corresponds to the data for the
- * area within the panel. For example, given an array of data values:
- *
- *
- *
- * As with the panel & area case, the datum that is passed to the
- * psuedo-properties x and y are the values (an element in
- * crimea); the second argument is the layer data (a string in
- * causes). Additional arguments specify the data of enclosing panels,
- * if any.
- *
- * @extends pv.Layout
- */
-pv.Layout.Stack = function() {
- pv.Layout.call(this);
- var that = this,
- /** @ignore */ none = function() { return null; },
- prop = {t: none, l: none, r: none, b: none, w: none, h: none},
- values,
- buildImplied = that.buildImplied;
-
- /** @private Proxy the given property on the layer. */
- function proxy(name) {
- return function() {
- return prop[name](this.parent.index, this.index);
- };
- }
-
- /** @private Compute the layout! */
- this.buildImplied = function(s) {
- buildImplied.call(this, s);
-
- var data = s.layers,
- n = data.length,
- m,
- orient = s.orient,
- horizontal = /^(top|bottom)\b/.test(orient),
- h = this.parent[horizontal ? "height" : "width"](),
- x = [],
- y = [],
- dy = [];
-
- /*
- * Iterate over the data, evaluating the values, x and y functions. The
- * context in which the x and y psuedo-properties are evaluated is a
- * pseudo-mark that is a grandchild of this layout.
- */
- var stack = pv.Mark.stack, o = {parent: {parent: this}};
- stack.unshift(null);
- values = [];
- for (var i = 0; i < n; i++) {
- dy[i] = [];
- y[i] = [];
- o.parent.index = i;
- stack[0] = data[i];
- values[i] = this.$values.apply(o.parent, stack);
- if (!i) m = values[i].length;
- stack.unshift(null);
- for (var j = 0; j < m; j++) {
- stack[0] = values[i][j];
- o.index = j;
- if (!i) x[j] = this.$x.apply(o, stack);
- dy[i][j] = this.$y.apply(o, stack);
- }
- stack.shift();
- }
- stack.shift();
-
- /* order */
- var index;
- switch (s.order) {
- case "inside-out": {
- var max = dy.map(function(v) { return pv.max.index(v); }),
- map = pv.range(n).sort(function(a, b) { return max[a] - max[b]; }),
- sums = dy.map(function(v) { return pv.sum(v); }),
- top = 0,
- bottom = 0,
- tops = [],
- bottoms = [];
- for (var i = 0; i < n; i++) {
- var j = map[i];
- if (top < bottom) {
- top += sums[j];
- tops.push(j);
- } else {
- bottom += sums[j];
- bottoms.push(j);
- }
- }
- index = bottoms.reverse().concat(tops);
- break;
- }
- case "reverse": index = pv.range(n - 1, -1, -1); break;
- default: index = pv.range(n); break;
- }
-
- /* offset */
- switch (s.offset) {
- case "silohouette": {
- for (var j = 0; j < m; j++) {
- var o = 0;
- for (var i = 0; i < n; i++) o += dy[i][j];
- y[index[0]][j] = (h - o) / 2;
- }
- break;
- }
- case "wiggle": {
- var o = 0;
- for (var i = 0; i < n; i++) o += dy[i][0];
- y[index[0]][0] = o = (h - o) / 2;
- for (var j = 1; j < m; j++) {
- var s1 = 0, s2 = 0, dx = x[j] - x[j - 1];
- for (var i = 0; i < n; i++) s1 += dy[i][j];
- for (var i = 0; i < n; i++) {
- var s3 = (dy[index[i]][j] - dy[index[i]][j - 1]) / (2 * dx);
- for (var k = 0; k < i; k++) {
- s3 += (dy[index[k]][j] - dy[index[k]][j - 1]) / dx;
- }
- s2 += s3 * dy[index[i]][j];
- }
- y[index[0]][j] = o -= s1 ? s2 / s1 * dx : 0;
- }
- break;
- }
- case "expand": {
- for (var j = 0; j < m; j++) {
- y[index[0]][j] = 0;
- var k = 0;
- for (var i = 0; i < n; i++) k += dy[i][j];
- if (k) {
- k = h / k;
- for (var i = 0; i < n; i++) dy[i][j] *= k;
- } else {
- k = h / n;
- for (var i = 0; i < n; i++) dy[i][j] = k;
- }
- }
- break;
- }
- default: {
- for (var j = 0; j < m; j++) y[index[0]][j] = 0;
- break;
- }
- }
-
- /* Propagate the offset to the other series. */
- for (var j = 0; j < m; j++) {
- var o = y[index[0]][j];
- for (var i = 1; i < n; i++) {
- o += dy[index[i - 1]][j];
- y[index[i]][j] = o;
- }
- }
-
- /* Find the property definitions for dynamic substitution. */
- var i = orient.indexOf("-"),
- pdy = horizontal ? "h" : "w",
- px = i < 0 ? (horizontal ? "l" : "b") : orient.charAt(i + 1),
- py = orient.charAt(0);
- for (var p in prop) prop[p] = none;
- prop[px] = function(i, j) { return x[j]; };
- prop[py] = function(i, j) { return y[i][j]; };
- prop[pdy] = function(i, j) { return dy[i][j]; };
- };
-
- /**
- * The layer prototype. This prototype is intended to be used with an area,
- * bar or panel mark (or subclass thereof). Other mark types may be possible,
- * though note that the stack layout is not currently designed to support
- * radial stacked visualizations using wedges.
- *
- *
The layer is not a direct child of the stack layout; a hidden panel is
- * used to replicate layers.
- *
- * @type pv.Mark
- * @name pv.Layout.Stack.prototype.layer
- */
- this.layer = new pv.Mark()
- .data(function() { return values[this.parent.index]; })
- .top(proxy("t"))
- .left(proxy("l"))
- .right(proxy("r"))
- .bottom(proxy("b"))
- .width(proxy("w"))
- .height(proxy("h"));
-
- this.layer.add = function(type) {
- return that.add(pv.Panel)
- .data(function() { return that.layers(); })
- .add(type)
- .extend(this);
- };
-};
-
-pv.Layout.Stack.prototype = pv.extend(pv.Layout)
- .property("orient", String)
- .property("offset", String)
- .property("order", String)
- .property("layers");
-
-/**
- * Default properties for stack layouts. The default orientation is
- * "bottom-left", the default offset is "zero", and the default layers is
- * [[]].
- *
- * @type pv.Layout.Stack
- */
-pv.Layout.Stack.prototype.defaults = new pv.Layout.Stack()
- .extend(pv.Layout.prototype.defaults)
- .orient("bottom-left")
- .offset("zero")
- .layers([[]]);
-
-/** @private */
-pv.Layout.Stack.prototype.$x
- = /** @private */ pv.Layout.Stack.prototype.$y
- = function() { return 0; };
-
-/**
- * The x psuedo-property; determines the position of the value within the layer.
- * This typically corresponds to the independent variable. For example, with the
- * default "bottom-left" orientation, this function defines the "left" property.
- *
- * @param {function} f the x function.
- * @returns {pv.Layout.Stack} this.
- */
-pv.Layout.Stack.prototype.x = function(f) {
- /** @private */ this.$x = pv.functor(f);
- return this;
-};
-
-/**
- * The y psuedo-property; determines the thickness of the layer at the given
- * value. This typically corresponds to the dependent variable. For example,
- * with the default "bottom-left" orientation, this function defines the
- * "height" property.
- *
- * @param {function} f the y function.
- * @returns {pv.Layout.Stack} this.
- */
-pv.Layout.Stack.prototype.y = function(f) {
- /** @private */ this.$y = pv.functor(f);
- return this;
-};
-
-/** @private The default value function; identity. */
-pv.Layout.Stack.prototype.$values = pv.identity;
-
-/**
- * The values function; determines the values for a given layer. The default
- * value is the identity function, which assumes that the layers property is
- * specified as a two-dimensional (i.e., nested) array.
- *
- * @param {function} f the values function.
- * @returns {pv.Layout.Stack} this.
- */
-pv.Layout.Stack.prototype.values = function(f) {
- this.$values = pv.functor(f);
- return this;
-};
-
-/**
- * The layer data in row-major order. The value of this property is typically a
- * two-dimensional (i.e., nested) array, but any array can be used, provided the
- * values psuedo-property is defined accordingly.
- *
- * @type array[]
- * @name pv.Layout.Stack.prototype.layers
- */
-
-/**
- * The layer orientation. The following values are supported:
- *
- *
bottom-left == bottom
- *
bottom-right
- *
top-left == top
- *
top-right
- *
left-top
- *
left-bottom == left
- *
right-top
- *
right-bottom == right
- *
- *
. The default value is "bottom-left", which means that the layers will
- * be built from the bottom-up, and the values within layers will be laid out
- * from left-to-right.
- *
- *
Note that with non-zero baselines, some orientations may give similar
- * results. For example, offset("silohouette") centers the layers, resulting in
- * a streamgraph. Thus, the orientations "bottom-left" and "top-left" will
- * produce similar results, differing only in the layer order.
- *
- * @type string
- * @name pv.Layout.Stack.prototype.orient
- */
-
-/**
- * The layer order. The following values are supported:
- *
- *
null - use given layer order.
- *
inside-out - sort by maximum value, with balanced order.
- *
reverse - use reverse of given layer order.
- *
- *
For details on the inside-out order algorithm, refer to "Stacked Graphs
- * -- Geometry & Aesthetics" by L. Byron and M. Wattenberg, IEEE TVCG
- * November/December 2008.
- *
- * @type string
- * @name pv.Layout.Stack.prototype.order
- */
-
-/**
- * The layer offset; the y-position of the bottom of the lowest layer. The
- * following values are supported:
- *
- *
zero - use a zero baseline, i.e., the y-axis.
- *
silohouette - center the stream, i.e., ThemeRiver.
- *
wiggle - minimize weighted change in slope.
- *
expand - expand layers to fill the enclosing layout dimensions.
- *
- *
For details on these offset algorithms, refer to "Stacked Graphs --
- * Geometry & Aesthetics" by L. Byron and M. Wattenberg, IEEE TVCG
- * November/December 2008.
- *
- * @type string
- * @name pv.Layout.Stack.prototype.offset
- */
-/**
- * Constructs a new, empty treemap layout. Layouts are not typically
- * constructed directly; instead, they are added to an existing panel via
- * {@link pv.Mark#add}.
- *
- * @class Implements a space-filling rectangular layout, with the hierarchy
- * represented via containment. Treemaps represent nodes as boxes, with child
- * nodes placed within parent boxes. The size of each box is proportional to the
- * size of the node in the tree. This particular algorithm is taken from Bruls,
- * D.M., C. Huizing, and J.J. van Wijk, "Squarified Treemaps" in
- * Data Visualization 2000, Proceedings of the Joint Eurographics and IEEE
- * TCVG Sumposium on Visualization, 2000, pp. 33-42.
- *
- *
The meaning of the exported mark prototypes changes slightly in the
- * space-filling implementation:
- *
- *
node - for rendering nodes; typically a {@link pv.Bar}. The node
- * data is populated with dx and dy attributes, in addition to
- * the standard x and y position attributes.
- *
- *
leaf - for rendering leaf nodes only, with no fill or stroke
- * style by default; typically a {@link pv.Panel} or another layout!
- *
- *
link - unsupported; undefined. Links are encoded implicitly
- * in the arrangement of the space-filling nodes.
- *
- *
label - for rendering node labels; typically a
- * {@link pv.Label}.
- *
- *
For more details on how to use this layout, see
- * {@link pv.Layout.Hierarchy}.
- *
- * @extends pv.Layout.Hierarchy
- */
-pv.Layout.Treemap = function() {
- pv.Layout.Hierarchy.call(this);
-
- this.node
- .strokeStyle("#fff")
- .fillStyle("rgba(31, 119, 180, .25)")
- .width(function(n) { return n.dx; })
- .height(function(n) { return n.dy; });
-
- this.label
- .visible(function(n) { return !n.firstChild; })
- .left(function(n) { return n.x + (n.dx / 2); })
- .top(function(n) { return n.y + (n.dy / 2); })
- .textAlign("center")
- .textAngle(function(n) { return n.dx > n.dy ? 0 : -Math.PI / 2; });
-
- (this.leaf = new pv.Mark()
- .extend(this.node)
- .fillStyle(null)
- .strokeStyle(null)
- .visible(function(n) { return !n.firstChild; })).parent = this;
-
- /* Hide unsupported link. */
- delete this.link;
-};
-
-pv.Layout.Treemap.prototype = pv.extend(pv.Layout.Hierarchy)
- .property("round", Boolean)
- .property("paddingLeft", Number)
- .property("paddingRight", Number)
- .property("paddingTop", Number)
- .property("paddingBottom", Number)
- .property("mode", String)
- .property("order", String);
-
-/**
- * Default propertiess for treemap layouts. The default mode is "squarify" and
- * the default order is "ascending".
- *
- * @type pv.Layout.Treemap
- */
-pv.Layout.Treemap.prototype.defaults = new pv.Layout.Treemap()
- .extend(pv.Layout.Hierarchy.prototype.defaults)
- .mode("squarify") // squarify, slice-and-dice, slice, dice
- .order("ascending"); // ascending, descending, reverse, null
-
-/**
- * Whether node sizes should be rounded to integer values. This has a similar
- * effect to setting antialias(false) for node values, but allows the
- * treemap algorithm to accumulate error related to pixel rounding.
- *
- * @type boolean
- * @name pv.Layout.Treemap.prototype.round
- */
-
-/**
- * The left inset between parent add child in pixels. Defaults to 0.
- *
- * @type number
- * @name pv.Layout.Treemap.prototype.paddingLeft
- * @see #padding
- */
-
-/**
- * The right inset between parent add child in pixels. Defaults to 0.
- *
- * @type number
- * @name pv.Layout.Treemap.prototype.paddingRight
- * @see #padding
- */
-
-/**
- * The top inset between parent and child in pixels. Defaults to 0.
- *
- * @type number
- * @name pv.Layout.Treemap.prototype.paddingTop
- * @see #padding
- */
-
-/**
- * The bottom inset between parent and child in pixels. Defaults to 0.
- *
- * @type number
- * @name pv.Layout.Treemap.prototype.paddingBottom
- * @see #padding
- */
-
-/**
- * The treemap algorithm. The default value is "squarify". The "slice-and-dice"
- * algorithm may also be used, which alternates between horizontal and vertical
- * slices for different depths. In addition, the "slice" and "dice" algorithms
- * may be specified explicitly to control whether horizontal or vertical slices
- * are used, which may be useful for nested treemap layouts.
- *
- * @type string
- * @name pv.Layout.Treemap.prototype.mode
- * @see "Ordered Treemap Layouts" by B. Shneiderman & M. Wattenberg, IEEE
- * InfoVis 2001.
- */
-
-/**
- * The sibling node order. A null value means to use the sibling order
- * specified by the nodes property as-is; "reverse" will reverse the given
- * order. The default value "ascending" will sort siblings in ascending order of
- * size, while "descending" will do the reverse. For sorting based on data
- * attributes other than size, use the default null for the order
- * property, and sort the nodes beforehand using the {@link pv.Dom} operator.
- *
- * @type string
- * @name pv.Layout.Treemap.prototype.order
- */
-
-/**
- * Alias for setting the left, right, top and bottom padding properties
- * simultaneously.
- *
- * @see #paddingLeft
- * @see #paddingRight
- * @see #paddingTop
- * @see #paddingBottom
- * @returns {pv.Layout.Treemap} this.
- */
-pv.Layout.Treemap.prototype.padding = function(n) {
- return this.paddingLeft(n).paddingRight(n).paddingTop(n).paddingBottom(n);
-};
-
-/** @private The default size function. */
-pv.Layout.Treemap.prototype.$size = function(d) {
- return Number(d.nodeValue);
-};
-
-/**
- * Specifies the sizing function. By default, the size function uses the
- * nodeValue attribute of nodes as a numeric value: function(d)
- * Number(d.nodeValue).
- *
- *
The sizing function is invoked for each leaf node in the tree, per the
- * nodes property. For example, if the tree data structure represents a
- * file system, with files as leaf nodes, and each file has a bytes
- * attribute, you can specify a size function as:
- *
- *
.size(function(d) d.bytes)
- *
- * @param {function} f the new sizing function.
- * @returns {pv.Layout.Treemap} this.
- */
-pv.Layout.Treemap.prototype.size = function(f) {
- this.$size = pv.functor(f);
- return this;
-};
-
-/** @private */
-pv.Layout.Treemap.prototype.buildImplied = function(s) {
- if (pv.Layout.Hierarchy.prototype.buildImplied.call(this, s)) return;
-
- var that = this,
- nodes = s.nodes,
- root = nodes[0],
- stack = pv.Mark.stack,
- left = s.paddingLeft,
- right = s.paddingRight,
- top = s.paddingTop,
- bottom = s.paddingBottom,
- /** @ignore */ size = function(n) { return n.size; },
- round = s.round ? Math.round : Number,
- mode = s.mode;
-
- /** @private */
- function slice(row, sum, horizontal, x, y, w, h) {
- for (var i = 0, d = 0; i < row.length; i++) {
- var n = row[i];
- if (horizontal) {
- n.x = x + d;
- n.y = y;
- d += n.dx = round(w * n.size / sum);
- n.dy = h;
- } else {
- n.x = x;
- n.y = y + d;
- n.dx = w;
- d += n.dy = round(h * n.size / sum);
- }
- }
- if (n) { // correct on-axis rounding error
- if (horizontal) {
- n.dx += w - d;
- } else {
- n.dy += h - d;
- }
- }
- }
-
- /** @private */
- function ratio(row, l) {
- var rmax = -Infinity, rmin = Infinity, s = 0;
- for (var i = 0; i < row.length; i++) {
- var r = row[i].size;
- if (r < rmin) rmin = r;
- if (r > rmax) rmax = r;
- s += r;
- }
- s = s * s;
- l = l * l;
- return Math.max(l * rmax / s, s / (l * rmin));
- }
-
- /** @private */
- function layout(n, i) {
- var x = n.x + left,
- y = n.y + top,
- w = n.dx - left - right,
- h = n.dy - top - bottom;
-
- /* Assume squarify by default. */
- if (mode != "squarify") {
- slice(n.childNodes, n.size,
- mode == "slice" ? true
- : mode == "dice" ? false
- : i & 1, x, y, w, h);
- return;
- }
-
- var row = [],
- mink = Infinity,
- l = Math.min(w, h),
- k = w * h / n.size;
-
- /* Abort if the size is nonpositive. */
- if (n.size <= 0) return;
-
- /* Scale the sizes to fill the current subregion. */
- n.visitBefore(function(n) { n.size *= k; });
-
- /** @private Position the specified nodes along one dimension. */
- function position(row) {
- var horizontal = w == l,
- sum = pv.sum(row, size),
- r = l ? round(sum / l) : 0;
- slice(row, sum, horizontal, x, y, horizontal ? w : r, horizontal ? r : h);
- if (horizontal) {
- y += r;
- h -= r;
- } else {
- x += r;
- w -= r;
- }
- l = Math.min(w, h);
- return horizontal;
- }
-
- var children = n.childNodes.slice(); // copy
- while (children.length) {
- var child = children[children.length - 1];
- if (!child.size) {
- children.pop();
- continue;
- }
- row.push(child);
-
- var k = ratio(row, l);
- if (k <= mink) {
- children.pop();
- mink = k;
- } else {
- row.pop();
- position(row);
- row.length = 0;
- mink = Infinity;
- }
- }
-
- /* correct off-axis rounding error */
- if (position(row)) for (var i = 0; i < row.length; i++) {
- row[i].dy += h;
- } else for (var i = 0; i < row.length; i++) {
- row[i].dx += w;
- }
- }
-
- /* Recursively compute the node depth and size. */
- stack.unshift(null);
- root.visitAfter(function(n, i) {
- n.depth = i;
- n.x = n.y = n.dx = n.dy = 0;
- n.size = n.firstChild
- ? pv.sum(n.childNodes, function(n) { return n.size; })
- : that.$size.apply(that, (stack[0] = n, stack));
- });
- stack.shift();
-
- /* Sort. */
- switch (s.order) {
- case "ascending": {
- root.sort(function(a, b) { return a.size - b.size; });
- break;
- }
- case "descending": {
- root.sort(function(a, b) { return b.size - a.size; });
- break;
- }
- case "reverse": root.reverse(); break;
- }
-
- /* Recursively compute the layout. */
- root.x = 0;
- root.y = 0;
- root.dx = s.width;
- root.dy = s.height;
- root.visitBefore(layout);
-};
-/**
- * Constructs a new, empty tree layout. Layouts are not typically constructed
- * directly; instead, they are added to an existing panel via
- * {@link pv.Mark#add}.
- *
- * @class Implements a node-link tree diagram using the Reingold-Tilford "tidy"
- * tree layout algorithm. The specific algorithm used by this layout is based on
- * "Improving
- * Walker's Algorithm to Run in Linear Time" by C. Buchheim, M. Jünger
- * & S. Leipert, Graph Drawing 2002. This layout supports both cartesian and
- * radial orientations orientations for node-link diagrams.
- *
- *
The tree layout supports a "group" property, which if true causes siblings
- * to be positioned closer together than unrelated nodes at the same depth. The
- * layout can be configured using the depth and breadth
- * properties, which control the increments in pixel space between nodes in both
- * dimensions, similar to the indent layout.
- *
- *
For more details on how to use this layout, see
- * {@link pv.Layout.Hierarchy}.
- *
- * @extends pv.Layout.Hierarchy
- */
-pv.Layout.Tree = function() {
- pv.Layout.Hierarchy.call(this);
-};
-
-pv.Layout.Tree.prototype = pv.extend(pv.Layout.Hierarchy)
- .property("group", Number)
- .property("breadth", Number)
- .property("depth", Number)
- .property("orient", String);
-
-/**
- * Default properties for tree layouts. The default orientation is "top", the
- * default group parameter is 1, and the default breadth and depth offsets are
- * 15 and 60 respectively.
- *
- * @type pv.Layout.Tree
- */
-pv.Layout.Tree.prototype.defaults = new pv.Layout.Tree()
- .extend(pv.Layout.Hierarchy.prototype.defaults)
- .group(1)
- .breadth(15)
- .depth(60)
- .orient("top");
-
-/** @private */
-pv.Layout.Tree.prototype.buildImplied = function(s) {
- if (pv.Layout.Hierarchy.prototype.buildImplied.call(this, s)) return;
-
- var nodes = s.nodes,
- orient = s.orient,
- depth = s.depth,
- breadth = s.breadth,
- group = s.group,
- w = s.width,
- h = s.height;
-
- /** @private */
- function firstWalk(v) {
- var l, r, a;
- if (!v.firstChild) {
- if (l = v.previousSibling) {
- v.prelim = l.prelim + distance(v.depth, true);
- }
- } else {
- l = v.firstChild;
- r = v.lastChild;
- a = l; // default ancestor
- for (var c = l; c; c = c.nextSibling) {
- firstWalk(c);
- a = apportion(c, a);
- }
- executeShifts(v);
- var midpoint = .5 * (l.prelim + r.prelim);
- if (l = v.previousSibling) {
- v.prelim = l.prelim + distance(v.depth, true);
- v.mod = v.prelim - midpoint;
- } else {
- v.prelim = midpoint;
- }
- }
- }
-
- /** @private */
- function secondWalk(v, m, depth) {
- v.breadth = v.prelim + m;
- m += v.mod;
- for (var c = v.firstChild; c; c = c.nextSibling) {
- secondWalk(c, m, depth);
- }
- }
-
- /** @private */
- function apportion(v, a) {
- var w = v.previousSibling;
- if (w) {
- var vip = v,
- vop = v,
- vim = w,
- vom = v.parentNode.firstChild,
- sip = vip.mod,
- sop = vop.mod,
- sim = vim.mod,
- som = vom.mod,
- nr = nextRight(vim),
- nl = nextLeft(vip);
- while (nr && nl) {
- vim = nr;
- vip = nl;
- vom = nextLeft(vom);
- vop = nextRight(vop);
- vop.ancestor = v;
- var shift = (vim.prelim + sim) - (vip.prelim + sip) + distance(vim.depth, false);
- if (shift > 0) {
- moveSubtree(ancestor(vim, v, a), v, shift);
- sip += shift;
- sop += shift;
- }
- sim += vim.mod;
- sip += vip.mod;
- som += vom.mod;
- sop += vop.mod;
- nr = nextRight(vim);
- nl = nextLeft(vip);
- }
- if (nr && !nextRight(vop)) {
- vop.thread = nr;
- vop.mod += sim - sop;
- }
- if (nl && !nextLeft(vom)) {
- vom.thread = nl;
- vom.mod += sip - som;
- a = v;
- }
- }
- return a;
- }
-
- /** @private */
- function nextLeft(v) {
- return v.firstChild || v.thread;
- }
-
- /** @private */
- function nextRight(v) {
- return v.lastChild || v.thread;
- }
-
- /** @private */
- function moveSubtree(wm, wp, shift) {
- var subtrees = wp.number - wm.number;
- wp.change -= shift / subtrees;
- wp.shift += shift;
- wm.change += shift / subtrees;
- wp.prelim += shift;
- wp.mod += shift;
- }
-
- /** @private */
- function executeShifts(v) {
- var shift = 0, change = 0;
- for (var c = v.lastChild; c; c = c.previousSibling) {
- c.prelim += shift;
- c.mod += shift;
- change += c.change;
- shift += c.shift + change;
- }
- }
-
- /** @private */
- function ancestor(vim, v, a) {
- return (vim.ancestor.parentNode == v.parentNode) ? vim.ancestor : a;
- }
-
- /** @private */
- function distance(depth, siblings) {
- return (siblings ? 1 : (group + 1)) / ((orient == "radial") ? depth : 1);
- }
-
- /* Initialize temporary layout variables. TODO: store separately. */
- var root = nodes[0];
- root.visitAfter(function(v, i) {
- v.ancestor = v;
- v.prelim = 0;
- v.mod = 0;
- v.change = 0;
- v.shift = 0;
- v.number = v.previousSibling ? (v.previousSibling.number + 1) : 0;
- v.depth = i;
- });
-
- /* Compute the layout using Buchheim et al.'s algorithm. */
- firstWalk(root);
- secondWalk(root, -root.prelim, 0);
-
- /** @private Returns the angle of the given node. */
- function midAngle(n) {
- return (orient == "radial") ? n.breadth / depth : 0;
- }
-
- /** @private */
- function x(n) {
- switch (orient) {
- case "left": return n.depth;
- case "right": return w - n.depth;
- case "top":
- case "bottom": return n.breadth + w / 2;
- case "radial": return w / 2 + n.depth * Math.cos(midAngle(n));
- }
- }
-
- /** @private */
- function y(n) {
- switch (orient) {
- case "left":
- case "right": return n.breadth + h / 2;
- case "top": return n.depth;
- case "bottom": return h - n.depth;
- case "radial": return h / 2 + n.depth * Math.sin(midAngle(n));
- }
- }
-
- /* Clear temporary layout variables; transform depth and breadth. */
- root.visitAfter(function(v) {
- v.breadth *= breadth;
- v.depth *= depth;
- v.midAngle = midAngle(v);
- v.x = x(v);
- v.y = y(v);
- if (v.firstChild) v.midAngle += Math.PI;
- delete v.breadth;
- delete v.depth;
- delete v.ancestor;
- delete v.prelim;
- delete v.mod;
- delete v.change;
- delete v.shift;
- delete v.number;
- delete v.thread;
- });
-};
-
-/**
- * The offset between siblings nodes; defaults to 15.
- *
- * @type number
- * @name pv.Layout.Tree.prototype.breadth
- */
-
-/**
- * The offset between parent and child nodes; defaults to 60.
- *
- * @type number
- * @name pv.Layout.Tree.prototype.depth
- */
-
-/**
- * The orientation. The default orientation is "top", which means that the root
- * node is placed on the top edge, leaf nodes appear at the bottom, and internal
- * nodes are in-between. The following orientations are supported:
- *
- *
left - left-to-right.
- *
right - right-to-left.
- *
top - top-to-bottom.
- *
bottom - bottom-to-top.
- *
radial - radially, with the root at the center.
- *
- * @type string
- * @name pv.Layout.Tree.prototype.orient
- */
-
-/**
- * The sibling grouping, i.e., whether differentiating space is placed between
- * sibling groups. The default is 1 (or true), causing sibling leaves to be
- * separated by one breadth offset. Setting this to false (or 0) causes
- * non-siblings to be adjacent.
- *
- * @type number
- * @name pv.Layout.Tree.prototype.group
- */
-/**
- * Constructs a new, empty indent layout. Layouts are not typically constructed
- * directly; instead, they are added to an existing panel via
- * {@link pv.Mark#add}.
- *
- * @class Implements a hierarchical layout using the indent algorithm. This
- * layout implements a node-link diagram where the nodes are presented in
- * preorder traversal, and nodes are indented based on their depth from the
- * root. This technique is used ubiquitously by operating systems to represent
- * file directories; although it requires much vertical space, indented trees
- * allow efficient interactive exploration of trees to find a specific
- * node. In addition they allow rapid scanning of node labels, and multivariate
- * data such as file sizes can be displayed adjacent to the hierarchy.
- *
- *
The indent layout can be configured using the depth and
- * breadth properties, which control the increments in pixel space for
- * each indent and row in the layout. This layout does not support multiple
- * orientations; the root node is rendered in the top-left, while
- * breadth is a vertical offset from the top, and depth is a
- * horizontal offset from the left.
- *
- *
For more details on how to use this layout, see
- * {@link pv.Layout.Hierarchy}.
- *
- * @extends pv.Layout.Hierarchy
- */
-pv.Layout.Indent = function() {
- pv.Layout.Hierarchy.call(this);
- this.link.interpolate("step-after");
-};
-
-pv.Layout.Indent.prototype = pv.extend(pv.Layout.Hierarchy)
- .property("depth", Number)
- .property("breadth", Number);
-
-/**
- * The horizontal offset between different levels of the tree; defaults to 15.
- *
- * @type number
- * @name pv.Layout.Indent.prototype.depth
- */
-
-/**
- * The vertical offset between nodes; defaults to 15.
- *
- * @type number
- * @name pv.Layout.Indent.prototype.breadth
- */
-
-/**
- * Default properties for indent layouts. By default the depth and breadth
- * offsets are 15 pixels.
- *
- * @type pv.Layout.Indent
- */
-pv.Layout.Indent.prototype.defaults = new pv.Layout.Indent()
- .extend(pv.Layout.Hierarchy.prototype.defaults)
- .depth(15)
- .breadth(15);
-
-/** @private */
-pv.Layout.Indent.prototype.buildImplied = function(s) {
- if (pv.Layout.Hierarchy.prototype.buildImplied.call(this, s)) return;
-
- var nodes = s.nodes,
- bspace = s.breadth,
- dspace = s.depth,
- ax = 0,
- ay = 0;
-
- /** @private */
- function position(n, breadth, depth) {
- n.x = ax + depth++ * dspace;
- n.y = ay + breadth++ * bspace;
- n.midAngle = 0;
- for (var c = n.firstChild; c; c = c.nextSibling) {
- breadth = position(c, breadth, depth);
- }
- return breadth;
- }
-
- position(nodes[0], 1, 1);
-};
-/**
- * Constructs a new, empty circle-packing layout. Layouts are not typically
- * constructed directly; instead, they are added to an existing panel via
- * {@link pv.Mark#add}.
- *
- * @class Implements a hierarchical layout using circle-packing. The meaning of
- * the exported mark prototypes changes slightly in the space-filling
- * implementation:
- *
- *
node - for rendering nodes; typically a {@link pv.Dot}.
- *
- *
link - unsupported; undefined. Links are encoded implicitly
- * in the arrangement of the space-filling nodes.
- *
- *
label - for rendering node labels; typically a
- * {@link pv.Label}.
- *
- *
The pack layout support dynamic sizing for leaf nodes, if a
- * {@link #size} psuedo-property is specified. The default size function returns
- * 1, causing all leaf nodes to be sized equally, and all internal nodes to be
- * sized by the number of leaf nodes they have as descendants.
- *
- *
The size function can be used in conjunction with the order property,
- * which allows the nodes to the sorted by the computed size. Note: for sorting
- * based on other data attributes, simply use the default null for the
- * order property, and sort the nodes beforehand using the {@link pv.Dom}
- * operator.
- *
- *
For more details on how to use this layout, see
- * {@link pv.Layout.Hierarchy}.
- *
- * @extends pv.Layout.Hierarchy
- * @see "Visualization of large hierarchical data by circle packing" by W. Wang,
- * H. Wang, G. Dai, and H. Wang, ACM CHI 2006.
- */
-pv.Layout.Pack = function() {
- pv.Layout.Hierarchy.call(this);
-
- this.node
- .radius(function(n) { return n.radius; })
- .strokeStyle("rgb(31, 119, 180)")
- .fillStyle("rgba(31, 119, 180, .25)");
-
- this.label
- .textAlign("center");
-
- /* Hide unsupported link. */
- delete this.link;
-};
-
-pv.Layout.Pack.prototype = pv.extend(pv.Layout.Hierarchy)
- .property("spacing", Number)
- .property("order", String); // ascending, descending, reverse, null
-
-/**
- * Default properties for circle-packing layouts. The default spacing parameter
- * is 1 and the default order is "ascending".
- *
- * @type pv.Layout.Pack
- */
-pv.Layout.Pack.prototype.defaults = new pv.Layout.Pack()
- .extend(pv.Layout.Hierarchy.prototype.defaults)
- .spacing(1)
- .order("ascending");
-
-/**
- * The spacing parameter; defaults to 1, which provides a little bit of padding
- * between sibling nodes and the enclosing circle. Larger values increase the
- * spacing, by making the sibling nodes smaller; a value of zero makes the leaf
- * nodes as large as possible, with no padding on enclosing circles.
- *
- * @type number
- * @name pv.Layout.Pack.prototype.spacing
- */
-
-/**
- * The sibling node order. The default order is null, which means to
- * use the sibling order specified by the nodes property as-is. A value of
- * "ascending" will sort siblings in ascending order of size, while "descending"
- * will do the reverse. For sorting based on data attributes other than size,
- * use the default null for the order property, and sort the nodes
- * beforehand using the {@link pv.Dom} operator.
- *
- * @see pv.Dom.Node#sort
- * @type string
- * @name pv.Layout.Pack.prototype.order
- */
-
-/** @private The default size function. */
-pv.Layout.Pack.prototype.$radius = function() { return 1; };
-
-// TODO is it possible for spacing to operate in pixel space?
-// Right now it appears to be multiples of the smallest radius.
-
-/**
- * Specifies the sizing function. By default, a sizing function is disabled and
- * all nodes are given constant size. The sizing function is invoked for each
- * leaf node in the tree (passed to the constructor).
- *
- *
For example, if the tree data structure represents a file system, with
- * files as leaf nodes, and each file has a bytes attribute, you can
- * specify a size function as:
- *
- *
.size(function(d) d.bytes)
- *
- * As with other properties, a size function may specify additional arguments to
- * access the data associated with the layout and any enclosing panels.
- *
- * @param {function} f the new sizing function.
- * @returns {pv.Layout.Pack} this.
- */
-pv.Layout.Pack.prototype.size = function(f) {
- this.$radius = typeof f == "function"
- ? function() { return Math.sqrt(f.apply(this, arguments)); }
- : (f = Math.sqrt(f), function() { return f; });
- return this;
-};
-
-/** @private */
-pv.Layout.Pack.prototype.buildImplied = function(s) {
- if (pv.Layout.Hierarchy.prototype.buildImplied.call(this, s)) return;
-
- var that = this,
- nodes = s.nodes,
- root = nodes[0];
-
- /** @private Compute the radii of the leaf nodes. */
- function radii(nodes) {
- var stack = pv.Mark.stack;
- stack.unshift(null);
- for (var i = 0, n = nodes.length; i < n; i++) {
- var c = nodes[i];
- if (!c.firstChild) {
- c.radius = that.$radius.apply(that, (stack[0] = c, stack));
- }
- }
- stack.shift();
- }
-
- /** @private */
- function packTree(n) {
- var nodes = [];
- for (var c = n.firstChild; c; c = c.nextSibling) {
- if (c.firstChild) c.radius = packTree(c);
- c.n = c.p = c;
- nodes.push(c);
- }
-
- /* Sort. */
- switch (s.order) {
- case "ascending": {
- nodes.sort(function(a, b) { return a.radius - b.radius; });
- break;
- }
- case "descending": {
- nodes.sort(function(a, b) { return b.radius - a.radius; });
- break;
- }
- case "reverse": nodes.reverse(); break;
- }
-
- return packCircle(nodes);
- }
-
- /** @private */
- function packCircle(nodes) {
- var xMin = Infinity,
- xMax = -Infinity,
- yMin = Infinity,
- yMax = -Infinity,
- a, b, c, j, k;
-
- /** @private */
- function bound(n) {
- xMin = Math.min(n.x - n.radius, xMin);
- xMax = Math.max(n.x + n.radius, xMax);
- yMin = Math.min(n.y - n.radius, yMin);
- yMax = Math.max(n.y + n.radius, yMax);
- }
-
- /** @private */
- function insert(a, b) {
- var c = a.n;
- a.n = b;
- b.p = a;
- b.n = c;
- c.p = b;
- }
-
- /** @private */
- function splice(a, b) {
- a.n = b;
- b.p = a;
- }
-
- /** @private */
- function intersects(a, b) {
- var dx = b.x - a.x,
- dy = b.y - a.y,
- dr = a.radius + b.radius;
- return (dr * dr - dx * dx - dy * dy) > .001; // within epsilon
- }
-
- /* Create first node. */
- a = nodes[0];
- a.x = -a.radius;
- a.y = 0;
- bound(a);
-
- /* Create second node. */
- if (nodes.length > 1) {
- b = nodes[1];
- b.x = b.radius;
- b.y = 0;
- bound(b);
-
- /* Create third node and build chain. */
- if (nodes.length > 2) {
- c = nodes[2];
- place(a, b, c);
- bound(c);
- insert(a, c);
- a.p = c;
- insert(c, b);
- b = a.n;
-
- /* Now iterate through the rest. */
- for (var i = 3; i < nodes.length; i++) {
- place(a, b, c = nodes[i]);
-
- /* Search for the closest intersection. */
- var isect = 0, s1 = 1, s2 = 1;
- for (j = b.n; j != b; j = j.n, s1++) {
- if (intersects(j, c)) {
- isect = 1;
- break;
- }
- }
- if (isect == 1) {
- for (k = a.p; k != j.p; k = k.p, s2++) {
- if (intersects(k, c)) {
- if (s2 < s1) {
- isect = -1;
- j = k;
- }
- break;
- }
- }
- }
-
- /* Update node chain. */
- if (isect == 0) {
- insert(a, c);
- b = c;
- bound(c);
- } else if (isect > 0) {
- splice(a, j);
- b = j;
- i--;
- } else if (isect < 0) {
- splice(j, b);
- a = j;
- i--;
- }
- }
- }
- }
-
- /* Re-center the circles and return the encompassing radius. */
- var cx = (xMin + xMax) / 2,
- cy = (yMin + yMax) / 2,
- cr = 0;
- for (var i = 0; i < nodes.length; i++) {
- var n = nodes[i];
- n.x -= cx;
- n.y -= cy;
- cr = Math.max(cr, n.radius + Math.sqrt(n.x * n.x + n.y * n.y));
- }
- return cr + s.spacing;
- }
-
- /** @private */
- function place(a, b, c) {
- var da = b.radius + c.radius,
- db = a.radius + c.radius,
- dx = b.x - a.x,
- dy = b.y - a.y,
- dc = Math.sqrt(dx * dx + dy * dy),
- cos = (db * db + dc * dc - da * da) / (2 * db * dc),
- theta = Math.acos(cos),
- x = cos * db,
- h = Math.sin(theta) * db;
- dx /= dc;
- dy /= dc;
- c.x = a.x + x * dx + h * dy;
- c.y = a.y + x * dy - h * dx;
- }
-
- /** @private */
- function transform(n, x, y, k) {
- for (var c = n.firstChild; c; c = c.nextSibling) {
- c.x += n.x;
- c.y += n.y;
- transform(c, x, y, k);
- }
- n.x = x + k * n.x;
- n.y = y + k * n.y;
- n.radius *= k;
- }
-
- radii(nodes);
-
- /* Recursively compute the layout. */
- root.x = 0;
- root.y = 0;
- root.radius = packTree(root);
-
- var w = this.width(),
- h = this.height(),
- k = 1 / Math.max(2 * root.radius / w, 2 * root.radius / h);
- transform(root, w / 2, h / 2, k);
-};
-/**
- * Constructs a new, empty force-directed layout. Layouts are not typically
- * constructed directly; instead, they are added to an existing panel via
- * {@link pv.Mark#add}.
- *
- * @class Implements force-directed network layout as a node-link diagram. This
- * layout uses the Fruchterman-Reingold algorithm, which applies an attractive
- * spring force between neighboring nodes, and a repulsive electrical charge
- * force between all nodes. An additional drag force improves stability of the
- * simulation. See {@link pv.Force.spring}, {@link pv.Force.drag} and {@link
- * pv.Force.charge} for more details; note that the n-body charge force is
- * approximated using the Barnes-Hut algorithm.
- *
- *
This layout is implemented on top of {@link pv.Simulation}, which can be
- * used directly for more control over simulation parameters. The simulation
- * uses Position Verlet integration, which does not compute velocities
- * explicitly, but allows for easy geometric constraints, such as bounding the
- * nodes within the layout panel. Many of the configuration properties supported
- * by this layout are simply passed through to the underlying forces and
- * constraints of the simulation.
- *
- *
Force layouts are typically interactive. The gradual movement of the nodes
- * as they stabilize to a local stress minimum can help reveal the structure of
- * the network, as can {@link pv.Behavior.drag}, which allows the user to pick
- * up nodes and reposition them while the physics simulation continues. This
- * layout can also be used with pan & zoom behaviors for interaction.
- *
- *
To facilitate interaction, this layout by default automatically re-renders
- * using a setInterval every 42 milliseconds. This can be disabled via
- * the iterations property, which if non-null specifies the number of
- * simulation iterations to run before the force-directed layout is finalized.
- * Be careful not to use too high an iteration count, as this can lead to an
- * annoying delay on page load.
- *
- *
As with other network layouts, the network data can be updated
- * dynamically, provided the property cache is reset. See
- * {@link pv.Layout.Network} for details. New nodes are initialized with random
- * positions near the center. Alternatively, positions can be specified manually
- * by setting the x and y attributes on nodes.
- *
- * @extends pv.Layout.Network
- * @see "Graph Drawing by Force-directed Placement" by T. Fruchterman &
- * E. Reingold, Software--Practice & Experience, November 1991.
- */
-pv.Layout.Force = function() {
- pv.Layout.Network.call(this);
-
- /* Force-directed graphs can be messy, so reduce the link width. */
- this.link.lineWidth(function(d, p) { return Math.sqrt(p.linkValue) * 1.5; });
- this.label.textAlign("center");
-};
-
-pv.Layout.Force.prototype = pv.extend(pv.Layout.Network)
- .property("bound", Boolean)
- .property("iterations", Number)
- .property("dragConstant", Number)
- .property("chargeConstant", Number)
- .property("chargeMinDistance", Number)
- .property("chargeMaxDistance", Number)
- .property("chargeTheta", Number)
- .property("springConstant", Number)
- .property("springDamping", Number)
- .property("springLength", Number);
-
-/**
- * The bound parameter; true if nodes should be constrained within the layout
- * panel. Bounding is disabled by default. Currently the layout does not observe
- * the radius of the nodes; strictly speaking, only the center of the node is
- * constrained to be within the panel, with an additional 6-pixel offset for
- * padding. A future enhancement could extend the bound constraint to observe
- * the node's radius, which would also support bounding for variable-size nodes.
- *
- *
Note that if this layout is used in conjunction with pan & zoom
- * behaviors, those behaviors should have their bound parameter set to the same
- * value.
- *
- * @type boolean
- * @name pv.Layout.Force.prototype.bound
- */
-
-/**
- * The number of simulation iterations to run, or null if this layout is
- * interactive. Force-directed layouts are interactive by default, using a
- * setInterval to advance the physics simulation and re-render
- * automatically.
- *
- * @type number
- * @name pv.Layout.Force.prototype.iterations
- */
-
-/**
- * The drag constant, in the range [0,1]. A value of 0 means no drag (a
- * perfectly frictionless environment), while a value of 1 means friction
- * immediately cancels all momentum. The default value is 0.1, which provides a
- * minimum amount of drag that helps stabilize bouncy springs; lower values may
- * result in excessive bounciness, while higher values cause the simulation to
- * take longer to converge.
- *
- * @type number
- * @name pv.Layout.Force.prototype.dragConstant
- * @see pv.Force.drag#constant
- */
-
-/**
- * The charge constant, which should be a negative number. The default value is
- * -40; more negative values will result in a stronger repulsive force, which
- * may lead to faster convergence at the risk of instability. Too strong
- * repulsive charge forces can cause comparatively weak springs to be stretched
- * well beyond their rest length, emphasizing global structure over local
- * structure. A nonnegative value will break the Fruchterman-Reingold algorithm,
- * and is for entertainment purposes only.
- *
- * @type number
- * @name pv.Layout.Force.prototype.chargeConstant
- * @see pv.Force.charge#constant
- */
-
-/**
- * The minimum distance at which charge forces are applied. The default minimum
- * distance of 2 avoids applying forces that are two strong; because the physics
- * simulation is run at discrete time intervals, it is possible for two same-
- * charged particles to become very close or even a singularity! Since the
- * charge force is inversely proportional to the square of the distance, very
- * small distances can break the simulation.
- *
- *
In rare cases, two particles can become stuck on top of each other, as a
- * minimum distance threshold will prevent the charge force from repelling them.
- * However, this occurs very rarely because other forces and momentum typically
- * cause the particles to become separated again, at which point the repulsive
- * charge force kicks in.
- *
- * @type number
- * @name pv.Layout.Force.prototype.chargeMinDistance
- * @see pv.Force.charge#domain
- */
-
-/**
- * The maximum distance at which charge forces are applied. This improves
- * performance by ignoring weak charge forces at great distances. Note that this
- * parameter is partly redundant, as the Barnes-Hut algorithm for n-body forces
- * already improves performance for far-away particles through approximation.
- *
- * @type number
- * @name pv.Layout.Force.prototype.chargeMaxDistance
- * @see pv.Force.charge#domain
- */
-
-/**
- * The Barnes-Hut approximation factor. The Barnes-Hut approximation criterion
- * is the ratio of the size of the quadtree node to the distance from the point
- * to the node's center of mass is beneath some threshold. The default value is
- * 0.9.
- *
- * @type number
- * @name pv.Layout.Force.prototype.chargeTheta
- * @see pv.Force.charge#theta
- */
-
-/**
- * The spring constant, which should be a positive number. The default value is
- * 0.1; greater values will result in a stronger attractive force, which may
- * lead to faster convergence at the risk of instability. Too strong spring
- * forces can cause comparatively weak charge forces to be ignored, emphasizing
- * local structure over global structure. A nonpositive value will break the
- * Fruchterman-Reingold algorithm, and is for entertainment purposes only.
- *
- *
The spring tension is automatically normalized using the inverse square
- * root of the maximum link degree of attached nodes.
- *
- * @type number
- * @name pv.Layout.Force.prototype.springConstant
- * @see pv.Force.spring#constant
- */
-
-/**
- * The spring damping factor, in the range [0,1]. Damping functions identically
- * to drag forces, damping spring bounciness by applying a force in the opposite
- * direction of attached nodes' velocities. The default value is 0.3.
- *
- *
The spring damping is automatically normalized using the inverse square
- * root of the maximum link degree of attached nodes.
- *
- * @type number
- * @name pv.Layout.Force.prototype.springDamping
- * @see pv.Force.spring#damping
- */
-
-/**
- * The spring rest length. The default value is 20 pixels. Larger values may be
- * appropriate if the layout panel is larger, or if the nodes are rendered
- * larger than the default dot size of 20.
- *
- * @type number
- * @name pv.Layout.Force.prototype.springLength
- * @see pv.Force.spring#length
- */
-
-/**
- * Default properties for force-directed layouts. The default drag constant is
- * 0.1, the default charge constant is -40 (with a domain of [2, 500] and theta
- * of 0.9), and the default spring constant is 0.1 (with a damping of 0.3 and a
- * rest length of 20).
- *
- * @type pv.Layout.Force
- */
-pv.Layout.Force.prototype.defaults = new pv.Layout.Force()
- .extend(pv.Layout.Network.prototype.defaults)
- .dragConstant(.1)
- .chargeConstant(-40)
- .chargeMinDistance(2)
- .chargeMaxDistance(500)
- .chargeTheta(.9)
- .springConstant(.1)
- .springDamping(.3)
- .springLength(20);
-
-/** @private Initialize the physics simulation. */
-pv.Layout.Force.prototype.buildImplied = function(s) {
-
- /* Any cached interactive layouts need to be rebound for the timer. */
- if (pv.Layout.Network.prototype.buildImplied.call(this, s)) {
- var f = s.$force;
- if (f) {
- f.next = this.binds.$force;
- this.binds.$force = f;
- }
- return;
- }
-
- var that = this,
- nodes = s.nodes,
- links = s.links,
- k = s.iterations,
- w = s.width,
- h = s.height;
-
- /* Initialize positions randomly near the center. */
- for (var i = 0, n; i < nodes.length; i++) {
- n = nodes[i];
- if (isNaN(n.x)) n.x = w / 2 + 40 * Math.random() - 20;
- if (isNaN(n.y)) n.y = h / 2 + 40 * Math.random() - 20;
- }
-
- /* Initialize the simulation. */
- var sim = pv.simulation(nodes);
-
- /* Drag force. */
- sim.force(pv.Force.drag(s.dragConstant));
-
- /* Charge (repelling) force. */
- sim.force(pv.Force.charge(s.chargeConstant)
- .domain(s.chargeMinDistance, s.chargeMaxDistance)
- .theta(s.chargeTheta));
-
- /* Spring (attracting) force. */
- sim.force(pv.Force.spring(s.springConstant)
- .damping(s.springDamping)
- .length(s.springLength)
- .links(links));
-
- /* Position constraint (for interactive dragging). */
- sim.constraint(pv.Constraint.position());
-
- /* Optionally add bound constraint. TODO: better padding. */
- if (s.bound) {
- sim.constraint(pv.Constraint.bound().x(6, w - 6).y(6, h - 6));
- }
-
- /** @private Returns the speed of the given node, to determine cooling. */
- function speed(n) {
- return n.fix ? 1 : n.vx * n.vx + n.vy * n.vy;
- }
-
- /*
- * If the iterations property is null (the default), the layout is
- * interactive. The simulation is run until the fastest particle drops below
- * an arbitrary minimum speed. Although the timer keeps firing, this speed
- * calculation is fast so there is minimal CPU overhead. Note: if a particle
- * is fixed for interactivity, treat this as a high speed and resume
- * simulation.
- */
- if (k == null) {
- sim.step(); // compute initial previous velocities
- sim.step(); // compute initial velocities
-
- /* Add the simulation state to the bound list. */
- var force = s.$force = this.binds.$force = {
- next: this.binds.$force,
- nodes: nodes,
- min: 1e-4 * (links.length + 1),
- sim: sim
- };
-
- /* Start the timer, if not already started. */
- if (!this.$timer) this.$timer = setInterval(function() {
- var render = false;
- for (var f = that.binds.$force; f; f = f.next) {
- if (pv.max(f.nodes, speed) > f.min) {
- f.sim.step();
- render = true;
- }
- }
- if (render) that.render();
- }, 42);
- } else for (var i = 0; i < k; i++) {
- sim.step();
- }
-};
-/**
- * Constructs a new, empty cluster layout. Layouts are not typically
- * constructed directly; instead, they are added to an existing panel via
- * {@link pv.Mark#add}.
- *
- * @class Implements a hierarchical layout using the cluster (or dendrogram)
- * algorithm. This layout provides both node-link and space-filling
- * implementations of cluster diagrams. In many ways it is similar to
- * {@link pv.Layout.Partition}, except that leaf nodes are positioned at maximum
- * depth, and the depth of internal nodes is based on their distance from their
- * deepest descendant, rather than their distance from the root.
- *
- *
The cluster layout supports a "group" property, which if true causes
- * siblings to be positioned closer together than unrelated nodes at the same
- * depth. Unlike the partition layout, this layout does not support dynamic
- * sizing for leaf nodes; all leaf nodes are the same size.
- *
- *
For more details on how to use this layout, see
- * {@link pv.Layout.Hierarchy}.
- *
- * @see pv.Layout.Cluster.Fill
- * @extends pv.Layout.Hierarchy
- */
-pv.Layout.Cluster = function() {
- pv.Layout.Hierarchy.call(this);
- var interpolate, // cached interpolate
- buildImplied = this.buildImplied;
-
- /** @private Cache layout state to optimize properties. */
- this.buildImplied = function(s) {
- buildImplied.call(this, s);
- interpolate
- = /^(top|bottom)$/.test(s.orient) ? "step-before"
- : /^(left|right)$/.test(s.orient) ? "step-after"
- : "linear";
- };
-
- this.link.interpolate(function() { return interpolate; });
-};
-
-pv.Layout.Cluster.prototype = pv.extend(pv.Layout.Hierarchy)
- .property("group", Number)
- .property("orient", String)
- .property("innerRadius", Number)
- .property("outerRadius", Number);
-
-/**
- * The group parameter; defaults to 0, disabling grouping of siblings. If this
- * parameter is set to a positive number (or true, which is equivalent to 1),
- * then additional space will be allotted between sibling groups. In other
- * words, siblings (nodes that share the same parent) will be positioned more
- * closely than nodes at the same depth that do not share a parent.
- *
- * @type number
- * @name pv.Layout.Cluster.prototype.group
- */
-
-/**
- * The orientation. The default orientation is "top", which means that the root
- * node is placed on the top edge, leaf nodes appear on the bottom edge, and
- * internal nodes are in-between. The following orientations are supported:
- *
- *
left - left-to-right.
- *
right - right-to-left.
- *
top - top-to-bottom.
- *
bottom - bottom-to-top.
- *
radial - radially, with the root at the center.
- *
- * @type string
- * @name pv.Layout.Cluster.prototype.orient
- */
-
-/**
- * The inner radius; defaults to 0. This property applies only to radial
- * orientations, and can be used to compress the layout radially. Note that for
- * the node-link implementation, the root node is always at the center,
- * regardless of the value of this property; this property only affects internal
- * and leaf nodes. For the space-filling implementation, a non-zero value of
- * this property will result in the root node represented as a ring rather than
- * a circle.
- *
- * @type number
- * @name pv.Layout.Cluster.prototype.innerRadius
- */
-
-/**
- * The outer radius; defaults to fill the containing panel, based on the height
- * and width of the layout. If the layout has no height and width specified, it
- * will extend to fill the enclosing panel.
- *
- * @type number
- * @name pv.Layout.Cluster.prototype.outerRadius
- */
-
-/**
- * Defaults for cluster layouts. The default group parameter is 0 and the
- * default orientation is "top".
- *
- * @type pv.Layout.Cluster
- */
-pv.Layout.Cluster.prototype.defaults = new pv.Layout.Cluster()
- .extend(pv.Layout.Hierarchy.prototype.defaults)
- .group(0)
- .orient("top");
-
-/** @private */
-pv.Layout.Cluster.prototype.buildImplied = function(s) {
- if (pv.Layout.Hierarchy.prototype.buildImplied.call(this, s)) return;
-
- var root = s.nodes[0],
- group = s.group,
- breadth,
- depth,
- leafCount = 0,
- leafIndex = .5 - group / 2;
-
- /* Count the leaf nodes and compute the depth of descendants. */
- var p = undefined;
- root.visitAfter(function(n) {
- if (n.firstChild) {
- n.depth = 1 + pv.max(n.childNodes, function(n) { return n.depth; });
- } else {
- if (group && (p != n.parentNode)) {
- p = n.parentNode;
- leafCount += group;
- }
- leafCount++;
- n.depth = 0;
- }
- });
- breadth = 1 / leafCount;
- depth = 1 / root.depth;
-
- /* Compute the unit breadth and depth of each node. */
- var p = undefined;
- root.visitAfter(function(n) {
- if (n.firstChild) {
- n.breadth = pv.mean(n.childNodes, function(n) { return n.breadth; });
- } else {
- if (group && (p != n.parentNode)) {
- p = n.parentNode;
- leafIndex += group;
- }
- n.breadth = breadth * leafIndex++;
- }
- n.depth = 1 - n.depth * depth;
- });
-
- /* Compute breadth and depth ranges for space-filling layouts. */
- root.visitAfter(function(n) {
- n.minBreadth = n.firstChild
- ? n.firstChild.minBreadth
- : (n.breadth - breadth / 2);
- n.maxBreadth = n.firstChild
- ? n.lastChild.maxBreadth
- : (n.breadth + breadth / 2);
- });
- root.visitBefore(function(n) {
- n.minDepth = n.parentNode
- ? n.parentNode.maxDepth
- : 0;
- n.maxDepth = n.parentNode
- ? (n.depth + root.depth)
- : (n.minDepth + 2 * root.depth);
- });
- root.minDepth = -depth;
-
- pv.Layout.Hierarchy.NodeLink.buildImplied.call(this, s);
-};
-
-/**
- * Constructs a new, empty space-filling cluster layout. Layouts are not
- * typically constructed directly; instead, they are added to an existing panel
- * via {@link pv.Mark#add}.
- *
- * @class A variant of cluster layout that is space-filling. The meaning of the
- * exported mark prototypes changes slightly in the space-filling
- * implementation:
- *
- *
node - for rendering nodes; typically a {@link pv.Bar} for
- * non-radial orientations, and a {@link pv.Wedge} for radial orientations.
- *
- *
link - unsupported; undefined. Links are encoded implicitly
- * in the arrangement of the space-filling nodes.
- *
- *
label - for rendering node labels; typically a
- * {@link pv.Label}.
- *
- *
For more details on how to use this layout, see
- * {@link pv.Layout.Cluster}.
- *
- * @extends pv.Layout.Cluster
- */
-pv.Layout.Cluster.Fill = function() {
- pv.Layout.Cluster.call(this);
- pv.Layout.Hierarchy.Fill.constructor.call(this);
-};
-
-pv.Layout.Cluster.Fill.prototype = pv.extend(pv.Layout.Cluster);
-
-/** @private */
-pv.Layout.Cluster.Fill.prototype.buildImplied = function(s) {
- if (pv.Layout.Cluster.prototype.buildImplied.call(this, s)) return;
- pv.Layout.Hierarchy.Fill.buildImplied.call(this, s);
-};
-/**
- * Constructs a new, empty partition layout. Layouts are not typically
- * constructed directly; instead, they are added to an existing panel via
- * {@link pv.Mark#add}.
- *
- * @class Implemeents a hierarchical layout using the partition (or sunburst,
- * icicle) algorithm. This layout provides both node-link and space-filling
- * implementations of partition diagrams. In many ways it is similar to
- * {@link pv.Layout.Cluster}, except that leaf nodes are positioned based on
- * their distance from the root.
- *
- *
The partition layout support dynamic sizing for leaf nodes, if a
- * {@link #size} psuedo-property is specified. The default size function returns
- * 1, causing all leaf nodes to be sized equally, and all internal nodes to be
- * sized by the number of leaf nodes they have as descendants.
- *
- *
The size function can be used in conjunction with the order property,
- * which allows the nodes to the sorted by the computed size. Note: for sorting
- * based on other data attributes, simply use the default null for the
- * order property, and sort the nodes beforehand using the {@link pv.Dom}
- * operator.
- *
- *
For more details on how to use this layout, see
- * {@link pv.Layout.Hierarchy}.
- *
- * @see pv.Layout.Partition.Fill
- * @extends pv.Layout.Hierarchy
- */
-pv.Layout.Partition = function() {
- pv.Layout.Hierarchy.call(this);
-};
-
-pv.Layout.Partition.prototype = pv.extend(pv.Layout.Hierarchy)
- .property("order", String) // null, ascending, descending?
- .property("orient", String) // top, left, right, bottom, radial
- .property("innerRadius", Number)
- .property("outerRadius", Number);
-
-/**
- * The sibling node order. The default order is null, which means to
- * use the sibling order specified by the nodes property as-is. A value of
- * "ascending" will sort siblings in ascending order of size, while "descending"
- * will do the reverse. For sorting based on data attributes other than size,
- * use the default null for the order property, and sort the nodes
- * beforehand using the {@link pv.Dom} operator.
- *
- * @see pv.Dom.Node#sort
- * @type string
- * @name pv.Layout.Partition.prototype.order
- */
-
-/**
- * The orientation. The default orientation is "top", which means that the root
- * node is placed on the top edge, leaf nodes appear at the bottom, and internal
- * nodes are in-between. The following orientations are supported:
- *
- *
left - left-to-right.
- *
right - right-to-left.
- *
top - top-to-bottom.
- *
bottom - bottom-to-top.
- *
radial - radially, with the root at the center.
- *
- * @type string
- * @name pv.Layout.Partition.prototype.orient
- */
-
-/**
- * The inner radius; defaults to 0. This property applies only to radial
- * orientations, and can be used to compress the layout radially. Note that for
- * the node-link implementation, the root node is always at the center,
- * regardless of the value of this property; this property only affects internal
- * and leaf nodes. For the space-filling implementation, a non-zero value of
- * this property will result in the root node represented as a ring rather than
- * a circle.
- *
- * @type number
- * @name pv.Layout.Partition.prototype.innerRadius
- */
-
-/**
- * The outer radius; defaults to fill the containing panel, based on the height
- * and width of the layout. If the layout has no height and width specified, it
- * will extend to fill the enclosing panel.
- *
- * @type number
- * @name pv.Layout.Partition.prototype.outerRadius
- */
-
-/**
- * Default properties for partition layouts. The default orientation is "top".
- *
- * @type pv.Layout.Partition
- */
-pv.Layout.Partition.prototype.defaults = new pv.Layout.Partition()
- .extend(pv.Layout.Hierarchy.prototype.defaults)
- .orient("top");
-
-/** @private */
-pv.Layout.Partition.prototype.$size = function() { return 1; };
-
-/**
- * Specifies the sizing function. By default, a sizing function is disabled and
- * all nodes are given constant size. The sizing function is invoked for each
- * leaf node in the tree (passed to the constructor).
- *
- *
For example, if the tree data structure represents a file system, with
- * files as leaf nodes, and each file has a bytes attribute, you can
- * specify a size function as:
- *
- *
.size(function(d) d.bytes)
- *
- * As with other properties, a size function may specify additional arguments to
- * access the data associated with the layout and any enclosing panels.
- *
- * @param {function} f the new sizing function.
- * @returns {pv.Layout.Partition} this.
- */
-pv.Layout.Partition.prototype.size = function(f) {
- this.$size = f;
- return this;
-};
-
-/** @private */
-pv.Layout.Partition.prototype.buildImplied = function(s) {
- if (pv.Layout.Hierarchy.prototype.buildImplied.call(this, s)) return;
-
- var that = this,
- root = s.nodes[0],
- stack = pv.Mark.stack,
- maxDepth = 0;
-
- /* Recursively compute the tree depth and node size. */
- stack.unshift(null);
- root.visitAfter(function(n, i) {
- if (i > maxDepth) maxDepth = i;
- n.size = n.firstChild
- ? pv.sum(n.childNodes, function(n) { return n.size; })
- : that.$size.apply(that, (stack[0] = n, stack));
- });
- stack.shift();
-
- /* Order */
- switch (s.order) {
- case "ascending": root.sort(function(a, b) { return a.size - b.size; }); break;
- case "descending": root.sort(function(b, a) { return a.size - b.size; }); break;
- }
-
- /* Compute the unit breadth and depth of each node. */
- var ds = 1 / maxDepth;
- root.minBreadth = 0;
- root.breadth = .5;
- root.maxBreadth = 1;
- root.visitBefore(function(n) {
- var b = n.minBreadth, s = n.maxBreadth - b;
- for (var c = n.firstChild; c; c = c.nextSibling) {
- c.minBreadth = b;
- c.maxBreadth = b += (c.size / n.size) * s;
- c.breadth = (b + c.minBreadth) / 2;
- }
- });
- root.visitAfter(function(n, i) {
- n.minDepth = (i - 1) * ds;
- n.maxDepth = n.depth = i * ds;
- });
-
- pv.Layout.Hierarchy.NodeLink.buildImplied.call(this, s);
-};
-
-/**
- * Constructs a new, empty space-filling partition layout. Layouts are not
- * typically constructed directly; instead, they are added to an existing panel
- * via {@link pv.Mark#add}.
- *
- * @class A variant of partition layout that is space-filling. The meaning of
- * the exported mark prototypes changes slightly in the space-filling
- * implementation:
- *
- *
node - for rendering nodes; typically a {@link pv.Bar} for
- * non-radial orientations, and a {@link pv.Wedge} for radial orientations.
- *
- *
link - unsupported; undefined. Links are encoded implicitly
- * in the arrangement of the space-filling nodes.
- *
- *
label - for rendering node labels; typically a
- * {@link pv.Label}.
- *
- *
For more details on how to use this layout, see
- * {@link pv.Layout.Partition}.
- *
- * @extends pv.Layout.Partition
- */
-pv.Layout.Partition.Fill = function() {
- pv.Layout.Partition.call(this);
- pv.Layout.Hierarchy.Fill.constructor.call(this);
-};
-
-pv.Layout.Partition.Fill.prototype = pv.extend(pv.Layout.Partition);
-
-/** @private */
-pv.Layout.Partition.Fill.prototype.buildImplied = function(s) {
- if (pv.Layout.Partition.prototype.buildImplied.call(this, s)) return;
- pv.Layout.Hierarchy.Fill.buildImplied.call(this, s);
-};
-/**
- * Constructs a new, empty arc layout. Layouts are not typically constructed
- * directly; instead, they are added to an existing panel via
- * {@link pv.Mark#add}.
- *
- * @class Implements a layout for arc diagrams. An arc diagram is a network
- * visualization with a one-dimensional layout of nodes, using circular arcs to
- * render links between nodes. For undirected networks, arcs are rendering on a
- * single side; this makes arc diagrams useful as annotations to other
- * two-dimensional network layouts, such as rollup, matrix or table layouts. For
- * directed networks, links in opposite directions can be rendered on opposite
- * sides using directed(true).
- *
- *
Arc layouts are particularly sensitive to node ordering; for best results,
- * order the nodes such that related nodes are close to each other. A poor
- * (e.g., random) order may result in large arcs with crossovers that impede
- * visual processing. A future improvement to this layout may include automatic
- * reordering using, e.g., spectral graph layout or simulated annealing.
- *
- *
This visualization technique is related to that developed by
- * M. Wattenberg, "Arc
- * Diagrams: Visualizing Structure in Strings" in IEEE InfoVis, 2002.
- * However, this implementation is limited to simple node-link networks, as
- * opposed to structures with hierarchical self-similarity (such as strings).
- *
- *
As with other network layouts, three mark prototypes are provided:
- *
- *
node - for rendering nodes; typically a {@link pv.Dot}.
- *
link - for rendering links; typically a {@link pv.Line}.
- *
label - for rendering node labels; typically a {@link pv.Label}.
- *
- *
For more details on how this layout is structured and can be customized,
- * see {@link pv.Layout.Network}.
- *
- * @extends pv.Layout.Network
- **/
-pv.Layout.Arc = function() {
- pv.Layout.Network.call(this);
- var interpolate, // cached interpolate
- directed, // cached directed
- reverse, // cached reverse
- buildImplied = this.buildImplied;
-
- /** @private Cache layout state to optimize properties. */
- this.buildImplied = function(s) {
- buildImplied.call(this, s);
- directed = s.directed;
- interpolate = s.orient == "radial" ? "linear" : "polar";
- reverse = s.orient == "right" || s.orient == "top";
- };
-
- /* Override link properties to handle directedness and orientation. */
- this.link
- .data(function(p) {
- var s = p.sourceNode, t = p.targetNode;
- return reverse != (directed || (s.breadth < t.breadth)) ? [s, t] : [t, s];
- })
- .interpolate(function() { return interpolate; });
-};
-
-pv.Layout.Arc.prototype = pv.extend(pv.Layout.Network)
- .property("orient", String)
- .property("directed", Boolean);
-
-/**
- * Default properties for arc layouts. By default, the orientation is "bottom".
- *
- * @type pv.Layout.Arc
- */
-pv.Layout.Arc.prototype.defaults = new pv.Layout.Arc()
- .extend(pv.Layout.Network.prototype.defaults)
- .orient("bottom");
-
-/**
- * Specifies an optional sort function. The sort function follows the same
- * comparator contract required by {@link pv.Dom.Node#sort}. Specifying a sort
- * function provides an alternative to sort the nodes as they are specified by
- * the nodes property; the main advantage of doing this is that the
- * comparator function can access implicit fields populated by the network
- * layout, such as the linkDegree.
- *
- *
Note that arc diagrams are particularly sensitive to order. This is
- * referred to as the seriation problem, and many different techniques exist to
- * find good node orders that emphasize clusters, such as spectral layout and
- * simulated annealing.
- *
- * @param {function} f comparator function for nodes.
- * @returns {pv.Layout.Arc} this.
- */
-pv.Layout.Arc.prototype.sort = function(f) {
- this.$sort = f;
- return this;
-};
-
-/** @private Populates the x, y and angle attributes on the nodes. */
-pv.Layout.Arc.prototype.buildImplied = function(s) {
- if (pv.Layout.Network.prototype.buildImplied.call(this, s)) return;
-
- var nodes = s.nodes,
- orient = s.orient,
- sort = this.$sort,
- index = pv.range(nodes.length),
- w = s.width,
- h = s.height,
- r = Math.min(w, h) / 2;
-
- /* Sort the nodes. */
- if (sort) index.sort(function(a, b) { return sort(nodes[a], nodes[b]); });
-
- /** @private Returns the mid-angle, given the breadth. */
- function midAngle(b) {
- switch (orient) {
- case "top": return -Math.PI / 2;
- case "bottom": return Math.PI / 2;
- case "left": return Math.PI;
- case "right": return 0;
- case "radial": return (b - .25) * 2 * Math.PI;
- }
- }
-
- /** @private Returns the x-position, given the breadth. */
- function x(b) {
- switch (orient) {
- case "top":
- case "bottom": return b * w;
- case "left": return 0;
- case "right": return w;
- case "radial": return w / 2 + r * Math.cos(midAngle(b));
- }
- }
-
- /** @private Returns the y-position, given the breadth. */
- function y(b) {
- switch (orient) {
- case "top": return 0;
- case "bottom": return h;
- case "left":
- case "right": return b * h;
- case "radial": return h / 2 + r * Math.sin(midAngle(b));
- }
- }
-
- /* Populate the x, y and mid-angle attributes. */
- for (var i = 0; i < nodes.length; i++) {
- var n = nodes[index[i]], b = n.breadth = (i + .5) / nodes.length;
- n.x = x(b);
- n.y = y(b);
- n.midAngle = midAngle(b);
- }
-};
-
-/**
- * The orientation. The default orientation is "left", which means that nodes
- * will be positioned from left-to-right in the order they are specified in the
- * nodes property. The following orientations are supported:
- *
- *
left - left-to-right.
- *
right - right-to-left.
- *
top - top-to-bottom.
- *
bottom - bottom-to-top.
- *
radial - radially, starting at 12 o'clock and proceeding clockwise.
- *
- * @type string
- * @name pv.Layout.Arc.prototype.orient
- */
-
-/**
- * Whether this arc digram is directed (bidirectional); only applies to
- * non-radial orientations. By default, arc digrams are undirected, such that
- * all arcs appear on one side. If the arc digram is directed, then forward
- * links are drawn on the conventional side (the same as as undirected
- * links--right, left, bottom and top for left, right, top and bottom,
- * respectively), while reverse links are drawn on the opposite side.
- *
- * @type boolean
- * @name pv.Layout.Arc.prototype.directed
- */
-/**
- * Constructs a new, empty horizon layout. Layouts are not typically constructed
- * directly; instead, they are added to an existing panel via
- * {@link pv.Mark#add}.
- *
- * @class Implements a horizon layout, which is a variation of a single-series
- * area chart where the area is folded into multiple bands. Color is used to
- * encode band, allowing the size of the chart to be reduced significantly
- * without impeding readability. This layout algorithm is based on the work of
- * J. Heer, N. Kong and M. Agrawala in "Sizing
- * the Horizon: The Effects of Chart Size and Layering on the Graphical
- * Perception of Time Series Visualizations", CHI 2009.
- *
- *
This layout exports a single band mark prototype, which is
- * intended to be used with an area mark. The band mark is contained in a panel
- * which is replicated per band (and for negative/positive bands). For example,
- * to create a simple horizon graph given an array of numbers:
- *
- *
- *
- * The layout can be further customized by changing the number of bands, and
- * toggling whether the negative bands are mirrored or offset. (See the
- * above-referenced paper for guidance.)
- *
- *
The fillStyle of the area can be overridden, though typically it
- * is easier to customize the layout's behavior through the custom
- * backgroundStyle, positiveStyle and negativeStyle
- * properties. By default, the background is white, positive bands are blue, and
- * negative bands are red. For the most accurate presentation, use fully-opaque
- * colors of equal intensity for the negative and positive bands.
- *
- * @extends pv.Layout
- */
-pv.Layout.Horizon = function() {
- pv.Layout.call(this);
- var that = this,
- bands, // cached bands
- mode, // cached mode
- size, // cached height
- fill, // cached background style
- red, // cached negative color (ramp)
- blue, // cached positive color (ramp)
- buildImplied = this.buildImplied;
-
- /** @private Cache the layout state to optimize properties. */
- this.buildImplied = function(s) {
- buildImplied.call(this, s);
- bands = s.bands;
- mode = s.mode;
- size = Math.round((mode == "color" ? .5 : 1) * s.height);
- fill = s.backgroundStyle;
- red = pv.ramp(fill, s.negativeStyle).domain(0, bands);
- blue = pv.ramp(fill, s.positiveStyle).domain(0, bands);
- };
-
- var bands = new pv.Panel()
- .data(function() { return pv.range(bands * 2); })
- .overflow("hidden")
- .height(function() { return size; })
- .top(function(i) { return mode == "color" ? (i & 1) * size : 0; })
- .fillStyle(function(i) { return i ? null : fill; });
-
- /**
- * The band prototype. This prototype is intended to be used with an Area
- * mark to render the horizon bands.
- *
- * @type pv.Mark
- * @name pv.Layout.Horizon.prototype.band
- */
- this.band = new pv.Mark()
- .top(function(d, i) {
- return mode == "mirror" && i & 1
- ? (i + 1 >> 1) * size
- : null;
- })
- .bottom(function(d, i) {
- return mode == "mirror"
- ? (i & 1 ? null : (i + 1 >> 1) * -size)
- : ((i & 1 || -1) * (i + 1 >> 1) * size);
- })
- .fillStyle(function(d, i) {
- return (i & 1 ? red : blue)((i >> 1) + 1);
- });
-
- this.band.add = function(type) {
- return that.add(pv.Panel).extend(bands).add(type).extend(this);
- };
-};
-
-pv.Layout.Horizon.prototype = pv.extend(pv.Layout)
- .property("bands", Number)
- .property("mode", String)
- .property("backgroundStyle", pv.color)
- .property("positiveStyle", pv.color)
- .property("negativeStyle", pv.color);
-
-/**
- * Default properties for horizon layouts. By default, there are two bands, the
- * mode is "offset", the background style is "white", the positive style is
- * blue, negative style is red.
- *
- * @type pv.Layout.Horizon
- */
-pv.Layout.Horizon.prototype.defaults = new pv.Layout.Horizon()
- .extend(pv.Layout.prototype.defaults)
- .bands(2)
- .mode("offset")
- .backgroundStyle("white")
- .positiveStyle("#1f77b4")
- .negativeStyle("#d62728");
-
-/**
- * The horizon mode: offset, mirror, or color. The default is "offset".
- *
- * @type string
- * @name pv.Layout.Horizon.prototype.mode
- */
-
-/**
- * The number of bands. Must be at least one. The default value is two.
- *
- * @type number
- * @name pv.Layout.Horizon.prototype.bands
- */
-
-/**
- * The positive band color; if non-null, the interior of positive bands are
- * filled with the specified color. The default value of this property is blue.
- * For accurate blending, this color should be fully opaque.
- *
- * @type pv.Color
- * @name pv.Layout.Horizon.prototype.positiveStyle
- */
-
-/**
- * The negative band color; if non-null, the interior of negative bands are
- * filled with the specified color. The default value of this property is red.
- * For accurate blending, this color should be fully opaque.
- *
- * @type pv.Color
- * @name pv.Layout.Horizon.prototype.negativeStyle
- */
-
-/**
- * The background color. The panel background is filled with the specified
- * color, and the negative and positive bands are filled with an interpolated
- * color between this color and the respective band color. The default value of
- * this property is white. For accurate blending, this color should be fully
- * opaque.
- *
- * @type pv.Color
- * @name pv.Layout.Horizon.prototype.backgroundStyle
- */
-/**
- * Constructs a new, empty rollup network layout. Layouts are not typically
- * constructed directly; instead, they are added to an existing panel via
- * {@link pv.Mark#add}.
- *
- * @class Implements a network visualization using a node-link diagram where
- * nodes are rolled up along two dimensions. This implementation is based on the
- * "PivotGraph" designed by Martin Wattenberg:
- *
- *
The method is designed for graphs that are "multivariate", i.e.,
- * where each node is associated with several attributes. Unlike visualizations
- * which emphasize global graph topology, PivotGraph uses a simple grid-based
- * approach to focus on the relationship between node attributes &
- * connections.
- *
- * This layout requires two psuedo-properties to be specified, which assign node
- * positions along the two dimensions {@link #x} and {@link #y}, corresponding
- * to the left and top properties, respectively. Typically, these functions are
- * specified using an {@link pv.Scale.ordinal}. Nodes that share the same
- * position in x and y are "rolled up" into a meta-node, and
- * similarly links are aggregated between meta-nodes. For example, to construct
- * a rollup to analyze links by gender and affiliation, first define two ordinal
- * scales:
- *
- *
var x = pv.Scale.ordinal(nodes, function(d) d.gender).split(0, w),
- * y = pv.Scale.ordinal(nodes, function(d) d.aff).split(0, h);
- *
- * Next, define the position psuedo-properties:
- *
- *
- *
- * Linear and other quantitative scales can alternatively be used to position
- * the nodes along either dimension. Note, however, that the rollup requires
- * that the positions match exactly, and thus ordinal scales are recommended to
- * avoid precision errors.
- *
- *
Note that because this layout provides a visualization of the rolled up
- * graph, the data properties for the mark prototypes (node,
- * link and label) are different from most other network
- * layouts: they reference the rolled-up nodes and links, rather than the nodes
- * and links of the full network. The underlying nodes and links for each
- * rolled-up node and link can be accessed via the nodes and
- * links attributes, respectively. The aggregated link values for
- * rolled-up links can similarly be accessed via the linkValue
- * attribute.
- *
- *
For undirected networks, links are duplicated in both directions. For
- * directed networks, use directed(true). The graph is assumed to be
- * undirected by default.
- *
- * @extends pv.Layout.Network
- * @see "Visual Exploration of Multivariate Graphs" by M. Wattenberg, CHI 2006.
- */
-pv.Layout.Rollup = function() {
- pv.Layout.Network.call(this);
- var that = this,
- nodes, // cached rollup nodes
- links, // cached rollup links
- buildImplied = that.buildImplied;
-
- /** @private Cache layout state to optimize properties. */
- this.buildImplied = function(s) {
- buildImplied.call(this, s);
- nodes = s.$rollup.nodes;
- links = s.$rollup.links;
- };
-
- /* Render rollup nodes. */
- this.node
- .data(function() { return nodes; })
- .size(function(d) { return d.nodes.length * 20; });
-
- /* Render rollup links. */
- this.link
- .interpolate("polar")
- .eccentricity(.8);
-
- this.link.add = function(type) {
- return that.add(pv.Panel)
- .data(function() { return links; })
- .add(type)
- .extend(this);
- };
-};
-
-pv.Layout.Rollup.prototype = pv.extend(pv.Layout.Network)
- .property("directed", Boolean);
-
-/**
- * Whether the underlying network is directed. By default, the graph is assumed
- * to be undirected, and links are rendered in both directions. If the network
- * is directed, then forward links are drawn above the diagonal, while reverse
- * links are drawn below.
- *
- * @type boolean
- * @name pv.Layout.Rollup.prototype.directed
- */
-
-/**
- * Specifies the x-position function used to rollup nodes. The rolled up
- * nodes are positioned horizontally using the return values from the given
- * function. Typically the function is specified as an ordinal scale. For
- * single-dimension rollups, a constant value can be specified.
- *
- * @param {function} f the x-position function.
- * @returns {pv.Layout.Rollup} this.
- * @see pv.Scale.ordinal
- */
-pv.Layout.Rollup.prototype.x = function(f) {
- this.$x = pv.functor(f);
- return this;
-};
-
-/**
- * Specifies the y-position function used to rollup nodes. The rolled up
- * nodes are positioned vertically using the return values from the given
- * function. Typically the function is specified as an ordinal scale. For
- * single-dimension rollups, a constant value can be specified.
- *
- * @param {function} f the y-position function.
- * @returns {pv.Layout.Rollup} this.
- * @see pv.Scale.ordinal
- */
-pv.Layout.Rollup.prototype.y = function(f) {
- this.$y = pv.functor(f);
- return this;
-};
-
-/** @private */
-pv.Layout.Rollup.prototype.buildImplied = function(s) {
- if (pv.Layout.Network.prototype.buildImplied.call(this, s)) return;
-
- var nodes = s.nodes,
- links = s.links,
- directed = s.directed,
- n = nodes.length,
- x = [],
- y = [],
- rnindex = 0,
- rnodes = {},
- rlinks = {};
-
- /** @private */
- function id(i) {
- return x[i] + "," + y[i];
- }
-
- /* Iterate over the data, evaluating the x and y functions. */
- var stack = pv.Mark.stack, o = {parent: this};
- stack.unshift(null);
- for (var i = 0; i < n; i++) {
- o.index = i;
- stack[0] = nodes[i];
- x[i] = this.$x.apply(o, stack);
- y[i] = this.$y.apply(o, stack);
- }
- stack.shift();
-
- /* Compute rollup nodes. */
- for (var i = 0; i < nodes.length; i++) {
- var nodeId = id(i),
- rn = rnodes[nodeId];
- if (!rn) {
- rn = rnodes[nodeId] = pv.extend(nodes[i]);
- rn.index = rnindex++;
- rn.x = x[i];
- rn.y = y[i];
- rn.nodes = [];
- }
- rn.nodes.push(nodes[i]);
- }
-
- /* Compute rollup links. */
- for (var i = 0; i < links.length; i++) {
- var source = links[i].sourceNode,
- target = links[i].targetNode,
- rsource = rnodes[id(source.index)],
- rtarget = rnodes[id(target.index)],
- reverse = !directed && rsource.index > rtarget.index,
- linkId = reverse
- ? rtarget.index + "," + rsource.index
- : rsource.index + "," + rtarget.index,
- rl = rlinks[linkId];
- if (!rl) {
- rl = rlinks[linkId] = {
- sourceNode: rsource,
- targetNode: rtarget,
- linkValue: 0,
- links: []
- };
- }
- rl.links.push(links[i]);
- rl.linkValue += links[i].linkValue;
- }
-
- /* Export the rolled up nodes and links to the scene. */
- s.$rollup = {
- nodes: pv.values(rnodes),
- links: pv.values(rlinks)
- };
-};
-/**
- * Constructs a new, empty matrix network layout. Layouts are not typically
- * constructed directly; instead, they are added to an existing panel via
- * {@link pv.Mark#add}.
- *
- * @class Implements a network visualization using a matrix view. This is, in
- * effect, a visualization of the graph's adjacency matrix: the cell at
- * row i, column j, corresponds to the link from node i to
- * node j. The fill color of each cell is binary by default, and
- * corresponds to whether a link exists between the two nodes. If the underlying
- * graph has links with variable values, the fillStyle property can be
- * substited to use an appropriate color function, such as {@link pv.ramp}.
- *
- *
For undirected networks, the matrix is symmetric around the diagonal. For
- * directed networks, links in opposite directions can be rendered on opposite
- * sides of the diagonal using directed(true). The graph is assumed to
- * be undirected by default.
- *
- *
The mark prototypes for this network layout are slightly different than
- * other implementations:
- *
- *
node - unsupported; undefined. No mark is needed to visualize
- * nodes directly, as the nodes are implicit in the location (rows and columns)
- * of the links.
- *
- *
link - for rendering links; typically a {@link pv.Bar}. The
- * link mark is added directly to the layout, with the data property defined as
- * all possible pairs of nodes. Each pair is represented as a
- * {@link pv.Network.Layout.Link}, though the linkValue attribute may
- * be 0 if no link exists in the graph.
- *
- *
label - for rendering node labels; typically a
- * {@link pv.Label}. The label mark is added directly to the layout, with the
- * data property defined via the layout's nodes property; note,
- * however, that the nodes are duplicated so as to provide a label across the
- * top and down the side. Properties such as strokeStyle and
- * fillStyle can be overridden to compute properties from node data
- * dynamically.
- *
- *
For more details on how to use this layout, see
- * {@link pv.Layout.Network}.
- *
- * @extends pv.Layout.Network
- */
-pv.Layout.Matrix = function() {
- pv.Layout.Network.call(this);
- var that = this,
- n, // cached matrix size
- dx, // cached cell width
- dy, // cached cell height
- labels, // cached labels (array of strings)
- pairs, // cached pairs (array of links)
- buildImplied = that.buildImplied;
-
- /** @private Cache layout state to optimize properties. */
- this.buildImplied = function(s) {
- buildImplied.call(this, s);
- n = s.nodes.length;
- dx = s.width / n;
- dy = s.height / n;
- labels = s.$matrix.labels;
- pairs = s.$matrix.pairs;
- };
-
- /* Links are all pairs of nodes. */
- this.link
- .data(function() { return pairs; })
- .left(function() { return dx * (this.index % n); })
- .top(function() { return dy * Math.floor(this.index / n); })
- .width(function() { return dx; })
- .height(function() { return dy; })
- .lineWidth(1.5)
- .strokeStyle("#fff")
- .fillStyle(function(l) { return l.linkValue ? "#555" : "#eee"; })
- .parent = this;
-
- /* No special add for links! */
- delete this.link.add;
-
- /* Labels are duplicated for top & left. */
- this.label
- .data(function() { return labels; })
- .left(function() { return this.index & 1 ? dx * ((this.index >> 1) + .5) : null; })
- .top(function() { return this.index & 1 ? null : dy * ((this.index >> 1) + .5); })
- .textMargin(4)
- .textAlign(function() { return this.index & 1 ? "left" : "right"; })
- .textAngle(function() { return this.index & 1 ? -Math.PI / 2 : 0; });
-
- /* The node mark is unused. */
- delete this.node;
-};
-
-pv.Layout.Matrix.prototype = pv.extend(pv.Layout.Network)
- .property("directed", Boolean);
-
-/**
- * Whether this matrix visualization is directed (bidirectional). By default,
- * the graph is assumed to be undirected, such that the visualization is
- * symmetric across the matrix diagonal. If the network is directed, then
- * forward links are drawn above the diagonal, while reverse links are drawn
- * below.
- *
- * @type boolean
- * @name pv.Layout.Matrix.prototype.directed
- */
-
-/**
- * Specifies an optional sort function. The sort function follows the same
- * comparator contract required by {@link pv.Dom.Node#sort}. Specifying a sort
- * function provides an alternative to sort the nodes as they are specified by
- * the nodes property; the main advantage of doing this is that the
- * comparator function can access implicit fields populated by the network
- * layout, such as the linkDegree.
- *
- *
Note that matrix visualizations are particularly sensitive to order. This
- * is referred to as the seriation problem, and many different techniques exist
- * to find good node orders that emphasize clusters, such as spectral layout and
- * simulated annealing.
- *
- * @param {function} f comparator function for nodes.
- * @returns {pv.Layout.Matrix} this.
- */
-pv.Layout.Matrix.prototype.sort = function(f) {
- this.$sort = f;
- return this;
-};
-
-/** @private */
-pv.Layout.Matrix.prototype.buildImplied = function(s) {
- if (pv.Layout.Network.prototype.buildImplied.call(this, s)) return;
-
- var nodes = s.nodes,
- links = s.links,
- sort = this.$sort,
- n = nodes.length,
- index = pv.range(n),
- labels = [],
- pairs = [],
- map = {};
-
- s.$matrix = {labels: labels, pairs: pairs};
-
- /* Sort the nodes. */
- if (sort) index.sort(function(a, b) { return sort(nodes[a], nodes[b]); });
-
- /* Create pairs. */
- for (var i = 0; i < n; i++) {
- for (var j = 0; j < n; j++) {
- var a = index[i],
- b = index[j],
- p = {
- row: i,
- col: j,
- sourceNode: nodes[a],
- targetNode: nodes[b],
- linkValue: 0
- };
- pairs.push(map[a + "." + b] = p);
- }
- }
-
- /* Create labels. */
- for (var i = 0; i < n; i++) {
- var a = index[i];
- labels.push(nodes[a], nodes[a]);
- }
-
- /* Accumulate link values. */
- for (var i = 0; i < links.length; i++) {
- var l = links[i],
- source = l.sourceNode.index,
- target = l.targetNode.index,
- value = l.linkValue;
- map[source + "." + target].linkValue += value;
- if (!s.directed) map[target + "." + source].linkValue += value;
- }
-};
-// ranges (bad, satisfactory, good)
-// measures (actual, forecast)
-// markers (previous, goal)
-
-/*
- * Chart design based on the recommendations of Stephen Few. Implementation
- * based on the work of Clint Ivy, Jamie Love, and Jason Davies.
- * http://projects.instantcognition.com/protovis/bulletchart/
- */
-
-/**
- * Constructs a new, empty bullet layout. Layouts are not typically constructed
- * directly; instead, they are added to an existing panel via
- * {@link pv.Mark#add}.
- *
- * @class
- * @extends pv.Layout
- */
-pv.Layout.Bullet = function() {
- pv.Layout.call(this);
- var that = this,
- buildImplied = that.buildImplied,
- scale = that.x = pv.Scale.linear(),
- orient,
- horizontal,
- rangeColor,
- measureColor,
- x;
-
- /** @private Cache layout state to optimize properties. */
- this.buildImplied = function(s) {
- buildImplied.call(this, x = s);
- orient = s.orient;
- horizontal = /^left|right$/.test(orient);
- rangeColor = pv.ramp("#bbb", "#eee")
- .domain(0, Math.max(1, x.ranges.length - 1));
- measureColor = pv.ramp("steelblue", "lightsteelblue")
- .domain(0, Math.max(1, x.measures.length - 1));
- };
-
- /**
- * The range prototype.
- *
- * @type pv.Mark
- * @name pv.Layout.Bullet.prototype.range
- */
- (this.range = new pv.Mark())
- .data(function() { return x.ranges; })
- .reverse(true)
- .left(function() { return orient == "left" ? 0 : null; })
- .top(function() { return orient == "top" ? 0 : null; })
- .right(function() { return orient == "right" ? 0 : null; })
- .bottom(function() { return orient == "bottom" ? 0 : null; })
- .width(function(d) { return horizontal ? scale(d) : null; })
- .height(function(d) { return horizontal ? null : scale(d); })
- .fillStyle(function() { return rangeColor(this.index); })
- .antialias(false)
- .parent = that;
-
- /**
- * The measure prototype.
- *
- * @type pv.Mark
- * @name pv.Layout.Bullet.prototype.measure
- */
- (this.measure = new pv.Mark())
- .extend(this.range)
- .data(function() { return x.measures; })
- .left(function() { return orient == "left" ? 0 : horizontal ? null : this.parent.width() / 3.25; })
- .top(function() { return orient == "top" ? 0 : horizontal ? this.parent.height() / 3.25 : null; })
- .right(function() { return orient == "right" ? 0 : horizontal ? null : this.parent.width() / 3.25; })
- .bottom(function() { return orient == "bottom" ? 0 : horizontal ? this.parent.height() / 3.25 : null; })
- .fillStyle(function() { return measureColor(this.index); })
- .parent = that;
-
- /**
- * The marker prototype.
- *
- * @type pv.Mark
- * @name pv.Layout.Bullet.prototype.marker
- */
- (this.marker = new pv.Mark())
- .data(function() { return x.markers; })
- .left(function(d) { return orient == "left" ? scale(d) : horizontal ? null : this.parent.width() / 2; })
- .top(function(d) { return orient == "top" ? scale(d) : horizontal ? this.parent.height() / 2 : null; })
- .right(function(d) { return orient == "right" ? scale(d) : null; })
- .bottom(function(d) { return orient == "bottom" ? scale(d) : null; })
- .strokeStyle("black")
- .shape("bar")
- .angle(function() { return horizontal ? 0 : Math.PI / 2; })
- .parent = that;
-
- (this.tick = new pv.Mark())
- .data(function() { return scale.ticks(7); })
- .left(function(d) { return orient == "left" ? scale(d) : null; })
- .top(function(d) { return orient == "top" ? scale(d) : null; })
- .right(function(d) { return orient == "right" ? scale(d) : horizontal ? null : -6; })
- .bottom(function(d) { return orient == "bottom" ? scale(d) : horizontal ? -8 : null; })
- .height(function() { return horizontal ? 6 : null; })
- .width(function() { return horizontal ? null : 6; })
- .parent = that;
-};
-
-pv.Layout.Bullet.prototype = pv.extend(pv.Layout)
- .property("orient", String) // left, right, top, bottom
- .property("ranges")
- .property("markers")
- .property("measures")
- .property("maximum", Number);
-
-/**
- * Default properties for bullet layouts.
- *
- * @type pv.Layout.Bullet
- */
-pv.Layout.Bullet.prototype.defaults = new pv.Layout.Bullet()
- .extend(pv.Layout.prototype.defaults)
- .orient("left")
- .ranges([])
- .markers([])
- .measures([]);
-
-/**
- * The orientation.
- *
- * @type string
- * @name pv.Layout.Bullet.prototype.orient
- */
-
-/**
- * The array of range values.
- *
- * @type array
- * @name pv.Layout.Bullet.prototype.ranges
- */
-
-/**
- * The array of marker values.
- *
- * @type array
- * @name pv.Layout.Bullet.prototype.markers
- */
-
-/**
- * The array of measure values.
- *
- * @type array
- * @name pv.Layout.Bullet.prototype.measures
- */
-
-/**
- * Optional; the maximum range value.
- *
- * @type number
- * @name pv.Layout.Bullet.prototype.maximum
- */
-
-/** @private */
-pv.Layout.Bullet.prototype.buildImplied = function(s) {
- pv.Layout.prototype.buildImplied.call(this, s);
- var size = this.parent[/^left|right$/.test(s.orient) ? "width" : "height"]();
- s.maximum = s.maximum || pv.max([].concat(s.ranges, s.markers, s.measures));
- this.x.domain(0, s.maximum).range(0, size);
-};
-/**
- * Abstract; see an implementing class for details.
- *
- * @class Represents a reusable interaction; applies an interactive behavior to
- * a given mark. Behaviors are themselves functions designed to be used as event
- * handlers. For example, to add pan and zoom support to any panel, say:
- *
- *
- *
- * The behavior should be registered on the event that triggers the start of the
- * behavior. Typically, the behavior will take care of registering for any
- * additional events that are necessary. For example, dragging starts on
- * mousedown, while the drag behavior automatically listens for mousemove and
- * mouseup events on the window. By listening to the window, the behavior can
- * continue to receive mouse events even if the mouse briefly leaves the mark
- * being dragged, or even the root panel.
- *
- *
Each behavior implementation has specific requirements as to which events
- * it supports, and how it should be used. For example, the drag behavior
- * requires that the data associated with the mark be an object with x
- * and y attributes, such as a {@link pv.Vector}, storing the mark's
- * position. See an implementing class for details.
- *
- * @see pv.Behavior.drag
- * @see pv.Behavior.pan
- * @see pv.Behavior.point
- * @see pv.Behavior.select
- * @see pv.Behavior.zoom
- * @extends function
- */
-pv.Behavior = {};
-/**
- * Returns a new drag behavior to be registered on mousedown events.
- *
- * @class Implements interactive dragging starting with mousedown events.
- * Register this behavior on marks that should be draggable by the user, such as
- * the selected region for brushing and linking. This behavior can be used in
- * tandom with {@link pv.Behavior.select} to allow the selected region to be
- * dragged interactively.
- *
- *
After the initial mousedown event is triggered, this behavior listens for
- * mousemove and mouseup events on the window. This allows dragging to continue
- * even if the mouse temporarily leaves the mark that is being dragged, or even
- * the root panel.
- *
- *
This behavior requires that the data associated with the mark being
- * dragged have x and y attributes that correspond to the
- * mark's location in pixels. The mark's positional properties are not set
- * directly by this behavior; instead, the positional properties should be
- * defined as:
- *
- *
.left(function(d) d.x)
- * .top(function(d) d.y)
- *
- * Thus, the behavior does not move the mark directly, but instead updates the
- * mark position by updating the underlying data. Note that if the positional
- * properties are defined with bottom and right (rather than top and left), the
- * drag behavior will be inverted, which will confuse users!
- *
- *
The drag behavior is bounded by the parent panel; the x and
- * y attributes are clamped such that the mark being dragged does not
- * extend outside the enclosing panel's bounds. To facilitate this, the drag
- * behavior also queries for dx and dy attributes on the
- * underlying data, to determine the dimensions of the bar being dragged. For
- * non-rectangular marks, the drag behavior simply treats the mark as a point,
- * which means that only the mark's center is bounded.
- *
- *
The mark being dragged is automatically re-rendered for each mouse event
- * as part of the drag operation. In addition, a fix attribute is
- * populated on the mark, which allows visual feedback for dragging. For
- * example, to change the mark fill color while dragging:
- *
- *
- *
- * In some cases, such as with network layouts, dragging the mark may cause
- * related marks to change, in which case additional marks may also need to be
- * rendered. This can be accomplished by listening for the drag
- * psuedo-events:
- *
- *
dragstart (on mousedown)
- *
drag (on mousemove)
- *
dragend (on mouseup)
- *
- *
For example, to render the parent panel while dragging, thus
- * re-rendering all sibling marks:
- *
- *
- *
- * This behavior may be enhanced in the future to allow more flexible
- * configuration of drag behavior.
- *
- * @extends pv.Behavior
- * @see pv.Behavior
- * @see pv.Behavior.select
- * @see pv.Layout.force
- */
-pv.Behavior.drag = function() {
- var scene, // scene context
- index, // scene context
- p, // particle being dragged
- v1, // initial mouse-particle offset
- max;
-
- /** @private */
- function mousedown(d) {
- index = this.index;
- scene = this.scene;
- var m = this.mouse();
- v1 = ((p = d).fix = pv.vector(d.x, d.y)).minus(m);
- max = {
- x: this.parent.width() - (d.dx || 0),
- y: this.parent.height() - (d.dy || 0)
- };
- scene.mark.context(scene, index, function() { this.render(); });
- pv.Mark.dispatch("dragstart", scene, index);
- }
-
- /** @private */
- function mousemove() {
- if (!scene) return;
- scene.mark.context(scene, index, function() {
- var m = this.mouse();
- p.x = p.fix.x = Math.max(0, Math.min(v1.x + m.x, max.x));
- p.y = p.fix.y = Math.max(0, Math.min(v1.y + m.y, max.y));
- this.render();
- });
- pv.Mark.dispatch("drag", scene, index);
- }
-
- /** @private */
- function mouseup() {
- if (!scene) return;
- p.fix = null;
- scene.mark.context(scene, index, function() { this.render(); });
- pv.Mark.dispatch("dragend", scene, index);
- scene = null;
- }
-
- pv.listen(window, "mousemove", mousemove);
- pv.listen(window, "mouseup", mouseup);
- return mousedown;
-};
-/**
- * Returns a new point behavior to be registered on mousemove events.
- *
- * @class Implements interactive fuzzy pointing, identifying marks that are in
- * close proximity to the mouse cursor. This behavior is an alternative to the
- * native mouseover and mouseout events, improving usability. Rather than
- * requiring the user to mouseover a mark exactly, the mouse simply needs to
- * move near the given mark and a "point" event is triggered. In addition, if
- * multiple marks overlap, the point behavior can be used to identify the mark
- * instance closest to the cursor, as opposed to the one that is rendered on
- * top.
- *
- *
The point behavior can also identify the closest mark instance for marks
- * that produce a continuous graphic primitive. The point behavior can thus be
- * used to provide details-on-demand for both discrete marks (such as dots and
- * bars), as well as continuous marks (such as lines and areas).
- *
- *
This behavior is implemented by finding the closest mark instance to the
- * mouse cursor on every mousemove event. If this closest mark is within the
- * given radius threshold, which defaults to 30 pixels, a "point" psuedo-event
- * is dispatched to the given mark instance. If any mark were previously
- * pointed, it would receive a corresponding "unpoint" event. These two
- * psuedo-event types correspond to the native "mouseover" and "mouseout"
- * events, respectively. To increase the radius at which the point behavior can
- * be applied, specify an appropriate threshold to the constructor, up to
- * Infinity.
- *
- *
By default, the standard Cartesian distance is computed. However, with
- * some visualizations it is desirable to consider only a single dimension, such
- * as the x-dimension for an independent variable. In this case, the
- * collapse parameter can be set to collapse the y dimension:
- *
- *
This behavior only listens to mousemove events on the assigned panel,
- * which is typically the root panel. The behavior will search recursively for
- * descendant marks to point. If the mouse leaves the assigned panel, the
- * behavior no longer receives mousemove events; an unpoint psuedo-event is
- * automatically dispatched to unpoint any pointed mark. Marks may be re-pointed
- * when the mouse reenters the panel.
- *
- *
Panels have transparent fill styles by default; this means that panels may
- * not receive the initial mousemove event to start pointing. To fix this
- * problem, either given the panel a visible fill style (such as "white"), or
- * set the events property to "all" such that the panel receives events
- * despite its transparent fill.
- *
- *
Note: this behavior does not currently wedge marks.
- *
- * @extends pv.Behavior
- *
- * @param {number} [r] the fuzzy radius threshold in pixels
- * @see "The Bubble Cursor: Enhancing Target Acquisition by Dynamic Resizing of the
- * Cursor's Activation Area" by T. Grossman & R. Balakrishnan, CHI 2005.
- */
-pv.Behavior.point = function(r) {
- var unpoint, // the current pointer target
- collapse = null, // dimensions to collapse
- kx = 1, // x-dimension cost scale
- ky = 1, // y-dimension cost scale
- r2 = arguments.length ? r * r : 900; // fuzzy radius
-
- /** @private Search for the mark closest to the mouse. */
- function search(scene, index) {
- var s = scene[index],
- point = {cost: Infinity};
- for (var i = 0, n = s.visible && s.children.length; i < n; i++) {
- var child = s.children[i], mark = child.mark, p;
- if (mark.type == "panel") {
- mark.scene = child;
- for (var j = 0, m = child.length; j < m; j++) {
- mark.index = j;
- p = search(child, j);
- if (p.cost < point.cost) point = p;
- }
- delete mark.scene;
- delete mark.index;
- } else if (mark.$handlers.point) {
- var v = mark.mouse();
- for (var j = 0, m = child.length; j < m; j++) {
- var c = child[j],
- dx = v.x - c.left - (c.width || 0) / 2,
- dy = v.y - c.top - (c.height || 0) / 2,
- dd = kx * dx * dx + ky * dy * dy;
- if (dd < point.cost) {
- point.distance = dx * dx + dy * dy;
- point.cost = dd;
- point.scene = child;
- point.index = j;
- }
- }
- }
- }
- return point;
- }
-
- /** @private */
- function mousemove() {
- /* If the closest mark is far away, clear the current target. */
- var point = search(this.scene, this.index);
- if ((point.cost == Infinity) || (point.distance > r2)) point = null;
-
- /* Unpoint the old target, if it's not the new target. */
- if (unpoint) {
- if (point
- && (unpoint.scene == point.scene)
- && (unpoint.index == point.index)) return;
- pv.Mark.dispatch("unpoint", unpoint.scene, unpoint.index);
- }
-
- /* Point the new target, if there is one. */
- if (unpoint = point) {
- pv.Mark.dispatch("point", point.scene, point.index);
-
- /* Unpoint when the mouse leaves the root panel. */
- pv.listen(this.root.canvas(), "mouseout", mouseout);
- }
- }
-
- /** @private */
- function mouseout(e) {
- if (unpoint && !pv.ancestor(this, e.relatedTarget)) {
- pv.Mark.dispatch("unpoint", unpoint.scene, unpoint.index);
- unpoint = null;
- }
- }
-
- /**
- * Sets or gets the collapse parameter. By default, the standard Cartesian
- * distance is computed. However, with some visualizations it is desirable to
- * consider only a single dimension, such as the x-dimension for an
- * independent variable. In this case, the collapse parameter can be set to
- * collapse the y dimension:
- *
- *
- *
- * @function
- * @returns {pv.Behavior.point} this, or the current collapse parameter.
- * @name pv.Behavior.point.prototype.collapse
- * @param {string} [x] the new collapse parameter
- */
- mousemove.collapse = function(x) {
- if (arguments.length) {
- collapse = String(x);
- switch (collapse) {
- case "y": kx = 1; ky = 0; break;
- case "x": kx = 0; ky = 1; break;
- default: kx = 1; ky = 1; break;
- }
- return mousemove;
- }
- return collapse;
- };
-
- return mousemove;
-};
-/**
- * Returns a new select behavior to be registered on mousedown events.
- *
- * @class Implements interactive selecting starting with mousedown events.
- * Register this behavior on panels that should be selectable by the user, such
- * for brushing and linking. This behavior can be used in tandom with
- * {@link pv.Behavior.drag} to allow the selected region to be dragged
- * interactively.
- *
- *
After the initial mousedown event is triggered, this behavior listens for
- * mousemove and mouseup events on the window. This allows selecting to continue
- * even if the mouse temporarily leaves the assigned panel, or even the root
- * panel.
- *
- *
This behavior requires that the data associated with the mark being
- * dragged have x, y, dx and dy attributes
- * that correspond to the mark's location and dimensions in pixels. The mark's
- * positional properties are not set directly by this behavior; instead, the
- * positional properties should be defined as:
- *
- *
- *
- * Thus, the behavior does not resize the mark directly, but instead updates the
- * selection by updating the assigned panel's underlying data. Note that if the
- * positional properties are defined with bottom and right (rather than top and
- * left), the drag behavior will be inverted, which will confuse users!
- *
- *
The select behavior is bounded by the assigned panel; the positional
- * attributes are clamped such that the selection does not extend outside the
- * panel's bounds.
- *
- *
The panel being selected is automatically re-rendered for each mouse event
- * as part of the drag operation. This behavior may be enhanced in the future to
- * allow more flexible configuration of select behavior. In some cases, such as
- * with parallel coordinates, making a selection may cause related marks to
- * change, in which case additional marks may also need to be rendered. This can
- * be accomplished by listening for the select psuedo-events:
- *
- *
selectstart (on mousedown)
- *
select (on mousemove)
- *
selectend (on mouseup)
- *
- *
For example, to render the parent panel while selecting, thus
- * re-rendering all sibling marks:
- *
- *
- *
- * This behavior may be enhanced in the future to allow more flexible
- * configuration of the selection behavior.
- *
- * @extends pv.Behavior
- * @see pv.Behavior.drag
- */
-pv.Behavior.select = function() {
- var scene, // scene context
- index, // scene context
- r, // region being selected
- m1; // initial mouse position
-
- /** @private */
- function mousedown(d) {
- index = this.index;
- scene = this.scene;
- m1 = this.mouse();
- r = d;
- r.x = m1.x;
- r.y = m1.y;
- r.dx = r.dy = 0;
- pv.Mark.dispatch("selectstart", scene, index);
- }
-
- /** @private */
- function mousemove() {
- if (!scene) return;
- scene.mark.context(scene, index, function() {
- var m2 = this.mouse();
- r.x = Math.max(0, Math.min(m1.x, m2.x));
- r.y = Math.max(0, Math.min(m1.y, m2.y));
- r.dx = Math.min(this.width(), Math.max(m2.x, m1.x)) - r.x;
- r.dy = Math.min(this.height(), Math.max(m2.y, m1.y)) - r.y;
- this.render();
- });
- pv.Mark.dispatch("select", scene, index);
- }
-
- /** @private */
- function mouseup() {
- if (!scene) return;
- pv.Mark.dispatch("selectend", scene, index);
- scene = null;
- }
-
- pv.listen(window, "mousemove", mousemove);
- pv.listen(window, "mouseup", mouseup);
- return mousedown;
-};
-/**
- * Returns a new resize behavior to be registered on mousedown events.
- *
- * @class Implements interactive resizing of a selection starting with mousedown
- * events. Register this behavior on selection handles that should be resizeable
- * by the user, such for brushing and linking. This behavior can be used in
- * tandom with {@link pv.Behavior.select} and {@link pv.Behavior.drag} to allow
- * the selected region to be selected and dragged interactively.
- *
- *
After the initial mousedown event is triggered, this behavior listens for
- * mousemove and mouseup events on the window. This allows resizing to continue
- * even if the mouse temporarily leaves the assigned panel, or even the root
- * panel.
- *
- *
This behavior requires that the data associated with the mark being
- * resized have x, y, dx and dy attributes
- * that correspond to the mark's location and dimensions in pixels. The mark's
- * positional properties are not set directly by this behavior; instead, the
- * positional properties should be defined as:
- *
- *
- *
- * Thus, the behavior does not resize the mark directly, but instead updates the
- * size by updating the assigned panel's underlying data. Note that if the
- * positional properties are defined with bottom and right (rather than top and
- * left), the resize behavior will be inverted, which will confuse users!
- *
- *
The resize behavior is bounded by the assigned mark's enclosing panel; the
- * positional attributes are clamped such that the selection does not extend
- * outside the panel's bounds.
- *
- *
The mark being resized is automatically re-rendered for each mouse event
- * as part of the resize operation. This behavior may be enhanced in the future
- * to allow more flexible configuration. In some cases, such as with parallel
- * coordinates, resizing the selection may cause related marks to change, in
- * which case additional marks may also need to be rendered. This can be
- * accomplished by listening for the select psuedo-events:
- *
- *
resizestart (on mousedown)
- *
resize (on mousemove)
- *
resizeend (on mouseup)
- *
- *
For example, to render the parent panel while resizing, thus
- * re-rendering all sibling marks:
- *
- *
- *
- * The pan behavior currently supports only mouse events; support for keyboard
- * shortcuts to improve accessibility may be added in the future.
- *
- *
After the initial mousedown event is triggered, this behavior listens for
- * mousemove and mouseup events on the window. This allows panning to continue
- * even if the mouse temporarily leaves the panel that is being panned, or even
- * the root panel.
- *
- *
The implementation of this behavior relies on the panel's
- * transform property, which specifies a matrix transformation that is
- * applied to child marks. Note that the transform property only affects the
- * panel's children, but not the panel itself; therefore the panel's fill and
- * stroke will not change when the contents are panned.
- *
- *
Panels have transparent fill styles by default; this means that panels may
- * not receive the initial mousedown event to start panning. To fix this
- * problem, either given the panel a visible fill style (such as "white"), or
- * set the events property to "all" such that the panel receives events
- * despite its transparent fill.
- *
- *
The pan behavior has optional support for bounding. If enabled, the user
- * will not be able to pan the panel outside of the initial bounds. This feature
- * is designed to work in conjunction with the zoom behavior; otherwise,
- * bounding the panel effectively disables all panning.
- *
- * @extends pv.Behavior
- * @see pv.Behavior.zoom
- * @see pv.Panel#transform
- */
-pv.Behavior.pan = function() {
- var scene, // scene context
- index, // scene context
- m1, // transformation matrix at the start of panning
- v1, // mouse location at the start of panning
- k, // inverse scale
- bound; // whether to bound to the panel
-
- /** @private */
- function mousedown() {
- index = this.index;
- scene = this.scene;
- v1 = pv.vector(pv.event.pageX, pv.event.pageY);
- m1 = this.transform();
- k = 1 / (m1.k * this.scale);
- if (bound) {
- bound = {
- x: (1 - m1.k) * this.width(),
- y: (1 - m1.k) * this.height()
- };
- }
- }
-
- /** @private */
- function mousemove() {
- if (!scene) return;
- scene.mark.context(scene, index, function() {
- var x = (pv.event.pageX - v1.x) * k,
- y = (pv.event.pageY - v1.y) * k,
- m = m1.translate(x, y);
- if (bound) {
- m.x = Math.max(bound.x, Math.min(0, m.x));
- m.y = Math.max(bound.y, Math.min(0, m.y));
- }
- this.transform(m).render();
- });
- pv.Mark.dispatch("pan", scene, index);
- }
-
- /** @private */
- function mouseup() {
- scene = null;
- }
-
- /**
- * Sets or gets the bound parameter. If bounding is enabled, the user will not
- * be able to pan outside the initial panel bounds; this typically applies
- * only when the pan behavior is used in tandem with the zoom behavior.
- * Bounding is not enabled by default.
- *
- *
Note: enabling bounding after panning has already occurred will not
- * immediately reset the transform. Bounding should be enabled before the
- * panning behavior is applied.
- *
- * @function
- * @returns {pv.Behavior.pan} this, or the current bound parameter.
- * @name pv.Behavior.pan.prototype.bound
- * @param {boolean} [x] the new bound parameter.
- */
- mousedown.bound = function(x) {
- if (arguments.length) {
- bound = Boolean(x);
- return this;
- }
- return Boolean(bound);
- };
-
- pv.listen(window, "mousemove", mousemove);
- pv.listen(window, "mouseup", mouseup);
- return mousedown;
-};
-/**
- * Returns a new zoom behavior to be registered on mousewheel events.
- *
- * @class Implements interactive zooming using mousewheel events. Register this
- * behavior on panels to allow zooming. This behavior can be used in tandem with
- * {@link pv.Behavior.pan} to allow both panning and zooming:
- *
- *
- *
- * The zoom behavior currently supports only mousewheel events; support for
- * keyboard shortcuts and gesture events to improve accessibility may be added
- * in the future.
- *
- *
The implementation of this behavior relies on the panel's
- * transform property, which specifies a matrix transformation that is
- * applied to child marks. Note that the transform property only affects the
- * panel's children, but not the panel itself; therefore the panel's fill and
- * stroke will not change when the contents are zoomed. The built-in support for
- * transforms only supports uniform scaling and translates, which is sufficient
- * for panning and zooming. Note that this is not a strict geometric
- * transformation, as the lineWidth property is scale-aware: strokes
- * are drawn at constant size independent of scale.
- *
- *
Panels have transparent fill styles by default; this means that panels may
- * not receive mousewheel events to zoom. To fix this problem, either given the
- * panel a visible fill style (such as "white"), or set the events
- * property to "all" such that the panel receives events despite its transparent
- * fill.
- *
- *
The zoom behavior has optional support for bounding. If enabled, the user
- * will not be able to zoom out farther than the initial bounds. This feature is
- * designed to work in conjunction with the pan behavior.
- *
- * @extends pv.Behavior
- * @see pv.Panel#transform
- * @see pv.Mark#scale
- * @param {number} speed
- */
-pv.Behavior.zoom = function(speed) {
- var bound; // whether to bound to the panel
-
- if (!arguments.length) speed = 1 / 48;
-
- /** @private */
- function mousewheel() {
- var v = this.mouse(),
- k = pv.event.wheel * speed,
- m = this.transform().translate(v.x, v.y)
- .scale((k < 0) ? (1e3 / (1e3 - k)) : ((1e3 + k) / 1e3))
- .translate(-v.x, -v.y);
- if (bound) {
- m.k = Math.max(1, m.k);
- m.x = Math.max((1 - m.k) * this.width(), Math.min(0, m.x));
- m.y = Math.max((1 - m.k) * this.height(), Math.min(0, m.y));
- }
- this.transform(m).render();
- pv.Mark.dispatch("zoom", this.scene, this.index);
- }
-
- /**
- * Sets or gets the bound parameter. If bounding is enabled, the user will not
- * be able to zoom out farther than the initial panel bounds. Bounding is not
- * enabled by default. If this behavior is used in tandem with the pan
- * behavior, both should use the same bound parameter.
- *
- *
Note: enabling bounding after zooming has already occurred will not
- * immediately reset the transform. Bounding should be enabled before the zoom
- * behavior is applied.
- *
- * @function
- * @returns {pv.Behavior.zoom} this, or the current bound parameter.
- * @name pv.Behavior.zoom.prototype.bound
- * @param {boolean} [x] the new bound parameter.
- */
- mousewheel.bound = function(x) {
- if (arguments.length) {
- bound = Boolean(x);
- return this;
- }
- return Boolean(bound);
- };
-
- return mousewheel;
-};
-/**
- * @ignore
- * @namespace
- */
-pv.Geo = function() {};
-/**
- * Abstract; not implemented. There is no explicit constructor; this class
- * merely serves to document the representation used by {@link pv.Geo.scale}.
- *
- * @class Represents a pair of geographic coordinates.
- *
- * @name pv.Geo.LatLng
- * @see pv.Geo.scale
- */
-
-/**
- * The latitude coordinate in degrees; positive is North.
- *
- * @type number
- * @name pv.Geo.LatLng.prototype.lat
- */
-
-/**
- * The longitude coordinate in degrees; positive is East.
- *
- * @type number
- * @name pv.Geo.LatLng.prototype.lng
- */
-/**
- * Abstract; not implemented. There is no explicit constructor; this class
- * merely serves to document the representation used by {@link pv.Geo.scale}.
- *
- * @class Represents a geographic projection. This class provides the core
- * implementation for {@link pv.Geo.scale}s, mapping between geographic
- * coordinates (latitude and longitude) and normalized screen space in the range
- * [-1,1]. The remaining mapping between normalized screen space and actual
- * pixels is performed by pv.Geo.scale.
- *
- *
Many geographic projections have a point around which the projection is
- * centered. Rather than have each implementation add support for a
- * user-specified center point, the pv.Geo.scale translates the
- * geographic coordinates relative to the center point for both the forward and
- * inverse projection.
- *
- *
In general, this class should not be used directly, unless the desire is
- * to implement a new geographic projection. Instead, use pv.Geo.scale.
- * Implementations are not required to implement inverse projections, but are
- * needed for some forms of interactivity. Also note that some inverse
- * projections are ambiguous, such as the connecting points in Dymaxian maps.
- *
- * @name pv.Geo.Projection
- * @see pv.Geo.scale
- */
-
-/**
- * The forward projection.
- *
- * @function
- * @name pv.Geo.Projection.prototype.project
- * @param {pv.Geo.LatLng} latlng the latitude and longitude to project.
- * @returns {pv.Vector} the xy-coordinates of the given point.
- */
-
-/**
- * The inverse projection; optional.
- *
- * @function
- * @name pv.Geo.Projection.prototype.invert
- * @param {pv.Vector} xy the x- and y-coordinates to invert.
- * @returns {pv.Geo.LatLng} the latitude and longitude of the given point.
- */
-/**
- * The built-in projections.
- *
- * @see pv.Geo.Projection
- * @namespace
- */
-pv.Geo.projections = {
-
- /** @see http://en.wikipedia.org/wiki/Mercator_projection */
- mercator: {
- project: function(latlng) {
- return {
- x: latlng.lng / 180,
- y: latlng.lat > 85 ? 1 : latlng.lat < -85 ? -1
- : Math.log(Math.tan(Math.PI / 4
- + pv.radians(latlng.lat) / 2)) / Math.PI
- };
- },
- invert: function(xy) {
- return {
- lng: xy.x * 180,
- lat: pv.degrees(2 * Math.atan(Math.exp(xy.y * Math.PI)) - Math.PI / 2)
- };
- }
- },
-
- /** @see http://en.wikipedia.org/wiki/Gall-Peters_projection */
- "gall-peters": {
- project: function(latlng) {
- return {
- x: latlng.lng / 180,
- y: Math.sin(pv.radians(latlng.lat))
- };
- },
- invert: function(xy) {
- return {
- lng: xy.x * 180,
- lat: pv.degrees(Math.asin(xy.y))
- };
- }
- },
-
- /** @see http://en.wikipedia.org/wiki/Sinusoidal_projection */
- sinusoidal: {
- project: function(latlng) {
- return {
- x: pv.radians(latlng.lng) * Math.cos(pv.radians(latlng.lat)) / Math.PI,
- y: latlng.lat / 90
- };
- },
- invert: function(xy) {
- return {
- lng: pv.degrees((xy.x * Math.PI) / Math.cos(xy.y * Math.PI / 2)),
- lat: xy.y * 90
- };
- }
- },
-
- /** @see http://en.wikipedia.org/wiki/Aitoff_projection */
- aitoff: {
- project: function(latlng) {
- var l = pv.radians(latlng.lng),
- f = pv.radians(latlng.lat),
- a = Math.acos(Math.cos(f) * Math.cos(l / 2));
- return {
- x: 2 * (a ? (Math.cos(f) * Math.sin(l / 2) * a / Math.sin(a)) : 0) / Math.PI,
- y: 2 * (a ? (Math.sin(f) * a / Math.sin(a)) : 0) / Math.PI
- };
- },
- invert: function(xy) {
- var x = xy.x * Math.PI / 2,
- y = xy.y * Math.PI / 2;
- return {
- lng: pv.degrees(x / Math.cos(y)),
- lat: pv.degrees(y)
- };
- }
- },
-
- /** @see http://en.wikipedia.org/wiki/Hammer_projection */
- hammer: {
- project: function(latlng) {
- var l = pv.radians(latlng.lng),
- f = pv.radians(latlng.lat),
- c = Math.sqrt(1 + Math.cos(f) * Math.cos(l / 2));
- return {
- x: 2 * Math.SQRT2 * Math.cos(f) * Math.sin(l / 2) / c / 3,
- y: Math.SQRT2 * Math.sin(f) / c / 1.5
- };
- },
- invert: function(xy) {
- var x = xy.x * 3,
- y = xy.y * 1.5,
- z = Math.sqrt(1 - x * x / 16 - y * y / 4);
- return {
- lng: pv.degrees(2 * Math.atan2(z * x, 2 * (2 * z * z - 1))),
- lat: pv.degrees(Math.asin(z * y))
- };
- }
- },
-
- /** The identity or "none" projection. */
- identity: {
- project: function(latlng) {
- return {
- x: latlng.lng / 180,
- y: latlng.lat / 90
- };
- },
- invert: function(xy) {
- return {
- lng: xy.x * 180,
- lat: xy.y * 90
- };
- }
- }
-};
-/**
- * Returns a geographic scale. The arguments to this constructor are optional,
- * and equivalent to calling {@link #projection}.
- *
- * @class Represents a geographic scale; a mapping between latitude-longitude
- * coordinates and screen pixel coordinates. By default, the domain is inferred
- * from the geographic coordinates, so that the domain fills the output range.
- *
- *
Note that geographic scales are two-dimensional transformations, rather
- * than the one-dimensional bidrectional mapping typical of other scales.
- * Rather than mapping (for example) between a numeric domain and a numeric
- * range, geographic scales map between two coordinate objects: {@link
- * pv.Geo.LatLng} and {@link pv.Vector}.
- *
- * @param {pv.Geo.Projection} [p] optional projection.
- * @see pv.Geo.scale#ticks
- */
-pv.Geo.scale = function(p) {
- var rmin = {x: 0, y: 0}, // default range minimum
- rmax = {x: 1, y: 1}, // default range maximum
- d = [], // default domain
- j = pv.Geo.projections.identity, // domain <-> normalized range
- x = pv.Scale.linear(-1, 1).range(0, 1), // normalized <-> range
- y = pv.Scale.linear(-1, 1).range(1, 0), // normalized <-> range
- c = {lng: 0, lat: 0}, // Center Point
- lastLatLng, // cached latlng
- lastPoint; // cached point
-
- /** @private */
- function scale(latlng) {
- if (!lastLatLng
- || (latlng.lng != lastLatLng.lng)
- || (latlng.lat != lastLatLng.lat)) {
- lastLatLng = latlng;
- var p = project(latlng);
- lastPoint = {x: x(p.x), y: y(p.y)};
- }
- return lastPoint;
- }
-
- /** @private */
- function project(latlng) {
- var offset = {lng: latlng.lng - c.lng, lat: latlng.lat};
- return j.project(offset);
- }
-
- /** @private */
- function invert(xy) {
- var latlng = j.invert(xy);
- latlng.lng += c.lng;
- return latlng;
- }
-
- /** Returns the projected x-coordinate. */
- scale.x = function(latlng) {
- return scale(latlng).x;
- };
-
- /** Returns the projected y-coordinate. */
- scale.y = function(latlng) {
- return scale(latlng).y;
- };
-
- /**
- * Abstract; this is a local namespace on a given geographic scale.
- *
- * @namespace Tick functions for geographic scales. Because geographic scales
- * represent two-dimensional transformations (as opposed to one-dimensional
- * transformations typical of other scales), the tick values are similarly
- * represented as two-dimensional coordinates in the input domain, i.e.,
- * {@link pv.Geo.LatLng} objects.
- *
- *
Also, note that non-rectilinear projections, such as sinsuoidal and
- * aitoff, may not produce straight lines for constant longitude or constant
- * latitude. Therefore the returned array of ticks is a two-dimensional array,
- * sampling various latitudes as constant longitude, and vice versa.
- *
- *
The tick lines can therefore be approximated as polylines, either with
- * "linear" or "cardinal" interpolation. This is not as accurate as drawing
- * the true curve through the projection space, but is usually sufficient.
- *
- * @name pv.Geo.scale.prototype.ticks
- * @see pv.Geo.scale
- * @see pv.Geo.LatLng
- * @see pv.Line#interpolate
- */
- scale.ticks = {
-
- /**
- * Returns longitude ticks.
- *
- * @function
- * @param {number} [m] the desired number of ticks.
- * @returns {array} a nested array of pv.Geo.LatLng ticks.
- * @name pv.Geo.scale.prototype.ticks.prototype.lng
- */
- lng: function(m) {
- var lat, lng;
- if (d.length > 1) {
- var s = pv.Scale.linear();
- if (m == undefined) m = 10;
- lat = s.domain(d, function(d) { return d.lat; }).ticks(m);
- lng = s.domain(d, function(d) { return d.lng; }).ticks(m);
- } else {
- lat = pv.range(-80, 81, 10);
- lng = pv.range(-180, 181, 10);
- }
- return lng.map(function(lng) {
- return lat.map(function(lat) {
- return {lat: lat, lng: lng};
- });
- });
- },
-
- /**
- * Returns latitude ticks.
- *
- * @function
- * @param {number} [m] the desired number of ticks.
- * @returns {array} a nested array of pv.Geo.LatLng ticks.
- * @name pv.Geo.scale.prototype.ticks.prototype.lat
- */
- lat: function(m) {
- return pv.transpose(scale.ticks.lng(m));
- }
- };
-
- /**
- * Inverts the specified value in the output range, returning the
- * corresponding value in the input domain. This is frequently used to convert
- * the mouse location (see {@link pv.Mark#mouse}) to a value in the input
- * domain. Inversion is only supported for numeric ranges, and not colors.
- *
- *
Note that this method does not do any rounding or bounds checking. If
- * the input domain is discrete (e.g., an array index), the returned value
- * should be rounded. If the specified y value is outside the range,
- * the returned value may be equivalently outside the input domain.
- *
- * @function
- * @name pv.Geo.scale.prototype.invert
- * @param {number} y a value in the output range (a pixel location).
- * @returns {number} a value in the input domain.
- */
- scale.invert = function(p) {
- return invert({x: x.invert(p.x), y: y.invert(p.y)});
- };
-
- /**
- * Sets or gets the input domain. Note that unlike quantitative scales, the
- * domain cannot be reduced to a simple rectangle (i.e., minimum and maximum
- * values for latitude and longitude). Instead, the domain values must be
- * projected to normalized space, effectively finding the domain in normalized
- * space rather than in terms of latitude and longitude. Thus, changing the
- * projection requires recomputing the normalized domain.
- *
- *
This method can be invoked several ways:
- *
- *
1. domain(values...)
- *
- *
Specifying the domain as a series of {@link pv.Geo.LatLng}s is the most
- * explicit and recommended approach. However, if the domain values are
- * derived from data, you may find the second method more appropriate.
- *
- *
2. domain(array, f)
- *
- *
Rather than enumerating the domain explicitly, you can specify a single
- * argument of an array. In addition, you can specify an optional accessor
- * function to extract the domain values (as {@link pv.Geo.LatLng}s) from the
- * array. If the specified array has fewer than two elements, this scale will
- * default to the full normalized domain.
- *
- *
2. domain()
- *
- *
Invoking the domain method with no arguments returns the
- * current domain as an array.
- *
- * @function
- * @name pv.Geo.scale.prototype.domain
- * @param {...} domain... domain values.
- * @returns {pv.Geo.scale} this, or the current domain.
- */
- scale.domain = function(array, f) {
- if (arguments.length) {
- d = (array instanceof Array)
- ? ((arguments.length > 1) ? pv.map(array, f) : array)
- : Array.prototype.slice.call(arguments);
- if (d.length > 1) {
- var lngs = d.map(function(c) { return c.lng; });
- var lats = d.map(function(c) { return c.lat; });
- c = {
- lng: (pv.max(lngs) + pv.min(lngs)) / 2,
- lat: (pv.max(lats) + pv.min(lats)) / 2
- };
- var n = d.map(project); // normalized domain
- x.domain(n, function(p) { return p.x; });
- y.domain(n, function(p) { return p.y; });
- } else {
- c = {lng: 0, lat: 0};
- x.domain(-1, 1);
- y.domain(-1, 1);
- }
- lastLatLng = null; // invalidate the cache
- return this;
- }
- return d;
- };
-
- /**
- * Sets or gets the output range. This method can be invoked several ways:
- *
- *
1. range(min, max)
- *
- *
If two objects are specified, the arguments should be {@link pv.Vector}s
- * which specify the minimum and maximum values of the x- and y-coordinates
- * explicitly.
- *
- *
2. range(width, height)
- *
- *
If two numbers are specified, the arguments specify the maximum values
- * of the x- and y-coordinates explicitly; the minimum values are implicitly
- * zero.
- *
- *
3. range()
- *
- *
Invoking the range method with no arguments returns the current
- * range as an array of two {@link pv.Vector}s: the minimum (top-left) and
- * maximum (bottom-right) values.
- *
- * @function
- * @name pv.Geo.scale.prototype.range
- * @param {...} range... range values.
- * @returns {pv.Geo.scale} this, or the current range.
- */
- scale.range = function(min, max) {
- if (arguments.length) {
- if (typeof min == "object") {
- rmin = {x: Number(min.x), y: Number(min.y)};
- rmax = {x: Number(max.x), y: Number(max.y)};
- } else {
- rmin = {x: 0, y: 0};
- rmax = {x: Number(min), y: Number(max)};
- }
- x.range(rmin.x, rmax.x);
- y.range(rmax.y, rmin.y); // XXX flipped?
- lastLatLng = null; // invalidate the cache
- return this;
- }
- return [rmin, rmax];
- };
-
- /**
- * Sets or gets the projection. This method can be invoked several ways:
- *
- *
1. projection(string)
- *
- *
Specifying a string sets the projection to the given named projection in
- * {@link pv.Geo.projections}. If no such projection is found, the identity
- * projection is used.
- *
- *
2. projection(object)
- *
- *
Specifying an object sets the projection to the given custom projection,
- * which must implement the forward and inverse methods per the
- * {@link pv.Geo.Projection} interface.
- *
- *